Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds CreateNetworkStatuses for CNI results with multiple pod interfaces #68

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions pkg/utils/net-attach-def.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,67 @@ func GetNetworkStatus(pod *corev1.Pod) ([]v1.NetworkStatus, error) {
return netStatuses, err
}

// CreateNetworkStatuses creates an array of NetworkStatus from CNI result
// Not to be confused with CreateNetworkStatus (singular)
// This is the preferred method and picks up when CNI ADD results contain multiple container interfaces
func CreateNetworkStatuses(r cnitypes.Result, networkName string, defaultNetwork bool, dev *v1.DeviceInfo) ([]*v1.NetworkStatus, error) {
var networkStatuses []*v1.NetworkStatus
// indexMap is from original CNI result index to networkStatuses index
indexMap := make(map[int]int)

// Convert whatever the IPAM result was into the current Result type
result, err := cni100.NewResultFromResult(r)
if err != nil {
return nil, fmt.Errorf("error converting the type.Result to cni100.Result: %v", err)
}

// Discover default routes upfront and reuse them if necessary.
var useDefaultRoute []string
for _, route := range result.Routes {
if isDefaultRoute(route) {
useDefaultRoute = append(useDefaultRoute, route.GW.String())
}
}

// Same for DNS
v1dns := convertDNS(result.DNS)

// Initialize NetworkStatus for each container interface (e.g. with sandbox present)
indexOfFoundPodInterface := 0
for i, iface := range result.Interfaces {
if iface.Sandbox != "" {
ns := &v1.NetworkStatus{
Name: networkName,
Default: defaultNetwork,
Interface: iface.Name,
Mac: iface.Mac,
Mtu: iface.Mtu,
IPs: []string{},
Gateway: useDefaultRoute,
DeviceInfo: dev,
DNS: *v1dns,
}
networkStatuses = append(networkStatuses, ns)
// Map original index to the new slice index
indexMap[i] = indexOfFoundPodInterface
indexOfFoundPodInterface++
}
}

// Map IPs to network interface based on index
for _, ipConfig := range result.IPs {
if ipConfig.Interface != nil {
originalIndex := *ipConfig.Interface
if newIndex, ok := indexMap[originalIndex]; ok {
ns := networkStatuses[newIndex]
ns.IPs = append(ns.IPs, ipConfig.Address.IP.String())
}
}
}

return networkStatuses, nil
}

// CreateNetworkStatus create NetworkStatus from CNI result
func CreateNetworkStatus(r cnitypes.Result, networkName string, defaultNetwork bool, dev *v1.DeviceInfo) (*v1.NetworkStatus, error) {
netStatus := &v1.NetworkStatus{}
Expand Down
73 changes: 73 additions & 0 deletions pkg/utils/net-attach-def_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,79 @@ var _ = Describe("Netwok Attachment Definition manipulations", func() {
})
})

Context("create network statuses from CNI result with multiple interfaces", func() {
var cniResult *cni100.Result
var networkStatuses []*v1.NetworkStatus

BeforeEach(func() {
cniResult = &cni100.Result{
CNIVersion: "1.1.0",
Interfaces: []*cni100.Interface{
{
Name: "example0",
Mac: "00:AA:BB:CC:DD:01",
Sandbox: "/path/to/network/namespace",
Mtu: 1500,
},
{
Name: "foo",
Mac: "00:AA:BB:CC:DD:33",
},
{
Name: "example1",
Mac: "00:AA:BB:CC:DD:02",
Sandbox: "/path/to/network/namespace",
Mtu: 1500,
},
},
IPs: []*cni100.IPConfig{
{
Address: *EnsureCIDR("192.0.2.1/24"),
Interface: &[]int{0}[0],
},
{
Address: *EnsureCIDR("192.0.2.2/24"),
Interface: &[]int{0}[0],
},
{
Address: *EnsureCIDR("192.0.2.3/24"),
Interface: &[]int{2}[0],
},
},
DNS: cnitypes.DNS{
Nameservers: []string{"8.8.8.8", "8.8.4.4"},
Search: []string{"example.com"},
Options: []string{"ndots:2"},
},
}
var err error
networkStatuses, err = CreateNetworkStatuses(cniResult, "test-multi-net-attach-def", false, nil)
Expect(err).NotTo(HaveOccurred())
})

It("creates network statuses for interfaces with sandbox", func() {
Expect(networkStatuses).To(HaveLen(2))
// Check details for the first returned network status
Expect(networkStatuses[0].Name).To(Equal("test-multi-net-attach-def"))
Expect(networkStatuses[0].Interface).To(Equal("example0"))
Expect(networkStatuses[0].Mtu).To(Equal(1500))
Expect(networkStatuses[0].Mac).To(Equal("00:AA:BB:CC:DD:01"))
Expect(networkStatuses[0].IPs).To(ConsistOf("192.0.2.1", "192.0.2.2"))

// Check details for the second returned network status
Expect(networkStatuses[1].Interface).To(Equal("example1"))
Expect(networkStatuses[1].Mtu).To(Equal(1500))
Expect(networkStatuses[1].Mac).To(Equal("00:AA:BB:CC:DD:02"))
Expect(networkStatuses[1].IPs).To(ConsistOf("192.0.2.3"))
})

It("excludes interfaces without a sandbox", func() {
for _, status := range networkStatuses {
Expect(status.Interface).NotTo(Equal("foo"))
}
})
})

It("parse network selection element in pod", func() {
selectionElement := `
[{
Expand Down
Loading