in plugins/vpc-shared-eni/plugin/commands.go [28:140]
func (plugin *Plugin) Add(args *cniSkel.CmdArgs) error {
// Parse network configuration.
netConfig, err := config.New(args, true)
if err != nil {
log.Errorf("Failed to parse netconfig from args: %v.", err)
return err
}
log.Infof("Executing ADD with netconfig: %+v ContainerID:%v Netns:%v IfName:%v Args:%v.",
netConfig, args.ContainerID, args.Netns, args.IfName, args.Args)
// Find the ENI.
sharedENI, err := eni.NewENI(netConfig.ENIName, netConfig.ENIMACAddress)
if err != nil {
log.Errorf("Failed to find ENI %s: %v.", netConfig.ENIName, err)
return err
}
// Find the ENI link.
err = sharedENI.AttachToLink()
if err != nil {
log.Errorf("Failed to find ENI link: %v.", err)
return err
}
// Call the operating system specific network builder.
nb := plugin.nb
// Find or create the container network for the shared ENI.
nw := network.Network{
Name: netConfig.Name,
BridgeType: netConfig.BridgeType,
BridgeNetNSPath: netConfig.BridgeNetNSPath,
SharedENI: sharedENI,
ENIIPAddresses: netConfig.ENIIPAddresses,
GatewayIPAddress: netConfig.GatewayIPAddress,
VPCCIDRs: netConfig.VPCCIDRs,
DNSServers: netConfig.DNS.Nameservers,
DNSSuffixSearchList: netConfig.DNS.Search,
}
if netConfig.Kubernetes != nil {
nw.ServiceCIDR = netConfig.Kubernetes.ServiceCIDR
}
// Below creates a bridge but doesn't require attaching any IPs given it is L3 bridge not L2
err = nb.FindOrCreateNetwork(&nw)
if err != nil {
log.Errorf("Failed to create network: %v.", err)
return err
}
// Find or create the container endpoint on the network.
ep := network.Endpoint{
ContainerID: args.ContainerID,
NetNSName: args.Netns,
IfName: args.IfName,
IfType: netConfig.InterfaceType,
TapUserID: netConfig.TapUserID,
IPAddresses: netConfig.IPAddresses,
}
err = nb.FindOrCreateEndpoint(&nw, &ep)
if err != nil {
log.Errorf("Failed to create endpoint: %v.", err)
return err
}
// Generate CNI result.
result := &cniTypesCurrent.Result{
Interfaces: []*cniTypesCurrent.Interface{
{
Name: args.IfName,
Mac: ep.MACAddress.String(),
Sandbox: args.Netns,
},
},
}
// Populate an IPConfig entry for each IP address.
for _, ipAddr := range netConfig.IPAddresses {
ipCfg := &cniTypesCurrent.IPConfig{
Interface: cniTypesCurrent.Int(0),
Address: ipAddr,
}
if ipAddr.IP.To4() != nil {
ipCfg.Version = "4"
ipCfg.Gateway = netConfig.GatewayIPAddress
} else {
ipCfg.Version = "6"
// Kubernetes doesn't implement dual-stack behavior properly. It defaults to IPv4 if
// both an IPv4 and IPv6 address are present. Work around that by reporting only the
// first IPv6 address in dual-stack setups.
if netConfig.Kubernetes != nil {
result.IPs = []*cniTypesCurrent.IPConfig{ipCfg}
break
}
}
result.IPs = append(result.IPs, ipCfg)
}
// Output CNI result.
log.Infof("Writing CNI result to stdout: %+v", result)
err = cniTypes.PrintResult(result, netConfig.CNIVersion)
if err != nil {
log.Errorf("Failed to print result for CNI ADD command: %v", err)
}
return err
}