func()

in cns/restserver/util.go [605:708]


func (service *HTTPRestService) attachOrDetachHelper(req cns.ConfigureContainerNetworkingRequest, operation, method string) cns.Response {
	if method != "POST" {
		return cns.Response{
			ReturnCode: types.InvalidParameter,
			Message:    "[Azure CNS] Error. " + operation + "ContainerToNetwork did not receive a POST.",
		}
	}
	if req.Containerid == "" {
		return cns.Response{
			ReturnCode: types.DockerContainerNotSpecified,
			Message:    "[Azure CNS] Error. Containerid is empty",
		}
	}
	if req.NetworkContainerid == "" {
		return cns.Response{
			ReturnCode: types.NetworkContainerNotSpecified,
			Message:    "[Azure CNS] Error. NetworkContainerid is empty",
		}
	}

	existing, ok := service.getNetworkContainerDetails(cns.SwiftPrefix + req.NetworkContainerid)
	if service.ChannelMode == cns.Managed && operation == attach {
		if ok {
			if !existing.VfpUpdateComplete {
				ctx, cancel := context.WithTimeout(context.Background(), nmaAPICallTimeout)
				defer cancel()
				ncVersionListResp, err := service.nma.GetNCVersionList(ctx)
				if err != nil {
					logger.Errorf("failed to get nc version list from nmagent")
					return cns.Response{
						ReturnCode: types.NmAgentInternalServerError,
						Message:    err.Error(),
					}
				}
				nmaNCs := map[string]string{}
				for _, nc := range ncVersionListResp.Containers {
					// store nmaNCID as lower case to allow case insensitive comparison with nc stored in CNS
					nmaNCs[strings.TrimPrefix(lowerCaseNCGuid(nc.NetworkContainerID), cns.SwiftPrefix)] = nc.Version
				}
				_, returnCode, message := service.isNCWaitingForUpdate(existing.CreateNetworkContainerRequest.Version, req.NetworkContainerid, nmaNCs)
				if returnCode == types.NetworkContainerVfpProgramPending {
					return cns.Response{
						ReturnCode: returnCode,
						Message:    message,
					}
				}
			}
		} else {
			var (
				dncEP     = service.GetOption(acn.OptPrivateEndpoint).(string)
				infraVnet = service.GetOption(acn.OptInfrastructureNetworkID).(string)
				nodeID    = service.GetOption(acn.OptNodeID).(string)
			)

			returnCode, msg := service.SyncNodeStatus(dncEP, infraVnet, nodeID, json.RawMessage{})
			if returnCode != types.Success {
				return cns.Response{
					ReturnCode: returnCode,
					Message:    msg,
				}
			}

			existing, _ = service.getNetworkContainerDetails(cns.SwiftPrefix + req.NetworkContainerid)
		}
	} else if !ok {
		return cns.Response{
			ReturnCode: types.NotFound,
			Message:    fmt.Sprintf("[Azure CNS] Error. Network Container %s does not exist.", req.NetworkContainerid),
		}
	}

	var returnCode types.ResponseCode
	var returnMessage string
	switch service.state.OrchestratorType {
	case cns.Batch:
		podInfo, err := cns.UnmarshalPodInfo(existing.CreateNetworkContainerRequest.OrchestratorContext)
		if err != nil {
			returnCode = types.UnexpectedError
			returnMessage = fmt.Sprintf("Unmarshalling orchestrator context failed with error %+v", err)
		} else {
			nc := service.networkContainer
			netPluginConfig := service.getNetPluginDetails()
			switch operation {
			case attach:
				err = nc.Attach(podInfo, req.Containerid, netPluginConfig)
			case detach:
				err = nc.Detach(podInfo, req.Containerid, netPluginConfig)
			}
			if err != nil {
				returnCode = types.UnexpectedError
				returnMessage = fmt.Sprintf("[Azure CNS] Error. "+operation+"ContainerToNetwork failed %+v", err.Error())
			}
		}

	default:
		returnMessage = fmt.Sprintf("[Azure CNS] Invalid orchestrator type %v", service.state.OrchestratorType)
		returnCode = types.UnsupportedOrchestratorType
	}

	return cns.Response{
		ReturnCode: returnCode,
		Message:    returnMessage,
	}
}