Skip to content

Commit 8513ed1

Browse files
authored
Merge pull request Azure#822 from kmurudi/CNS_debugApi_getPodContexts
CNS Debug API to expose PodIpIdByOrchrestratorContext
2 parents 28cf37b + 2d318a8 commit 8513ed1

File tree

6 files changed

+146
-9
lines changed

6 files changed

+146
-9
lines changed

cns/NetworkContainerContract.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const (
2323
RequestIPConfig = "/network/requestipconfig"
2424
ReleaseIPConfig = "/network/releaseipconfig"
2525
GetIPAddresses = "/debug/getipaddresses"
26+
GetPodIPOrchestratorContext = "/debug/getpodcontext"
2627
)
2728

2829
// NetworkContainer Prefixes
@@ -244,8 +245,14 @@ type GetIPAddressStateResponse struct {
244245

245246
// GetIPAddressStatusResponse is used in CNS IPAM mode as a response to get IP address, state and Pod info
246247
type GetIPAddressStatusResponse struct {
247-
IPConfigurationStatus[] IPConfigurationStatus
248-
Response Response
248+
IPConfigurationStatus []IPConfigurationStatus
249+
Response Response
250+
}
251+
252+
//GetPodContextResponse is used in CNS Client debug mode to get mapping of Orchestrator Context to Pod IP UUID
253+
type GetPodContextResponse struct {
254+
PodContext map[string]string
255+
Response Response
249256
}
250257

251258
// IPAddressState Only used in the GetIPConfig API to return IP's that match a filter

cns/cnsclient/cli.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const (
1515
getAllocatedArg = "Allocated"
1616
getAllArg = "All"
1717
getPendingReleaseArg = "PendingRelease"
18+
getPodCmdArg = "getPodContexts"
1819

1920
releaseArg = "release"
2021

@@ -28,6 +29,7 @@ const (
2829
var (
2930
availableCmds = []string{
3031
getCmdArg,
32+
getPodCmdArg,
3133
}
3234

3335
getFlags = []string{
@@ -49,6 +51,8 @@ func HandleCNSClientCommands(cmd, arg string) error {
4951
switch {
5052
case strings.EqualFold(getCmdArg, cmd):
5153
return getCmd(cnsClient, arg)
54+
case strings.EqualFold(getPodCmdArg, cmd):
55+
return getPodCmd(cnsClient)
5256
default:
5357
return fmt.Errorf("No debug cmd supplied, options are: %v", getCmdArg)
5458
}
@@ -96,3 +100,22 @@ func printIPAddresses(addrSlice []cns.IPConfigurationStatus) {
96100
cns.IPConfigurationStatus.String(addr)
97101
}
98102
}
103+
104+
func getPodCmd(client *CNSClient) error {
105+
106+
resp, err := client.GetPodOrchestratorContext()
107+
if err != nil {
108+
return err
109+
}
110+
111+
printPodContext(resp)
112+
return nil
113+
}
114+
115+
func printPodContext(podContext map[string]string) {
116+
var i = 1
117+
for orchContext, podID := range podContext {
118+
fmt.Println(i, " ", orchContext, " : ", podID)
119+
i++
120+
}
121+
}

cns/cnsclient/cnsclient.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,3 +371,42 @@ func (cnsClient *CNSClient) GetIPAddressesMatchingStates(StateFilter ...string)
371371

372372
return resp.IPConfigurationStatus, err
373373
}
374+
375+
//GetPodOrchestratorContext calls GetPodIpOrchestratorContext API on CNS
376+
func (cnsClient *CNSClient) GetPodOrchestratorContext() (map[string]string, error) {
377+
var (
378+
resp cns.GetPodContextResponse
379+
err error
380+
res *http.Response
381+
)
382+
383+
url := cnsClient.connectionURL + cns.GetPodIPOrchestratorContext
384+
log.Printf("GetPodIPOrchestratorContext url %v", url)
385+
386+
res, err = http.Get(url)
387+
if err != nil {
388+
log.Errorf("[Azure CNSClient] GetPodIPOrchestratorContext HTTP Get returned error %v", err.Error())
389+
return resp.PodContext, err
390+
}
391+
392+
defer res.Body.Close()
393+
394+
if res.StatusCode != http.StatusOK {
395+
errMsg := fmt.Sprintf("[Azure CNSClient] GetPodIPOrchestratorContext invalid http status code: %v", res.StatusCode)
396+
log.Errorf(errMsg)
397+
return resp.PodContext, fmt.Errorf(errMsg)
398+
}
399+
400+
err = json.NewDecoder(res.Body).Decode(&resp)
401+
if err != nil {
402+
log.Errorf("[Azure CNSClient] Error received while parsing GetPodContext response resp:%v err:%v", res.Body, err.Error())
403+
return resp.PodContext, err
404+
}
405+
406+
if resp.Response.ReturnCode != 0 {
407+
log.Errorf("[Azure CNSClient] GetPodContext received error response :%v", resp.Response.Message)
408+
return resp.PodContext, fmt.Errorf(resp.Response.Message)
409+
}
410+
411+
return resp.PodContext, err
412+
}

cns/cnsclient/cnsclient_test.go

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -226,24 +226,60 @@ func TestCNSClientRequestAndRelease(t *testing.T) {
226226
if reflect.DeepEqual(desired, resultIPnet) != true {
227227
t.Fatalf("Desired result not matching actual result, expected: %+v, actual: %+v", desired, resultIPnet)
228228
}
229+
//checking for allocated IP address and pod context printing before ReleaseIPAddress is called
230+
ipaddresses, err := cnsClient.GetIPAddressesMatchingStates(cns.Allocated)
231+
if err != nil {
232+
t.Fatalf("Get allocated IP addresses failed %+v", err)
233+
}
234+
235+
if len(ipaddresses) != 1 {
236+
t.Fatalf("Number of available IP addresses expected to be 1, actual %+v", ipaddresses)
237+
}
238+
239+
if ipaddresses[0].IPAddress != desiredIpAddress && ipaddresses[0].State != cns.Allocated {
240+
t.Fatalf("Available IP address does not match expected, address state: %+v", ipaddresses)
241+
}
242+
243+
t.Log(ipaddresses)
229244

230245
// release requested IP address, expect success
231246
err = cnsClient.ReleaseIPAddress(orchestratorContext)
232247
if err != nil {
233248
t.Fatalf("Expected to not fail when releasing IP reservation found with context: %+v", err)
234249
}
250+
}
235251

236-
ipaddresses, err := cnsClient.GetIPAddressesMatchingStates(cns.Available)
252+
func TestCNSClientPodContextApi(t *testing.T) {
253+
podName := "testpodname"
254+
podNamespace := "testpodnamespace"
255+
desiredIpAddress := "10.0.0.5"
256+
257+
secondaryIps := make([]string, 0)
258+
secondaryIps = append(secondaryIps, desiredIpAddress)
259+
cnsClient, _ := InitCnsClient("")
260+
261+
addTestStateToRestServer(t, secondaryIps)
262+
263+
podInfo := cns.KubernetesPodInfo{PodName: podName, PodNamespace: podNamespace}
264+
orchestratorContext, err := json.Marshal(podInfo)
237265
if err != nil {
238-
t.Fatalf("Get allocated IP addresses failed %+v", err)
266+
t.Fatal(err)
239267
}
240268

241-
if len(ipaddresses) != 1 {
242-
t.Fatalf("Number of available IP addresses expected to be 1, actual %+v", ipaddresses)
269+
// request IP address
270+
_, err = cnsClient.RequestIPAddress(orchestratorContext)
271+
if err != nil {
272+
t.Fatalf("get IP from CNS failed with %+v", err)
243273
}
244274

245-
if ipaddresses[0].IPAddress != desiredIpAddress && ipaddresses[0].State != cns.Available {
246-
t.Fatalf("Available IP address does not match expected, address state: %+v", ipaddresses)
275+
//test for pod ip by orch context map
276+
podcontext, err := cnsClient.GetPodOrchestratorContext()
277+
if err != nil {
278+
t.Errorf("Get pod ip by orchestrator context failed: %+v", err)
247279
}
248-
fmt.Println(ipaddresses)
280+
if len(podcontext) < 1 {
281+
t.Errorf("Expected atleast 1 entry in map for podcontext: %+v", podcontext)
282+
}
283+
284+
t.Log(podcontext)
249285
}

cns/restserver/ipam.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,37 @@ func (service *HTTPRestService) GetPodIPConfigState() map[string]cns.IPConfigura
190190
return service.PodIPConfigState
191191
}
192192

193+
func (service *HTTPRestService) getPodIPIDByOrchestratorContexthandler(w http.ResponseWriter, r *http.Request) {
194+
var (
195+
resp cns.GetPodContextResponse
196+
statusCode int
197+
returnMessage string
198+
err error
199+
)
200+
201+
statusCode = UnexpectedError
202+
203+
defer func() {
204+
if err != nil {
205+
resp.Response.ReturnCode = statusCode
206+
resp.Response.Message = returnMessage
207+
}
208+
209+
err = service.Listener.Encode(w, &resp)
210+
logger.Response(service.Name, resp, resp.Response.ReturnCode, ReturnCodeToString(resp.Response.ReturnCode), err)
211+
}()
212+
213+
resp.PodContext = service.GetPodIPIDByOrchestratorContext()
214+
215+
return
216+
}
217+
218+
func (service *HTTPRestService) GetPodIPIDByOrchestratorContext() map[string]string {
219+
service.RLock()
220+
defer service.RUnlock()
221+
return service.PodIPIDByOrchestratorContext
222+
}
223+
193224
// GetPendingProgramIPConfigs returns list of IPs which are in pending program status
194225
func (service *HTTPRestService) GetPendingProgramIPConfigs() []cns.IPConfigurationStatus {
195226
service.RLock()

cns/restserver/restserver.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ func (service *HTTPRestService) Init(config *common.ServiceConfig) error {
174174
listener.AddHandler(cns.ReleaseIPConfig, service.releaseIPConfigHandler)
175175
listener.AddHandler(cns.NmAgentSupportedApisPath, service.nmAgentSupportedApisHandler)
176176
listener.AddHandler(cns.GetIPAddresses, service.getIPAddressesHandler)
177+
listener.AddHandler(cns.GetPodIPOrchestratorContext, service.getPodIPIDByOrchestratorContexthandler)
177178

178179
// handlers for v0.2
179180
listener.AddHandler(cns.V2Prefix+cns.SetEnvironmentPath, service.setEnvironment)

0 commit comments

Comments
 (0)