diff --git a/cnm/ipam/ipam.go b/cnm/ipam/ipam.go index ec15b31aaf..4a6d2fec90 100644 --- a/cnm/ipam/ipam.go +++ b/cnm/ipam/ipam.go @@ -118,7 +118,7 @@ func (plugin *ipamPlugin) getCapabilities(w http.ResponseWriter, r *http.Request RequiresRequestReplay: requiresRequestReplay, } - err := plugin.Listener.Encode(w, &resp) + err := common.Encode(w, &resp) log.Response(plugin.Name, &resp, returnCode, returnStr, err) } @@ -135,7 +135,7 @@ func (plugin *ipamPlugin) getDefaultAddressSpaces(w http.ResponseWriter, r *http resp.LocalDefaultAddressSpace = localId resp.GlobalDefaultAddressSpace = globalId - err := plugin.Listener.Encode(w, &resp) + err := common.Encode(w, &resp) log.Response(plugin.Name, &resp, returnCode, returnStr, err) } @@ -145,7 +145,7 @@ func (plugin *ipamPlugin) requestPool(w http.ResponseWriter, r *http.Request) { var req RequestPoolRequest // Decode request. - err := plugin.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) log.Request(plugin.Name, &req, err) if err != nil { return @@ -163,7 +163,7 @@ func (plugin *ipamPlugin) requestPool(w http.ResponseWriter, r *http.Request) { poolId = ipam.NewAddressPoolId(req.AddressSpace, poolId, "").String() resp := RequestPoolResponse{PoolID: poolId, Pool: subnet, Data: data} - err = plugin.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) log.Response(plugin.Name, &resp, returnCode, returnStr, err) } @@ -173,7 +173,7 @@ func (plugin *ipamPlugin) releasePool(w http.ResponseWriter, r *http.Request) { var req ReleasePoolRequest // Decode request. - err := plugin.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) log.Request(plugin.Name, &req, err) if err != nil { return @@ -195,7 +195,7 @@ func (plugin *ipamPlugin) releasePool(w http.ResponseWriter, r *http.Request) { // Encode response. resp := ReleasePoolResponse{} - err = plugin.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) log.Response(plugin.Name, &resp, returnCode, returnStr, err) } @@ -205,7 +205,7 @@ func (plugin *ipamPlugin) getPoolInfo(w http.ResponseWriter, r *http.Request) { var req GetPoolInfoRequest // Decode request. - err := plugin.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) log.Request(plugin.Name, &req, err) if err != nil { return @@ -234,7 +234,7 @@ func (plugin *ipamPlugin) getPoolInfo(w http.ResponseWriter, r *http.Request) { resp.UnhealthyAddresses = append(resp.UnhealthyAddresses, addr.String()) } - err = plugin.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) log.Response(plugin.Name, &resp, returnCode, returnStr, err) } @@ -244,7 +244,7 @@ func (plugin *ipamPlugin) requestAddress(w http.ResponseWriter, r *http.Request) var req RequestAddressRequest // Decode request. - err := plugin.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) log.Request(plugin.Name, &req, err) if err != nil { return @@ -275,7 +275,7 @@ func (plugin *ipamPlugin) requestAddress(w http.ResponseWriter, r *http.Request) data := make(map[string]string) resp := RequestAddressResponse{Address: addr, Data: data} - err = plugin.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) log.Response(plugin.Name, &resp, returnCode, returnStr, err) } @@ -285,7 +285,7 @@ func (plugin *ipamPlugin) releaseAddress(w http.ResponseWriter, r *http.Request) var req ReleaseAddressRequest // Decode request. - err := plugin.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) log.Request(plugin.Name, &req, err) if err != nil { return @@ -307,7 +307,7 @@ func (plugin *ipamPlugin) releaseAddress(w http.ResponseWriter, r *http.Request) // Encode response. resp := ReleaseAddressResponse{} - err = plugin.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) log.Response(plugin.Name, &resp, returnCode, returnStr, err) } diff --git a/cnm/network/network.go b/cnm/network/network.go index 4358d1a485..af9484e229 100644 --- a/cnm/network/network.go +++ b/cnm/network/network.go @@ -128,7 +128,7 @@ func (plugin *netPlugin) getCapabilities(w http.ResponseWriter, r *http.Request) log.Request(plugin.Name, &req, nil) resp := getCapabilitiesResponse{Scope: plugin.scope} - err := plugin.Listener.Encode(w, &resp) + err := common.Encode(w, &resp) log.Response(plugin.Name, &resp, returnCode, returnStr, err) } @@ -138,7 +138,7 @@ func (plugin *netPlugin) createNetwork(w http.ResponseWriter, r *http.Request) { var req createNetworkRequest // Decode request. - err := plugin.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) log.Request(plugin.Name, &req, err) if err != nil { return @@ -182,7 +182,7 @@ func (plugin *netPlugin) createNetwork(w http.ResponseWriter, r *http.Request) { // Encode response. resp := createNetworkResponse{} - err = plugin.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) log.Response(plugin.Name, &resp, returnCode, returnStr, err) } @@ -192,7 +192,7 @@ func (plugin *netPlugin) deleteNetwork(w http.ResponseWriter, r *http.Request) { var req deleteNetworkRequest // Decode request. - err := plugin.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) log.Request(plugin.Name, &req, err) if err != nil { return @@ -207,7 +207,7 @@ func (plugin *netPlugin) deleteNetwork(w http.ResponseWriter, r *http.Request) { // Encode response. resp := deleteNetworkResponse{} - err = plugin.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) log.Response(plugin.Name, &resp, returnCode, returnStr, err) } @@ -217,7 +217,7 @@ func (plugin *netPlugin) createEndpoint(w http.ResponseWriter, r *http.Request) var req createEndpointRequest // Decode request. - err := plugin.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) log.Request(plugin.Name, &req, err) if err != nil { return @@ -256,7 +256,7 @@ func (plugin *netPlugin) createEndpoint(w http.ResponseWriter, r *http.Request) // Encode response. resp := createEndpointResponse{} - err = plugin.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) log.Response(plugin.Name, &resp, returnCode, returnStr, err) } @@ -266,7 +266,7 @@ func (plugin *netPlugin) deleteEndpoint(w http.ResponseWriter, r *http.Request) var req deleteEndpointRequest // Decode request. - err := plugin.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) log.Request(plugin.Name, &req, err) if err != nil { return @@ -281,7 +281,7 @@ func (plugin *netPlugin) deleteEndpoint(w http.ResponseWriter, r *http.Request) // Encode response. resp := deleteEndpointResponse{} - err = plugin.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) log.Response(plugin.Name, &resp, returnCode, returnStr, err) } @@ -291,7 +291,7 @@ func (plugin *netPlugin) join(w http.ResponseWriter, r *http.Request) { var req joinRequest // Decode request. - err := plugin.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) log.Request(plugin.Name, &req, err) if err != nil { return @@ -315,7 +315,7 @@ func (plugin *netPlugin) join(w http.ResponseWriter, r *http.Request) { Gateway: ep.Gateways[0].String(), } - err = plugin.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) log.Response(plugin.Name, &resp, returnCode, returnStr, err) } @@ -325,7 +325,7 @@ func (plugin *netPlugin) leave(w http.ResponseWriter, r *http.Request) { var req leaveRequest // Decode request. - err := plugin.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) log.Request(plugin.Name, &req, err) if err != nil { return @@ -340,7 +340,7 @@ func (plugin *netPlugin) leave(w http.ResponseWriter, r *http.Request) { // Encode response. resp := leaveResponse{} - err = plugin.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) log.Response(plugin.Name, &resp, returnCode, returnStr, err) } @@ -350,7 +350,7 @@ func (plugin *netPlugin) endpointOperInfo(w http.ResponseWriter, r *http.Request var req endpointOperInfoRequest // Decode request. - err := plugin.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) log.Request(plugin.Name, &req, err) if err != nil { return @@ -365,7 +365,7 @@ func (plugin *netPlugin) endpointOperInfo(w http.ResponseWriter, r *http.Request // Encode response. resp := endpointOperInfoResponse{Value: epInfo.Data} - err = plugin.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) log.Response(plugin.Name, &resp, returnCode, returnStr, err) } diff --git a/cnm/plugin.go b/cnm/plugin.go index af22dcd1f8..417552920c 100644 --- a/cnm/plugin.go +++ b/cnm/plugin.go @@ -121,7 +121,7 @@ func (plugin *Plugin) activate(w http.ResponseWriter, r *http.Request) { log.Request(plugin.Name, &req, nil) resp := ActivateResponse{Implements: plugin.Listener.GetEndpoints()} - err := plugin.Listener.Encode(w, &resp) + err := common.Encode(w, &resp) log.Response(plugin.Name, &resp, 0, "Success", err) } @@ -129,7 +129,7 @@ func (plugin *Plugin) activate(w http.ResponseWriter, r *http.Request) { // SendErrorResponse sends and logs an error response. func (plugin *Plugin) SendErrorResponse(w http.ResponseWriter, errMsg error) { resp := errorResponse{errMsg.Error()} - err := plugin.Listener.Encode(w, &resp) + err := common.Encode(w, &resp) log.Response(plugin.Name, &resp, 0, "Success", err) } diff --git a/cns/common/service.go b/cns/common/service.go index b621c07d1d..f37d3bba1a 100644 --- a/cns/common/service.go +++ b/cns/common/service.go @@ -38,8 +38,16 @@ type ServiceConfig struct { Listener *acn.Listener ErrChan chan<- error Store store.KeyValueStore + Server server ChannelMode string - TlsSettings tls.TlsSettings + TLSSettings tls.TlsSettings +} + +// server struct to store primaryInterfaceIP from VM, port where customer provides by -p and temporary flag EnableLocalServer +type server struct { + PrimaryInterfaceIP string + Port string + EnableLocalServer bool // TODO: Remove this flag once -c option gets deprecated } // NewService creates a new Service object. diff --git a/cns/restserver/api.go b/cns/restserver/api.go index 61bee3ac12..89ff1b5a5a 100644 --- a/cns/restserver/api.go +++ b/cns/restserver/api.go @@ -20,6 +20,7 @@ import ( "github.com/Azure/azure-container-networking/cns/logger" "github.com/Azure/azure-container-networking/cns/types" "github.com/Azure/azure-container-networking/cns/wireserver" + "github.com/Azure/azure-container-networking/common" "github.com/pkg/errors" ) @@ -46,7 +47,7 @@ func (service *HTTPRestService) setEnvironment(w http.ResponseWriter, r *http.Re logger.Printf("[Azure CNS] setEnvironment") var req cns.SetEnvironmentRequest - err := service.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { @@ -64,7 +65,7 @@ func (service *HTTPRestService) setEnvironment(w http.ResponseWriter, r *http.Re } resp := &cns.Response{ReturnCode: 0} - err = service.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) logger.Response(service.Name, resp, resp.ReturnCode, err) } @@ -79,7 +80,7 @@ func (service *HTTPRestService) createNetwork(w http.ResponseWriter, r *http.Req if service.state.Initialized { var req cns.CreateNetworkRequest - err = service.Listener.Decode(w, r, &req) + err = common.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { @@ -166,7 +167,7 @@ func (service *HTTPRestService) createNetwork(w http.ResponseWriter, r *http.Req Message: returnMessage, } - err = service.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) if returnCode == 0 { service.saveState() @@ -182,7 +183,7 @@ func (service *HTTPRestService) deleteNetwork(w http.ResponseWriter, r *http.Req var req cns.DeleteNetworkRequest var returnCode types.ResponseCode returnMessage := "" - err := service.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { @@ -221,7 +222,7 @@ func (service *HTTPRestService) deleteNetwork(w http.ResponseWriter, r *http.Req Message: returnMessage, } - err = service.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) if returnCode == 0 { service.removeNetworkInfo(req.NetworkName) @@ -240,7 +241,7 @@ func (service *HTTPRestService) createHnsNetwork(w http.ResponseWriter, r *http. returnMessage := "" var req cns.CreateHnsNetworkRequest - err = service.Listener.Decode(w, r, &req) + err = common.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { @@ -273,7 +274,7 @@ func (service *HTTPRestService) createHnsNetwork(w http.ResponseWriter, r *http. Message: returnMessage, } - err = service.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) if returnCode == 0 { service.saveState() @@ -291,7 +292,7 @@ func (service *HTTPRestService) deleteHnsNetwork(w http.ResponseWriter, r *http. var returnCode types.ResponseCode returnMessage := "" - err = service.Listener.Decode(w, r, &req) + err = common.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { @@ -324,7 +325,7 @@ func (service *HTTPRestService) deleteHnsNetwork(w http.ResponseWriter, r *http. Message: returnMessage, } - err = service.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) if returnCode == 0 { service.removeNetworkInfo(req.NetworkName) @@ -343,7 +344,7 @@ func (service *HTTPRestService) reserveIPAddress(w http.ResponseWriter, r *http. returnMessage := "" addr := "" address := "" - err := service.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) logger.Request(service.Name, &req, err) @@ -414,7 +415,7 @@ func (service *HTTPRestService) reserveIPAddress(w http.ResponseWriter, r *http. } reserveResp := &cns.ReserveIPAddressResponse{Response: resp, IPAddress: address} - err = service.Listener.Encode(w, &reserveResp) + err = common.Encode(w, &reserveResp) logger.Response(service.Name, reserveResp, resp.ReturnCode, err) } @@ -426,7 +427,7 @@ func (service *HTTPRestService) releaseIPAddress(w http.ResponseWriter, r *http. var returnCode types.ResponseCode returnMessage := "" - err := service.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { @@ -485,7 +486,7 @@ func (service *HTTPRestService) releaseIPAddress(w http.ResponseWriter, r *http. publishIPStateMetrics(service.buildIPState()) } - err = service.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) logger.Response(service.Name, resp, resp.ReturnCode, err) } @@ -536,7 +537,7 @@ func (service *HTTPRestService) getHostLocalIP(w http.ResponseWriter, r *http.Re IPAddress: hostLocalIP, } - err := service.Listener.Encode(w, &hostLocalIPResponse) + err := common.Encode(w, &hostLocalIPResponse) logger.Response(service.Name, hostLocalIPResponse, resp.ReturnCode, err) } @@ -602,7 +603,7 @@ func (service *HTTPRestService) getIPAddressUtilization(w http.ResponseWriter, r Unhealthy: len(unhealthyAddrs), } - err := service.Listener.Encode(w, &utilResponse) + err := common.Encode(w, &utilResponse) logger.Response(service.Name, utilResponse, resp.ReturnCode, err) } @@ -613,7 +614,7 @@ func (service *HTTPRestService) getAvailableIPAddresses(w http.ResponseWriter, r resp := cns.Response{ReturnCode: 0} ipResp := &cns.GetIPAddressesResponse{Response: resp} - err := service.Listener.Encode(w, &ipResp) + err := common.Encode(w, &ipResp) logger.Response(service.Name, ipResp, resp.ReturnCode, err) } @@ -625,7 +626,7 @@ func (service *HTTPRestService) getReservedIPAddresses(w http.ResponseWriter, r resp := cns.Response{ReturnCode: 0} ipResp := &cns.GetIPAddressesResponse{Response: resp} - err := service.Listener.Encode(w, &ipResp) + err := common.Encode(w, &ipResp) logger.Response(service.Name, ipResp, resp.ReturnCode, err) } @@ -689,7 +690,7 @@ func (service *HTTPRestService) getUnhealthyIPAddresses(w http.ResponseWriter, r IPAddresses: unhealthyAddrs, } - err := service.Listener.Encode(w, &ipResp) + err := common.Encode(w, &ipResp) logger.Response(service.Name, ipResp, resp.ReturnCode, err) } @@ -700,7 +701,7 @@ func (service *HTTPRestService) getAllIPAddresses(w http.ResponseWriter, r *http resp := cns.Response{ReturnCode: 0} ipResp := &cns.GetIPAddressesResponse{Response: resp} - err := service.Listener.Encode(w, &ipResp) + err := common.Encode(w, &ipResp) logger.Response(service.Name, ipResp, resp.ReturnCode, err) } @@ -711,7 +712,7 @@ func (service *HTTPRestService) getHealthReport(w http.ResponseWriter, r *http.R logger.Request(service.Name, "getHealthReport", nil) resp := &cns.Response{ReturnCode: 0} - err := service.Listener.Encode(w, &resp) + err := common.Encode(w, &resp) logger.Response(service.Name, resp, resp.ReturnCode, err) } @@ -726,7 +727,7 @@ func (service *HTTPRestService) setOrchestratorType(w http.ResponseWriter, r *ht nodeID string ) - err := service.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) if err != nil { return } @@ -759,7 +760,7 @@ func (service *HTTPRestService) setOrchestratorType(w http.ResponseWriter, r *ht Message: returnMessage, } - err = service.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) logger.Response(service.Name, resp, resp.ReturnCode, err) } @@ -784,7 +785,7 @@ func (service *HTTPRestService) getHomeAz(w http.ResponseWriter, r *http.Request func (service *HTTPRestService) createOrUpdateNetworkContainer(w http.ResponseWriter, r *http.Request) { var req cns.CreateNetworkContainerRequest - if err := service.Listener.Decode(w, r, &req); err != nil { + if err := common.Decode(w, r, &req); err != nil { logger.Errorf("[Azure CNS] could not decode request: %v", err) w.WriteHeader(http.StatusBadRequest) return @@ -843,7 +844,7 @@ func (service *HTTPRestService) createOrUpdateNetworkContainer(w http.ResponseWr } reserveResp := &cns.CreateNetworkContainerResponse{Response: resp} - err = service.Listener.Encode(w, &reserveResp) + err = common.Encode(w, &reserveResp) // If the NC was created successfully, log NC snapshot. if returnCode == types.Success { @@ -860,7 +861,7 @@ func (service *HTTPRestService) getNetworkContainerByID(w http.ResponseWriter, r var returnCode types.ResponseCode returnMessage := "" - err := service.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { return @@ -872,7 +873,7 @@ func (service *HTTPRestService) getNetworkContainerByID(w http.ResponseWriter, r } reserveResp := &cns.GetNetworkContainerResponse{Response: resp} - err = service.Listener.Encode(w, &reserveResp) + err = common.Encode(w, &reserveResp) logger.Response(service.Name, reserveResp, resp.ReturnCode, err) } @@ -882,7 +883,7 @@ func (service *HTTPRestService) GetAllNetworkContainers(w http.ResponseWriter, r var req cns.GetNetworkContainerRequest - err := service.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { logger.Errorf("[Azure CNS] failed to decode cns request with req %+v due to %+v", req, err) @@ -915,7 +916,7 @@ func (service *HTTPRestService) GetAllNetworkContainers(w http.ResponseWriter, r resp.Response.Message = "Successfully retrieved NCs" } - err = service.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) logger.Response(service.Name, resp, resp.Response.ReturnCode, err) } @@ -924,14 +925,14 @@ func (service *HTTPRestService) GetNetworkContainerByOrchestratorContext(w http. var req cns.GetNetworkContainerRequest - err := service.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { return } getNetworkContainerResponses := service.getAllNetworkContainerResponses(req) // nolint - err = service.Listener.Encode(w, &getNetworkContainerResponses[0]) + err = common.Encode(w, &getNetworkContainerResponses[0]) logger.Response(service.Name, getNetworkContainerResponses[0], getNetworkContainerResponses[0].Response.ReturnCode, err) } @@ -963,7 +964,7 @@ func (service *HTTPRestService) deleteNetworkContainer(w http.ResponseWriter, r var returnCode types.ResponseCode returnMessage := "" - err := service.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { return @@ -1027,7 +1028,7 @@ func (service *HTTPRestService) deleteNetworkContainer(w http.ResponseWriter, r } reserveResp := &cns.DeleteNetworkContainerResponse{Response: resp} - err = service.Listener.Encode(w, &reserveResp) + err = common.Encode(w, &reserveResp) logger.Response(service.Name, reserveResp, resp.ReturnCode, err) } @@ -1038,7 +1039,7 @@ func (service *HTTPRestService) getInterfaceForContainer(w http.ResponseWriter, var returnCode types.ResponseCode returnMessage := "" - err := service.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { return @@ -1080,7 +1081,7 @@ func (service *HTTPRestService) getInterfaceForContainer(w http.ResponseWriter, NetworkContainerVersion: version, } - err = service.Listener.Encode(w, &getInterfaceForContainerResponse) + err = common.Encode(w, &getInterfaceForContainerResponse) logger.Response(service.Name, getInterfaceForContainerResponse, resp.ReturnCode, err) } @@ -1089,7 +1090,7 @@ func (service *HTTPRestService) attachNetworkContainerToNetwork(w http.ResponseW logger.Printf("[Azure CNS] attachNetworkContainerToNetwork") var req cns.ConfigureContainerNetworkingRequest - err := service.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { return @@ -1097,7 +1098,7 @@ func (service *HTTPRestService) attachNetworkContainerToNetwork(w http.ResponseW resp := service.attachOrDetachHelper(req, attach, r.Method) attachResp := &cns.AttachContainerToNetworkResponse{Response: resp} - err = service.Listener.Encode(w, &attachResp) + err = common.Encode(w, &attachResp) logger.Response(service.Name, attachResp, resp.ReturnCode, err) } @@ -1105,7 +1106,7 @@ func (service *HTTPRestService) detachNetworkContainerFromNetwork(w http.Respons logger.Printf("[Azure CNS] detachNetworkContainerFromNetwork") var req cns.ConfigureContainerNetworkingRequest - err := service.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { return @@ -1113,7 +1114,7 @@ func (service *HTTPRestService) detachNetworkContainerFromNetwork(w http.Respons resp := service.attachOrDetachHelper(req, detach, r.Method) detachResp := &cns.DetachContainerFromNetworkResponse{Response: resp} - err = service.Listener.Encode(w, &detachResp) + err = common.Encode(w, &detachResp) logger.Response(service.Name, detachResp, resp.ReturnCode, err) } @@ -1143,7 +1144,7 @@ func (service *HTTPRestService) getNumberOfCPUCores(w http.ResponseWriter, r *ht NumOfCPUCores: num, } - err := service.Listener.Encode(w, &numOfCPUCoresResp) + err := common.Encode(w, &numOfCPUCoresResp) logger.Response(service.Name, numOfCPUCoresResp, resp.ReturnCode, err) } @@ -1392,7 +1393,7 @@ func (service *HTTPRestService) CreateHostNCApipaEndpoint(w http.ResponseWriter, endpointID string ) - err = service.Listener.Decode(w, r, &req) + err = common.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { return @@ -1436,7 +1437,7 @@ func (service *HTTPRestService) CreateHostNCApipaEndpoint(w http.ResponseWriter, EndpointID: endpointID, } - err = service.Listener.Encode(w, &response) + err = common.Encode(w, &response) logger.Response(service.Name, response, response.Response.ReturnCode, err) } @@ -1450,7 +1451,7 @@ func (service *HTTPRestService) DeleteHostNCApipaEndpoint(w http.ResponseWriter, returnMessage string ) - err = service.Listener.Decode(w, r, &req) + err = common.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { return @@ -1475,7 +1476,7 @@ func (service *HTTPRestService) DeleteHostNCApipaEndpoint(w http.ResponseWriter, }, } - err = service.Listener.Encode(w, &response) + err = common.Encode(w, &response) logger.Response(service.Name, response, response.Response.ReturnCode, err) } @@ -1492,7 +1493,7 @@ func (service *HTTPRestService) nmAgentSupportedApisHandler(w http.ResponseWrite ctx := r.Context() - err = service.Listener.Decode(w, r, &req) + err = common.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { return @@ -1517,7 +1518,7 @@ func (service *HTTPRestService) nmAgentSupportedApisHandler(w http.ResponseWrite SupportedApis: supportedApis, } - serviceErr := service.Listener.Encode(w, &nmAgentSupportedApisResponse) + serviceErr := common.Encode(w, &nmAgentSupportedApisResponse) logger.Response(service.Name, nmAgentSupportedApisResponse, resp.ReturnCode, serviceErr) } diff --git a/cns/restserver/api_test.go b/cns/restserver/api_test.go index 4188bb3e54..145ce3b5b7 100644 --- a/cns/restserver/api_test.go +++ b/cns/restserver/api_test.go @@ -1684,6 +1684,8 @@ func startService() error { return err } svc = service.(*HTTPRestService) + svc.Service.Options[acncommon.OptCnsURL] = "" + svc.Service.Options[acncommon.OptCnsPort] = "" svc.Name = "cns-test-server" nmagentClient.GetNCVersionListF = func(context.Context) (nmagent.NCVersionList, error) { @@ -1720,6 +1722,9 @@ func startService() error { file, _ := os.Create(cnsJsonFileName) file.Close() + // mock localhost as primary interface IP + config.Server.PrimaryInterfaceIP = "localhost" + err = service.Init(&config) if err != nil { logger.Errorf("Failed to Init CNS, err:%v.\n", err) diff --git a/cns/restserver/ipam.go b/cns/restserver/ipam.go index 1031b15c3c..8371bea1f5 100644 --- a/cns/restserver/ipam.go +++ b/cns/restserver/ipam.go @@ -94,7 +94,7 @@ func (service *HTTPRestService) requestIPConfigHandlerHelper(ctx context.Context // RequestIPConfigHandler requests an IPConfig from the CNS state func (service *HTTPRestService) RequestIPConfigHandler(w http.ResponseWriter, r *http.Request) { var ipconfigRequest cns.IPConfigRequest - err := service.Listener.Decode(w, r, &ipconfigRequest) + err := common.Decode(w, r, &ipconfigRequest) operationName := "requestIPConfigHandler" logger.Request(service.Name+operationName, ipconfigRequest, err) if err != nil { @@ -111,7 +111,7 @@ func (service *HTTPRestService) RequestIPConfigHandler(w http.ResponseWriter, r }, } w.Header().Set(cnsReturnCode, reserveResp.Response.ReturnCode.String()) - err = service.Listener.Encode(w, &reserveResp) + err = common.Encode(w, &reserveResp) logger.ResponseEx(service.Name+operationName, ipconfigRequest, reserveResp, reserveResp.Response.ReturnCode, err) return } @@ -136,7 +136,7 @@ func (service *HTTPRestService) RequestIPConfigHandler(w http.ResponseWriter, r Response: ipConfigsResp.Response, } w.Header().Set(cnsReturnCode, reserveResp.Response.ReturnCode.String()) - err = service.Listener.Encode(w, &reserveResp) + err = common.Encode(w, &reserveResp) logger.ResponseEx(service.Name+operationName, ipconfigsRequest, reserveResp, reserveResp.Response.ReturnCode, err) return } @@ -152,7 +152,7 @@ func (service *HTTPRestService) RequestIPConfigHandler(w http.ResponseWriter, r }, } w.Header().Set(cnsReturnCode, reserveResp.Response.ReturnCode.String()) - err = service.Listener.Encode(w, &reserveResp) + err = common.Encode(w, &reserveResp) logger.ResponseEx(service.Name+operationName, ipconfigRequest, reserveResp, reserveResp.Response.ReturnCode, err) return } @@ -162,14 +162,14 @@ func (service *HTTPRestService) RequestIPConfigHandler(w http.ResponseWriter, r PodIpInfo: ipConfigsResp.PodIPInfo[0], } w.Header().Set(cnsReturnCode, reserveResp.Response.ReturnCode.String()) - err = service.Listener.Encode(w, &reserveResp) + err = common.Encode(w, &reserveResp) logger.ResponseEx(service.Name+operationName, ipconfigsRequest, reserveResp, reserveResp.Response.ReturnCode, err) } // RequestIPConfigsHandler requests multiple IPConfigs from the CNS state func (service *HTTPRestService) RequestIPConfigsHandler(w http.ResponseWriter, r *http.Request) { var ipconfigsRequest cns.IPConfigsRequest - err := service.Listener.Decode(w, r, &ipconfigsRequest) + err := common.Decode(w, r, &ipconfigsRequest) operationName := "requestIPConfigsHandler" logger.Request(service.Name+operationName, ipconfigsRequest, err) if err != nil { @@ -188,13 +188,13 @@ func (service *HTTPRestService) RequestIPConfigsHandler(w http.ResponseWriter, r if err != nil { w.Header().Set(cnsReturnCode, ipConfigsResp.Response.ReturnCode.String()) - err = service.Listener.Encode(w, &ipConfigsResp) + err = common.Encode(w, &ipConfigsResp) logger.ResponseEx(service.Name+operationName, ipconfigsRequest, ipConfigsResp, ipConfigsResp.Response.ReturnCode, err) return } w.Header().Set(cnsReturnCode, ipConfigsResp.Response.ReturnCode.String()) - err = service.Listener.Encode(w, &ipConfigsResp) + err = common.Encode(w, &ipConfigsResp) logger.ResponseEx(service.Name+operationName, ipconfigsRequest, ipConfigsResp, ipConfigsResp.Response.ReturnCode, err) } @@ -304,7 +304,7 @@ func (service *HTTPRestService) ReleaseIPConfigHandlerHelper(ctx context.Context // ReleaseIPConfigHandler frees the IP assigned to a pod from CNS func (service *HTTPRestService) ReleaseIPConfigHandler(w http.ResponseWriter, r *http.Request) { var ipconfigRequest cns.IPConfigRequest - err := service.Listener.Decode(w, r, &ipconfigRequest) + err := common.Decode(w, r, &ipconfigRequest) logger.Request(service.Name+"releaseIPConfigHandler", ipconfigRequest, err) if err != nil { resp := cns.Response{ @@ -313,7 +313,7 @@ func (service *HTTPRestService) ReleaseIPConfigHandler(w http.ResponseWriter, r } logger.Errorf("releaseIPConfigHandler decode failed becase %v, release IP config info %s", resp.Message, ipconfigRequest) w.Header().Set(cnsReturnCode, resp.ReturnCode.String()) - err = service.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) logger.ResponseEx(service.Name, ipconfigRequest, resp, resp.ReturnCode, err) return } @@ -327,7 +327,7 @@ func (service *HTTPRestService) ReleaseIPConfigHandler(w http.ResponseWriter, r }, } w.Header().Set(cnsReturnCode, reserveResp.Response.ReturnCode.String()) - err = service.Listener.Encode(w, &reserveResp) + err = common.Encode(w, &reserveResp) logger.ResponseEx(service.Name, ipconfigRequest, reserveResp, reserveResp.Response.ReturnCode, err) return } @@ -345,19 +345,19 @@ func (service *HTTPRestService) ReleaseIPConfigHandler(w http.ResponseWriter, r resp, err := service.ReleaseIPConfigHandlerHelper(r.Context(), ipconfigsRequest) if err != nil { w.Header().Set(cnsReturnCode, resp.Response.ReturnCode.String()) - err = service.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) logger.ResponseEx(service.Name, ipconfigRequest, resp, resp.Response.ReturnCode, err) } w.Header().Set(cnsReturnCode, resp.Response.ReturnCode.String()) - err = service.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) logger.ResponseEx(service.Name, ipconfigRequest, resp, resp.Response.ReturnCode, err) } // ReleaseIPConfigsHandler frees multiple IPConfigs from the CNS state func (service *HTTPRestService) ReleaseIPConfigsHandler(w http.ResponseWriter, r *http.Request) { var ipconfigsRequest cns.IPConfigsRequest - err := service.Listener.Decode(w, r, &ipconfigsRequest) + err := common.Decode(w, r, &ipconfigsRequest) logger.Request(service.Name+"releaseIPConfigsHandler", ipconfigsRequest, err) if err != nil { resp := cns.Response{ @@ -366,7 +366,7 @@ func (service *HTTPRestService) ReleaseIPConfigsHandler(w http.ResponseWriter, r } logger.Errorf("releaseIPConfigsHandler decode failed because %v, release IP config info %+v", resp.Message, ipconfigsRequest) w.Header().Set(cnsReturnCode, resp.ReturnCode.String()) - err = service.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) logger.ResponseEx(service.Name, ipconfigsRequest, resp, resp.ReturnCode, err) return } @@ -374,12 +374,12 @@ func (service *HTTPRestService) ReleaseIPConfigsHandler(w http.ResponseWriter, r resp, err := service.ReleaseIPConfigHandlerHelper(r.Context(), ipconfigsRequest) if err != nil { w.Header().Set(cnsReturnCode, resp.Response.ReturnCode.String()) - err = service.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) logger.ResponseEx(service.Name, ipconfigsRequest, resp, resp.Response.ReturnCode, err) } w.Header().Set(cnsReturnCode, resp.Response.ReturnCode.String()) - err = service.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) logger.ResponseEx(service.Name, ipconfigsRequest, resp, resp.Response.ReturnCode, err) } @@ -566,7 +566,7 @@ func (service *HTTPRestService) HandleDebugPodContext(w http.ResponseWriter, r * resp := cns.GetPodContextResponse{ PodContext: service.PodIPIDByPodInterfaceKey, } - err := service.Listener.Encode(w, &resp) + err := common.Encode(w, &resp) logger.Response(service.Name, resp, resp.Response.ReturnCode, err) } @@ -579,20 +579,20 @@ func (service *HTTPRestService) HandleDebugRestData(w http.ResponseWriter, r *ht PodIPConfigState: service.PodIPConfigState, }, } - err := service.Listener.Encode(w, &resp) + err := common.Encode(w, &resp) logger.Response(service.Name, resp, resp.Response.ReturnCode, err) } func (service *HTTPRestService) HandleDebugIPAddresses(w http.ResponseWriter, r *http.Request) { var req cns.GetIPAddressesRequest - if err := service.Listener.Decode(w, r, &req); err != nil { + if err := common.Decode(w, r, &req); err != nil { resp := cns.GetIPAddressStatusResponse{ Response: cns.Response{ ReturnCode: types.UnexpectedError, Message: err.Error(), }, } - err = service.Listener.Encode(w, &resp) + err = common.Encode(w, &resp) logger.ResponseEx(service.Name, req, resp, resp.Response.ReturnCode, err) return } @@ -600,7 +600,7 @@ func (service *HTTPRestService) HandleDebugIPAddresses(w http.ResponseWriter, r resp := cns.GetIPAddressStatusResponse{ IPConfigurationStatus: filter.MatchAnyIPConfigState(service.PodIPConfigState, filter.PredicatesForStates(req.IPConfigStateFilter...)...), } - err := service.Listener.Encode(w, &resp) + err := common.Encode(w, &resp) logger.ResponseEx(service.Name, req, resp, resp.Response.ReturnCode, err) } @@ -991,7 +991,7 @@ func (service *HTTPRestService) EndpointHandlerAPI(w http.ResponseWriter, r *htt ReturnCode: types.UnexpectedError, Message: fmt.Sprintf("[EndpointHandlerAPI] EndpointHandlerAPI failed with error: %s", ErrOptManageEndpointState), } - err := service.Listener.Encode(w, &response) + err := common.Encode(w, &response) logger.Response(service.Name, response, response.ReturnCode, err) return } @@ -1027,7 +1027,7 @@ func (service *HTTPRestService) GetEndpointHandler(w http.ResponseWriter, r *htt } } w.Header().Set(cnsReturnCode, response.Response.ReturnCode.String()) - err = service.Listener.Encode(w, &response) + err = common.Encode(w, &response) logger.Response(service.Name, response, response.Response.ReturnCode, err) return } @@ -1039,7 +1039,7 @@ func (service *HTTPRestService) GetEndpointHandler(w http.ResponseWriter, r *htt EndpointInfo: *endpointInfo, } w.Header().Set(cnsReturnCode, response.Response.ReturnCode.String()) - err = service.Listener.Encode(w, &response) + err = common.Encode(w, &response) logger.Response(service.Name, response, response.Response.ReturnCode, err) } @@ -1084,7 +1084,7 @@ func (service *HTTPRestService) UpdateEndpointHandler(w http.ResponseWriter, r * logger.Printf("[updateEndpoint] updateEndpoint for %s", r.URL.Path) var req map[string]*IPInfo - err := service.Listener.Decode(w, r, &req) + err := common.Decode(w, r, &req) endpointID := strings.TrimPrefix(r.URL.Path, cns.EndpointPath) logger.Request(service.Name, &req, err) // Check if the request is valid @@ -1094,7 +1094,7 @@ func (service *HTTPRestService) UpdateEndpointHandler(w http.ResponseWriter, r * Message: fmt.Sprintf("[updateEndpoint] updateEndpoint failed with error: %s", err.Error()), } w.Header().Set(cnsReturnCode, response.ReturnCode.String()) - err = service.Listener.Encode(w, &response) + err = common.Encode(w, &response) logger.Response(service.Name, response, response.ReturnCode, err) return } @@ -1104,7 +1104,7 @@ func (service *HTTPRestService) UpdateEndpointHandler(w http.ResponseWriter, r * Message: err.Error(), } w.Header().Set(cnsReturnCode, response.ReturnCode.String()) - err = service.Listener.Encode(w, &response) + err = common.Encode(w, &response) logger.Response(service.Name, response, response.ReturnCode, err) return } @@ -1116,7 +1116,7 @@ func (service *HTTPRestService) UpdateEndpointHandler(w http.ResponseWriter, r * Message: fmt.Sprintf("[updateEndpoint] updateEndpoint failed with error: %s", err.Error()), } w.Header().Set(cnsReturnCode, response.ReturnCode.String()) - err = service.Listener.Encode(w, &response) + err = common.Encode(w, &response) logger.Response(service.Name, response, response.ReturnCode, err) return } @@ -1125,7 +1125,7 @@ func (service *HTTPRestService) UpdateEndpointHandler(w http.ResponseWriter, r * Message: "[updateEndpoint] updateEndpoint retruned successfully", } w.Header().Set(cnsReturnCode, response.ReturnCode.String()) - err = service.Listener.Encode(w, &response) + err = common.Encode(w, &response) logger.Response(service.Name, response, response.ReturnCode, err) } diff --git a/cns/restserver/restserver.go b/cns/restserver/restserver.go index 6fccc0e07a..268c97ef14 100644 --- a/cns/restserver/restserver.go +++ b/cns/restserver/restserver.go @@ -186,6 +186,9 @@ func NewHTTPRestService(config *common.ServiceConfig, wscli interfaceGetter, wsp return nil, errors.Wrap(err, "failed to get primary interface from IMDS response") } + // add primaryInterfaceIP to cns config + config.Server.PrimaryInterfaceIP = primaryInterface.PrimaryIP + serviceState := &httpRestServiceState{ Networks: make(map[string]*networkInfo), joinedNetworks: make(map[string]struct{}), diff --git a/cns/restserver/util.go b/cns/restserver/util.go index b65e440a54..94a51048e8 100644 --- a/cns/restserver/util.go +++ b/cns/restserver/util.go @@ -913,7 +913,7 @@ func (service *HTTPRestService) handleGetNetworkContainers(w http.ResponseWriter ReturnCode: types.Success, }, } - err := service.Listener.Encode(w, &response) + err := acn.Encode(w, &response) logger.Response(service.Name, response, response.Response.ReturnCode, err) } @@ -921,7 +921,7 @@ func (service *HTTPRestService) handleGetNetworkContainers(w http.ResponseWriter func (service *HTTPRestService) handlePostNetworkContainers(w http.ResponseWriter, r *http.Request) { logger.Printf("[Azure CNS] handlePostNetworkContainers") var req cns.PostNetworkContainersRequest - err := service.Listener.Decode(w, r, &req) + err := acn.Decode(w, r, &req) logger.Request(service.Name, &req, err) if err != nil { response := cns.PostNetworkContainersResponse{ @@ -930,7 +930,7 @@ func (service *HTTPRestService) handlePostNetworkContainers(w http.ResponseWrite Message: fmt.Sprintf("[Azure CNS] handlePostNetworkContainers failed with error: %s", err.Error()), }, } - err = service.Listener.Encode(w, &response) + err = acn.Encode(w, &response) logger.Response(service.Name, response, response.Response.ReturnCode, err) return } @@ -944,7 +944,7 @@ func (service *HTTPRestService) handlePostNetworkContainers(w http.ResponseWrite response := cns.PostNetworkContainersResponse{ Response: createNCsResp, } - err = service.Listener.Encode(w, &response) + err = acn.Encode(w, &response) logger.Response(service.Name, response, response.Response.ReturnCode, err) } @@ -982,7 +982,7 @@ func (service *HTTPRestService) createNetworkContainers(createNetworkContainerRe // setResponse encodes the http response func (service *HTTPRestService) setResponse(w http.ResponseWriter, returnCode types.ResponseCode, response interface{}) { - serviceErr := service.Listener.Encode(w, &response) + serviceErr := acn.Encode(w, &response) logger.Response(service.Name, response, returnCode, serviceErr) } diff --git a/cns/restserver/v2/server.go b/cns/restserver/v2/server.go index 50849ec9fb..c8ca1aaf99 100644 --- a/cns/restserver/v2/server.go +++ b/cns/restserver/v2/server.go @@ -1,12 +1,14 @@ package v2 import ( + "context" "net/http" "github.com/Azure/azure-container-networking/cns" + "github.com/Azure/azure-container-networking/cns/logger" "github.com/Azure/azure-container-networking/cns/restserver" "github.com/labstack/echo/v4" - "go.uber.org/zap" + "github.com/pkg/errors" ) type Server struct { @@ -17,28 +19,38 @@ func New(s *restserver.HTTPRestService) *Server { return &Server{s} } -func (s Server) Start(log *zap.Logger, addr string) { +func (s Server) Start(ctx context.Context, addr string) error { e := echo.New() e.HideBanner = true - e.GET(cns.RequestIPConfig, echo.WrapHandler(restserver.NewHandlerFuncWithHistogram(s.RequestIPConfigHandler, restserver.HTTPRequestLatency))) - e.GET(cns.RequestIPConfigs, echo.WrapHandler(restserver.NewHandlerFuncWithHistogram(s.RequestIPConfigsHandler, restserver.HTTPRequestLatency))) - e.GET(cns.ReleaseIPConfig, echo.WrapHandler(restserver.NewHandlerFuncWithHistogram(s.ReleaseIPConfigHandler, restserver.HTTPRequestLatency))) - e.GET(cns.ReleaseIPConfigs, echo.WrapHandler(restserver.NewHandlerFuncWithHistogram(s.ReleaseIPConfigsHandler, restserver.HTTPRequestLatency))) - e.GET(cns.PathDebugIPAddresses, echo.WrapHandler(http.HandlerFunc(s.HandleDebugIPAddresses))) - e.GET(cns.PathDebugPodContext, echo.WrapHandler(http.HandlerFunc(s.HandleDebugPodContext))) - e.GET(cns.PathDebugRestData, echo.WrapHandler(http.HandlerFunc(s.HandleDebugRestData))) - e.GET(cns.GetNetworkContainerByOrchestratorContext, echo.WrapHandler(http.HandlerFunc(s.GetNetworkContainerByOrchestratorContext))) - e.GET(cns.GetAllNetworkContainers, echo.WrapHandler(http.HandlerFunc(s.GetAllNetworkContainers))) - e.GET(cns.CreateHostNCApipaEndpointPath, echo.WrapHandler(http.HandlerFunc(s.CreateHostNCApipaEndpoint))) - e.GET(cns.DeleteHostNCApipaEndpointPath, echo.WrapHandler(http.HandlerFunc(s.DeleteHostNCApipaEndpoint))) + e.POST(cns.RequestIPConfig, echo.WrapHandler(restserver.NewHandlerFuncWithHistogram(s.RequestIPConfigHandler, restserver.HTTPRequestLatency))) + e.POST(cns.RequestIPConfigs, echo.WrapHandler(restserver.NewHandlerFuncWithHistogram(s.RequestIPConfigsHandler, restserver.HTTPRequestLatency))) + e.POST(cns.ReleaseIPConfig, echo.WrapHandler(restserver.NewHandlerFuncWithHistogram(s.ReleaseIPConfigHandler, restserver.HTTPRequestLatency))) + e.POST(cns.ReleaseIPConfigs, echo.WrapHandler(restserver.NewHandlerFuncWithHistogram(s.ReleaseIPConfigsHandler, restserver.HTTPRequestLatency))) + e.POST(cns.PathDebugIPAddresses, echo.WrapHandler(http.HandlerFunc(s.HandleDebugIPAddresses))) + e.POST(cns.PathDebugPodContext, echo.WrapHandler(http.HandlerFunc(s.HandleDebugPodContext))) + e.POST(cns.PathDebugRestData, echo.WrapHandler(http.HandlerFunc(s.HandleDebugRestData))) + e.POST(cns.GetNetworkContainerByOrchestratorContext, echo.WrapHandler(http.HandlerFunc(s.GetNetworkContainerByOrchestratorContext))) + e.POST(cns.GetAllNetworkContainers, echo.WrapHandler(http.HandlerFunc(s.GetAllNetworkContainers))) + e.POST(cns.CreateHostNCApipaEndpointPath, echo.WrapHandler(http.HandlerFunc(s.CreateHostNCApipaEndpoint))) + e.POST(cns.DeleteHostNCApipaEndpointPath, echo.WrapHandler(http.HandlerFunc(s.DeleteHostNCApipaEndpoint))) // for handlers 2.0 - e.GET(cns.V2Prefix+cns.GetNetworkContainerByOrchestratorContext, echo.WrapHandler(http.HandlerFunc(s.GetNetworkContainerByOrchestratorContext))) - e.GET(cns.V2Prefix+cns.GetAllNetworkContainers, echo.WrapHandler(http.HandlerFunc(s.GetAllNetworkContainers))) - e.GET(cns.V2Prefix+cns.CreateHostNCApipaEndpointPath, echo.WrapHandler(http.HandlerFunc(s.CreateHostNCApipaEndpoint))) - e.GET(cns.V2Prefix+cns.DeleteHostNCApipaEndpointPath, echo.WrapHandler(http.HandlerFunc(s.DeleteHostNCApipaEndpoint))) + e.POST(cns.V2Prefix+cns.GetNetworkContainerByOrchestratorContext, echo.WrapHandler(http.HandlerFunc(s.GetNetworkContainerByOrchestratorContext))) + e.POST(cns.V2Prefix+cns.GetAllNetworkContainers, echo.WrapHandler(http.HandlerFunc(s.GetAllNetworkContainers))) + e.POST(cns.V2Prefix+cns.CreateHostNCApipaEndpointPath, echo.WrapHandler(http.HandlerFunc(s.CreateHostNCApipaEndpoint))) + e.POST(cns.V2Prefix+cns.DeleteHostNCApipaEndpointPath, echo.WrapHandler(http.HandlerFunc(s.DeleteHostNCApipaEndpoint))) if err := e.Start(addr); err != nil { - log.Error("failed to run server", zap.Error(err)) + logger.Errorf("failed to run echo server due to %+v", err) + return errors.Wrap(err, "failed to start echo server") } + + // after context is done, shutdown local server + <-ctx.Done() + if err := e.Shutdown(ctx); err != nil { + logger.Errorf("failed to shutdown echo server due to %+v", err) + return errors.Wrap(err, "failed to shutdown echo server") + } + + return nil } diff --git a/cns/restserver/v2/server_test.go b/cns/restserver/v2/server_test.go new file mode 100644 index 0000000000..605a0061ba --- /dev/null +++ b/cns/restserver/v2/server_test.go @@ -0,0 +1,98 @@ +package v2 + +import ( + "net" + "net/url" + "testing" + "time" + + "github.com/Azure/azure-container-networking/cns/common" + "github.com/Azure/azure-container-networking/cns/fakes" + "github.com/Azure/azure-container-networking/cns/logger" + "github.com/Azure/azure-container-networking/cns/restserver" + acncommon "github.com/Azure/azure-container-networking/common" + "github.com/pkg/errors" +) + +// TestStartServices will test three scenarios: +// 1. when customer provides -p option, make sure local server is running and server is using this port +// 2. when customer provides -c option, local server will this -c URL + +func TestStartServerWithCNSPort(t *testing.T) { + var err error + + logger.InitLogger("testlogs", 0, 0, "./") + cnsPort := "8000" + + // Create the service with -p 8000 + if err = startService(cnsPort, ""); err != nil { + t.Fatalf("Failed to connect to CNS Service on expected port:%s. Error: %v", cnsPort, err) + } +} + +func TestStartServerWithCNSURL(t *testing.T) { + var err error + + logger.InitLogger("testlogs", 0, 0, "./") + + // Create the service with -c "localhost:8000" + cnsURL := "tcp://localhost:8500" + if err = startService("", cnsURL); err != nil { + t.Fatalf("Failed to connect to CNS Service by this cns url:%s. Error: %v", cnsURL, err) + } +} + +// startService will return a URL that running server is using and check if sever can start +// mock primaryVMIP as a fixed IP +func startService(cnsPort, cnsURL string) error { + // Create the service. + config := common.ServiceConfig{} + + nmagentClient := &fakes.NMAgentClientFake{} + service, err := restserver.NewHTTPRestService(&config, &fakes.WireserverClientFake{}, &fakes.WireserverProxyFake{}, nmagentClient, nil, nil, nil) + if err != nil { + return errors.Wrap(err, "Failed to initialize service") + } + + if service != nil { + service.Name = "cns-test-server" + + service.SetOption(acncommon.OptCnsPort, cnsPort) + service.SetOption(acncommon.OptCnsURL, cnsURL) + + config.Server.PrimaryInterfaceIP = "localhost" + + err = service.Init(&config) + if err != nil { + logger.Errorf("Failed to Init CNS, err:%v.\n", err) + return errors.Wrap(err, "Failed to Init CNS") + } + + err = service.Start(&config) + if err != nil { + logger.Errorf("Failed to start CNS, err:%v.\n", err) + return errors.Wrap(err, "Failed to Start CNS") + } + } + + if cnsPort == "" { + cnsPort = "10090" + } + // check if we can reach this URL + urls := "localhost:" + cnsPort + + if cnsURL != "" { + u, _ := url.Parse(cnsURL) + port := u.Port() + urls = "localhost:" + port + } + + _, err = net.DialTimeout("tcp", urls, 10*time.Millisecond) + if err != nil { + return errors.Wrapf(err, "Failed to check reachability to urls %+v", urls) + } + + service.Stop() + + return nil +} diff --git a/cns/service.go b/cns/service.go index 4f9e398eca..e0cdd75ab7 100644 --- a/cns/service.go +++ b/cns/service.go @@ -24,9 +24,8 @@ import ( ) const ( - // Default CNS server URL. - defaultAPIServerURL = "tcp://localhost:10090" - genericData = "com.microsoft.azure.network.generic" + defaultAPIServerPort = "10090" + genericData = "com.microsoft.azure.network.generic" ) // Service defines Container Networking Service. @@ -48,64 +47,100 @@ func NewService(name, version, channelMode string, store store.KeyValueStore) (* }, nil } -// GetAPIServerURL returns the API server URL. -func (service *Service) getAPIServerURL() string { - urls, _ := service.GetOption(acn.OptCnsURL).(string) - if urls == "" { - urls = defaultAPIServerURL +func (service *Service) AddListener(config *common.ServiceConfig) error { + var ( + err error + nodeURL *url.URL + ) + + // if cnsURL is empty the VM primary interface IP will be used + // if customer specifies -c option, then use this URL with warning message and it will be deprecated soon + cnsURL, ok := service.GetOption(acn.OptCnsURL).(string) + if !ok { + return errors.New("cnsURL type is wrong") } - return urls -} - -// Initialize initializes the service and starts the listener. -func (service *Service) Initialize(config *common.ServiceConfig) error { - log.Debugf("[Azure CNS] Going to initialize a service with config: %+v", config) - - // Initialize the base service. - if err := service.Service.Initialize(config); err != nil { - return errors.Wrap(err, "failed to initialize") + // if customer provides port number by -p option, then use VM IP with this port and localhost server also uses this port + // otherwise it will use defaultAPIServerPort 10090 + cnsPort, ok := service.GetOption(acn.OptCnsPort).(string) + if !ok { + return errors.New("cnsPort type is wrong") } - // Initialize the listener. - if config.Listener == nil { - // Fetch and parse the API server URL. - u, err := url.Parse(service.getAPIServerURL()) + if cnsURL == "" { + config.Server.EnableLocalServer = true + // get VM primary interface's private IP + // if customer does use -p option, then use port number customers provide + if cnsPort == "" { + nodeURL, err = url.Parse(fmt.Sprintf("tcp://%s:%s", config.Server.PrimaryInterfaceIP, defaultAPIServerPort)) + } else { + config.Server.Port = cnsPort + nodeURL, err = url.Parse(fmt.Sprintf("tcp://%s:%s", config.Server.PrimaryInterfaceIP, cnsPort)) + } + if err != nil { - return err + return errors.Wrap(err, "Failed to parse URL for legacy server") } + } else { + // use the URL that customer provides by -c + logger.Printf("user specifies -c option") - listener, err := acn.NewListener(u) + // do not enable local server if customer uses -c option + config.Server.EnableLocalServer = false + nodeURL, err = url.Parse(cnsURL) if err != nil { - return err + return errors.Wrap(err, "Failed to parse URL that customer provides") } + } - if config.TlsSettings.TLSPort != "" { + logger.Debugf("CNS remote server url: %+v", nodeURL) + + nodeListener, err := acn.NewListener(nodeURL) + if err != nil { + return errors.Wrap(err, "Failed to construct url for node listener") + } + + // only use TLS connection for DNC/CNS listener: + if config.TLSSettings.TLSPort != "" { + if config.TLSSettings.TLSPort != "" { // listener.URL.Host will always be hostname:port, passed in to CNS via CNS command // else it will default to localhost // extract hostname and override tls port. - hostParts := strings.Split(listener.URL.Host, ":") - tlsAddress := net.JoinHostPort(hostParts[0], config.TlsSettings.TLSPort) + hostParts := strings.Split(nodeListener.URL.Host, ":") + tlsAddress := net.JoinHostPort(hostParts[0], config.TLSSettings.TLSPort) // Start the listener and HTTP and HTTPS server. - tlsConfig, err := getTLSConfig(config.TlsSettings, config.ErrChan) + tlsConfig, err := getTLSConfig(config.TLSSettings, config.ErrChan) //nolint if err != nil { log.Printf("Failed to compose Tls Configuration with error: %+v", err) return errors.Wrap(err, "could not get tls config") } - if err := listener.StartTLS(config.ErrChan, tlsConfig, tlsAddress); err != nil { - return err + if err := nodeListener.StartTLS(config.ErrChan, tlsConfig, tlsAddress); err != nil { + return errors.Wrap(err, "could not start tls") } } + } + + service.Listener = nodeListener + log.Debugf("[Azure CNS] Successfully initialized a service with config: %+v", config) - logger.Printf("HTTP listener will be started later after CNS state has been reconciled") - config.Listener = listener + return nil +} + +// Initialize initializes the service and starts the listener. +func (service *Service) Initialize(config *common.ServiceConfig) error { + log.Debugf("[Azure CNS] Going to initialize a service with config: %+v", config) + + // Initialize the base service. + if err := service.Service.Initialize(config); err != nil { + return errors.Wrap(err, "failed to initialize") } - service.Listener = config.Listener + if err := service.AddListener(config); err != nil { + return errors.Wrap(err, "failed to initialize listener") + } - log.Debugf("[Azure CNS] Successfully initialized a service with config: %+v", config) return nil } @@ -226,6 +261,6 @@ func (service *Service) ParseOptions(options OptionMap) OptionMap { // SendErrorResponse sends and logs an error response. func (service *Service) SendErrorResponse(w http.ResponseWriter, errMsg error) { resp := errorResponse{errMsg.Error()} - err := service.Listener.Encode(w, &resp) + err := acn.Encode(w, &resp) log.Errorf("[%s] %+v %s.", service.Name, &resp, err.Error()) } diff --git a/cns/service/main.go b/cns/service/main.go index 442f8d3f75..6fa20abad4 100644 --- a/cns/service/main.go +++ b/cns/service/main.go @@ -43,6 +43,7 @@ import ( "github.com/Azure/azure-container-networking/cns/multitenantcontroller" "github.com/Azure/azure-container-networking/cns/multitenantcontroller/multitenantoperator" "github.com/Azure/azure-container-networking/cns/restserver" + restserverv2 "github.com/Azure/azure-container-networking/cns/restserver/v2" cnstypes "github.com/Azure/azure-container-networking/cns/types" "github.com/Azure/azure-container-networking/cns/wireserver" acn "github.com/Azure/azure-container-networking/common" @@ -101,7 +102,9 @@ const ( // envVarEnableCNIConflistGeneration enables cni conflist generation if set (value doesn't matter) envVarEnableCNIConflistGeneration = "CNS_ENABLE_CNI_CONFLIST_GENERATION" - cnsReqTimeout = 15 * time.Second + cnsReqTimeout = 15 * time.Second + defaultLocalServerIP = "localhost" + defaultLocalServerPort = "10090" ) type cniConflistScenario string @@ -200,6 +203,13 @@ var args = acn.ArgumentList{ Type: "string", DefaultValue: "", }, + { + Name: acn.OptCnsPort, + Shorthand: acn.OptCnsPortAlias, + Description: "Set the URL port for CNS to listen on", + Type: "string", + DefaultValue: "", + }, { Name: acn.OptStartAzureCNM, Shorthand: acn.OptStartAzureCNMAlias, @@ -490,6 +500,7 @@ func main() { cniPath := acn.GetArg(acn.OptNetPluginPath).(string) cniConfigFile := acn.GetArg(acn.OptNetPluginConfigFile).(string) cnsURL := acn.GetArg(acn.OptCnsURL).(string) + cnsPort := acn.GetArg(acn.OptCnsPort).(string) logLevel := acn.GetArg(acn.OptLogLevel).(int) logTarget := acn.GetArg(acn.OptLogTarget).(int) logDirectory := acn.GetArg(acn.OptLogLocation).(string) @@ -735,7 +746,7 @@ func main() { Logger: logger.Log, } - httpRestService, err := restserver.NewHTTPRestService(&config, wsclient, &wsProxy, nmaClient, + httpRemoteRestService, err := restserver.NewHTTPRestService(&config, wsclient, &wsProxy, nmaClient, endpointStateStore, conflistGenerator, homeAzMonitor) if err != nil { logger.Errorf("Failed to create CNS object, err:%v.\n", err) @@ -743,14 +754,15 @@ func main() { } // Set CNS options. - httpRestService.SetOption(acn.OptCnsURL, cnsURL) - httpRestService.SetOption(acn.OptNetPluginPath, cniPath) - httpRestService.SetOption(acn.OptNetPluginConfigFile, cniConfigFile) - httpRestService.SetOption(acn.OptCreateDefaultExtNetworkType, createDefaultExtNetworkType) - httpRestService.SetOption(acn.OptHttpConnectionTimeout, httpConnectionTimeout) - httpRestService.SetOption(acn.OptHttpResponseHeaderTimeout, httpResponseHeaderTimeout) - httpRestService.SetOption(acn.OptProgramSNATIPTables, cnsconfig.ProgramSNATIPTables) - httpRestService.SetOption(acn.OptManageEndpointState, cnsconfig.ManageEndpointState) + httpRemoteRestService.SetOption(acn.OptCnsURL, cnsURL) + httpRemoteRestService.SetOption(acn.OptCnsPort, cnsPort) + httpRemoteRestService.SetOption(acn.OptNetPluginPath, cniPath) + httpRemoteRestService.SetOption(acn.OptNetPluginConfigFile, cniConfigFile) + httpRemoteRestService.SetOption(acn.OptCreateDefaultExtNetworkType, createDefaultExtNetworkType) + httpRemoteRestService.SetOption(acn.OptHttpConnectionTimeout, httpConnectionTimeout) + httpRemoteRestService.SetOption(acn.OptHttpResponseHeaderTimeout, httpResponseHeaderTimeout) + httpRemoteRestService.SetOption(acn.OptProgramSNATIPTables, cnsconfig.ProgramSNATIPTables) + httpRemoteRestService.SetOption(acn.OptManageEndpointState, cnsconfig.ManageEndpointState) // Create default ext network if commandline option is set if len(strings.TrimSpace(createDefaultExtNetworkType)) > 0 { @@ -762,10 +774,10 @@ func main() { } } - logger.Printf("[Azure CNS] Initialize HTTPRestService") - if httpRestService != nil { + logger.Printf("[Azure CNS] Initialize HTTPRemoteRestService") + if httpRemoteRestService != nil { if cnsconfig.UseHTTPS { - config.TlsSettings = localtls.TlsSettings{ + config.TLSSettings = localtls.TlsSettings{ TLSSubjectName: cnsconfig.TLSSubjectName, TLSCertificatePath: cnsconfig.TLSCertificatePath, TLSPort: cnsconfig.TLSPort, @@ -776,7 +788,7 @@ func main() { } } - err = httpRestService.Init(&config) + err = httpRemoteRestService.Init(&config) if err != nil { logger.Errorf("Failed to init HTTPService, err:%v.\n", err) return @@ -840,7 +852,7 @@ func main() { logger.Printf("Set GlobalPodInfoScheme %v (InitializeFromCNI=%t)", cns.GlobalPodInfoScheme, cnsconfig.InitializeFromCNI) - err = InitializeCRDState(rootCtx, httpRestService, cnsconfig) + err = InitializeCRDState(rootCtx, httpRemoteRestService, cnsconfig) if err != nil { logger.Errorf("Failed to start CRD Controller, err:%v.\n", err) return @@ -848,27 +860,52 @@ func main() { } // Initialize multi-tenant controller if the CNS is running in MultiTenantCRD mode. - // It must be started before we start HTTPRestService. + // It must be started before we start HTTPRemoteRestService. if config.ChannelMode == cns.MultiTenantCRD { - err = InitializeMultiTenantController(rootCtx, httpRestService, *cnsconfig) + err = InitializeMultiTenantController(rootCtx, httpRemoteRestService, *cnsconfig) if err != nil { logger.Errorf("Failed to start multiTenantController, err:%v.\n", err) return } - } - logger.Printf("[Azure CNS] Start HTTP listener") - if httpRestService != nil { + // if user provides cns url by -c option, then only start HTTP remote server using this url + logger.Printf("[Azure CNS] Start HTTP Remote server") + if httpRemoteRestService != nil { if cnsconfig.EnablePprof { - httpRestService.RegisterPProfEndpoints() + httpRemoteRestService.RegisterPProfEndpoints() } - err = httpRestService.Start(&config) + err = httpRemoteRestService.Start(&config) if err != nil { logger.Errorf("Failed to start CNS, err:%v.\n", err) return } + + } + + // if user does not provide cns url by -c option, then start http local server + // TODO: we will deprecated -c option in next phase and start local server in any case + if config.Server.EnableLocalServer { + logger.Printf("[Azure CNS] Start HTTP local server") + + var localServerURL string + if config.Server.Port != "" { + localServerURL = fmt.Sprintf(defaultLocalServerIP + ":" + config.Server.Port) + } else { + localServerURL = fmt.Sprintf(defaultLocalServerIP + ":" + defaultLocalServerPort) + } + + httpLocalRestService := restserverv2.New(httpRemoteRestService) + if httpLocalRestService != nil { + go func() { + err = httpLocalRestService.Start(rootCtx, localServerURL) + if err != nil { + logger.Errorf("Failed to start local echo server, err:%v.\n", err) + return + } + }() + } } if cnsconfig.EnableAsyncPodDelete { @@ -896,7 +933,7 @@ func main() { if !disableTelemetry { go logger.SendHeartBeat(rootCtx, cnsconfig.TelemetrySettings.HeartBeatIntervalInMins) - go httpRestService.SendNCSnapShotPeriodically(rootCtx, cnsconfig.TelemetrySettings.SnapshotIntervalInMins) + go httpRemoteRestService.SendNCSnapShotPeriodically(rootCtx, cnsconfig.TelemetrySettings.SnapshotIntervalInMins) } // If CNS is running on managed DNC mode @@ -909,14 +946,14 @@ func main() { return } - httpRestService.SetOption(acn.OptPrivateEndpoint, privateEndpoint) - httpRestService.SetOption(acn.OptInfrastructureNetworkID, infravnet) - httpRestService.SetOption(acn.OptNodeID, nodeID) + httpRemoteRestService.SetOption(acn.OptPrivateEndpoint, privateEndpoint) + httpRemoteRestService.SetOption(acn.OptInfrastructureNetworkID, infravnet) + httpRemoteRestService.SetOption(acn.OptNodeID, nodeID) // Passing in the default http client that already implements Do function standardClient := http.DefaultClient - registerErr := registerNode(rootCtx, standardClient, httpRestService, privateEndpoint, infravnet, nodeID, nmaClient) + registerErr := registerNode(rootCtx, standardClient, httpRemoteRestService, privateEndpoint, infravnet, nodeID, nmaClient) if registerErr != nil { logger.Errorf("[Azure CNS] Registering Node failed with error: %v PrivateEndpoint: %s InfrastructureNetworkID: %s NodeID: %s", registerErr, @@ -930,7 +967,7 @@ func main() { tickerChannel := time.Tick(time.Duration(cnsconfig.ManagedSettings.NodeSyncIntervalInSeconds) * time.Second) for { <-tickerChannel - httpRestService.SyncNodeStatus(ep, vnet, node, json.RawMessage{}) + httpRemoteRestService.SyncNodeStatus(ep, vnet, node, json.RawMessage{}) } }(privateEndpoint, infravnet, nodeID) } @@ -1009,8 +1046,8 @@ func main() { logger.Printf("stop cns service") // Cleanup. - if httpRestService != nil { - httpRestService.Stop() + if httpRemoteRestService != nil { + httpRemoteRestService.Stop() } if startCNM { diff --git a/common/config.go b/common/config.go index ababe24d1e..54e2dea276 100644 --- a/common/config.go +++ b/common/config.go @@ -18,6 +18,8 @@ const ( OptAPIServerURLAlias = "u" OptCnsURL = "cns-url" OptCnsURLAlias = "c" + OptCnsPort = "cns-port" + OptCnsPortAlias = "p" // Logging level. OptLogLevel = "log-level" diff --git a/common/listener.go b/common/listener.go index 06645741f9..0214c36b59 100644 --- a/common/listener.go +++ b/common/listener.go @@ -133,7 +133,7 @@ func (l *Listener) AddHandler(path string, handler http.HandlerFunc) { // todo: Decode and Encode below should not be methods, just functions. They make no use of Listener fields. // Decode receives and decodes JSON payload to a request. -func (l *Listener) Decode(w http.ResponseWriter, r *http.Request, request interface{}) error { +func Decode(w http.ResponseWriter, r *http.Request, request interface{}) error { var err error if r.Body == nil { err = errors.New("request body is empty") @@ -149,7 +149,7 @@ func (l *Listener) Decode(w http.ResponseWriter, r *http.Request, request interf } // Encode encodes and sends a response as JSON payload. -func (l *Listener) Encode(w http.ResponseWriter, response interface{}) error { +func Encode(w http.ResponseWriter, response interface{}) error { // Set the content type as application json w.Header().Set("Content-Type", "application/json; charset=UTF-8") err := json.NewEncoder(w).Encode(response)