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
}