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 }