zotregistry.dev/zot@v1.4.4-0.20240314164342-eec277e14d20/pkg/cli/client/config_cmd_test.go (about)

     1  //go:build search
     2  // +build search
     3  
     4  package client_test
     5  
     6  import (
     7  	"bytes"
     8  	"log"
     9  	"os"
    10  	"regexp"
    11  	"strings"
    12  	"testing"
    13  
    14  	. "github.com/smartystreets/goconvey/convey"
    15  
    16  	zerr "zotregistry.dev/zot/errors"
    17  	"zotregistry.dev/zot/pkg/cli/client"
    18  )
    19  
    20  func TestConfigCmdBasics(t *testing.T) {
    21  	Convey("Test config help", t, func() {
    22  		args := []string{"--help"}
    23  		configPath := makeConfigFile("showspinner = false")
    24  		defer os.Remove(configPath)
    25  		cmd := client.NewConfigCommand()
    26  		buff := bytes.NewBufferString("")
    27  		cmd.SetOut(buff)
    28  		cmd.SetErr(buff)
    29  		cmd.SetArgs(args)
    30  		err := cmd.Execute()
    31  		So(buff.String(), ShouldContainSubstring, "Usage")
    32  		So(err, ShouldBeNil)
    33  		Convey("with the shorthand", func() {
    34  			args[0] = "-h"
    35  			configPath := makeConfigFile("showspinner = false")
    36  			defer os.Remove(configPath)
    37  			cmd := client.NewConfigCommand()
    38  			buff := bytes.NewBufferString("")
    39  			cmd.SetOut(buff)
    40  			cmd.SetErr(buff)
    41  			cmd.SetArgs(args)
    42  			err := cmd.Execute()
    43  			So(buff.String(), ShouldContainSubstring, "Usage")
    44  			So(err, ShouldBeNil)
    45  		})
    46  	})
    47  
    48  	Convey("Test config no args", t, func() {
    49  		args := []string{}
    50  		configPath := makeConfigFile("showspinner = false")
    51  		defer os.Remove(configPath)
    52  		cmd := client.NewConfigCommand()
    53  		buff := bytes.NewBufferString("")
    54  		cmd.SetOut(buff)
    55  		cmd.SetErr(buff)
    56  		cmd.SetArgs(args)
    57  		err := cmd.Execute()
    58  		So(buff.String(), ShouldContainSubstring, "Usage")
    59  		So(err, ShouldNotBeNil)
    60  	})
    61  }
    62  
    63  func TestConfigCmdMain(t *testing.T) {
    64  	Convey("Test add config", t, func() {
    65  		args := []string{"add", "configtest1", "https://test-url.com"}
    66  		file := makeConfigFile("")
    67  		defer os.Remove(file)
    68  		cmd := client.NewConfigCommand()
    69  		buff := bytes.NewBufferString("")
    70  		cmd.SetOut(buff)
    71  		cmd.SetErr(buff)
    72  		cmd.SetArgs(args)
    73  		_ = cmd.Execute()
    74  
    75  		actual, err := os.ReadFile(file)
    76  		if err != nil {
    77  			panic(err)
    78  		}
    79  		actualStr := string(actual)
    80  		So(actualStr, ShouldContainSubstring, "configtest1")
    81  		So(actualStr, ShouldContainSubstring, "https://test-url.com")
    82  	})
    83  
    84  	Convey("Test error on home directory", t, func() {
    85  		args := []string{"add", "configtest1", "https://test-url.com"}
    86  		file := makeConfigFile("")
    87  		defer os.Remove(file)
    88  
    89  		err := os.Setenv("HOME", "nonExistentDirectory")
    90  		if err != nil {
    91  			panic(err)
    92  		}
    93  
    94  		cmd := client.NewConfigCommand()
    95  		buff := bytes.NewBufferString("")
    96  		cmd.SetOut(buff)
    97  		cmd.SetErr(buff)
    98  		cmd.SetArgs(args)
    99  		err = cmd.Execute()
   100  		So(err, ShouldNotBeNil)
   101  
   102  		home, err := os.UserHomeDir()
   103  		if err != nil {
   104  			panic(err)
   105  		}
   106  		err = os.Setenv("HOME", home)
   107  		if err != nil {
   108  			log.Fatal(err)
   109  		}
   110  	})
   111  
   112  	Convey("Test error on home directory at new add config", t, func() {
   113  		args := []string{"add", "configtest1", "https://test-url.com"}
   114  		file := makeConfigFile("")
   115  		defer os.Remove(file)
   116  
   117  		err := os.Setenv("HOME", "nonExistentDirectory")
   118  		if err != nil {
   119  			panic(err)
   120  		}
   121  
   122  		cmd := client.NewConfigAddCommand()
   123  		buff := bytes.NewBufferString("")
   124  		cmd.SetOut(buff)
   125  		cmd.SetErr(buff)
   126  		cmd.SetArgs(args)
   127  		err = cmd.Execute()
   128  		So(err, ShouldNotBeNil)
   129  
   130  		home, err := os.UserHomeDir()
   131  		if err != nil {
   132  			panic(err)
   133  		}
   134  		err = os.Setenv("HOME", home)
   135  		if err != nil {
   136  			log.Fatal(err)
   137  		}
   138  	})
   139  
   140  	Convey("Test add config with invalid format", t, func() {
   141  		args := []string{"--list"}
   142  		configPath := makeConfigFile(`{"configs":{"_name":"configtest","url":"https://test-url.com","showspinner":false}}`)
   143  		defer os.Remove(configPath)
   144  		cmd := client.NewConfigCommand()
   145  		buff := bytes.NewBufferString("")
   146  		cmd.SetOut(buff)
   147  		cmd.SetErr(buff)
   148  		cmd.SetArgs(args)
   149  		err := cmd.Execute()
   150  		So(err, ShouldEqual, zerr.ErrCliBadConfig)
   151  	})
   152  
   153  	Convey("Test add config with invalid URL", t, func() {
   154  		args := []string{"add", "configtest1", "test..com"}
   155  		file := makeConfigFile("")
   156  		defer os.Remove(file)
   157  		cmd := client.NewConfigCommand()
   158  		buff := bytes.NewBufferString("")
   159  		cmd.SetOut(buff)
   160  		cmd.SetErr(buff)
   161  		cmd.SetArgs(args)
   162  		err := cmd.Execute()
   163  		So(err, ShouldNotBeNil)
   164  		So(strings.Contains(err.Error(), zerr.ErrInvalidURL.Error()), ShouldBeTrue)
   165  	})
   166  
   167  	Convey("Test remove config entry successfully", t, func() {
   168  		args := []string{"remove", "configtest"}
   169  		configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
   170  		defer os.Remove(configPath)
   171  		cmd := client.NewConfigCommand()
   172  		buff := bytes.NewBufferString("")
   173  		cmd.SetOut(buff)
   174  		cmd.SetErr(buff)
   175  		cmd.SetArgs(args)
   176  		err := cmd.Execute()
   177  		So(err, ShouldBeNil)
   178  		actual, err := os.ReadFile(configPath)
   179  		So(err, ShouldBeNil)
   180  		space := regexp.MustCompile(`\s+`)
   181  		actualString := space.ReplaceAllString(string(actual), " ")
   182  		So(actualString, ShouldEqual, `{ "configs": [] }`)
   183  	})
   184  
   185  	Convey("Test remove missing config entry", t, func() {
   186  		args := []string{"remove", "configtest"}
   187  		configPath := makeConfigFile(`{"configs":[]`)
   188  		defer os.Remove(configPath)
   189  		cmd := client.NewConfigCommand()
   190  		buff := bytes.NewBufferString("")
   191  		cmd.SetOut(buff)
   192  		cmd.SetErr(buff)
   193  		cmd.SetArgs(args)
   194  		err := cmd.Execute()
   195  		So(err, ShouldNotBeNil)
   196  		So(buff.String(), ShouldContainSubstring, "does not exist")
   197  	})
   198  
   199  	Convey("Test remove bad config file content", t, func() {
   200  		args := []string{"remove", "configtest"}
   201  		configPath := makeConfigFile(`{"asdf":[]`)
   202  		defer os.Remove(configPath)
   203  		cmd := client.NewConfigCommand()
   204  		buff := bytes.NewBufferString("")
   205  		cmd.SetOut(buff)
   206  		cmd.SetErr(buff)
   207  		cmd.SetArgs(args)
   208  		err := cmd.Execute()
   209  		So(err, ShouldNotBeNil)
   210  		So(buff.String(), ShouldContainSubstring, "config json is empty")
   211  	})
   212  
   213  	Convey("Test remove bad config file entry", t, func() {
   214  		args := []string{"remove", "configtest"}
   215  		configPath := makeConfigFile(`{"configs":[asdad]`)
   216  		defer os.Remove(configPath)
   217  		cmd := client.NewConfigCommand()
   218  		buff := bytes.NewBufferString("")
   219  		cmd.SetOut(buff)
   220  		cmd.SetErr(buff)
   221  		cmd.SetArgs(args)
   222  		err := cmd.Execute()
   223  		So(err, ShouldNotBeNil)
   224  		So(buff.String(), ShouldContainSubstring, "invalid server config")
   225  	})
   226  
   227  	Convey("Test remove config bad permissions", t, func() {
   228  		args := []string{"remove", "configtest"}
   229  		configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
   230  		defer func() {
   231  			_ = os.Chmod(configPath, 0o600)
   232  			os.Remove(configPath)
   233  		}()
   234  		err := os.Chmod(configPath, 0o400) // Read-only, so we fail only on updating the file, not reading
   235  		So(err, ShouldBeNil)
   236  		cmd := client.NewConfigCommand()
   237  		buff := bytes.NewBufferString("")
   238  		cmd.SetOut(buff)
   239  		cmd.SetErr(buff)
   240  		cmd.SetArgs(args)
   241  		err = cmd.Execute()
   242  		So(err, ShouldNotBeNil)
   243  		So(buff.String(), ShouldContainSubstring, "permission denied")
   244  	})
   245  
   246  	Convey("Test fetch all config", t, func() {
   247  		args := []string{"--list"}
   248  		configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
   249  		defer os.Remove(configPath)
   250  		cmd := client.NewConfigCommand()
   251  		buff := bytes.NewBufferString("")
   252  		cmd.SetOut(buff)
   253  		cmd.SetErr(buff)
   254  		cmd.SetArgs(args)
   255  		err := cmd.Execute()
   256  		So(buff.String(), ShouldContainSubstring, "https://test-url.com")
   257  		So(err, ShouldBeNil)
   258  
   259  		Convey("with the shorthand", func() {
   260  			args := []string{"-l"}
   261  			configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
   262  			defer os.Remove(configPath)
   263  			cmd := client.NewConfigCommand()
   264  			buff := bytes.NewBufferString("")
   265  			cmd.SetOut(buff)
   266  			cmd.SetErr(buff)
   267  			cmd.SetArgs(args)
   268  			err := cmd.Execute()
   269  			So(buff.String(), ShouldContainSubstring, "https://test-url.com")
   270  			So(err, ShouldBeNil)
   271  		})
   272  
   273  		Convey("From empty file", func() {
   274  			args := []string{"-l"}
   275  			configPath := makeConfigFile(``)
   276  			defer os.Remove(configPath)
   277  			cmd := client.NewConfigCommand()
   278  			buff := bytes.NewBufferString("")
   279  			cmd.SetOut(buff)
   280  			cmd.SetErr(buff)
   281  			cmd.SetArgs(args)
   282  			err := cmd.Execute()
   283  			So(err, ShouldBeNil)
   284  			So(strings.TrimSpace(buff.String()), ShouldEqual, "")
   285  		})
   286  	})
   287  
   288  	Convey("Test fetch a config", t, func() {
   289  		args := []string{"configtest", "--list"}
   290  		configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
   291  		defer os.Remove(configPath)
   292  		cmd := client.NewConfigCommand()
   293  		buff := bytes.NewBufferString("")
   294  		cmd.SetOut(buff)
   295  		cmd.SetErr(buff)
   296  		cmd.SetArgs(args)
   297  		err := cmd.Execute()
   298  		So(buff.String(), ShouldContainSubstring, "url = https://test-url.com")
   299  		So(buff.String(), ShouldContainSubstring, "showspinner = false")
   300  		So(err, ShouldBeNil)
   301  
   302  		Convey("with the shorthand", func() {
   303  			args := []string{"configtest", "-l"}
   304  			configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
   305  			defer os.Remove(configPath)
   306  			cmd := client.NewConfigCommand()
   307  			buff := bytes.NewBufferString("")
   308  			cmd.SetOut(buff)
   309  			cmd.SetErr(buff)
   310  			cmd.SetArgs(args)
   311  			err := cmd.Execute()
   312  			So(buff.String(), ShouldContainSubstring, "url = https://test-url.com")
   313  			So(buff.String(), ShouldContainSubstring, "showspinner = false")
   314  			So(err, ShouldBeNil)
   315  		})
   316  
   317  		Convey("From empty file", func() {
   318  			args := []string{"configtest", "-l"}
   319  			configPath := makeConfigFile(``)
   320  			defer os.Remove(configPath)
   321  			cmd := client.NewConfigCommand()
   322  			buff := bytes.NewBufferString("")
   323  			cmd.SetOut(buff)
   324  			cmd.SetErr(buff)
   325  			cmd.SetArgs(args)
   326  			err := cmd.Execute()
   327  			So(err, ShouldBeNil)
   328  			So(strings.TrimSpace(buff.String()), ShouldEqual, "")
   329  		})
   330  	})
   331  
   332  	Convey("Test fetch a config val", t, func() {
   333  		args := []string{"configtest", "url"}
   334  		configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
   335  		defer os.Remove(configPath)
   336  		cmd := client.NewConfigCommand()
   337  		buff := bytes.NewBufferString("")
   338  		cmd.SetOut(buff)
   339  		cmd.SetErr(buff)
   340  		cmd.SetArgs(args)
   341  		err := cmd.Execute()
   342  		So(buff.String(), ShouldEqual, "https://test-url.com\n")
   343  		So(err, ShouldBeNil)
   344  
   345  		Convey("From empty file", func() {
   346  			args := []string{"configtest", "url"}
   347  			configPath := makeConfigFile(``)
   348  			defer os.Remove(configPath)
   349  			cmd := client.NewConfigCommand()
   350  			buff := bytes.NewBufferString("")
   351  			cmd.SetOut(buff)
   352  			cmd.SetErr(buff)
   353  			cmd.SetArgs(args)
   354  			err := cmd.Execute()
   355  			So(err, ShouldNotBeNil)
   356  			So(buff.String(), ShouldContainSubstring, "does not exist")
   357  		})
   358  	})
   359  
   360  	Convey("Test add a config val", t, func() {
   361  		args := []string{"configtest", "showspinner", "false"}
   362  		configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com"}]}`)
   363  		defer os.Remove(configPath)
   364  		cmd := client.NewConfigCommand()
   365  		buff := bytes.NewBufferString("")
   366  		cmd.SetOut(buff)
   367  		cmd.SetErr(buff)
   368  		cmd.SetArgs(args)
   369  		err := cmd.Execute()
   370  		So(err, ShouldBeNil)
   371  
   372  		actual, err := os.ReadFile(configPath)
   373  		if err != nil {
   374  			panic(err)
   375  		}
   376  		actualStr := string(actual)
   377  		So(actualStr, ShouldContainSubstring, "https://test-url.com")
   378  		So(actualStr, ShouldContainSubstring, `"showspinner": false`)
   379  		So(buff.String(), ShouldEqual, "")
   380  
   381  		Convey("To an empty file", func() {
   382  			args := []string{"configtest", "showspinner", "false"}
   383  			configPath := makeConfigFile(``)
   384  			defer os.Remove(configPath)
   385  			cmd := client.NewConfigCommand()
   386  			buff := bytes.NewBufferString("")
   387  			cmd.SetOut(buff)
   388  			cmd.SetErr(buff)
   389  			cmd.SetArgs(args)
   390  			err := cmd.Execute()
   391  			So(err, ShouldNotBeNil)
   392  			So(buff.String(), ShouldContainSubstring, "does not exist")
   393  		})
   394  	})
   395  
   396  	Convey("Test overwrite a config", t, func() {
   397  		args := []string{"configtest", "url", "https://new-url.com"}
   398  		configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
   399  		defer os.Remove(configPath)
   400  		cmd := client.NewConfigCommand()
   401  		buff := bytes.NewBufferString("")
   402  		cmd.SetOut(buff)
   403  		cmd.SetErr(buff)
   404  		cmd.SetArgs(args)
   405  		err := cmd.Execute()
   406  		So(err, ShouldBeNil)
   407  
   408  		actual, err := os.ReadFile(configPath)
   409  		if err != nil {
   410  			panic(err)
   411  		}
   412  		actualStr := string(actual)
   413  		So(actualStr, ShouldContainSubstring, `https://new-url.com`)
   414  		So(actualStr, ShouldContainSubstring, `"showspinner": false`)
   415  		So(actualStr, ShouldNotContainSubstring, `https://test-url.com`)
   416  		So(buff.String(), ShouldEqual, "")
   417  	})
   418  
   419  	Convey("Test reset a config val", t, func() {
   420  		args := []string{"configtest", "showspinner", "--reset"}
   421  		configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
   422  		defer os.Remove(configPath)
   423  		cmd := client.NewConfigCommand()
   424  		buff := bytes.NewBufferString("")
   425  		cmd.SetOut(buff)
   426  		cmd.SetErr(buff)
   427  		cmd.SetArgs(args)
   428  		err := cmd.Execute()
   429  		So(err, ShouldBeNil)
   430  
   431  		actual, err := os.ReadFile(configPath)
   432  		if err != nil {
   433  			panic(err)
   434  		}
   435  		actualStr := string(actual)
   436  		So(actualStr, ShouldNotContainSubstring, "showspinner")
   437  		So(actualStr, ShouldContainSubstring, `"url": "https://test-url.com"`)
   438  		So(buff.String(), ShouldEqual, "")
   439  	})
   440  
   441  	Convey("Test reset a url", t, func() {
   442  		args := []string{"configtest", "url", "--reset"}
   443  		configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
   444  		defer os.Remove(configPath)
   445  		cmd := client.NewConfigCommand()
   446  		buff := bytes.NewBufferString("")
   447  		cmd.SetOut(buff)
   448  		cmd.SetErr(buff)
   449  		cmd.SetArgs(args)
   450  		err := cmd.Execute()
   451  		So(err, ShouldNotBeNil)
   452  		So(buff.String(), ShouldContainSubstring, "cannot reset")
   453  	})
   454  
   455  	Convey("Test add a config with an existing saved name", t, func() {
   456  		args := []string{"add", "configtest", "https://test-url.com/new"}
   457  		configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
   458  		defer os.Remove(configPath)
   459  		cmd := client.NewConfigCommand()
   460  		buff := bytes.NewBufferString("")
   461  		cmd.SetOut(buff)
   462  		cmd.SetErr(buff)
   463  		cmd.SetArgs(args)
   464  		err := cmd.Execute()
   465  		So(err, ShouldNotBeNil)
   466  		So(buff.String(), ShouldContainSubstring, "cli config name already added")
   467  	})
   468  }