github.com/oam-dev/kubevela@v1.9.11/references/cli/addon_test.go (about)

     1  /*
     2  Copyright 2021 The KubeVela Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package cli
    18  
    19  import (
    20  	"fmt"
    21  	"os"
    22  	"testing"
    23  
    24  	. "github.com/onsi/ginkgo/v2"
    25  	. "github.com/onsi/gomega"
    26  
    27  	"github.com/fatih/color"
    28  	"github.com/getkin/kin-openapi/openapi3"
    29  	"github.com/stretchr/testify/assert"
    30  
    31  	pkgaddon "github.com/oam-dev/kubevela/pkg/addon"
    32  	"github.com/oam-dev/kubevela/pkg/utils/common"
    33  	"github.com/oam-dev/kubevela/pkg/utils/util"
    34  )
    35  
    36  func TestParseMap(t *testing.T) {
    37  	testcase := []struct {
    38  		args     []string
    39  		res      map[string]interface{}
    40  		nilError bool
    41  	}{
    42  		{
    43  			args: []string{"key1=value1"},
    44  			res: map[string]interface{}{
    45  				"key1": "value1",
    46  			},
    47  			nilError: true,
    48  		},
    49  		{
    50  			args: []string{"dbUrl=mongodb=mgset-58800212"},
    51  			res: map[string]interface{}{
    52  				"dbUrl": "mongodb=mgset-58800212",
    53  			},
    54  			nilError: true,
    55  		},
    56  		{
    57  			args: []string{"imagePullSecrets={a,b,c}"},
    58  			res: map[string]interface{}{
    59  				"imagePullSecrets": []interface{}{
    60  					"a", "b", "c",
    61  				},
    62  			},
    63  			nilError: true,
    64  		},
    65  		{
    66  			args: []string{"image.repo=www.test.com", "image.tag=1.1"},
    67  			res: map[string]interface{}{
    68  				"image": map[string]interface{}{
    69  					"repo": "www.test.com",
    70  					"tag":  "1.1",
    71  				},
    72  			},
    73  			nilError: true,
    74  		},
    75  		{
    76  			args: []string{"local=true"},
    77  			res: map[string]interface{}{
    78  				"local": true,
    79  			},
    80  			nilError: true,
    81  		},
    82  		{
    83  			args: []string{"replicas=3"},
    84  			res: map[string]interface{}{
    85  				"replicas": int64(3),
    86  			},
    87  			nilError: true,
    88  		},
    89  	}
    90  	for _, s := range testcase {
    91  		r, err := parseAddonArgsToMap(s.args)
    92  		if s.nilError {
    93  			assert.NoError(t, err)
    94  			assert.Equal(t, s.res, r)
    95  		} else {
    96  			assert.Error(t, err, fmt.Sprintf("%v should be error case", s.args))
    97  		}
    98  	}
    99  }
   100  
   101  func TestAddonEnableCmdWithErrLocalPath(t *testing.T) {
   102  	testcase := []struct {
   103  		args   []string
   104  		errMsg string
   105  	}{
   106  		{
   107  			args:   []string{"./a_local_path"},
   108  			errMsg: "addon directory ./a_local_path not found in local",
   109  		},
   110  		{
   111  			args:   []string{"a_local_path/"},
   112  			errMsg: "addon directory a_local_path/ not found in local",
   113  		},
   114  	}
   115  
   116  	ioStream := util.IOStreams{}
   117  	commandArgs := common.Args{}
   118  	cmd := NewAddonEnableCommand(commandArgs, ioStream)
   119  	initCommand(cmd)
   120  
   121  	for _, s := range testcase {
   122  		cmd.SetArgs(s.args)
   123  		err := cmd.Execute()
   124  		assert.Error(t, err, s.errMsg)
   125  	}
   126  }
   127  
   128  var _ = Describe("Test AddonRegistry Cmd", func() {
   129  	It("Test AddonRegistryAddCmd", func() {
   130  		testAddonRegistryAddCmd()
   131  	})
   132  })
   133  
   134  func testAddonRegistryAddCmd() {
   135  	testcase := []struct {
   136  		args   []string
   137  		errMsg string
   138  		result *pkgaddon.Registry
   139  	}{
   140  		{
   141  			args:   []string{"noAuthRegistry", "--type=helm", "--endpoint=http://127.0.0.1/chartrepo/oam"},
   142  			errMsg: "fail to add no auth addon registry",
   143  		},
   144  		{
   145  			args:   []string{"basicAuthRegistry", "--type=helm", "--endpoint=http://127.0.0.1/chartrepo/oam", "--username=hello", "--password=word"},
   146  			errMsg: "fail to add basis auth addon registry",
   147  		},
   148  		{
   149  			args: []string{"skipTlsRegistry", "--type=helm", "--endpoint=https://127.0.0.1/chartrepo/oam", "--insecureSkipTLS=true"},
   150  		},
   151  	}
   152  
   153  	ioStream := util.IOStreams{}
   154  	commandArgs := common.Args{}
   155  	commandArgs.SetClient(k8sClient)
   156  
   157  	cmd := NewAddAddonRegistryCommand(commandArgs, ioStream)
   158  
   159  	for _, s := range testcase {
   160  		cmd.SetArgs(s.args)
   161  		err := cmd.Execute()
   162  		Expect(err).To(HaveOccurred())
   163  	}
   164  }
   165  
   166  func TestAddonUpgradeCmdWithErrLocalPath(t *testing.T) {
   167  	testcase := []struct {
   168  		args   []string
   169  		errMsg string
   170  	}{
   171  		{
   172  			args:   []string{"./a_local_path"},
   173  			errMsg: "addon directory ./a_local_path not found in local",
   174  		},
   175  		{
   176  			args:   []string{"a_local_path/"},
   177  			errMsg: "addon directory a_local_path/ not found in local",
   178  		},
   179  	}
   180  
   181  	ioStream := util.IOStreams{}
   182  	commandArgs := common.Args{}
   183  	cmd := NewAddonUpgradeCommand(commandArgs, ioStream)
   184  	initCommand(cmd)
   185  
   186  	for _, s := range testcase {
   187  		cmd.SetArgs(s.args)
   188  		err := cmd.Execute()
   189  		assert.Error(t, err, s.errMsg)
   190  	}
   191  }
   192  
   193  func TestTransCluster(t *testing.T) {
   194  	testcase := []struct {
   195  		str string
   196  		res []interface{}
   197  	}{
   198  		{
   199  			str: "{cluster1, cluster2}",
   200  			res: []interface{}{"cluster1", "cluster2"},
   201  		},
   202  		{
   203  			str: "{cluster1,cluster2}",
   204  			res: []interface{}{"cluster1", "cluster2"},
   205  		},
   206  		{
   207  			str: "{cluster1,  cluster2   }",
   208  			res: []interface{}{"cluster1", "cluster2"},
   209  		},
   210  	}
   211  	for _, s := range testcase {
   212  		assert.Equal(t, transClusters(s.str), s.res)
   213  	}
   214  }
   215  
   216  func TestGenerateAvailableVersions(t *testing.T) {
   217  	type testcase struct {
   218  		inVersion string
   219  		versions  []string
   220  	}
   221  	testcases := []struct {
   222  		c   testcase
   223  		res string
   224  	}{
   225  		{
   226  			c: testcase{
   227  				inVersion: "1.2.1",
   228  				versions:  []string{"1.2.1"},
   229  			},
   230  			res: fmt.Sprintf("[%s]", color.New(color.Bold, color.FgGreen).Sprintf("1.2.1")),
   231  		},
   232  		{
   233  			c: testcase{
   234  				inVersion: "1.2.1",
   235  				versions:  []string{"1.2.3", "1.2.2", "1.2.1"},
   236  			},
   237  			res: fmt.Sprintf("[%s, 1.2.3, 1.2.2]", color.New(color.Bold, color.FgGreen).Sprintf("1.2.1")),
   238  		},
   239  		{
   240  			c: testcase{
   241  				inVersion: "1.2.1",
   242  				versions:  []string{"1.2.3", "1.2.2", "1.2.1", "1.2.0"},
   243  			},
   244  			res: fmt.Sprintf("[%s, 1.2.3, 1.2.2, ...]", color.New(color.Bold, color.FgGreen).Sprintf("1.2.1")),
   245  		},
   246  	}
   247  	for _, s := range testcases {
   248  		re := genAvailableVersionInfo(s.c.versions, s.c.inVersion, 3)
   249  		assert.Equal(t, re, s.res)
   250  	}
   251  }
   252  
   253  func TestLimitStringLength(t *testing.T) {
   254  	type testcase struct {
   255  		testString  string
   256  		lengthLimit int
   257  	}
   258  
   259  	testcases := []struct {
   260  		c   testcase
   261  		res string
   262  	}{
   263  		// len = limit
   264  		{
   265  			c: testcase{
   266  				testString:  "4444",
   267  				lengthLimit: 4,
   268  			},
   269  			res: "4444",
   270  		},
   271  		// len > limit
   272  		{
   273  			c: testcase{
   274  				testString:  "3333",
   275  				lengthLimit: 3,
   276  			},
   277  			res: "333...",
   278  		},
   279  		// len < limit
   280  		{
   281  			c: testcase{
   282  				testString:  "22",
   283  				lengthLimit: 3,
   284  			},
   285  			res: "22",
   286  		},
   287  		// limit = 0
   288  		{
   289  			c: testcase{
   290  				testString:  "000",
   291  				lengthLimit: 0,
   292  			},
   293  			res: "000",
   294  		},
   295  		// limit < 0
   296  		{
   297  			c: testcase{
   298  				testString:  "000",
   299  				lengthLimit: -1,
   300  			},
   301  			res: "000",
   302  		},
   303  	}
   304  
   305  	for _, s := range testcases {
   306  		re := limitStringLength(s.c.testString, s.c.lengthLimit)
   307  		assert.Equal(t, re, s.res)
   308  	}
   309  }
   310  
   311  func TestAddonPackageCmdWithInvalidArgs(t *testing.T) {
   312  	testcase := []struct {
   313  		args []string
   314  		msg  string
   315  	}{
   316  		{
   317  			args: []string{},
   318  			msg:  "must specify addon directory path",
   319  		},
   320  		{
   321  			args: []string{"./a_local_path"},
   322  			msg:  "fail to package",
   323  		},
   324  		{
   325  			args: []string{"a_local_path/"},
   326  			msg:  "fail to package",
   327  		},
   328  	}
   329  
   330  	commandArgs := common.Args{}
   331  	cmd := NewAddonPackageCommand(commandArgs)
   332  
   333  	for _, s := range testcase {
   334  		cmd.SetArgs(s.args)
   335  		err := cmd.Execute()
   336  		assert.ErrorContains(t, err, s.msg)
   337  	}
   338  }
   339  
   340  func TestPackageValidAddon(t *testing.T) {
   341  	commandArgs := common.Args{}
   342  	cmd := NewAddonPackageCommand(commandArgs)
   343  	cmd.SetArgs([]string{"./test-data/addon/sample"})
   344  	err := cmd.Execute()
   345  	assert.NoError(t, err)
   346  	defer func() {
   347  		_ = os.RemoveAll("sample-1.0.1.tgz")
   348  	}()
   349  }
   350  
   351  func TestGenerateParameterString(t *testing.T) {
   352  	testcase := []struct {
   353  		status       pkgaddon.Status
   354  		addonPackage *pkgaddon.WholeAddonPackage
   355  		outputs      []string
   356  	}{
   357  		{
   358  			status: pkgaddon.Status{},
   359  			addonPackage: &pkgaddon.WholeAddonPackage{
   360  				APISchema: nil,
   361  			},
   362  			outputs: []string{""},
   363  		},
   364  		{
   365  			status: pkgaddon.Status{
   366  				Parameters: map[string]interface{}{
   367  					"database": "kubevela",
   368  					"dbType":   "kubeapi",
   369  				},
   370  			},
   371  			addonPackage: &pkgaddon.WholeAddonPackage{
   372  				APISchema: &openapi3.Schema{
   373  					Required: []string{"dbType", "serviceAccountName", "serviceType", "dex"},
   374  					Properties: openapi3.Schemas{
   375  						"database": &openapi3.SchemaRef{
   376  							Value: &openapi3.Schema{
   377  								Description: "Specify the database name, for the kubeapi db type, it represents namespace.",
   378  								Default:     nil,
   379  							},
   380  						},
   381  						"dbURL": &openapi3.SchemaRef{
   382  							Value: &openapi3.Schema{
   383  								Description: "Specify the MongoDB URL. it only enabled where DB type is MongoDB.",
   384  								Default:     "abc.com",
   385  							},
   386  						},
   387  						"dbType": &openapi3.SchemaRef{
   388  							Value: &openapi3.Schema{
   389  								Description: "Specify the database type, current support KubeAPI(default) and MongoDB.",
   390  								Enum:        []interface{}{"kubeapi", "mongodb"},
   391  							},
   392  						},
   393  					},
   394  				},
   395  			},
   396  			outputs: []string{
   397  				// dbType
   398  				color.New(color.FgCyan).Sprintf("-> ") +
   399  					color.New(color.Bold).Sprint("dbType") + ": " +
   400  					"Specify the database type, current support KubeAPI(default) and MongoDB.\n" +
   401  					"\tcurrent value: " + color.New(color.FgGreen).Sprint("\"kubeapi\"\n") +
   402  					"\trequired: " + color.GreenString("✔\n") +
   403  					"\toptions: \"kubeapi\", \"mongodb\"\n",
   404  				// dbURL
   405  				color.New(color.FgCyan).Sprintf("-> ") +
   406  					color.New(color.Bold).Sprint("dbURL") + ": " +
   407  					"Specify the MongoDB URL. it only enabled where DB type is MongoDB.\n" +
   408  					"\tdefault: " + "\"abc.com\"\n",
   409  				// database
   410  				color.New(color.FgCyan).Sprintf("-> ") +
   411  					color.New(color.Bold).Sprint("database") + ": " +
   412  					"Specify the database name, for the kubeapi db type, it represents namespace.\n" +
   413  					"\tcurrent value: " + color.New(color.FgGreen).Sprint("\"kubevela\""),
   414  			},
   415  		},
   416  	}
   417  
   418  	for _, s := range testcase {
   419  		res := generateParameterString(s.status, s.addonPackage)
   420  		for _, o := range s.outputs {
   421  			assert.Contains(t, res, o)
   422  		}
   423  
   424  	}
   425  }
   426  
   427  func TestNewAddonCreateCommand(t *testing.T) {
   428  	cmd := NewAddonInitCommand()
   429  	cmd.SetArgs([]string{})
   430  	err := cmd.Execute()
   431  	assert.ErrorContains(t, err, "required")
   432  
   433  	cmd.SetArgs([]string{"--chart", "a", "--helm-repo", "https://some.com", "--chart-version", "c"})
   434  	err = cmd.Execute()
   435  	assert.ErrorContains(t, err, "required")
   436  
   437  	cmd.SetArgs([]string{"test-addon", "--chart", "a", "--helm-repo", "https://some.com", "--chart-version", "c"})
   438  	err = cmd.Execute()
   439  	assert.NoError(t, err)
   440  	_ = os.RemoveAll("test-addon")
   441  
   442  	cmd.SetArgs([]string{"test-addon"})
   443  	err = cmd.Execute()
   444  	assert.NoError(t, err)
   445  	_ = os.RemoveAll("test-addon")
   446  
   447  }
   448  
   449  func TestCheckSpecifyRegistry(t *testing.T) {
   450  	testCases := []struct {
   451  		name      string
   452  		registry  string
   453  		addonName string
   454  		hasError  bool
   455  	}{
   456  		{
   457  			name:      "fluxcd",
   458  			registry:  "",
   459  			addonName: "fluxcd",
   460  			hasError:  false,
   461  		},
   462  		{
   463  			name:      "kubevela/fluxcd",
   464  			registry:  "kubevela",
   465  			addonName: "fluxcd",
   466  			hasError:  false,
   467  		},
   468  		{
   469  			name:      "test/kubevela/fluxcd",
   470  			registry:  "",
   471  			addonName: "",
   472  			hasError:  true,
   473  		},
   474  	}
   475  	for _, testCase := range testCases {
   476  		r, n, err := splitSpecifyRegistry(testCase.name)
   477  		assert.Equal(t, err != nil, testCase.hasError)
   478  		assert.Equal(t, r, testCase.registry)
   479  		assert.Equal(t, n, testCase.addonName)
   480  	}
   481  }