func()

in cni/network/invoker_azure.go [49:133]


func (invoker *AzureIPAMInvoker) Add(addConfig IPAMAddConfig) (IPAMAddResult, error) {
	addResult := IPAMAddResult{interfaceInfo: make(map[string]network.InterfaceInfo)}

	if addConfig.nwCfg == nil {
		return addResult, invoker.plugin.Errorf("nil nwCfg passed to CNI ADD, stack: %+v", string(debug.Stack()))
	}

	if len(invoker.nwInfo.Subnets) > 0 {
		addConfig.nwCfg.IPAM.Subnet = invoker.nwInfo.Subnets[0].Prefix.String()
	}

	// Call into IPAM plugin to allocate an address pool for the network.
	result, err := invoker.plugin.DelegateAdd(addConfig.nwCfg.IPAM.Type, addConfig.nwCfg)
	if err != nil && strings.Contains(err.Error(), ipam.ErrNoAvailableAddressPools.Error()) {
		invoker.deleteIpamState()
		logger.Info("Retry pool allocation after deleting IPAM state")
		result, err = invoker.plugin.DelegateAdd(addConfig.nwCfg.IPAM.Type, addConfig.nwCfg)
	}

	if err != nil {
		err = invoker.plugin.Errorf("Failed to allocate pool: %v", err)
		return addResult, err
	}

	defer func() {
		if err != nil {
			if len(addResult.interfaceInfo) > 0 && len(addResult.interfaceInfo[invoker.getInterfaceInfoKey(cns.InfraNIC)].IPConfigs) > 0 {
				if er := invoker.Delete(&addResult.interfaceInfo[invoker.getInterfaceInfoKey(cns.InfraNIC)].IPConfigs[0].Address, addConfig.nwCfg, nil, addConfig.options); er != nil {
					err = invoker.plugin.Errorf("Failed to clean up IP's during Delete with error %v, after Add failed with error %w", er, err)
				}
			} else {
				err = fmt.Errorf("No IP's to delete on error: %v", err)
			}
		}
	}()

	if addConfig.nwCfg.IPV6Mode != "" {
		nwCfg6 := *addConfig.nwCfg
		nwCfg6.IPAM.Environment = common.OptEnvironmentIPv6NodeIpam
		nwCfg6.IPAM.Type = ipamV6

		if len(invoker.nwInfo.Subnets) > 1 {
			// ipv6 is the second subnet of the slice
			nwCfg6.IPAM.Subnet = invoker.nwInfo.Subnets[1].Prefix.String()
		}

		var ipv6Result *cniTypesCurr.Result
		ipv6Result, err = invoker.plugin.DelegateAdd(nwCfg6.IPAM.Type, &nwCfg6)
		if err != nil {
			err = invoker.plugin.Errorf("Failed to allocate v6 pool: %v", err)
		} else {
			result.IPs = append(result.IPs, ipv6Result.IPs...)
			result.Routes = append(result.Routes, ipv6Result.Routes...)
			addResult.ipv6Enabled = true
		}
	}

	ipconfigs := make([]*network.IPConfig, len(result.IPs))
	for i, ipconfig := range result.IPs {
		ipconfigs[i] = &network.IPConfig{Address: ipconfig.Address, Gateway: ipconfig.Gateway}
	}

	routes := make([]network.RouteInfo, len(result.Routes))
	for i, route := range result.Routes {
		routes[i] = network.RouteInfo{Dst: route.Dst, Gw: route.GW}
	}

	// TODO: changed how host subnet prefix populated (check)
	hostSubnetPrefix := net.IPNet{}
	if len(result.IPs) > 0 {
		hostSubnetPrefix = result.IPs[0].Address
	}
	addResult.interfaceInfo[invoker.getInterfaceInfoKey(cns.InfraNIC)] = network.InterfaceInfo{
		IPConfigs: ipconfigs,
		Routes:    routes,
		DNS: network.DNSInfo{
			Suffix:  result.DNS.Domain,
			Servers: result.DNS.Nameservers,
		},
		NICType:          cns.InfraNIC,
		HostSubnetPrefix: hostSubnetPrefix,
	}

	return addResult, err
}