1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
19 "git.curoverse.com/arvados.git/sdk/go/arvados"
20 "git.curoverse.com/arvados.git/sdk/go/arvadostest"
21 "git.curoverse.com/arvados.git/sdk/go/httpserver"
22 "git.curoverse.com/arvados.git/sdk/go/keepclient"
23 "github.com/Sirupsen/logrus"
24 check "gopkg.in/check.v1"
27 // Gocheck boilerplate
28 var _ = check.Suite(&FederationSuite{})
30 type FederationSuite struct {
32 // testServer and testHandler are the controller being tested,
34 testServer *httpserver.Server
36 // remoteServer ("zzzzz") forwards requests to the Rails API
37 // provided by the integration test environment.
38 remoteServer *httpserver.Server
39 // remoteMock ("zmock") appends each incoming request to
40 // remoteMockRequests, and returns an empty 200 response.
41 remoteMock *httpserver.Server
42 remoteMockRequests []http.Request
45 func (s *FederationSuite) SetUpTest(c *check.C) {
47 s.log.Formatter = &logrus.JSONFormatter{}
48 s.log.Out = &logWriter{c.Log}
50 s.remoteServer = newServerFromIntegrationTestEnv(c)
51 c.Assert(s.remoteServer.Start(), check.IsNil)
53 s.remoteMock = newServerFromIntegrationTestEnv(c)
54 s.remoteMock.Server.Handler = http.HandlerFunc(s.remoteMockHandler)
55 c.Assert(s.remoteMock.Start(), check.IsNil)
57 nodeProfile := arvados.NodeProfile{
58 Controller: arvados.SystemServiceInstance{Listen: ":"},
59 RailsAPI: arvados.SystemServiceInstance{Listen: ":1"}, // local reqs will error "connection refused"
61 s.testHandler = &Handler{Cluster: &arvados.Cluster{
63 PostgreSQL: integrationTestCluster().PostgreSQL,
64 NodeProfiles: map[string]arvados.NodeProfile{
67 }, NodeProfile: &nodeProfile}
68 s.testServer = newServerFromIntegrationTestEnv(c)
69 s.testServer.Server.Handler = httpserver.AddRequestIDs(httpserver.LogRequests(s.log, s.testHandler))
71 s.testHandler.Cluster.RemoteClusters = map[string]arvados.RemoteCluster{
73 Host: s.remoteServer.Addr,
78 Host: s.remoteMock.Addr,
84 c.Assert(s.testServer.Start(), check.IsNil)
86 s.remoteMockRequests = nil
89 func (s *FederationSuite) remoteMockHandler(w http.ResponseWriter, req *http.Request) {
90 s.remoteMockRequests = append(s.remoteMockRequests, *req)
93 func (s *FederationSuite) TearDownTest(c *check.C) {
94 if s.remoteServer != nil {
95 s.remoteServer.Close()
97 if s.testServer != nil {
102 func (s *FederationSuite) testRequest(req *http.Request) *http.Response {
103 resp := httptest.NewRecorder()
104 s.testServer.Server.Handler.ServeHTTP(resp, req)
108 func (s *FederationSuite) TestLocalRequest(c *check.C) {
109 req := httptest.NewRequest("GET", "/arvados/v1/workflows/"+strings.Replace(arvadostest.WorkflowWithDefinitionYAMLUUID, "zzzzz-", "zhome-", 1), nil)
110 resp := s.testRequest(req)
111 s.checkHandledLocally(c, resp)
114 func (s *FederationSuite) checkHandledLocally(c *check.C, resp *http.Response) {
115 // Our "home" controller can't handle local requests because
116 // it doesn't have its own stub/test Rails API, so we rely on
117 // "connection refused" to indicate the controller tried to
118 // proxy the request to its local Rails API.
119 c.Check(resp.StatusCode, check.Equals, http.StatusBadGateway)
120 s.checkJSONErrorMatches(c, resp, `.*connection refused`)
123 func (s *FederationSuite) TestNoAuth(c *check.C) {
124 req := httptest.NewRequest("GET", "/arvados/v1/workflows/"+arvadostest.WorkflowWithDefinitionYAMLUUID, nil)
125 resp := s.testRequest(req)
126 c.Check(resp.StatusCode, check.Equals, http.StatusUnauthorized)
127 s.checkJSONErrorMatches(c, resp, `Not logged in`)
130 func (s *FederationSuite) TestBadAuth(c *check.C) {
131 req := httptest.NewRequest("GET", "/arvados/v1/workflows/"+arvadostest.WorkflowWithDefinitionYAMLUUID, nil)
132 req.Header.Set("Authorization", "Bearer aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
133 resp := s.testRequest(req)
134 c.Check(resp.StatusCode, check.Equals, http.StatusUnauthorized)
135 s.checkJSONErrorMatches(c, resp, `Not logged in`)
138 func (s *FederationSuite) TestNoAccess(c *check.C) {
139 req := httptest.NewRequest("GET", "/arvados/v1/workflows/"+arvadostest.WorkflowWithDefinitionYAMLUUID, nil)
140 req.Header.Set("Authorization", "Bearer "+arvadostest.SpectatorToken)
141 resp := s.testRequest(req)
142 c.Check(resp.StatusCode, check.Equals, http.StatusNotFound)
143 s.checkJSONErrorMatches(c, resp, `.*not found`)
146 func (s *FederationSuite) TestGetUnknownRemote(c *check.C) {
147 req := httptest.NewRequest("GET", "/arvados/v1/workflows/"+strings.Replace(arvadostest.WorkflowWithDefinitionYAMLUUID, "zzzzz-", "zz404-", 1), nil)
148 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
149 resp := s.testRequest(req)
150 c.Check(resp.StatusCode, check.Equals, http.StatusNotFound)
151 s.checkJSONErrorMatches(c, resp, `.*no proxy available for cluster zz404`)
154 func (s *FederationSuite) TestRemoteError(c *check.C) {
155 rc := s.testHandler.Cluster.RemoteClusters["zzzzz"]
157 s.testHandler.Cluster.RemoteClusters["zzzzz"] = rc
159 req := httptest.NewRequest("GET", "/arvados/v1/workflows/"+arvadostest.WorkflowWithDefinitionYAMLUUID, nil)
160 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
161 resp := s.testRequest(req)
162 c.Check(resp.StatusCode, check.Equals, http.StatusBadGateway)
163 s.checkJSONErrorMatches(c, resp, `.*HTTP response to HTTPS client`)
166 func (s *FederationSuite) TestGetRemoteWorkflow(c *check.C) {
167 req := httptest.NewRequest("GET", "/arvados/v1/workflows/"+arvadostest.WorkflowWithDefinitionYAMLUUID, nil)
168 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
169 resp := s.testRequest(req)
170 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
171 var wf arvados.Workflow
172 c.Check(json.NewDecoder(resp.Body).Decode(&wf), check.IsNil)
173 c.Check(wf.UUID, check.Equals, arvadostest.WorkflowWithDefinitionYAMLUUID)
174 c.Check(wf.OwnerUUID, check.Equals, arvadostest.ActiveUserUUID)
177 func (s *FederationSuite) TestOptionsMethod(c *check.C) {
178 req := httptest.NewRequest("OPTIONS", "/arvados/v1/workflows/"+arvadostest.WorkflowWithDefinitionYAMLUUID, nil)
179 req.Header.Set("Origin", "https://example.com")
180 resp := s.testRequest(req)
181 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
182 body, err := ioutil.ReadAll(resp.Body)
183 c.Check(err, check.IsNil)
184 c.Check(string(body), check.Equals, "")
185 c.Check(resp.Header.Get("Access-Control-Allow-Origin"), check.Equals, "*")
186 for _, hdr := range []string{"Authorization", "Content-Type"} {
187 c.Check(resp.Header.Get("Access-Control-Allow-Headers"), check.Matches, ".*"+hdr+".*")
189 for _, method := range []string{"GET", "HEAD", "PUT", "POST", "DELETE"} {
190 c.Check(resp.Header.Get("Access-Control-Allow-Methods"), check.Matches, ".*"+method+".*")
194 func (s *FederationSuite) TestRemoteWithTokenInQuery(c *check.C) {
195 req := httptest.NewRequest("GET", "/arvados/v1/workflows/"+strings.Replace(arvadostest.WorkflowWithDefinitionYAMLUUID, "zzzzz-", "zmock-", 1)+"?api_token="+arvadostest.ActiveToken, nil)
197 c.Assert(len(s.remoteMockRequests), check.Equals, 1)
198 pr := s.remoteMockRequests[0]
199 // Token is salted and moved from query to Authorization header.
200 c.Check(pr.URL.String(), check.Not(check.Matches), `.*api_token=.*`)
201 c.Check(pr.Header.Get("Authorization"), check.Equals, "Bearer v2/zzzzz-gj3su-077z32aux8dg2s1/7fd31b61f39c0e82a4155592163218272cedacdc")
204 func (s *FederationSuite) TestLocalTokenSalted(c *check.C) {
205 req := httptest.NewRequest("GET", "/arvados/v1/workflows/"+strings.Replace(arvadostest.WorkflowWithDefinitionYAMLUUID, "zzzzz-", "zmock-", 1), nil)
206 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
208 c.Assert(len(s.remoteMockRequests), check.Equals, 1)
209 pr := s.remoteMockRequests[0]
210 // The salted token here has a "zzzzz-" UUID instead of a
211 // "ztest-" UUID because ztest's local database has the
212 // "zzzzz-" test fixtures. The "secret" part is HMAC(sha1,
213 // arvadostest.ActiveToken, "zmock") = "7fd3...".
214 c.Check(pr.Header.Get("Authorization"), check.Equals, "Bearer v2/zzzzz-gj3su-077z32aux8dg2s1/7fd31b61f39c0e82a4155592163218272cedacdc")
217 func (s *FederationSuite) TestRemoteTokenNotSalted(c *check.C) {
218 // remoteToken can be any v1 token that doesn't appear in
220 remoteToken := "abcdef00000000000000000000000000000000000000000000"
221 req := httptest.NewRequest("GET", "/arvados/v1/workflows/"+strings.Replace(arvadostest.WorkflowWithDefinitionYAMLUUID, "zzzzz-", "zmock-", 1), nil)
222 req.Header.Set("Authorization", "Bearer "+remoteToken)
224 c.Assert(len(s.remoteMockRequests), check.Equals, 1)
225 pr := s.remoteMockRequests[0]
226 c.Check(pr.Header.Get("Authorization"), check.Equals, "Bearer "+remoteToken)
229 func (s *FederationSuite) TestWorkflowCRUD(c *check.C) {
230 wf := arvados.Workflow{
231 Description: "TestCRUD",
234 body := &strings.Builder{}
235 json.NewEncoder(body).Encode(&wf)
236 req := httptest.NewRequest("POST", "/arvados/v1/workflows", strings.NewReader(url.Values{
237 "workflow": {body.String()},
239 req.Header.Set("Content-type", "application/x-www-form-urlencoded")
240 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
241 rec := httptest.NewRecorder()
242 s.remoteServer.Server.Handler.ServeHTTP(rec, req) // direct to remote -- can't proxy a create req because no uuid
244 s.checkResponseOK(c, resp)
245 json.NewDecoder(resp.Body).Decode(&wf)
248 req := httptest.NewRequest("DELETE", "/arvados/v1/workflows/"+wf.UUID, nil)
249 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
250 s.remoteServer.Server.Handler.ServeHTTP(httptest.NewRecorder(), req)
252 c.Check(wf.UUID, check.Not(check.Equals), "")
254 c.Assert(wf.ModifiedAt, check.NotNil)
255 c.Logf("wf.ModifiedAt: %v", wf.ModifiedAt)
256 c.Check(time.Since(*wf.ModifiedAt) < time.Minute, check.Equals, true)
258 for _, method := range []string{"PATCH", "PUT", "POST"} {
260 "workflow": {`{"description": "Updated with ` + method + `"}`},
262 if method == "POST" {
263 form["_method"] = []string{"PATCH"}
265 req := httptest.NewRequest(method, "/arvados/v1/workflows/"+wf.UUID, strings.NewReader(form.Encode()))
266 req.Header.Set("Content-type", "application/x-www-form-urlencoded")
267 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
268 resp := s.testRequest(req)
269 s.checkResponseOK(c, resp)
270 err := json.NewDecoder(resp.Body).Decode(&wf)
271 c.Check(err, check.IsNil)
273 c.Check(wf.Description, check.Equals, "Updated with "+method)
276 req := httptest.NewRequest("DELETE", "/arvados/v1/workflows/"+wf.UUID, nil)
277 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
278 resp := s.testRequest(req)
279 s.checkResponseOK(c, resp)
280 err := json.NewDecoder(resp.Body).Decode(&wf)
281 c.Check(err, check.IsNil)
284 req := httptest.NewRequest("GET", "/arvados/v1/workflows/"+wf.UUID, nil)
285 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
286 resp := s.testRequest(req)
287 c.Check(resp.StatusCode, check.Equals, http.StatusNotFound)
291 func (s *FederationSuite) checkResponseOK(c *check.C, resp *http.Response) {
292 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
293 if resp.StatusCode != http.StatusOK {
294 body, err := ioutil.ReadAll(resp.Body)
295 c.Logf("... response body = %q, %v\n", body, err)
299 func (s *FederationSuite) checkJSONErrorMatches(c *check.C, resp *http.Response, re string) {
300 var jresp httpserver.ErrorResponse
301 err := json.NewDecoder(resp.Body).Decode(&jresp)
302 c.Check(err, check.IsNil)
303 c.Assert(len(jresp.Errors), check.Equals, 1)
304 c.Check(jresp.Errors[0], check.Matches, re)
307 func (s *FederationSuite) localServiceReturns404(c *check.C) *httpserver.Server {
308 srv := &httpserver.Server{
310 Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
316 c.Assert(srv.Start(), check.IsNil)
318 np := arvados.NodeProfile{
319 Controller: arvados.SystemServiceInstance{Listen: ":"},
320 RailsAPI: arvados.SystemServiceInstance{Listen: srv.Addr,
321 TLS: false, Insecure: true}}
322 s.testHandler.Cluster.NodeProfiles["*"] = np
323 s.testHandler.NodeProfile = &np
328 func (s *FederationSuite) TestGetLocalCollection(c *check.C) {
329 np := arvados.NodeProfile{
330 Controller: arvados.SystemServiceInstance{Listen: ":"},
331 RailsAPI: arvados.SystemServiceInstance{Listen: os.Getenv("ARVADOS_TEST_API_HOST"),
332 TLS: true, Insecure: true}}
333 s.testHandler.Cluster.ClusterID = "zzzzz"
334 s.testHandler.Cluster.NodeProfiles["*"] = np
335 s.testHandler.NodeProfile = &np
337 req := httptest.NewRequest("GET", "/arvados/v1/collections/"+arvadostest.UserAgreementCollection, nil)
338 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
339 resp := s.testRequest(req)
341 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
342 var col arvados.Collection
343 c.Check(json.NewDecoder(resp.Body).Decode(&col), check.IsNil)
344 c.Check(col.UUID, check.Equals, arvadostest.UserAgreementCollection)
345 c.Check(col.ManifestText, check.Matches,
346 `\. 6a4ff0499484c6c79c95cd8c566bd25f\+249025\+A[0-9a-f]{40}@[0-9a-f]{8} 0:249025:GNU_General_Public_License,_version_3.pdf
350 func (s *FederationSuite) TestGetRemoteCollection(c *check.C) {
351 defer s.localServiceReturns404(c).Close()
353 req := httptest.NewRequest("GET", "/arvados/v1/collections/"+arvadostest.UserAgreementCollection, nil)
354 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
355 resp := s.testRequest(req)
356 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
357 var col arvados.Collection
358 c.Check(json.NewDecoder(resp.Body).Decode(&col), check.IsNil)
359 c.Check(col.UUID, check.Equals, arvadostest.UserAgreementCollection)
360 c.Check(col.ManifestText, check.Matches,
361 `\. 6a4ff0499484c6c79c95cd8c566bd25f\+249025\+Rzzzzz-[0-9a-f]{40}@[0-9a-f]{8} 0:249025:GNU_General_Public_License,_version_3.pdf
365 func (s *FederationSuite) TestGetRemoteCollectionError(c *check.C) {
366 defer s.localServiceReturns404(c).Close()
368 req := httptest.NewRequest("GET", "/arvados/v1/collections/zzzzz-4zz18-fakefakefakefak", nil)
369 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
370 resp := s.testRequest(req)
371 c.Check(resp.StatusCode, check.Equals, http.StatusNotFound)
374 func (s *FederationSuite) TestSignedLocatorPattern(c *check.C) {
375 // Confirm the regular expression identifies other groups of hints correctly
376 c.Check(keepclient.SignedLocatorRe.FindStringSubmatch(`6a4ff0499484c6c79c95cd8c566bd25f+249025+B1+C2+A05227438989d04712ea9ca1c91b556cef01d5cc7@5ba5405b+D3+E4`),
378 []string{"6a4ff0499484c6c79c95cd8c566bd25f+249025+B1+C2+A05227438989d04712ea9ca1c91b556cef01d5cc7@5ba5405b+D3+E4",
379 "6a4ff0499484c6c79c95cd8c566bd25f",
382 "+A05227438989d04712ea9ca1c91b556cef01d5cc7@5ba5405b",
383 "05227438989d04712ea9ca1c91b556cef01d5cc7", "5ba5405b",
387 func (s *FederationSuite) TestGetLocalCollectionByPDH(c *check.C) {
388 np := arvados.NodeProfile{
389 Controller: arvados.SystemServiceInstance{Listen: ":"},
390 RailsAPI: arvados.SystemServiceInstance{Listen: os.Getenv("ARVADOS_TEST_API_HOST"),
391 TLS: true, Insecure: true}}
392 s.testHandler.Cluster.NodeProfiles["*"] = np
393 s.testHandler.NodeProfile = &np
395 req := httptest.NewRequest("GET", "/arvados/v1/collections/"+arvadostest.UserAgreementPDH, nil)
396 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
397 resp := s.testRequest(req)
399 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
400 var col arvados.Collection
401 c.Check(json.NewDecoder(resp.Body).Decode(&col), check.IsNil)
402 c.Check(col.PortableDataHash, check.Equals, arvadostest.UserAgreementPDH)
403 c.Check(col.ManifestText, check.Matches,
404 `\. 6a4ff0499484c6c79c95cd8c566bd25f\+249025\+A[0-9a-f]{40}@[0-9a-f]{8} 0:249025:GNU_General_Public_License,_version_3.pdf
408 func (s *FederationSuite) TestGetRemoteCollectionByPDH(c *check.C) {
409 defer s.localServiceReturns404(c).Close()
411 req := httptest.NewRequest("GET", "/arvados/v1/collections/"+arvadostest.UserAgreementPDH, nil)
412 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
413 resp := s.testRequest(req)
415 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
417 var col arvados.Collection
418 c.Check(json.NewDecoder(resp.Body).Decode(&col), check.IsNil)
419 c.Check(col.PortableDataHash, check.Equals, arvadostest.UserAgreementPDH)
420 c.Check(col.ManifestText, check.Matches,
421 `\. 6a4ff0499484c6c79c95cd8c566bd25f\+249025\+Rzzzzz-[0-9a-f]{40}@[0-9a-f]{8} 0:249025:GNU_General_Public_License,_version_3.pdf
425 func (s *FederationSuite) TestGetCollectionByPDHError(c *check.C) {
426 defer s.localServiceReturns404(c).Close()
428 req := httptest.NewRequest("GET", "/arvados/v1/collections/99999999999999999999999999999999+99", nil)
429 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
431 resp := s.testRequest(req)
432 defer resp.Body.Close()
434 c.Check(resp.StatusCode, check.Equals, http.StatusNotFound)
437 func (s *FederationSuite) TestGetCollectionByPDHErrorBadHash(c *check.C) {
438 defer s.localServiceReturns404(c).Close()
440 srv2 := &httpserver.Server{
442 Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
444 // Return a collection where the hash
445 // of the manifest text doesn't match
446 // PDH that was requested.
447 var col arvados.Collection
448 col.PortableDataHash = "99999999999999999999999999999999+99"
449 col.ManifestText = `. 6a4ff0499484c6c79c95cd8c566bd25f\+249025 0:249025:GNU_General_Public_License,_version_3.pdf
451 enc := json.NewEncoder(w)
457 c.Assert(srv2.Start(), check.IsNil)
460 // Direct zzzzz to service that returns a 200 result with a bogus manifest_text
461 s.testHandler.Cluster.RemoteClusters["zzzzz"] = arvados.RemoteCluster{
467 req := httptest.NewRequest("GET", "/arvados/v1/collections/99999999999999999999999999999999+99", nil)
468 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
470 resp := s.testRequest(req)
471 defer resp.Body.Close()
473 c.Check(resp.StatusCode, check.Equals, http.StatusNotFound)
476 func (s *FederationSuite) TestSaltedTokenGetCollectionByPDH(c *check.C) {
477 np := arvados.NodeProfile{
478 Controller: arvados.SystemServiceInstance{Listen: ":"},
479 RailsAPI: arvados.SystemServiceInstance{Listen: os.Getenv("ARVADOS_TEST_API_HOST"),
480 TLS: true, Insecure: true}}
481 s.testHandler.Cluster.NodeProfiles["*"] = np
482 s.testHandler.NodeProfile = &np
484 req := httptest.NewRequest("GET", "/arvados/v1/collections/"+arvadostest.UserAgreementPDH, nil)
485 req.Header.Set("Authorization", "Bearer v2/zzzzz-gj3su-077z32aux8dg2s1/282d7d172b6cfdce364c5ed12ddf7417b2d00065")
486 resp := s.testRequest(req)
488 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
489 var col arvados.Collection
490 c.Check(json.NewDecoder(resp.Body).Decode(&col), check.IsNil)
491 c.Check(col.PortableDataHash, check.Equals, arvadostest.UserAgreementPDH)
492 c.Check(col.ManifestText, check.Matches,
493 `\. 6a4ff0499484c6c79c95cd8c566bd25f\+249025\+A[0-9a-f]{40}@[0-9a-f]{8} 0:249025:GNU_General_Public_License,_version_3.pdf
497 func (s *FederationSuite) TestSaltedTokenGetCollectionByPDHError(c *check.C) {
498 np := arvados.NodeProfile{
499 Controller: arvados.SystemServiceInstance{Listen: ":"},
500 RailsAPI: arvados.SystemServiceInstance{Listen: os.Getenv("ARVADOS_TEST_API_HOST"),
501 TLS: true, Insecure: true}}
502 s.testHandler.Cluster.NodeProfiles["*"] = np
503 s.testHandler.NodeProfile = &np
505 req := httptest.NewRequest("GET", "/arvados/v1/collections/99999999999999999999999999999999+99", nil)
506 req.Header.Set("Authorization", "Bearer v2/zzzzz-gj3su-077z32aux8dg2s1/282d7d172b6cfdce364c5ed12ddf7417b2d00065")
507 resp := s.testRequest(req)
509 c.Check(resp.StatusCode, check.Equals, http.StatusNotFound)
512 func (s *FederationSuite) TestGetRemoteContainerRequest(c *check.C) {
513 defer s.localServiceReturns404(c).Close()
514 req := httptest.NewRequest("GET", "/arvados/v1/container_requests/"+arvadostest.QueuedContainerRequestUUID, nil)
515 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
516 resp := s.testRequest(req)
517 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
518 var cr arvados.ContainerRequest
519 c.Check(json.NewDecoder(resp.Body).Decode(&cr), check.IsNil)
520 c.Check(cr.UUID, check.Equals, arvadostest.QueuedContainerRequestUUID)
521 c.Check(cr.Priority, check.Equals, 1)
524 func (s *FederationSuite) TestUpdateRemoteContainerRequest(c *check.C) {
525 defer s.localServiceReturns404(c).Close()
526 req := httptest.NewRequest("PATCH", "/arvados/v1/container_requests/"+arvadostest.QueuedContainerRequestUUID,
527 strings.NewReader(`{"container_request": {"priority": 696}}`))
528 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
529 req.Header.Set("Content-type", "application/json")
530 resp := s.testRequest(req)
531 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
532 var cr arvados.ContainerRequest
533 c.Check(json.NewDecoder(resp.Body).Decode(&cr), check.IsNil)
534 c.Check(cr.UUID, check.Equals, arvadostest.QueuedContainerRequestUUID)
535 c.Check(cr.Priority, check.Equals, 696)
538 func (s *FederationSuite) TestCreateRemoteContainerRequest1(c *check.C) {
539 defer s.localServiceReturns404(c).Close()
540 req := httptest.NewRequest("POST", "/arvados/v1/container_requests",
542 "cluster_id": "zzzzz",
543 "container_request": {
544 "name": "hello world",
545 "state": "Uncommitted",
547 "container_image": "123",
552 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
553 req.Header.Set("Content-type", "application/json")
554 resp := s.testRequest(req)
555 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
556 var cr arvados.ContainerRequest
557 c.Check(json.NewDecoder(resp.Body).Decode(&cr), check.IsNil)
558 c.Check(cr.Name, check.Equals, "hello world")
559 c.Check(strings.HasPrefix(cr.UUID, "zzzzz-"), check.Equals, true)
562 func (s *FederationSuite) TestCreateRemoteContainerRequest2(c *check.C) {
563 defer s.localServiceReturns404(c).Close()
564 // pass cluster_id via query parameter, this allows arvados-controller
565 // to avoid parsing the body
566 req := httptest.NewRequest("POST", "/arvados/v1/container_requests?cluster_id=zzzzz",
568 "container_request": {
569 "name": "hello world",
570 "state": "Uncommitted",
572 "container_image": "123",
577 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
578 req.Header.Set("Content-type", "application/json")
579 resp := s.testRequest(req)
580 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
581 var cr arvados.ContainerRequest
582 c.Check(json.NewDecoder(resp.Body).Decode(&cr), check.IsNil)
583 c.Check(cr.Name, check.Equals, "hello world")
584 c.Check(strings.HasPrefix(cr.UUID, "zzzzz-"), check.Equals, true)
587 func (s *FederationSuite) TestCreateRemoteContainerRequestError(c *check.C) {
588 defer s.localServiceReturns404(c).Close()
589 // pass cluster_id via query parameter, this allows arvados-controller
590 // to avoid parsing the body
591 req := httptest.NewRequest("POST", "/arvados/v1/container_requests?cluster_id=zz404",
593 "container_request": {
594 "name": "hello world",
595 "state": "Uncommitted",
597 "container_image": "123",
602 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
603 req.Header.Set("Content-type", "application/json")
604 resp := s.testRequest(req)
605 c.Check(resp.StatusCode, check.Equals, http.StatusNotFound)
608 func (s *FederationSuite) TestGetRemoteContainer(c *check.C) {
609 defer s.localServiceReturns404(c).Close()
610 req := httptest.NewRequest("GET", "/arvados/v1/containers/"+arvadostest.QueuedContainerUUID, nil)
611 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
612 resp := s.testRequest(req)
613 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
614 var cn arvados.Container
615 c.Check(json.NewDecoder(resp.Body).Decode(&cn), check.IsNil)
616 c.Check(cn.UUID, check.Equals, arvadostest.QueuedContainerUUID)
619 func (s *FederationSuite) TestListRemoteContainer(c *check.C) {
620 defer s.localServiceReturns404(c).Close()
621 req := httptest.NewRequest("GET", "/arvados/v1/containers?filters="+
622 url.QueryEscape(fmt.Sprintf(`[["uuid", "in", ["%v"]]]`, arvadostest.QueuedContainerUUID)), nil)
623 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
624 resp := s.testRequest(req)
625 c.Check(resp.StatusCode, check.Equals, http.StatusOK)
626 var cn arvados.ContainerList
627 c.Check(json.NewDecoder(resp.Body).Decode(&cn), check.IsNil)
628 c.Check(cn.Items[0].UUID, check.Equals, arvadostest.QueuedContainerUUID)
631 func (s *FederationSuite) TestListMultiRemoteContainers(c *check.C) {
632 defer s.localServiceReturns404(c).Close()
633 req := httptest.NewRequest("GET", "/arvados/v1/containers?filters="+
634 url.QueryEscape(fmt.Sprintf(`[["uuid", "in", ["%v", "zhome-xvhdp-cr5queuedcontnr"]]]`, arvadostest.QueuedContainerUUID)), nil)
635 req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
636 resp := s.testRequest(req)
637 log.Printf("got %+v", resp)
638 c.Assert(resp.StatusCode, check.Equals, http.StatusOK)
639 var cn arvados.ContainerList
640 c.Check(json.NewDecoder(resp.Body).Decode(&cn), check.IsNil)
641 c.Check(cn.Items[0].UUID, check.Equals, arvadostest.QueuedContainerUUID)