Skip to content
Open
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
15 changes: 15 additions & 0 deletions aks-node-controller/parser/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -810,3 +810,18 @@ func getLocalDnsMemoryLimitInMb(aksnodeconfig *aksnodeconfigv1.Configuration) st
}

// ---------------------- End of localdns related helper code ----------------------//

// ---------------------- Start of Ethtool Config related helper code ----------------------//

func getEthtoolContents(ethtool_config *aksnodeconfigv1.EthtoolConfig) string {
if ethtool_config == nil || ethtool_config.GetRxBufferSize() <= 0 {
return ""
}

m := make(map[string]interface{})
m["rx"] = ethtool_config.GetRxBufferSize()

return base64.StdEncoding.EncodeToString([]byte(createSortedKeyValuePairs(m, "\n")))
}

// ---------------------- End of Ethtool Config related helper code ----------------------//
126 changes: 126 additions & 0 deletions aks-node-controller/parser/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
_ "embed"
"encoding/base64"
"encoding/json"
"fmt"
"reflect"
"regexp"
"strings"
Expand Down Expand Up @@ -199,6 +200,131 @@ net.ipv4.tcp_retries2=8`)),
}
}

func Test_getEthtoolContents(t *testing.T) {
// Helper function to create base64 encoded rx value.
encodeRxValue := func(value int32) string {
return base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("rx=%d", value)))
}

type args struct {
e *aksnodeconfigv1.EthtoolConfig
}
tests := []struct {
name string
args args
want string
}{
{
name: "Nil EthtoolConfig - returns empty string",
args: args{
e: nil,
},
want: "",
},
{
name: "Empty EthtoolConfig - returns empty string",
args: args{
e: &aksnodeconfigv1.EthtoolConfig{},
},
want: "",
},
{
name: "Zero RxBufferSize pointer - returns empty string",
args: args{
e: &aksnodeconfigv1.EthtoolConfig{
RxBufferSize: to.Ptr(int32(0)),
},
},
want: "",
},
{
name: "Negative RxBufferSize - returns empty string",
args: args{
e: &aksnodeconfigv1.EthtoolConfig{
RxBufferSize: to.Ptr(int32(-1)),
},
},
want: "",
},
{
name: "Minimum positive value",
args: args{
e: &aksnodeconfigv1.EthtoolConfig{
RxBufferSize: to.Ptr(int32(1)),
},
},
want: encodeRxValue(1),
},
{
name: "Very small custom value",
args: args{
e: &aksnodeconfigv1.EthtoolConfig{
RxBufferSize: to.Ptr(int32(256)),
},
},
want: encodeRxValue(256),
},
{
name: "Custom RxBufferSize 512",
args: args{
e: &aksnodeconfigv1.EthtoolConfig{
RxBufferSize: to.Ptr(int32(512)),
},
},
want: encodeRxValue(512),
},
{
name: "Custom RxBufferSize 1024",
args: args{
e: &aksnodeconfigv1.EthtoolConfig{
RxBufferSize: to.Ptr(int32(1024)),
},
},
want: encodeRxValue(1024),
},
{
name: "Custom RxBufferSize 2048",
args: args{
e: &aksnodeconfigv1.EthtoolConfig{
RxBufferSize: to.Ptr(int32(2048)),
},
},
want: encodeRxValue(2048),
},
{
name: "Custom RxBufferSize 4096",
args: args{
e: &aksnodeconfigv1.EthtoolConfig{
RxBufferSize: to.Ptr(int32(4096)),
},
},
want: encodeRxValue(4096),
},
{
name: "Very large custom value",
args: args{
e: &aksnodeconfigv1.EthtoolConfig{
RxBufferSize: to.Ptr(int32(8192)),
},
},
want: encodeRxValue(8192),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := getEthtoolContents(tt.args.e)
if got != tt.want {
// Decode both values for better error reporting
gotDecoded, _ := base64.StdEncoding.DecodeString(got)
wantDecoded, _ := base64.StdEncoding.DecodeString(tt.want)
t.Errorf("getEthtoolContents() = %v (decoded: %s), want %v (decoded: %s)",
got, gotDecoded, tt.want, wantDecoded)
}
})
}
}

func Test_getUlimitContent(t *testing.T) {
type args struct {
u *aksnodeconfigv1.UlimitConfig
Expand Down
1 change: 1 addition & 0 deletions aks-node-controller/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ func getCSEEnv(config *aksnodeconfigv1.Configuration) map[string]string {
"SERVICE_ACCOUNT_IMAGE_PULL_DEFAULT_CLIENT_ID": config.GetServiceAccountImagePullProfile().GetDefaultClientId(),
"SERVICE_ACCOUNT_IMAGE_PULL_DEFAULT_TENANT_ID": config.GetServiceAccountImagePullProfile().GetDefaultTenantId(),
"IDENTITY_BINDINGS_LOCAL_AUTHORITY_SNI": config.GetServiceAccountImagePullProfile().GetLocalAuthoritySni(),
"ETHTOOL_CONTENT": fmt.Sprintf("%v", getEthtoolContents(config.GetCustomLinuxOsConfig().GetEthtoolConfig())),
}

for i, cert := range config.CustomCaCerts {
Expand Down
60 changes: 60 additions & 0 deletions aks-node-controller/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,62 @@ oom_score = -999
assert.Equal(t, "true", vars["NEEDS_CGROUPV2"])
},
},
{
name: "AKSUbuntu2204 with custom ethtool config",
folder: "AKSUbuntu2204+CustomEthtoolConfig",
k8sVersion: "1.24.2",
aksNodeConfigUpdator: func(aksNodeConfig *aksnodeconfigv1.Configuration) {
aksNodeConfig.CustomLinuxOsConfig = &aksnodeconfigv1.CustomLinuxOsConfig{
EthtoolConfig: &aksnodeconfigv1.EthtoolConfig{
RxBufferSize: to.Ptr(int32(4096)),
},
}
},
validator: func(cmd *exec.Cmd) {
vars := environToMap(cmd.Env)
ethtoolContent, err := getBase64DecodedValue([]byte(vars["ETHTOOL_CONTENT"]))
require.NoError(t, err)
assert.Equal(t, "rx=4096", ethtoolContent)
},
},
{
name: "AKSUbuntu2204 with default ethtool config (no defaults set)",
folder: "AKSUbuntu2204+DefaultEthtoolConfig",
k8sVersion: "1.24.2",
aksNodeConfigUpdator: func(aksNodeConfig *aksnodeconfigv1.Configuration) {
aksNodeConfig.CustomLinuxOsConfig = &aksnodeconfigv1.CustomLinuxOsConfig{
EthtoolConfig: &aksnodeconfigv1.EthtoolConfig{
// No RxBufferSize set, should return empty string.
},
}
},
validator: func(cmd *exec.Cmd) {
vars := environToMap(cmd.Env)
ethtoolContent, err := getBase64DecodedValue([]byte(vars["ETHTOOL_CONTENT"]))
require.NoError(t, err)
// Should return empty string when no value is set.
assert.Equal(t, "", ethtoolContent)
},
},
{
name: "AKSUbuntu2204 with zero ethtool buffer (returns empty)",
folder: "AKSUbuntu2204+ZeroEthtoolConfig",
k8sVersion: "1.24.2",
aksNodeConfigUpdator: func(aksNodeConfig *aksnodeconfigv1.Configuration) {
aksNodeConfig.CustomLinuxOsConfig = &aksnodeconfigv1.CustomLinuxOsConfig{
EthtoolConfig: &aksnodeconfigv1.EthtoolConfig{
RxBufferSize: to.Ptr(int32(0)), // Zero should return empty string.
},
}
},
validator: func(cmd *exec.Cmd) {
vars := environToMap(cmd.Env)
ethtoolContent, err := getBase64DecodedValue([]byte(vars["ETHTOOL_CONTENT"]))
require.NoError(t, err)
// Zero value should return empty string.
assert.Equal(t, "", ethtoolContent)
},
},
}

for _, tt := range tests {
Expand Down Expand Up @@ -387,6 +443,10 @@ func TestAKSNodeConfigCompatibilityFromJsonToCSECommand(t *testing.T) {
assert.Equal(t, "", vars["SECURE_TLS_BOOTSTRAPPING_AAD_RESOURCE"])
assert.Equal(t, "", vars["SECURE_TLS_BOOTSTRAPPING_USER_ASSIGNED_IDENTITY_ID"])
assert.Equal(t, "", vars["CUSTOM_SECURE_TLS_BOOTSTRAPPING_CLIENT_URL"])
ethtoolContent, err := getBase64DecodedValue([]byte(vars["ETHTOOL_CONTENT"]))
require.NoError(t, err)
// With empty config, no default should be set, so ethtool content should be empty.
assert.Equal(t, "", ethtoolContent)
},
},
}
Expand Down
Loading
Loading