func()

in azure-ipam/ipam.go [62:159]


func (p *IPAMPlugin) CmdAdd(args *cniSkel.CmdArgs) error {
	p.logger.Info("ADD called", zap.Any("args", args))

	// Parsing network conf
	nwCfg, err := parseNetConf(args.StdinData)
	if err != nil {
		p.logger.Error("Failed to parse CNI network config from stdin", zap.Error(err), zap.Any("argStdinData", args.StdinData))
		return cniTypes.NewError(cniTypes.ErrDecodingFailure, err.Error(), "failed to parse CNI network config from stdin")
	}
	p.logger.Debug("Parsed network config", zap.Any("netconf", nwCfg))

	// Create ip config request from args
	req, err := ipconfig.CreateIPConfigsReq(args)
	if err != nil {
		p.logger.Error("Failed to create CNS IP configs request", zap.Error(err))
		return cniTypes.NewError(ErrCreateIPConfigsRequest, err.Error(), "failed to create CNS IP configs request")
	}
	p.logger.Debug("Created CNS IP config request", zap.Any("request", req))

	p.logger.Debug("Making request to CNS")
	// if this fails, the caller plugin should execute again with cmdDel before returning error.
	// https://www.cni.dev/docs/spec/#delegated-plugin-execution-procedure
	resp, err := p.cnsClient.RequestIPs(context.TODO(), req)
	if err != nil {
		if cnscli.IsUnsupportedAPI(err) {
			p.logger.Error("Failed to request IPs using RequestIPs from CNS, going to try RequestIPAddress", zap.Error(err), zap.Any("request", req))
			ipconfigReq, err := ipconfig.CreateIPConfigReq(args)
			if err != nil {
				p.logger.Error("Failed to create CNS IP config request", zap.Error(err))
				return cniTypes.NewError(ErrCreateIPConfigRequest, err.Error(), "failed to create CNS IP config request")
			}
			p.logger.Debug("Created CNS IP config request", zap.Any("request", ipconfigReq))

			p.logger.Debug("Making request to CNS")
			res, err := p.cnsClient.RequestIPAddress(context.TODO(), ipconfigReq)

			// if the old API fails as well then we just return the error
			if err != nil {
				p.logger.Error("Failed to request IP address from CNS using RequestIPAddress", zap.Error(err), zap.Any("request", ipconfigReq))
				return cniTypes.NewError(ErrRequestIPConfigFromCNS, err.Error(), "failed to request IP address from CNS using RequestIPAddress")
			}
			// takes values from the IPConfigResponse struct and puts them in a IPConfigsResponse struct
			resp = &cns.IPConfigsResponse{
				Response: res.Response,
				PodIPInfo: []cns.PodIpInfo{
					res.PodIpInfo,
				},
			}
		} else {
			p.logger.Error("Failed to request IP address from CNS", zap.Error(err), zap.Any("request", req))
			return cniTypes.NewError(ErrRequestIPConfigFromCNS, err.Error(), "failed to request IP address from CNS")
		}
	}
	p.logger.Debug("Received CNS IP config response", zap.Any("response", resp))

	// Get Pod IP and gateway IP from ip config response
	podIPNet, err := ipconfig.ProcessIPConfigsResp(resp)
	if err != nil {
		p.logger.Error("Failed to interpret CNS IPConfigResponse", zap.Error(err), zap.Any("response", resp))
		return cniTypes.NewError(ErrProcessIPConfigResponse, err.Error(), "failed to interpret CNS IPConfigResponse")
	}
	cniResult := &types100.Result{}
	cniResult.IPs = make([]*types100.IPConfig, len(*podIPNet))
	for i, ipNet := range *podIPNet {
		p.logger.Debug("Parsed pod IP", zap.String("podIPNet", ipNet.String()))
		ipConfig := &types100.IPConfig{}
		if ipNet.Addr().Is4() {
			ipConfig.Address = net.IPNet{
				IP:   net.ParseIP(ipNet.Addr().String()),
				Mask: net.CIDRMask(ipNet.Bits(), 32), // nolint
			}
		} else {
			ipConfig.Address = net.IPNet{
				IP:   net.ParseIP(ipNet.Addr().String()),
				Mask: net.CIDRMask(ipNet.Bits(), 128), // nolint
			}
		}
		cniResult.IPs[i] = ipConfig
	}

	// Get versioned result
	versionedCniResult, err := cniResult.GetAsVersion(nwCfg.CNIVersion)
	if err != nil {
		p.logger.Error("Failed to interpret CNI result with netconf CNI version", zap.Error(err), zap.Any("cniVersion", nwCfg.CNIVersion))
		return cniTypes.NewError(cniTypes.ErrIncompatibleCNIVersion, err.Error(), "failed to interpret CNI result with netconf CNI version")
	}

	p.logger.Info("ADD success", zap.Any("result", versionedCniResult))

	// Write result to output channel
	err = versionedCniResult.PrintTo(p.out)
	if err != nil {
		p.logger.Error("Failed to print CNI result to output channel", zap.Error(err), zap.Any("result", versionedCniResult))
		return cniTypes.NewError(cniTypes.ErrIOFailure, err.Error(), "failed to print CNI result to output channel")
	}

	return nil
}