18215: Adds tests for Create & Update calls.
[arvados.git] / lib / controller / handler_test.go
index 935208fc4e621c7c8040e09a1381e39c949e0232..f854079f97d87376c9d6e3813b10b2872701d0f5 100644 (file)
@@ -88,6 +88,104 @@ func (s *HandlerSuite) TestConfigExport(c *check.C) {
        }
 }
 
+func (s *HandlerSuite) TestVocabularyExport(c *check.C) {
+       voc := `{
+               "strict_tags": false,
+               "tags": {
+                       "IDTAGIMPORTANCE": {
+                               "strict": false,
+                               "labels": [{"label": "Importance"}],
+                               "values": {
+                                       "HIGH": {
+                                               "labels": [{"label": "High"}]
+                                       },
+                                       "LOW": {
+                                               "labels": [{"label": "Low"}]
+                                       }
+                               }
+                       }
+               }
+       }`
+       f, err := os.CreateTemp("", "test-vocabulary-*.json")
+       c.Assert(err, check.IsNil)
+       defer os.Remove(f.Name())
+       _, err = f.WriteString(voc)
+       c.Assert(err, check.IsNil)
+       f.Close()
+       s.cluster.API.VocabularyPath = f.Name()
+       for _, method := range []string{"GET", "OPTIONS"} {
+               c.Log(c.TestName()+" ", method)
+               req := httptest.NewRequest(method, "/arvados/v1/vocabulary", nil)
+               resp := httptest.NewRecorder()
+               s.handler.ServeHTTP(resp, req)
+               c.Log(resp.Body.String())
+               if !c.Check(resp.Code, check.Equals, http.StatusOK) {
+                       continue
+               }
+               c.Check(resp.Header().Get("Access-Control-Allow-Origin"), check.Equals, `*`)
+               c.Check(resp.Header().Get("Access-Control-Allow-Methods"), check.Matches, `.*\bGET\b.*`)
+               c.Check(resp.Header().Get("Access-Control-Allow-Headers"), check.Matches, `.+`)
+               if method == "OPTIONS" {
+                       c.Check(resp.Body.String(), check.HasLen, 0)
+                       continue
+               }
+               var expectedVoc, receivedVoc *arvados.Vocabulary
+               err := json.Unmarshal([]byte(voc), &expectedVoc)
+               c.Check(err, check.IsNil)
+               err = json.Unmarshal(resp.Body.Bytes(), &receivedVoc)
+               c.Check(err, check.IsNil)
+               c.Check(receivedVoc, check.DeepEquals, expectedVoc)
+       }
+}
+
+func (s *HandlerSuite) TestVocabularyFailedCheckStatus(c *check.C) {
+       voc := `{
+               "strict_tags": false,
+               "tags": {
+                       "IDTAGIMPORTANCE": {
+                               "strict": true,
+                               "labels": [{"label": "Importance"}],
+                               "values": {
+                                       "HIGH": {
+                                               "labels": [{"label": "High"}]
+                                       },
+                                       "LOW": {
+                                               "labels": [{"label": "Low"}]
+                                       }
+                               }
+                       }
+               }
+       }`
+       f, err := os.CreateTemp("", "test-vocabulary-*.json")
+       c.Assert(err, check.IsNil)
+       defer os.Remove(f.Name())
+       _, err = f.WriteString(voc)
+       c.Assert(err, check.IsNil)
+       f.Close()
+       s.cluster.API.VocabularyPath = f.Name()
+
+       req := httptest.NewRequest("POST", "/arvados/v1/collections",
+               strings.NewReader(`{
+                       "collection": {
+                               "properties": {
+                                       "IDTAGIMPORTANCE": "Critical"
+                               }
+                       }
+               }`))
+       req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
+       req.Header.Set("Content-type", "application/json")
+
+       resp := httptest.NewRecorder()
+       s.handler.ServeHTTP(resp, req)
+       c.Log(resp.Body.String())
+       c.Assert(resp.Code, check.Equals, http.StatusBadRequest)
+       var jresp httpserver.ErrorResponse
+       err = json.Unmarshal(resp.Body.Bytes(), &jresp)
+       c.Check(err, check.IsNil)
+       c.Assert(len(jresp.Errors), check.Equals, 1)
+       c.Check(jresp.Errors[0], check.Matches, `.*tag value.*is not valid for key.*`)
+}
+
 func (s *HandlerSuite) TestProxyDiscoveryDoc(c *check.C) {
        req := httptest.NewRequest("GET", "/discovery/v1/apis/arvados/v1/rest", nil)
        resp := httptest.NewRecorder()
@@ -164,34 +262,6 @@ func (s *HandlerSuite) TestProxyNotFound(c *check.C) {
        c.Check(jresp["errors"], check.FitsTypeOf, []interface{}{})
 }
 
-func (s *HandlerSuite) TestProxyRedirect(c *check.C) {
-       s.cluster.Login.SSO.Enable = true
-       s.cluster.Login.SSO.ProviderAppID = "test"
-       s.cluster.Login.SSO.ProviderAppSecret = "test"
-       req := httptest.NewRequest("GET", "https://0.0.0.0:1/login?return_to=foo", nil)
-       resp := httptest.NewRecorder()
-       s.handler.ServeHTTP(resp, req)
-       if !c.Check(resp.Code, check.Equals, http.StatusFound) {
-               c.Log(resp.Body.String())
-       }
-       // Old "proxy entire request" code path returns an absolute
-       // URL. New lib/controller/federation code path returns a
-       // relative URL.
-       c.Check(resp.Header().Get("Location"), check.Matches, `(https://0.0.0.0:1)?/auth/joshid\?return_to=%2Cfoo&?`)
-}
-
-func (s *HandlerSuite) TestLogoutSSO(c *check.C) {
-       s.cluster.Login.SSO.Enable = true
-       s.cluster.Login.SSO.ProviderAppID = "test"
-       req := httptest.NewRequest("GET", "https://0.0.0.0:1/logout?return_to=https://example.com/foo", nil)
-       resp := httptest.NewRecorder()
-       s.handler.ServeHTTP(resp, req)
-       if !c.Check(resp.Code, check.Equals, http.StatusFound) {
-               c.Log(resp.Body.String())
-       }
-       c.Check(resp.Header().Get("Location"), check.Equals, "http://localhost:3002/users/sign_out?"+url.Values{"redirect_uri": {"https://example.com/foo"}}.Encode())
-}
-
 func (s *HandlerSuite) TestLogoutGoogle(c *check.C) {
        s.cluster.Login.Google.Enable = true
        s.cluster.Login.Google.ClientID = "test"
@@ -273,7 +343,7 @@ func (s *HandlerSuite) CheckObjectType(c *check.C, url string, token string, ski
        resp := httptest.NewRecorder()
        s.handler.ServeHTTP(resp, req)
        c.Assert(resp.Code, check.Equals, http.StatusOK,
-               check.Commentf("Wasn't able to get data from the controller at %q", url))
+               check.Commentf("Wasn't able to get data from the controller at %q: %q", url, resp.Body.String()))
        err = json.Unmarshal(resp.Body.Bytes(), &proxied)
        c.Check(err, check.Equals, nil)
 
@@ -344,3 +414,19 @@ func (s *HandlerSuite) TestGetObjects(c *check.C) {
                s.CheckObjectType(c, "/arvados/v1/"+url, arvadostest.AdminToken, skippedFields)
        }
 }
+
+func (s *HandlerSuite) TestRedactRailsAPIHostFromErrors(c *check.C) {
+       req := httptest.NewRequest("GET", "https://0.0.0.0:1/arvados/v1/collections/zzzzz-4zz18-abcdefghijklmno", nil)
+       req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
+       resp := httptest.NewRecorder()
+       s.handler.ServeHTTP(resp, req)
+       c.Check(resp.Code, check.Equals, http.StatusNotFound)
+       var jresp struct {
+               Errors []string
+       }
+       c.Log(resp.Body.String())
+       c.Assert(json.NewDecoder(resp.Body).Decode(&jresp), check.IsNil)
+       c.Assert(jresp.Errors, check.HasLen, 1)
+       c.Check(jresp.Errors[0], check.Matches, `.*//railsapi\.internal/arvados/v1/collections/.*: 404 Not Found.*`)
+       c.Check(jresp.Errors[0], check.Not(check.Matches), `(?ms).*127.0.0.1.*`)
+}