@@ -20,6 +20,7 @@ import (
20
20
var (
21
21
ErrStoreEmpty = errors .New ("empty endpoint state store" )
22
22
ErrParsePodIPFailed = errors .New ("failed to parse pod's ip" )
23
+ ErrNoNCs = errors .New ("No NCs found in the CNS internal state" )
23
24
)
24
25
25
26
// requestIPConfigHandlerHelper validates the request, assigns IPs, and returns a response
@@ -88,13 +89,13 @@ func (service *HTTPRestService) requestIPConfigHandler(w http.ResponseWriter, r
88
89
return
89
90
}
90
91
91
- // This method can only return 1 IP. If we have more than one NC then we expect to need to return one IP per NC
92
- if len (service .state .ContainerStatus ) > 1 {
92
+ // This method can only return EXACTLY 1 IP. If we have more than one NC then we expect to need to return one IP per NC
93
+ if len (service .state .ContainerStatus ) != 1 {
93
94
// we send a response back saying that this API won't be able to return the amount of IPs needed to fulfill the request
94
95
reserveResp := & cns.IPConfigResponse {
95
96
Response : cns.Response {
96
97
ReturnCode : types .InvalidRequest ,
97
- Message : fmt .Sprintf ("Called API that can only return 1 IP when expecting %d " , len (service .state .ContainerStatus )),
98
+ Message : fmt .Sprintf ("Expected 1 NC when calling this API but found %d NCs " , len (service .state .ContainerStatus )),
98
99
},
99
100
}
100
101
w .Header ().Set (cnsReturnCode , reserveResp .Response .ReturnCode .String ())
@@ -128,6 +129,21 @@ func (service *HTTPRestService) requestIPConfigHandler(w http.ResponseWriter, r
128
129
return
129
130
}
130
131
132
+ // Checks to make sure we return exactly 1 IP
133
+ // If IPAM assigned more than 1 IP then we need to raise an error since this API can only return one IP and IPAM may have assigned more than one
134
+ if len (ipConfigsResp .PodIPInfo ) != 1 {
135
+ // we send a response back saying that this API won't be able to return the amount of IPs needed to fulfill the request
136
+ reserveResp := & cns.IPConfigResponse {
137
+ Response : cns.Response {
138
+ ReturnCode : types .UnexpectedError ,
139
+ Message : fmt .Sprintf ("request returned incorrect number of IPs. Expected 1 and returned %d" , len (ipConfigsResp .PodIPInfo )),
140
+ },
141
+ }
142
+ w .Header ().Set (cnsReturnCode , reserveResp .Response .ReturnCode .String ())
143
+ err = service .Listener .Encode (w , & reserveResp )
144
+ logger .ResponseEx (service .Name + operationName , ipconfigRequest , reserveResp , reserveResp .Response .ReturnCode , err )
145
+ return
146
+ }
131
147
// As this API is expected to return IPConfigResponse, generate it from the IPConfigsResponse returned above.
132
148
reserveResp := & cns.IPConfigResponse {
133
149
Response : ipConfigsResp .Response ,
@@ -273,12 +289,12 @@ func (service *HTTPRestService) releaseIPConfigHandler(w http.ResponseWriter, r
273
289
return
274
290
}
275
291
276
- // check to make sure there aren't multiple NCs
277
- if len (service .state .ContainerStatus ) > 1 {
292
+ // check to make sure there is only one NC
293
+ if len (service .state .ContainerStatus ) != 1 {
278
294
reserveResp := & cns.IPConfigResponse {
279
295
Response : cns.Response {
280
296
ReturnCode : types .InvalidRequest ,
281
- Message : fmt .Sprintf ("Called API that can only return 1 IP when expecting %d " , len (service .state .ContainerStatus )),
297
+ Message : fmt .Sprintf ("Expected 1 NC when calling this API but found %d NCs " , len (service .state .ContainerStatus )),
282
298
},
283
299
}
284
300
w .Header ().Set (cnsReturnCode , reserveResp .Response .ReturnCode .String ())
@@ -661,7 +677,15 @@ func (service *HTTPRestService) GetExistingIPConfig(podInfo cns.PodInfo) ([]cns.
661
677
662
678
// Assigns a pod with all IPs desired
663
679
func (service * HTTPRestService ) AssignDesiredIPConfigs (podInfo cns.PodInfo , desiredIPAddresses []string ) ([]cns.PodIpInfo , error ) {
680
+ // Gets the number of NCs which will determine the number of IPs given to a pod
681
+ numOfNCs := len (service .state .ContainerStatus )
682
+ // checks to make sure we have NCs before trying to get IPs
683
+ if numOfNCs == 0 {
684
+ return nil , ErrNoNCs
685
+ }
686
+ // Sets the number of desired IPs equal to the number of desired IPs passed in
664
687
numDesiredIPAddresses := len (desiredIPAddresses )
688
+ // Creates a slice of PodIpInfo with the size as number of NCs to hold the result for assigned IP configs
665
689
podIPInfo := make ([]cns.PodIpInfo , numDesiredIPAddresses )
666
690
// creating a map for the loop to check to see if the IP in the pool is one of the desired IPs
667
691
desiredIPMap := make (map [string ]struct {})
@@ -756,12 +780,16 @@ func (service *HTTPRestService) AssignDesiredIPConfigs(podInfo cns.PodInfo, desi
756
780
// Assigns an available IP from each NC on the NNC. If there is one NC then we expect to only have one IP return
757
781
// In the case of dualstack we would expect to have one IPv6 from one NC and one IPv4 from a second NC
758
782
func (service * HTTPRestService ) AssignAvailableIPConfigs (podInfo cns.PodInfo ) ([]cns.PodIpInfo , error ) {
783
+ // Gets the number of NCs which will determine the number of IPs given to a pod
784
+ numOfNCs := len (service .state .ContainerStatus )
785
+ // if there are no NCs on the NNC there will be no IPs in the pool so return error
786
+ if numOfNCs == 0 {
787
+ return nil , ErrNoNCs
788
+ }
759
789
service .Lock ()
760
790
defer service .Unlock ()
761
- // Sets the number of IPs needed equal to the number of NCs so that we can get one IP per NC
762
- numIPsNeeded := len (service .state .ContainerStatus )
763
791
// Creates a slice of PodIpInfo with the size as number of NCs to hold the result for assigned IP configs
764
- podIPInfo := make ([]cns.PodIpInfo , numIPsNeeded )
792
+ podIPInfo := make ([]cns.PodIpInfo , numOfNCs )
765
793
// This map is used to store whether or not we have found an available IP from an NC when looping through the pool
766
794
ipsToAssign := make (map [string ]cns.IPConfigurationStatus )
767
795
@@ -777,13 +805,13 @@ func (service *HTTPRestService) AssignAvailableIPConfigs(podInfo cns.PodInfo) ([
777
805
}
778
806
ipsToAssign [ipState .NCID ] = ipState
779
807
// Once one IP per container is found break out of the loop and stop searching
780
- if len (ipsToAssign ) == numIPsNeeded {
808
+ if len (ipsToAssign ) == numOfNCs {
781
809
break
782
810
}
783
811
}
784
812
785
813
// Checks to make sure we found one IP for each NC
786
- if len (ipsToAssign ) != numIPsNeeded {
814
+ if len (ipsToAssign ) != numOfNCs {
787
815
//nolint:goerr113 // return error
788
816
return podIPInfo , fmt .Errorf ("not enough IPs available, waiting on Azure CNS to allocate more" )
789
817
}
0 commit comments