...

Source file src/edge-infra.dev/pkg/sds/ien/k8s/controllers/nodeagent/plugins/networking/cniplugin/cniplugin_test.go

Documentation: edge-infra.dev/pkg/sds/ien/k8s/controllers/nodeagent/plugins/networking/cniplugin

     1  package cniplugin
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	_ "embed"
     7  	"encoding/json"
     8  	"os"
     9  	"testing"
    10  	"text/template"
    11  
    12  	v1 "k8s.io/api/core/v1"
    13  
    14  	"github.com/spf13/afero"
    15  	"github.com/stretchr/testify/assert"
    16  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    17  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    18  
    19  	kruntime "k8s.io/apimachinery/pkg/runtime"
    20  	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
    21  	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
    22  
    23  	"edge-infra.dev/pkg/edge/constants"
    24  	"edge-infra.dev/pkg/sds/ien/k8s/controllers/nodeagent/config"
    25  	"edge-infra.dev/test/f2"
    26  )
    27  
    28  var (
    29  	//go:embed scripts/gateway
    30  	expectedScript string
    31  	path           = "/opt/cni/bin/gateway"
    32  	cm             = v1.ConfigMap{
    33  		ObjectMeta: metav1.ObjectMeta{
    34  			Name:      "network-service-ips",
    35  			Namespace: constants.SdsNamespace,
    36  		},
    37  		Data: constants.ClusterNetworkServiceDefaults,
    38  	}
    39  	emptyCM = v1.ConfigMap{
    40  		ObjectMeta: metav1.ObjectMeta{
    41  			Name:      "network-service-ips",
    42  			Namespace: constants.SdsNamespace,
    43  		},
    44  		Data: map[string]string{
    45  			constants.ServiceTypePodNetworkCIDR:     "",
    46  			constants.ServiceTypeClusterDNS:         "",
    47  			constants.ServiceTypeServiceNetworkCIDR: "",
    48  		},
    49  	}
    50  )
    51  
    52  var f f2.Framework
    53  
    54  func TestMain(m *testing.M) {
    55  	f = f2.New(context.Background(), f2.WithExtensions()).
    56  		Setup().
    57  		Teardown()
    58  	os.Exit(f.Run(m))
    59  }
    60  
    61  func TestAddCNIScript(t *testing.T) {
    62  	feature := f2.NewFeature("CNI scripts").
    63  		Test("plugin reconciles", func(ctx f2.Context, t *testing.T) f2.Context { // nolint: dupl
    64  			memFS, err := createMemFS(false)
    65  			assert.NoError(t, err)
    66  
    67  			kclient := fake.NewClientBuilder().WithScheme(createScheme()).WithObjects(&cm).Build()
    68  
    69  			cfg := config.NewConfig(kclient, nil, nil, config.Flags{}).WithFs(memFS)
    70  			_, err = CNIPlugin{}.Reconcile(context.Background(), nil, cfg)
    71  			assert.NoError(t, err)
    72  
    73  			assertValidCNIConfig(t, memFS)
    74  			return ctx
    75  		}).
    76  		Test("plugin reconciles with defaults pod and service cidr", func(ctx f2.Context, t *testing.T) f2.Context { // nolint: dupl
    77  			memFS, err := createMemFS(false)
    78  			assert.NoError(t, err)
    79  
    80  			kclient := fake.NewClientBuilder().WithScheme(createScheme()).Build()
    81  
    82  			cfg := config.NewConfig(kclient, nil, nil, config.Flags{}).WithFs(memFS)
    83  			_, err = CNIPlugin{}.Reconcile(context.Background(), nil, cfg)
    84  			assert.NoError(t, err)
    85  
    86  			assertValidCNIConfig(t, memFS)
    87  			return ctx
    88  		}).
    89  		Test("plugin reconciles with empty pod and service cidrs", func(ctx f2.Context, t *testing.T) f2.Context { // nolint: dupl
    90  			memFS, err := createMemFS(false)
    91  			assert.NoError(t, err)
    92  
    93  			kclient := fake.NewClientBuilder().WithScheme(createScheme()).WithObjects(&emptyCM).Build()
    94  
    95  			cfg := config.NewConfig(kclient, nil, nil, config.Flags{}).WithFs(memFS)
    96  			_, err = CNIPlugin{}.Reconcile(context.Background(), nil, cfg)
    97  			assert.NoError(t, err)
    98  
    99  			assertValidCNIConfig(t, memFS)
   100  			return ctx
   101  		}).Feature()
   102  
   103  	f.Test(t, feature)
   104  }
   105  
   106  func assertValidCNIConfig(t *testing.T, memFS afero.Fs) {
   107  	contents, err := afero.ReadFile(memFS, path)
   108  	assert.NoError(t, err)
   109  	expected, err := renderExpectedScript()
   110  	assert.NoError(t, err)
   111  	assert.Equal(t, expected, string(contents))
   112  
   113  	calicoConf, err := afero.ReadFile(memFS, calicoConfListPath)
   114  	assert.NoError(t, err)
   115  	assert.Equal(t, mockCalicoConfig(true), calicoConf)
   116  
   117  	fileInfo, err := memFS.Stat(path)
   118  	assert.NoError(t, err)
   119  	assert.Equal(t, pluginFSMode, fileInfo.Mode())
   120  
   121  	fileInfo, err = memFS.Stat(calicoConfListPath)
   122  	assert.NoError(t, err)
   123  	assert.Equal(t, calicoConfFSMode, fileInfo.Mode())
   124  }
   125  
   126  func createScheme() *kruntime.Scheme {
   127  	scheme := kruntime.NewScheme()
   128  	utilruntime.Must(clientgoscheme.AddToScheme(scheme))
   129  	utilruntime.Must(v1.AddToScheme(scheme))
   130  	return scheme
   131  }
   132  
   133  func mockCalicoConfig(pluginExists bool) []byte {
   134  	conf := CalicoConfList{
   135  		Plugins: []Plugin{
   136  			{
   137  				Type: "test",
   138  			},
   139  		},
   140  	}
   141  
   142  	if pluginExists {
   143  		conf.Plugins = append(conf.Plugins, Plugin{Type: "gateway", Capabilities: &Capabilities{EnableAnnotation: true}})
   144  	}
   145  
   146  	b, _ := json.MarshalIndent(conf, "", "  ")
   147  	return b
   148  }
   149  
   150  func createMemFS(pluginExists bool) (afero.Fs, error) {
   151  	contents := mockCalicoConfig(pluginExists)
   152  	fs := afero.NewMemMapFs()
   153  	if err := afero.WriteFile(fs, calicoConfListPath, contents, 0644); err != nil {
   154  		return nil, err
   155  	}
   156  	return fs, nil
   157  }
   158  
   159  func renderExpectedScript() (string, error) {
   160  	tmpl, err := template.New("test").Parse(expectedScript)
   161  	if err != nil {
   162  		return "", err
   163  	}
   164  	var tpl bytes.Buffer
   165  	values := templateVariables{
   166  		ServiceNetworkCidr: constants.ClusterNetworkServiceDefaults[constants.ServiceTypeServiceNetworkCIDR],
   167  		PodNetworkCidr:     constants.ClusterNetworkServiceDefaults[constants.ServiceTypePodNetworkCIDR],
   168  	}
   169  	if err = tmpl.Execute(&tpl, values); err != nil {
   170  		return "", err
   171  	}
   172  	return tpl.String(), nil
   173  }
   174  

View as plain text