1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
17 "git.arvados.org/arvados.git/lib/boot"
18 "git.arvados.org/arvados.git/lib/config"
19 "git.arvados.org/arvados.git/lib/controller/rpc"
20 "git.arvados.org/arvados.git/lib/service"
21 "git.arvados.org/arvados.git/sdk/go/arvados"
22 "git.arvados.org/arvados.git/sdk/go/arvadosclient"
23 "git.arvados.org/arvados.git/sdk/go/auth"
24 "git.arvados.org/arvados.git/sdk/go/ctxlog"
25 "git.arvados.org/arvados.git/sdk/go/keepclient"
26 check "gopkg.in/check.v1"
29 var _ = check.Suite(&IntegrationSuite{})
31 type testCluster struct {
34 controllerURL *url.URL
37 type IntegrationSuite struct {
38 testClusters map[string]*testCluster
41 func (s *IntegrationSuite) SetUpSuite(c *check.C) {
43 c.Skip("heavy integration tests don't run with forceLegacyAPI14")
48 s.testClusters = map[string]*testCluster{
53 hostport := map[string]string{}
54 for id := range s.testClusters {
55 hostport[id] = func() string {
56 // TODO: Instead of expecting random ports on
57 // 127.0.0.11, 22, 33 to be race-safe, try
58 // different 127.x.y.z until finding one that
60 ln, err := net.Listen("tcp", ":0")
61 c.Assert(err, check.IsNil)
63 _, port, err := net.SplitHostPort(ln.Addr().String())
64 c.Assert(err, check.IsNil)
65 return "127.0.0." + id[3:] + ":" + port
68 for id := range s.testClusters {
73 ExternalURL: https://` + hostport[id] + `
82 Host: ` + hostport["z1111"] + `
88 Host: ` + hostport["z2222"] + `
94 Host: ` + hostport["z3333"] + `
100 loader := config.NewLoader(bytes.NewBufferString(yaml), ctxlog.TestLogger(c))
102 loader.SkipLegacy = true
103 loader.SkipAPICalls = true
104 cfg, err := loader.Load()
105 c.Assert(err, check.IsNil)
106 s.testClusters[id] = &testCluster{
107 super: boot.Supervisor{
108 SourcePath: filepath.Join(cwd, "..", ".."),
110 ListenHost: "127.0.0." + id[3:],
111 ControllerAddr: ":0",
112 OwnTemporaryDatabase: true,
113 Stderr: &service.LogPrefixer{Writer: ctxlog.LogWriter(c.Log), Prefix: []byte("[" + id + "] ")},
117 s.testClusters[id].super.Start(context.Background(), &s.testClusters[id].config)
119 for _, tc := range s.testClusters {
120 au, ok := tc.super.WaitReady()
121 c.Assert(ok, check.Equals, true)
123 tc.controllerURL = &u
127 func (s *IntegrationSuite) TearDownSuite(c *check.C) {
128 for _, c := range s.testClusters {
133 func (s *IntegrationSuite) conn(clusterID string) *rpc.Conn {
134 return rpc.NewConn(clusterID, s.testClusters[clusterID].controllerURL, true, rpc.PassthroughTokenProvider)
137 func (s *IntegrationSuite) clientsWithToken(clusterID string, token string) (context.Context, *arvados.Client, *keepclient.KeepClient) {
138 cl := s.testClusters[clusterID].config.Clusters[clusterID]
139 ctx := auth.NewContext(context.Background(), auth.NewCredentials(token))
140 ac, err := arvados.NewClientFromConfig(&cl)
145 arv, err := arvadosclient.New(ac)
149 kc := keepclient.New(arv)
153 func (s *IntegrationSuite) userClients(rootctx context.Context, c *check.C, conn *rpc.Conn, clusterID string, activate bool) (context.Context, *arvados.Client, *keepclient.KeepClient) {
154 login, err := conn.UserSessionCreate(rootctx, rpc.UserSessionCreateOptions{
155 ReturnTo: ",https://example.com",
156 AuthInfo: rpc.UserSessionAuthInfo{
157 Email: "user@example.com",
158 FirstName: "Example",
163 c.Assert(err, check.IsNil)
164 redirURL, err := url.Parse(login.RedirectLocation)
165 c.Assert(err, check.IsNil)
166 userToken := redirURL.Query().Get("api_token")
167 c.Logf("user token: %q", userToken)
168 ctx, ac, kc := s.clientsWithToken(clusterID, userToken)
169 user, err := conn.UserGetCurrent(ctx, arvados.GetOptions{})
170 c.Assert(err, check.IsNil)
171 _, err = conn.UserSetup(rootctx, arvados.UserSetupOptions{UUID: user.UUID})
172 c.Assert(err, check.IsNil)
174 _, err = conn.UserActivate(rootctx, arvados.UserActivateOptions{UUID: user.UUID})
175 c.Assert(err, check.IsNil)
176 user, err = conn.UserGetCurrent(ctx, arvados.GetOptions{})
177 c.Assert(err, check.IsNil)
178 c.Logf("user UUID: %q", user.UUID)
180 c.Fatalf("failed to activate user -- %#v", user)
186 func (s *IntegrationSuite) rootClients(clusterID string) (context.Context, *arvados.Client, *keepclient.KeepClient) {
187 return s.clientsWithToken(clusterID, s.testClusters[clusterID].config.Clusters[clusterID].SystemRootToken)
190 func (s *IntegrationSuite) TestGetCollectionByPDH(c *check.C) {
191 conn1 := s.conn("z1111")
192 rootctx1, _, _ := s.rootClients("z1111")
193 conn3 := s.conn("z3333")
194 userctx1, ac1, kc1 := s.userClients(rootctx1, c, conn1, "z1111", true)
196 // Create the collection to find its PDH (but don't save it
198 var coll1 arvados.Collection
199 fs1, err := coll1.FileSystem(ac1, kc1)
200 c.Assert(err, check.IsNil)
201 f, err := fs1.OpenFile("test.txt", os.O_CREATE|os.O_RDWR, 0777)
202 c.Assert(err, check.IsNil)
203 _, err = io.WriteString(f, "IntegrationSuite.TestGetCollectionByPDH")
204 c.Assert(err, check.IsNil)
206 c.Assert(err, check.IsNil)
207 mtxt, err := fs1.MarshalManifest(".")
208 c.Assert(err, check.IsNil)
209 pdh := arvados.PortableDataHash(mtxt)
211 // Looking up the PDH before saving returns 404 if cycle
212 // detection is working.
213 _, err = conn1.CollectionGet(userctx1, arvados.GetOptions{UUID: pdh})
214 c.Assert(err, check.ErrorMatches, `.*404 Not Found.*`)
216 // Save the collection on cluster z1111.
217 coll1, err = conn1.CollectionCreate(userctx1, arvados.CreateOptions{Attrs: map[string]interface{}{
218 "manifest_text": mtxt,
220 c.Assert(err, check.IsNil)
222 // Retrieve the collection from cluster z3333.
223 coll, err := conn3.CollectionGet(userctx1, arvados.GetOptions{UUID: pdh})
224 c.Check(err, check.IsNil)
225 c.Check(coll.PortableDataHash, check.Equals, pdh)
228 // Test for bug #16263
229 func (s *IntegrationSuite) TestListUsers(c *check.C) {
230 rootctx1, _, _ := s.rootClients("z1111")
231 conn1 := s.conn("z1111")
232 conn3 := s.conn("z3333")
234 // Make sure LoginCluster is properly configured
235 for cls := range s.testClusters {
237 s.testClusters[cls].config.Clusters[cls].Login.LoginCluster,
238 check.Equals, "z1111",
239 check.Commentf("incorrect LoginCluster config on cluster %q", cls))
241 // Make sure z1111 has users with NULL usernames
242 lst, err := conn1.UserList(rootctx1, arvados.ListOptions{Limit: -1})
243 nullUsername := false
244 c.Assert(err, check.IsNil)
245 c.Assert(len(lst.Items), check.Not(check.Equals), 0)
246 for _, user := range lst.Items {
247 if user.Username == "" {
251 c.Assert(nullUsername, check.Equals, true)
252 // Ask for the user list on z3333 using z1111's system root token
253 _, err = conn3.UserList(rootctx1, arvados.ListOptions{Limit: -1})
254 c.Assert(err, check.IsNil, check.Commentf("getting user list: %q", err))
257 // Test for bug #16263
258 func (s *IntegrationSuite) TestListUsersWithMaxLimit(c *check.C) {
259 rootctx1, _, _ := s.rootClients("z1111")
260 conn3 := s.conn("z3333")
261 maxLimit := int64(math.MaxInt64)
263 // Make sure LoginCluster is properly configured
264 for cls := range s.testClusters {
266 s.testClusters[cls].config.Clusters[cls].Login.LoginCluster,
267 check.Equals, "z1111",
268 check.Commentf("incorrect LoginCluster config on cluster %q", cls))
271 // Ask for the user list on z3333 using z1111's system root token and
272 // limit: max int64 value.
273 _, err := conn3.UserList(rootctx1, arvados.ListOptions{Limit: maxLimit})
274 c.Assert(err, check.IsNil, check.Commentf("getting user list: %q", err))