Skip to content
Draft
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
8 changes: 5 additions & 3 deletions cns/NetworkContainerContract.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
"strconv"
"strings"

"github.com/Azure/azure-container-networking/cns/types"
"github.com/Azure/azure-container-networking/crd/nodenetworkconfig/api/v1alpha"
"github.com/Azure/azure-container-networking/network/policy"
"github.com/google/uuid"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"

"github.com/Azure/azure-container-networking/cns/types"
"github.com/Azure/azure-container-networking/crd/nodenetworkconfig/api/v1alpha"
"github.com/Azure/azure-container-networking/network/policy"

Check failure on line 16 in cns/NetworkContainerContract.go

View workflow job for this annotation

GitHub Actions / Lint (ubuntu-latest)

File is not properly formatted (gci)
)

// Container Network Service DNC Contract
Expand Down Expand Up @@ -128,6 +129,7 @@
AllowNCToHostCommunication bool
EndpointPolicies []NetworkContainerRequestPolicies
NCStatus v1alpha.NCStatus
SwiftV2PrefixOnNic bool // Indicates if is swiftv2 nc, PrefixOnNic scenario (isSwiftV2 && nc.Type == VNETBlock)
NetworkInterfaceInfo NetworkInterfaceInfo //nolint // introducing new field for backendnic, to be used later by cni code
}

Expand Down
4 changes: 3 additions & 1 deletion cns/kubecontroller/nodenetworkconfig/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
"strconv"
"strings"

"github.com/pkg/errors"

Check failure on line 9 in cns/kubecontroller/nodenetworkconfig/conversion.go

View workflow job for this annotation

GitHub Actions / Lint (ubuntu-latest)

File is not properly formatted (gci)

"github.com/Azure/azure-container-networking/cns"
"github.com/Azure/azure-container-networking/crd/nodenetworkconfig/api/v1alpha"
"github.com/pkg/errors"
)

var (
Expand Down Expand Up @@ -62,6 +63,7 @@
NetworkContainerid: nc.ID,
NetworkContainerType: cns.Docker,
Version: strconv.FormatInt(nc.Version, 10), //nolint:gomnd // it's decimal
SwiftV2PrefixOnNic: false, // Dynamic NCs don't use SwiftV2 PrefixOnNic
IPConfiguration: cns.IPConfiguration{
IPSubnet: subnet,
GatewayIPAddress: nc.DefaultGateway,
Expand Down
1 change: 1 addition & 0 deletions cns/kubecontroller/nodenetworkconfig/conversion_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func createNCRequestFromStaticNCHelper(nc v1alpha.NetworkContainer, primaryIPPre
GatewayIPv6Address: nc.DefaultGatewayV6,
},
NCStatus: nc.Status,
SwiftV2PrefixOnNic: isSwiftV2 && nc.Type == v1alpha.VNETBlock,
NetworkInterfaceInfo: cns.NetworkInterfaceInfo{
MACAddress: nc.MacAddress,
},
Expand Down
36 changes: 28 additions & 8 deletions cns/restserver/internalapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,19 @@
"net/http"
"net/http/httptest"
"reflect"
"runtime"
"strconv"
"strings"
"time"

"github.com/pkg/errors"

Check failure on line 20 in cns/restserver/internalapi.go

View workflow job for this annotation

GitHub Actions / Lint (ubuntu-latest)

File is not properly formatted (gci)

"github.com/Azure/azure-container-networking/cns"
"github.com/Azure/azure-container-networking/cns/logger"
"github.com/Azure/azure-container-networking/cns/nodesubnet"
"github.com/Azure/azure-container-networking/cns/types"
"github.com/Azure/azure-container-networking/common"
"github.com/Azure/azure-container-networking/crd/nodenetworkconfig/api/v1alpha"
"github.com/pkg/errors"
)

const (
Expand Down Expand Up @@ -228,8 +230,8 @@
return len(programmedNCs), errors.Wrap(err, "failed to get nc version list from nmagent")
}

// Get IMDS NC versions for delegated NIC scenarios
imdsNCVersions, err := service.GetIMDSNCs(ctx)
// Get IMDS NC versions for delegated NIC scenarios. If any of the NMA API check calls, imds calls fails assume that nma build doesn't have the latest changes and create empty map
imdsNCVersions := service.getIMDSNCs(ctx)
if err != nil {
// If any of the NMA API check calls, imds calls fails assume that nma build doesn't have the latest changes and create empty map
imdsNCVersions = make(map[string]string)
Expand Down Expand Up @@ -685,26 +687,26 @@
}

// GetIMDSNCs gets NC versions from IMDS and returns them as a map
func (service *HTTPRestService) GetIMDSNCs(ctx context.Context) (map[string]string, error) {
func (service *HTTPRestService) getIMDSNCs(ctx context.Context) map[string]string {
imdsClient := service.imdsClient
if imdsClient == nil {
//nolint:staticcheck // SA1019: suppress deprecated logger.Printf usage. Todo: legacy logger usage is consistent in cns repo. Migrates when all logger usage is migrated
logger.Errorf("IMDS client is not available")
return make(map[string]string), nil
return make(map[string]string)
}
// Check NC version support
if !service.isNCDetailsAPIExists(ctx) {
//nolint:staticcheck // SA1019: suppress deprecated logger.Printf usage. Todo: legacy logger usage is consistent in cns repo. Migrates when all logger usage is migrated
logger.Errorf("IMDS does not support NC details API")
return make(map[string]string), nil
return make(map[string]string)
}

// Get all network interfaces from IMDS
networkInterfaces, err := imdsClient.GetNetworkInterfaces(ctx)
if err != nil {
//nolint:staticcheck // SA1019: suppress deprecated logger.Printf usage. Todo: legacy logger usage is consistent in cns repo. Migrates when all logger usage is migrated
logger.Errorf("Failed to get network interfaces from IMDS: %v", err)
return make(map[string]string), nil
return make(map[string]string)
}

// Build ncs map from the network interfaces
Expand All @@ -717,8 +719,26 @@

if ncID != "" {
ncs[ncID] = PrefixOnNicNCVersion // for prefix on nic version scenario nc version is 1
} else if runtime.GOOS == "windows" && service.isPrefixonNicSwiftV2() {
err := service.setPrefixOnNICRegistry(true, iface.MacAddress.String())
if err != nil {
//nolint:staticcheck // SA1019: suppress deprecated logger.Debugf usage. Todo: legacy logger usage is consistent in cns repo. Migrates when all logger usage is migrated
logger.Debugf("failed to add PrefixOnNic keys to Windows registry: %w", err)
}
}
}

return ncs, nil
return ncs
}

// Check whether NC is SwiftV2 NIC associated NC and prefix on nic is enabled
func (service *HTTPRestService) isPrefixonNicSwiftV2() bool {
for i := range service.state.ContainerStatus {
req := service.state.ContainerStatus[i].CreateNetworkContainerRequest

if req.SwiftV2PrefixOnNic {
return true
}
}
return false
}
13 changes: 11 additions & 2 deletions cns/restserver/internalapi_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
"os/exec"
"strconv"

goiptables "github.com/coreos/go-iptables/iptables"

Check failure on line 9 in cns/restserver/internalapi_linux.go

View workflow job for this annotation

GitHub Actions / Lint (ubuntu-latest)

File is not properly formatted (gci)
"github.com/pkg/errors"

"github.com/Azure/azure-container-networking/cns"
"github.com/Azure/azure-container-networking/cns/logger"
"github.com/Azure/azure-container-networking/cns/types"
"github.com/Azure/azure-container-networking/iptables"
"github.com/Azure/azure-container-networking/network/networkutils"
goiptables "github.com/coreos/go-iptables/iptables"
"github.com/pkg/errors"
)

const SWIFTPOSTROUTING = "SWIFT-POSTROUTING"
Expand Down Expand Up @@ -181,3 +182,11 @@
func (service *HTTPRestService) setVFForAccelnetNICs() error {
return nil
}

func (service *HTTPRestService) setPrefixOnNICRegistry(enabled bool, infraNicMacAddress string) error {
// Assigning parameters to '_' to avoid unused parameter linting errors.
// These parameters are only used in the Windows implementation.
_ = enabled
_ = infraNicMacAddress
return nil
}
137 changes: 132 additions & 5 deletions cns/restserver/internalapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,19 @@
"net"
"os"
"reflect"
"runtime"
"strconv"
"strings"
"sync"
"testing"
"time"

"github.com/google/uuid"

Check failure on line 20 in cns/restserver/internalapi_test.go

View workflow job for this annotation

GitHub Actions / Lint (ubuntu-latest)

File is not properly formatted (gci)
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/exp/maps"

"github.com/Azure/azure-container-networking/cns"
"github.com/Azure/azure-container-networking/cns/common"
"github.com/Azure/azure-container-networking/cns/configuration"
Expand All @@ -25,11 +32,6 @@
"github.com/Azure/azure-container-networking/crd/nodenetworkconfig/api/v1alpha"
nma "github.com/Azure/azure-container-networking/nmagent"
"github.com/Azure/azure-container-networking/store"
"github.com/google/uuid"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/exp/maps"
)

const (
Expand Down Expand Up @@ -1680,3 +1682,128 @@
// Return cleanup function
return func() { svc.imdsClient = originalIMDS }
}

// TestSyncHostNCVersionWithWindowsSwiftV2 tests SyncHostNCVersion and verifies it calls Windows SwiftV2 PrefixOnNic scenario
func TestSyncHostNCVersionWithWindowsSwiftV2(t *testing.T) {
testSvc := getTestService(cns.Kubernetes)

// Set up test NCs with different scenarios
regularNCID := "regular-nc-id"
swiftV2NCID := "swift-v2-vnet-block-nc"

// Initialize ContainerStatus map if nil
if testSvc.state.ContainerStatus == nil {
testSvc.state.ContainerStatus = make(map[string]containerstatus)
}

// Add a regular NC
testSvc.state.ContainerStatus[regularNCID] = containerstatus{
ID: regularNCID,
CreateNetworkContainerRequest: cns.CreateNetworkContainerRequest{
NetworkContainerid: regularNCID,
SwiftV2PrefixOnNic: false,
NetworkContainerType: cns.Docker,
Version: "2",
},
HostVersion: "1",
}

// Add a SwiftV2 VNETBlock NC that should trigger Windows registry operations
testSvc.state.ContainerStatus[swiftV2NCID] = containerstatus{
ID: swiftV2NCID,
CreateNetworkContainerRequest: cns.CreateNetworkContainerRequest{
NetworkContainerid: swiftV2NCID,
SwiftV2PrefixOnNic: true,
NetworkContainerType: cns.Docker,
Version: "2",
},
HostVersion: "1",
}

// Set up mock NMAgent with NC versions
mockNMA := &fakes.NMAgentClientFake{}
mockNMA.GetNCVersionListF = func(_ context.Context) (nma.NCVersionList, error) {
return nma.NCVersionList{
Containers: []nma.NCVersion{
{
NetworkContainerID: regularNCID,
Version: "2",
},
{
NetworkContainerID: swiftV2NCID,
Version: "2",
},
},
}, nil
}
testSvc.nma = mockNMA

// Set up mock IMDS client for Windows SwiftV2 scenario
mac1, _ := net.ParseMAC("AA:BB:CC:DD:EE:FF")
mac2, _ := net.ParseMAC("11:22:33:44:55:66")

interfaceMap := map[string]imds.NetworkInterface{
"interface1": {
InterfaceCompartmentID: "", // Empty for Windows condition
MacAddress: imds.HardwareAddr(mac1),
},
"interface2": {
InterfaceCompartmentID: "nc-with-compartment-id",
MacAddress: imds.HardwareAddr(mac2),
},
}
mockIMDS := &mockIMDSAdapter{
mock: &struct {
networkInterfaces func(_ context.Context) ([]imds.NetworkInterface, error)
imdsVersions func(_ context.Context) (*imds.APIVersionsResponse, error)
}{
networkInterfaces: func(_ context.Context) ([]imds.NetworkInterface, error) {
var interfaces []imds.NetworkInterface
for _, iface := range interfaceMap {
interfaces = append(interfaces, iface)
}
return interfaces, nil
},
imdsVersions: func(_ context.Context) (*imds.APIVersionsResponse, error) {
return &imds.APIVersionsResponse{
APIVersions: []string{expectedIMDSAPIVersion},
}, nil
},
},
}

// Replace the IMDS client
originalIMDS := testSvc.imdsClient
testSvc.imdsClient = mockIMDS
defer func() { testSvc.imdsClient = originalIMDS }()

// Verify preconditions
assert.True(t, testSvc.isPrefixonNicSwiftV2(), "isPrefixonNicSwiftV2() should return true")

ctx := context.Background()
testSvc.SyncHostNCVersion(ctx, cns.CRD)

// Verify that NC versions were updated
updatedRegularNC := testSvc.state.ContainerStatus[regularNCID]
updatedSwiftV2NC := testSvc.state.ContainerStatus[swiftV2NCID]

assert.Equal(t, "2", updatedRegularNC.HostVersion, "Regular NC host version should be updated to 2")
assert.Equal(t, "2", updatedSwiftV2NC.HostVersion, "SwiftV2 NC host version should be updated to 2")

imdsNCs := testSvc.getIMDSNCs(ctx)

// Verify IMDS results
assert.Contains(t, imdsNCs, "nc-with-compartment-id", "NC with compartment ID should be in results")
assert.Equal(t, PrefixOnNicNCVersion, imdsNCs["nc-with-compartment-id"], "NC should have expected version")

// Log the conditions that would trigger Windows registry operations
isWindows := runtime.GOOS == "windows"
hasSwiftV2PrefixOnNic := testSvc.isPrefixonNicSwiftV2()

t.Logf("Windows SwiftV2 PrefixOnNic conditions: (runtime.GOOS == 'windows' && service.isPrefixonNicSwiftV2()): %t",
isWindows && hasSwiftV2PrefixOnNic)

// Test with no SwiftV2 NCs
delete(testSvc.state.ContainerStatus, swiftV2NCID)
assert.False(t, testSvc.isPrefixonNicSwiftV2(), "isPrefixonNicSwiftV2() should return false without SwiftV2 NCs")
}
Loading
Loading