zotregistry.dev/zot@v1.4.4-0.20240314164342-eec277e14d20/pkg/cli/client/server_info_cmd_test.go (about) 1 //go:build search 2 // +build search 3 4 package client //nolint:testpackage 5 6 import ( 7 "bytes" 8 "fmt" 9 "net/http" 10 "os" 11 "regexp" 12 "strings" 13 "testing" 14 15 . "github.com/smartystreets/goconvey/convey" 16 17 zerr "zotregistry.dev/zot/errors" 18 "zotregistry.dev/zot/pkg/api" 19 "zotregistry.dev/zot/pkg/api/config" 20 "zotregistry.dev/zot/pkg/api/constants" 21 extconf "zotregistry.dev/zot/pkg/extensions/config" 22 test "zotregistry.dev/zot/pkg/test/common" 23 ) 24 25 func TestServerStatusCommand(t *testing.T) { 26 Convey("ServerStatusCommand", t, func() { 27 port := test.GetFreePort() 28 baseURL := test.GetBaseURL(port) 29 conf := config.New() 30 conf.HTTP.Port = port 31 conf.Storage.GC = false 32 defaultVal := true 33 conf.Extensions = &extconf.ExtensionConfig{ 34 Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}}, 35 } 36 37 ctlr := api.NewController(conf) 38 ctlr.Config.Storage.RootDirectory = t.TempDir() 39 cm := test.NewControllerManager(ctlr) 40 41 cm.StartAndWait(conf.HTTP.Port) 42 defer cm.StopServer() 43 44 configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"status-test","url":"%s","showspinner":false}]}`, 45 baseURL)) 46 defer os.Remove(configPath) 47 48 args := []string{"status", "--config", "status-test"} 49 cmd := NewCliRootCmd() 50 buff := bytes.NewBufferString("") 51 cmd.SetOut(buff) 52 cmd.SetErr(buff) 53 cmd.SetArgs(args) 54 err := cmd.Execute() 55 So(err, ShouldBeNil) 56 space := regexp.MustCompile(`\s+`) 57 str := space.ReplaceAllString(buff.String(), " ") 58 actual := strings.TrimSpace(str) 59 So(actual, ShouldContainSubstring, config.ReleaseTag) 60 So(actual, ShouldContainSubstring, config.BinaryType) 61 62 // JSON 63 args = []string{"status", "--config", "status-test", "--format", "json"} 64 cmd = NewCliRootCmd() 65 buff = bytes.NewBufferString("") 66 cmd.SetOut(buff) 67 cmd.SetErr(buff) 68 cmd.SetArgs(args) 69 err = cmd.Execute() 70 So(err, ShouldBeNil) 71 space = regexp.MustCompile(`\s+`) 72 str = space.ReplaceAllString(buff.String(), " ") 73 actual = strings.TrimSpace(str) 74 So(actual, ShouldContainSubstring, config.ReleaseTag) 75 So(actual, ShouldContainSubstring, config.BinaryType) 76 77 // YAML 78 args = []string{"status", "--config", "status-test", "--format", "yaml"} 79 cmd = NewCliRootCmd() 80 buff = bytes.NewBufferString("") 81 cmd.SetOut(buff) 82 cmd.SetErr(buff) 83 cmd.SetArgs(args) 84 err = cmd.Execute() 85 So(err, ShouldBeNil) 86 space = regexp.MustCompile(`\s+`) 87 str = space.ReplaceAllString(buff.String(), " ") 88 actual = strings.TrimSpace(str) 89 So(actual, ShouldContainSubstring, config.ReleaseTag) 90 So(actual, ShouldContainSubstring, config.BinaryType) 91 92 // bad type 93 args = []string{"status", "--config", "status-test", "--format", "badType"} 94 cmd = NewCliRootCmd() 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 } 103 104 func TestServerStatusCommandErrors(t *testing.T) { 105 Convey("ServerStatusCommand", t, func() { 106 args := []string{"status"} 107 cmd := NewCliRootCmd() 108 buff := bytes.NewBufferString("") 109 cmd.SetOut(buff) 110 cmd.SetErr(buff) 111 cmd.SetArgs(args) 112 err := cmd.Execute() 113 So(err, ShouldNotBeNil) 114 115 // invalid URL 116 err = GetServerStatus(SearchConfig{ 117 ServURL: "a: ds", 118 ResultWriter: os.Stdout, 119 }) 120 So(err, ShouldNotBeNil) 121 122 // fail Get request 123 err = GetServerStatus(SearchConfig{ 124 ServURL: "http://127.0.0.1:8000", 125 ResultWriter: os.Stdout, 126 }) 127 So(err, ShouldBeNil) 128 }) 129 130 Convey("HTTP errors", t, func() { 131 port := test.GetFreePort() 132 result := bytes.NewBuffer([]byte{}) 133 searchConfig := SearchConfig{ 134 SearchService: mockService{}, 135 ServURL: fmt.Sprintf("http://127.0.0.1:%v", port), 136 User: "", 137 OutputFormat: "text", 138 ResultWriter: result, 139 } 140 141 Convey("v2 is Unauthorised", func() { 142 server := StartTestHTTPServer(HTTPRoutes{ 143 RouteHandler{ 144 Route: "/v2/", 145 HandlerFunc: func(w http.ResponseWriter, r *http.Request) { 146 w.WriteHeader(http.StatusUnauthorized) 147 }, 148 AllowedMethods: []string{http.MethodGet}, 149 }, 150 }, port) 151 defer server.Close() 152 153 err := GetServerStatus(searchConfig) 154 So(err, ShouldBeNil) 155 So(result.String(), ShouldContainSubstring, "unauthorised access, endpoint requires valid user credentials") 156 157 // with bad user set 158 searchConfig.User = "test:test" 159 err = GetServerStatus(searchConfig) 160 So(err, ShouldBeNil) 161 So(result.String(), ShouldContainSubstring, "unauthorised access, given credentials are invalid") 162 }) 163 164 Convey("v2 bad http status code", func() { 165 server := StartTestHTTPServer(HTTPRoutes{ 166 RouteHandler{ 167 Route: "/v2/", 168 HandlerFunc: func(w http.ResponseWriter, r *http.Request) { 169 w.WriteHeader(http.StatusInternalServerError) 170 }, 171 AllowedMethods: []string{http.MethodGet}, 172 }, 173 }, port) 174 defer server.Close() 175 176 err := GetServerStatus(searchConfig) 177 So(err, ShouldBeNil) 178 So(result.String(), ShouldContainSubstring, zerr.ErrAPINotSupported.Error()) 179 }) 180 181 Convey("MGMT errors", func() { 182 Convey("URL not found", func() { 183 server := StartTestHTTPServer(HTTPRoutes{ 184 RouteHandler{ 185 Route: "/v2/", 186 HandlerFunc: func(w http.ResponseWriter, r *http.Request) { 187 w.WriteHeader(http.StatusOK) 188 }, 189 AllowedMethods: []string{http.MethodGet}, 190 }, 191 }, port) 192 defer server.Close() 193 194 err := GetServerStatus(searchConfig) 195 So(err, ShouldBeNil) 196 So(result.String(), ShouldContainSubstring, "endpoint is not available") 197 }) 198 199 Convey("Unauthorized Access", func() { 200 server := StartTestHTTPServer(HTTPRoutes{ 201 RouteHandler{ 202 Route: "/v2/", 203 HandlerFunc: func(w http.ResponseWriter, r *http.Request) { 204 w.WriteHeader(http.StatusOK) 205 }, 206 AllowedMethods: []string{http.MethodGet}, 207 }, 208 RouteHandler{ 209 Route: constants.RoutePrefix + constants.ExtMgmt, 210 HandlerFunc: func(w http.ResponseWriter, r *http.Request) { 211 w.WriteHeader(http.StatusUnauthorized) 212 }, 213 AllowedMethods: []string{http.MethodGet}, 214 }, 215 }, port) 216 defer server.Close() 217 218 err := GetServerStatus(searchConfig) 219 So(err, ShouldBeNil) 220 So(result.String(), ShouldContainSubstring, "unauthorised access") 221 }) 222 223 Convey("Bad status code", func() { 224 server := StartTestHTTPServer(HTTPRoutes{ 225 RouteHandler{ 226 Route: "/v2/", 227 HandlerFunc: func(w http.ResponseWriter, r *http.Request) { 228 w.WriteHeader(http.StatusOK) 229 }, 230 AllowedMethods: []string{http.MethodGet}, 231 }, 232 RouteHandler{ 233 Route: constants.RoutePrefix + constants.ExtMgmt, 234 HandlerFunc: func(w http.ResponseWriter, r *http.Request) { 235 w.WriteHeader(http.StatusInternalServerError) 236 }, 237 AllowedMethods: []string{http.MethodGet}, 238 }, 239 }, port) 240 defer server.Close() 241 242 err := GetServerStatus(searchConfig) 243 So(err, ShouldBeNil) 244 So(result.String(), ShouldContainSubstring, zerr.ErrAPINotSupported.Error()) 245 }) 246 }) 247 }) 248 }