X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/54d8c4e41a276ac82c79506f63907a108ebd9bfd..c340eecc7a03dd066792e5f046f087b8b3dfced6:/lib/controller/integration_test.go diff --git a/lib/controller/integration_test.go b/lib/controller/integration_test.go index db1f7f0d0c..6851442054 100644 --- a/lib/controller/integration_test.go +++ b/lib/controller/integration_test.go @@ -20,12 +20,14 @@ import ( "path/filepath" "strconv" "strings" + "sync" "git.arvados.org/arvados.git/lib/boot" "git.arvados.org/arvados.git/lib/config" "git.arvados.org/arvados.git/sdk/go/arvados" "git.arvados.org/arvados.git/sdk/go/arvadostest" "git.arvados.org/arvados.git/sdk/go/ctxlog" + "git.arvados.org/arvados.git/sdk/go/httpserver" check "gopkg.in/check.v1" ) @@ -37,11 +39,6 @@ type IntegrationSuite struct { } func (s *IntegrationSuite) SetUpSuite(c *check.C) { - if forceLegacyAPI14 { - c.Skip("heavy integration tests don't run with forceLegacyAPI14") - return - } - cwd, _ := os.Getwd() s.oidcprovider = arvadostest.NewOIDCProvider(c) @@ -118,6 +115,8 @@ func (s *IntegrationSuite) SetUpSuite(c *check.C) { ClientSecret: ` + s.oidcprovider.ValidClientSecret + ` EmailClaim: email EmailVerifiedClaim: email_verified + AcceptAccessToken: true + AcceptAccessTokenScope: "" ` } else { yaml += ` @@ -135,8 +134,9 @@ func (s *IntegrationSuite) SetUpSuite(c *check.C) { tc := boot.NewTestCluster( filepath.Join(cwd, "..", ".."), id, cfg, "127.0.0."+id[3:], c.Log) + tc.Super.NoWorkbench1 = true + tc.Start() s.testClusters[id] = tc - s.testClusters[id].Start() } for _, tc := range s.testClusters { ok := tc.WaitReady() @@ -188,6 +188,49 @@ func (s *IntegrationSuite) TestGetCollectionByPDH(c *check.C) { c.Check(coll.PortableDataHash, check.Equals, pdh) } +// Tests bug #18004 +func (s *IntegrationSuite) TestRemoteUserAndTokenCacheRace(c *check.C) { + conn1 := s.testClusters["z1111"].Conn() + rootctx1, _, _ := s.testClusters["z1111"].RootClients() + rootctx2, _, _ := s.testClusters["z2222"].RootClients() + conn2 := s.testClusters["z2222"].Conn() + userctx1, _, _, _ := s.testClusters["z1111"].UserClients(rootctx1, c, conn1, "user2@example.com", true) + + var wg1, wg2 sync.WaitGroup + creqs := 100 + + // Make concurrent requests to z2222 with a local token to make sure more + // than one worker is listening. + wg1.Add(1) + for i := 0; i < creqs; i++ { + wg2.Add(1) + go func() { + defer wg2.Done() + wg1.Wait() + _, err := conn2.UserGetCurrent(rootctx2, arvados.GetOptions{}) + c.Check(err, check.IsNil, check.Commentf("warm up phase failed")) + }() + } + wg1.Done() + wg2.Wait() + + // Real test pass -- use a new remote token than the one used in the warm-up + // phase. + wg1.Add(1) + for i := 0; i < creqs; i++ { + wg2.Add(1) + go func() { + defer wg2.Done() + wg1.Wait() + // Retrieve the remote collection from cluster z2222. + _, err := conn2.UserGetCurrent(userctx1, arvados.GetOptions{}) + c.Check(err, check.IsNil, check.Commentf("testing phase failed")) + }() + } + wg1.Done() + wg2.Wait() +} + func (s *IntegrationSuite) TestS3WithFederatedToken(c *check.C) { if _, err := exec.LookPath("s3cmd"); err != nil { c.Skip("s3cmd not in PATH") @@ -434,8 +477,76 @@ func (s *IntegrationSuite) TestCreateContainerRequestWithBadToken(c *check.C) { } } +func (s *IntegrationSuite) TestRequestIDHeader(c *check.C) { + conn1 := s.testClusters["z1111"].Conn() + rootctx1, _, _ := s.testClusters["z1111"].RootClients() + userctx1, ac1, _, _ := s.testClusters["z1111"].UserClients(rootctx1, c, conn1, "user@example.com", true) + + coll, err := conn1.CollectionCreate(userctx1, arvados.CreateOptions{}) + c.Check(err, check.IsNil) + specimen, err := conn1.SpecimenCreate(userctx1, arvados.CreateOptions{}) + c.Check(err, check.IsNil) + + tests := []struct { + path string + reqIdProvided bool + notFoundRequest bool + }{ + {"/arvados/v1/collections", false, false}, + {"/arvados/v1/collections", true, false}, + {"/arvados/v1/nonexistant", false, true}, + {"/arvados/v1/nonexistant", true, true}, + {"/arvados/v1/collections/" + coll.UUID, false, false}, + {"/arvados/v1/collections/" + coll.UUID, true, false}, + {"/arvados/v1/specimens/" + specimen.UUID, false, false}, + {"/arvados/v1/specimens/" + specimen.UUID, true, false}, + {"/arvados/v1/collections/z1111-4zz18-0123456789abcde", false, true}, + {"/arvados/v1/collections/z1111-4zz18-0123456789abcde", true, true}, + {"/arvados/v1/specimens/z1111-j58dm-0123456789abcde", false, true}, + {"/arvados/v1/specimens/z1111-j58dm-0123456789abcde", true, true}, + } + + for _, tt := range tests { + c.Log(c.TestName() + " " + tt.path) + req, err := http.NewRequest("GET", "https://"+ac1.APIHost+tt.path, nil) + c.Assert(err, check.IsNil) + customReqId := "abcdeG" + if !tt.reqIdProvided { + c.Assert(req.Header.Get("X-Request-Id"), check.Equals, "") + } else { + req.Header.Set("X-Request-Id", customReqId) + } + resp, err := ac1.Do(req) + c.Assert(err, check.IsNil) + if tt.notFoundRequest { + c.Check(resp.StatusCode, check.Equals, http.StatusNotFound) + } else { + c.Check(resp.StatusCode, check.Equals, http.StatusOK) + } + if !tt.reqIdProvided { + c.Check(resp.Header.Get("X-Request-Id"), check.Matches, "^req-[0-9a-zA-Z]{20}$") + if tt.notFoundRequest { + var jresp httpserver.ErrorResponse + err := json.NewDecoder(resp.Body).Decode(&jresp) + c.Check(err, check.IsNil) + c.Assert(jresp.Errors, check.HasLen, 1) + c.Check(jresp.Errors[0], check.Matches, "^.*(req-[0-9a-zA-Z]{20}).*$") + } + } else { + c.Check(resp.Header.Get("X-Request-Id"), check.Equals, customReqId) + if tt.notFoundRequest { + var jresp httpserver.ErrorResponse + err := json.NewDecoder(resp.Body).Decode(&jresp) + c.Check(err, check.IsNil) + c.Assert(jresp.Errors, check.HasLen, 1) + c.Check(jresp.Errors[0], check.Matches, "^.*("+customReqId+").*$") + } + } + } +} + // We test the direct access to the database -// normally an integration test would not have a database access, but in this case we need +// normally an integration test would not have a database access, but in this case we need // to test tokens that are secret, so there is no API response that will give them back func (s *IntegrationSuite) dbConn(c *check.C, clusterID string) (*sql.DB, *sql.Conn) { ctx := context.Background()