From: Tom Clegg Date: Tue, 5 Apr 2022 15:38:09 +0000 (-0400) Subject: Merge branch '18865-collection-permission-links' X-Git-Tag: 2.5.0~227 X-Git-Url: https://git.arvados.org/arvados.git/commitdiff_plain/3c73e2337ed73cd44e9bcc2d38a4dd742637ad19?hp=3961f5bd4349fca6769fd4263d2f7fbe54e8bcaa Merge branch '18865-collection-permission-links' fixes #18865 Arvados-DCO-1.1-Signed-off-by: Tom Clegg --- diff --git a/apps/workbench/app/controllers/application_controller.rb b/apps/workbench/app/controllers/application_controller.rb index 5312e733f4..f8c8079a1e 100644 --- a/apps/workbench/app/controllers/application_controller.rb +++ b/apps/workbench/app/controllers/application_controller.rb @@ -172,7 +172,7 @@ class ApplicationController < ActionController::Base def find_objects_for_index @objects ||= model_class - @objects = @objects.filter(@filters).limit(@limit).offset(@offset) + @objects = @objects.filter(@filters).limit(@limit).offset(@offset).order(@order) @objects.fetch_multiple_pages(false) end diff --git a/apps/workbench/config/arvados_config.rb b/apps/workbench/config/arvados_config.rb index c5cc544b9b..7cc46d2983 100644 --- a/apps/workbench/config/arvados_config.rb +++ b/apps/workbench/config/arvados_config.rb @@ -199,4 +199,8 @@ ArvadosWorkbench::Application.configure do ConfigValidators.validate_wb2_url_config() ConfigValidators.validate_download_config() end + if Rails.configuration.Users.AnonymousUserToken and + !Rails.configuration.Users.AnonymousUserToken.starts_with?("v2/") + Rails.configuration.Users.AnonymousUserToken = "v2/#{clusterID}-gj3su-anonymouspublic/#{Rails.configuration.Users.AnonymousUserToken}" + end end diff --git a/build/run-tests.sh b/build/run-tests.sh index 3592efbdc2..67c54c98b0 100755 --- a/build/run-tests.sh +++ b/build/run-tests.sh @@ -556,6 +556,12 @@ setup_ruby_environment() { done "$bundle" version | tee /dev/stderr | grep -q 'version 2' ) || fatal 'install bundler' + if test -d /var/lib/arvados-arvbox/ ; then + # Inside arvbox, use bundler-installed binstubs. The + # system bundler and rail's own bin/bundle refuse to work. + # I don't know why. + bundle=binstubs/bundle + fi fi } diff --git a/doc/admin/upgrading.html.textile.liquid b/doc/admin/upgrading.html.textile.liquid index 1ed3b694ce..97f6ce2f89 100644 --- a/doc/admin/upgrading.html.textile.liquid +++ b/doc/admin/upgrading.html.textile.liquid @@ -46,7 +46,7 @@ The minimum supported Ruby version is now 2.6. If you are running Arvados on De h3. Anonymous token changes -The anonymous token configured in @Users.AnonymousUserToken@ must now be 32 characters or longer. This was already the suggestion in the documentation, now it is enforced. The @script/get_anonymous_user_token.rb@ script that was needed to register the anonymous user token in the database has been removed. Registration of the anonymous token is no longer necessary. If the anonymous token in @config.yml@ is specified as a full V2 token, that will now generate a warning - it should be updated to list just the secret (i.e. the part after the last forward slash). +The anonymous token configured in @Users.AnonymousUserToken@ must now be 32 characters or longer. This was already the suggestion in the documentation, now it is enforced. The @script/get_anonymous_user_token.rb@ script that was needed to register the anonymous user token in the database has been removed. Registration of the anonymous token is no longer necessary. h3. Preemptible instance support changes diff --git a/lib/config/load.go b/lib/config/load.go index de43b9d2e2..5afb51c5ad 100644 --- a/lib/config/load.go +++ b/lib/config/load.go @@ -369,10 +369,12 @@ func (ldr *Loader) checkToken(label, token string, mandatory bool, acceptV2 bool if !strings.HasPrefix(token, "v2/") { return fmt.Errorf("%s: unacceptable characters in token (only a-z, A-Z, 0-9 are acceptable)", label) } - ldr.Logger.Warnf("%s: token is a full V2 token, should just be a secret (remove everything up to and including the last forward slash)", label) if !acceptableTokenRe.MatchString(tmp[2]) { return fmt.Errorf("%s: unacceptable characters in V2 token secret (only a-z, A-Z, 0-9 are acceptable)", label) } + if len(tmp[2]) < acceptableTokenLength { + ldr.Logger.Warnf("%s: secret is too short (should be at least %d characters)", label, acceptableTokenLength) + } } else if len(token) < acceptableTokenLength { if ldr.Logger != nil { ldr.Logger.Warnf("%s: token is too short (should be at least %d characters)", label, acceptableTokenLength) diff --git a/lib/controller/federation/conn.go b/lib/controller/federation/conn.go index d3819f6262..1b8ec9e64a 100644 --- a/lib/controller/federation/conn.go +++ b/lib/controller/federation/conn.go @@ -69,14 +69,17 @@ func saltedTokenProvider(cluster *arvados.Cluster, local backend, remoteID strin return nil, errors.New("no token provided") } for _, token := range incoming.Tokens { - if strings.HasPrefix(token, "v2/"+cluster.ClusterID+"-") && remoteID == cluster.Login.LoginCluster { - // If we did this, the login cluster - // would call back to us and then - // reject our response because the - // user UUID prefix (i.e., the - // LoginCluster prefix) won't match - // the token UUID prefix (i.e., our - // prefix). + if strings.HasPrefix(token, "v2/"+cluster.ClusterID+"-") && + !strings.HasPrefix(token, "v2/"+cluster.ClusterID+"-gj3su-anonymouspublic/") && + remoteID == cluster.Login.LoginCluster { + // If we did this, the login cluster would call back to us and then + // reject our response because the user UUID prefix (i.e., the + // LoginCluster prefix) won't match the token UUID prefix (i.e., our + // prefix). The anonymous token is OK to forward, because (unlike other + // local tokens for real users) the validation callback will return the + // locally issued anonymous user ID instead of a login-cluster user ID. + // That anonymous user ID gets mapped to the local anonymous user + // automatically on the login cluster. return nil, httpErrorf(http.StatusUnauthorized, "cannot use a locally issued token to forward a request to our login cluster (%s)", remoteID) } salted, err := auth.SaltToken(token, remoteID) diff --git a/lib/controller/integration_test.go b/lib/controller/integration_test.go index 9f5d12598b..b71c4afb55 100644 --- a/lib/controller/integration_test.go +++ b/lib/controller/integration_test.go @@ -379,6 +379,56 @@ func (s *IntegrationSuite) TestGetCollectionAsAnonymous(c *check.C) { c.Check(coll.PortableDataHash, check.Equals, pdh) } +// z3333 should forward the locally-issued anonymous user token to its login +// cluster z1111. That is no problem because the login cluster controller will +// map any anonymous user token to its local anonymous user. +// +// This needs to work because wb1 has a tendency to slap the local anonymous +// user token on every request as a reader_token, which gets folded into the +// request token list controller. +// +// Use a z1111 user token and the anonymous token from z3333 passed in as a +// reader_token to do a request on z3333, asking for the z1111 anonymous user +// object. The request will be forwarded to the z1111 cluster. The presence of +// the z3333 anonymous user token should not prohibit the request from being +// forwarded. +func (s *IntegrationSuite) TestForwardAnonymousTokenToLoginCluster(c *check.C) { + conn1 := s.testClusters["z1111"].Conn() + s.testClusters["z3333"].Conn() + + rootctx1, _, _ := s.testClusters["z1111"].RootClients() + _, anonac3, _ := s.testClusters["z3333"].AnonymousClients() + + // Make a user connection to z3333 (using a z1111 user, because that's the login cluster) + _, userac1, _, _ := s.testClusters["z3333"].UserClients(rootctx1, c, conn1, "user@example.com", true) + + // Get the anonymous user token for z3333 + var anon3Auth arvados.APIClientAuthorization + err := anonac3.RequestAndDecode(&anon3Auth, "GET", "/arvados/v1/api_client_authorizations/current", nil, nil) + c.Check(err, check.IsNil) + + var userList arvados.UserList + where := make(map[string]string) + where["uuid"] = "z1111-tpzed-anonymouspublic" + err = userac1.RequestAndDecode(&userList, "GET", "/arvados/v1/users", nil, + map[string]interface{}{ + "reader_tokens": []string{anon3Auth.TokenV2()}, + "where": where, + }, + ) + // The local z3333 anonymous token must be allowed to be forwarded to the login cluster + c.Check(err, check.IsNil) + + userac1.AuthToken = "v2/z1111-gj3su-asdfasdfasdfasd/this-token-does-not-validate-so-anonymous-token-will-be-used-instead" + err = userac1.RequestAndDecode(&userList, "GET", "/arvados/v1/users", nil, + map[string]interface{}{ + "reader_tokens": []string{anon3Auth.TokenV2()}, + "where": where, + }, + ) + c.Check(err, check.IsNil) +} + // Get a token from the login cluster (z1111), use it to submit a // container request on z2222. func (s *IntegrationSuite) TestCreateContainerRequestWithFedToken(c *check.C) { diff --git a/sdk/python/arvados/util.py b/sdk/python/arvados/util.py index be8a03fc31..c383d529e8 100644 --- a/sdk/python/arvados/util.py +++ b/sdk/python/arvados/util.py @@ -392,7 +392,8 @@ def keyset_list_all(fn, order_key="created_at", num_retries=0, ascending=True, * pagesize = 1000 kwargs["limit"] = pagesize kwargs["count"] = 'none' - kwargs["order"] = ["%s %s" % (order_key, "asc" if ascending else "desc"), "uuid asc"] + asc = "asc" if ascending else "desc" + kwargs["order"] = ["%s %s" % (order_key, asc), "uuid %s" % asc] other_filters = kwargs.get("filters", []) if "select" in kwargs and "uuid" not in kwargs["select"]: @@ -436,7 +437,7 @@ def keyset_list_all(fn, order_key="created_at", num_retries=0, ascending=True, * if firstitem[order_key] == lastitem[order_key]: # Got a page where every item has the same order key. # Switch to using uuid for paging. - nextpage = [[order_key, "=", lastitem[order_key]], ["uuid", ">", lastitem["uuid"]]] + nextpage = [[order_key, "=", lastitem[order_key]], ["uuid", ">" if ascending else "<", lastitem["uuid"]]] prev_page_all_same_order_key = True else: # Start from the last order key seen, but skip the last diff --git a/sdk/python/tests/test_util.py b/sdk/python/tests/test_util.py index 1c0e437b41..4dba9ce3dc 100644 --- a/sdk/python/tests/test_util.py +++ b/sdk/python/tests/test_util.py @@ -166,10 +166,10 @@ class KeysetListAllTestCase(unittest.TestCase): def test_onepage_desc(self): ks = KeysetTestHelper([[ - {"limit": 1000, "count": "none", "order": ["created_at desc", "uuid asc"], "filters": []}, + {"limit": 1000, "count": "none", "order": ["created_at desc", "uuid desc"], "filters": []}, {"items": [{"created_at": "2", "uuid": "2"}, {"created_at": "1", "uuid": "1"}]} ], [ - {"limit": 1000, "count": "none", "order": ["created_at desc", "uuid asc"], "filters": [["created_at", "<=", "1"], ["uuid", "!=", "1"]]}, + {"limit": 1000, "count": "none", "order": ["created_at desc", "uuid desc"], "filters": [["created_at", "<=", "1"], ["uuid", "!=", "1"]]}, {"items": []} ]]) diff --git a/services/api/app/models/api_client_authorization.rb b/services/api/app/models/api_client_authorization.rb index 993a49e5b7..52922d32b1 100644 --- a/services/api/app/models/api_client_authorization.rb +++ b/services/api/app/models/api_client_authorization.rb @@ -116,7 +116,7 @@ class ApiClientAuthorization < ArvadosModel clnt end - def self.check_anonymous_user_token token + def self.check_anonymous_user_token(token:, remote:) case token[0..2] when 'v2/' _, token_uuid, secret, optional = token.split('/') @@ -130,11 +130,16 @@ class ApiClientAuthorization < ArvadosModel secret = token end + # Usually, the secret is salted + salted_secret = OpenSSL::HMAC.hexdigest('sha1', Rails.configuration.Users.AnonymousUserToken, remote) + + # The anonymous token could be specified as a full v2 token in the config, + # but the config loader strips it down to the secret part. # The anonymous token content and minimum length is verified in lib/config - if secret.length >= 0 && secret == Rails.configuration.Users.AnonymousUserToken + if secret.length >= 0 && (secret == Rails.configuration.Users.AnonymousUserToken || secret == salted_secret) return ApiClientAuthorization.new(user: User.find_by_uuid(anonymous_user_uuid), uuid: Rails.configuration.ClusterID+"-gj3su-anonymouspublic", - api_token: token, + api_token: secret, api_client: anonymous_user_token_api_client, scopes: ['GET /']) else @@ -157,7 +162,7 @@ class ApiClientAuthorization < ArvadosModel return nil if token.nil? or token.empty? remote ||= Rails.configuration.ClusterID - auth = self.check_anonymous_user_token(token) + auth = self.check_anonymous_user_token(token: token, remote: remote) if !auth.nil? return auth end diff --git a/services/api/app/models/arvados_model.rb b/services/api/app/models/arvados_model.rb index 327bf63b5f..07a31d81a8 100644 --- a/services/api/app/models/arvados_model.rb +++ b/services/api/app/models/arvados_model.rb @@ -220,7 +220,7 @@ class ArvadosModel < ApplicationRecord end def self.default_orders - ["#{table_name}.modified_at desc", "#{table_name}.uuid"] + ["#{table_name}.modified_at desc", "#{table_name}.uuid desc"] end def self.unique_columns diff --git a/services/api/db/migrate/20220401153101_fix_created_at_indexes.rb b/services/api/db/migrate/20220401153101_fix_created_at_indexes.rb new file mode 100644 index 0000000000..590e8413e9 --- /dev/null +++ b/services/api/db/migrate/20220401153101_fix_created_at_indexes.rb @@ -0,0 +1,28 @@ +# Copyright (C) The Arvados Authors. All rights reserved. +# +# SPDX-License-Identifier: AGPL-3.0 + +class FixCreatedAtIndexes < ActiveRecord::Migration[5.2] + @@idxtables = [:collections, :container_requests, :groups, :links, :repositories, :users, :virtual_machines, :workflows, :logs] + + def up + @@idxtables.each do |table| + ActiveRecord::Base.connection.execute("DROP INDEX IF EXISTS index_#{table.to_s}_on_created_at") + ActiveRecord::Base.connection.execute("DROP INDEX IF EXISTS index_#{table.to_s}_on_created_at_uuid") + ActiveRecord::Base.connection.execute("DROP INDEX IF EXISTS index_#{table.to_s}_on_created_at_and_uuid") + ActiveRecord::Base.connection.execute("DROP INDEX IF EXISTS index_#{table.to_s}_on_modified_at") + ActiveRecord::Base.connection.execute("DROP INDEX IF EXISTS index_#{table.to_s}_on_modified_at_uuid") + ActiveRecord::Base.connection.execute("DROP INDEX IF EXISTS index_#{table.to_s}_on_modified_at_and_uuid") + + ActiveRecord::Base.connection.execute("CREATE INDEX IF NOT EXISTS index_#{table.to_s}_on_created_at_and_uuid ON #{table.to_s} USING btree (created_at, uuid)") + ActiveRecord::Base.connection.execute("CREATE INDEX IF NOT EXISTS index_#{table.to_s}_on_modified_at_and_uuid ON #{table.to_s} USING btree (modified_at, uuid)") + end + end + + def down + @@idxtables.each do |table| + ActiveRecord::Base.connection.execute("DROP INDEX IF EXISTS index_#{table.to_s}_on_modified_at_and_uuid") + ActiveRecord::Base.connection.execute("CREATE INDEX IF NOT EXISTS index_#{table.to_s}_on_modified_at_uuid ON #{table.to_s} USING btree (modified_at desc, uuid asc)") + end + end +end diff --git a/services/api/db/structure.sql b/services/api/db/structure.sql index cfe21f7c9a..e6bba67625 100644 --- a/services/api/db/structure.sql +++ b/services/api/db/structure.sql @@ -1905,10 +1905,10 @@ CREATE UNIQUE INDEX index_authorized_keys_on_uuid ON public.authorized_keys USIN -- --- Name: index_collections_on_created_at; Type: INDEX; Schema: public; Owner: - +-- Name: index_collections_on_created_at_and_uuid; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_collections_on_created_at ON public.collections USING btree (created_at); +CREATE INDEX index_collections_on_created_at_and_uuid ON public.collections USING btree (created_at, uuid); -- @@ -1933,17 +1933,10 @@ CREATE INDEX index_collections_on_is_trashed ON public.collections USING btree ( -- --- Name: index_collections_on_modified_at; Type: INDEX; Schema: public; Owner: - +-- Name: index_collections_on_modified_at_and_uuid; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_collections_on_modified_at ON public.collections USING btree (modified_at); - - --- --- Name: index_collections_on_modified_at_uuid; Type: INDEX; Schema: public; Owner: - --- - -CREATE INDEX index_collections_on_modified_at_uuid ON public.collections USING btree (modified_at DESC, uuid); +CREATE INDEX index_collections_on_modified_at_and_uuid ON public.collections USING btree (modified_at, uuid); -- @@ -1989,10 +1982,17 @@ CREATE INDEX index_container_requests_on_container_uuid ON public.container_requ -- --- Name: index_container_requests_on_modified_at_uuid; Type: INDEX; Schema: public; Owner: - +-- Name: index_container_requests_on_created_at_and_uuid; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_container_requests_on_created_at_and_uuid ON public.container_requests USING btree (created_at, uuid); + + +-- +-- Name: index_container_requests_on_modified_at_and_uuid; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_container_requests_on_modified_at_uuid ON public.container_requests USING btree (modified_at DESC, uuid); +CREATE INDEX index_container_requests_on_modified_at_and_uuid ON public.container_requests USING btree (modified_at, uuid); -- @@ -2094,10 +2094,10 @@ CREATE UNIQUE INDEX index_frozen_groups_on_uuid ON public.frozen_groups USING bt -- --- Name: index_groups_on_created_at; Type: INDEX; Schema: public; Owner: - +-- Name: index_groups_on_created_at_and_uuid; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_groups_on_created_at ON public.groups USING btree (created_at); +CREATE INDEX index_groups_on_created_at_and_uuid ON public.groups USING btree (created_at, uuid); -- @@ -2122,17 +2122,10 @@ CREATE INDEX index_groups_on_is_trashed ON public.groups USING btree (is_trashed -- --- Name: index_groups_on_modified_at; Type: INDEX; Schema: public; Owner: - +-- Name: index_groups_on_modified_at_and_uuid; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_groups_on_modified_at ON public.groups USING btree (modified_at); - - --- --- Name: index_groups_on_modified_at_uuid; Type: INDEX; Schema: public; Owner: - --- - -CREATE INDEX index_groups_on_modified_at_uuid ON public.groups USING btree (modified_at DESC, uuid); +CREATE INDEX index_groups_on_modified_at_and_uuid ON public.groups USING btree (modified_at, uuid); -- @@ -2360,10 +2353,10 @@ CREATE UNIQUE INDEX index_keep_services_on_uuid ON public.keep_services USING bt -- --- Name: index_links_on_created_at; Type: INDEX; Schema: public; Owner: - +-- Name: index_links_on_created_at_and_uuid; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_links_on_created_at ON public.links USING btree (created_at); +CREATE INDEX index_links_on_created_at_and_uuid ON public.links USING btree (created_at, uuid); -- @@ -2374,17 +2367,10 @@ CREATE INDEX index_links_on_head_uuid ON public.links USING btree (head_uuid); -- --- Name: index_links_on_modified_at; Type: INDEX; Schema: public; Owner: - +-- Name: index_links_on_modified_at_and_uuid; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_links_on_modified_at ON public.links USING btree (modified_at); - - --- --- Name: index_links_on_modified_at_uuid; Type: INDEX; Schema: public; Owner: - --- - -CREATE INDEX index_links_on_modified_at_uuid ON public.links USING btree (modified_at DESC, uuid); +CREATE INDEX index_links_on_modified_at_and_uuid ON public.links USING btree (modified_at, uuid); -- @@ -2423,10 +2409,10 @@ CREATE UNIQUE INDEX index_links_on_uuid ON public.links USING btree (uuid); -- --- Name: index_logs_on_created_at; Type: INDEX; Schema: public; Owner: - +-- Name: index_logs_on_created_at_and_uuid; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_logs_on_created_at ON public.logs USING btree (created_at); +CREATE INDEX index_logs_on_created_at_and_uuid ON public.logs USING btree (created_at, uuid); -- @@ -2444,17 +2430,10 @@ CREATE INDEX index_logs_on_event_type ON public.logs USING btree (event_type); -- --- Name: index_logs_on_modified_at; Type: INDEX; Schema: public; Owner: - +-- Name: index_logs_on_modified_at_and_uuid; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_logs_on_modified_at ON public.logs USING btree (modified_at); - - --- --- Name: index_logs_on_modified_at_uuid; Type: INDEX; Schema: public; Owner: - --- - -CREATE INDEX index_logs_on_modified_at_uuid ON public.logs USING btree (modified_at DESC, uuid); +CREATE INDEX index_logs_on_modified_at_and_uuid ON public.logs USING btree (modified_at, uuid); -- @@ -2605,10 +2584,17 @@ CREATE UNIQUE INDEX index_pipeline_templates_on_uuid ON public.pipeline_template -- --- Name: index_repositories_on_modified_at_uuid; Type: INDEX; Schema: public; Owner: - +-- Name: index_repositories_on_created_at_and_uuid; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_repositories_on_modified_at_uuid ON public.repositories USING btree (modified_at DESC, uuid); +CREATE INDEX index_repositories_on_created_at_and_uuid ON public.repositories USING btree (created_at, uuid); + + +-- +-- Name: index_repositories_on_modified_at_and_uuid; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_repositories_on_modified_at_and_uuid ON public.repositories USING btree (modified_at, uuid); -- @@ -2689,10 +2675,10 @@ CREATE UNIQUE INDEX index_trashed_groups_on_group_uuid ON public.trashed_groups -- --- Name: index_users_on_created_at; Type: INDEX; Schema: public; Owner: - +-- Name: index_users_on_created_at_and_uuid; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_users_on_created_at ON public.users USING btree (created_at); +CREATE INDEX index_users_on_created_at_and_uuid ON public.users USING btree (created_at, uuid); -- @@ -2703,17 +2689,10 @@ CREATE UNIQUE INDEX index_users_on_identity_url ON public.users USING btree (ide -- --- Name: index_users_on_modified_at; Type: INDEX; Schema: public; Owner: - --- - -CREATE INDEX index_users_on_modified_at ON public.users USING btree (modified_at); - - --- --- Name: index_users_on_modified_at_uuid; Type: INDEX; Schema: public; Owner: - +-- Name: index_users_on_modified_at_and_uuid; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_users_on_modified_at_uuid ON public.users USING btree (modified_at DESC, uuid); +CREATE INDEX index_users_on_modified_at_and_uuid ON public.users USING btree (modified_at, uuid); -- @@ -2737,6 +2716,13 @@ CREATE UNIQUE INDEX index_users_on_username ON public.users USING btree (usernam CREATE UNIQUE INDEX index_users_on_uuid ON public.users USING btree (uuid); +-- +-- Name: index_virtual_machines_on_created_at_and_uuid; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_virtual_machines_on_created_at_and_uuid ON public.virtual_machines USING btree (created_at, uuid); + + -- -- Name: index_virtual_machines_on_hostname; Type: INDEX; Schema: public; Owner: - -- @@ -2745,10 +2731,10 @@ CREATE INDEX index_virtual_machines_on_hostname ON public.virtual_machines USING -- --- Name: index_virtual_machines_on_modified_at_uuid; Type: INDEX; Schema: public; Owner: - +-- Name: index_virtual_machines_on_modified_at_and_uuid; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_virtual_machines_on_modified_at_uuid ON public.virtual_machines USING btree (modified_at DESC, uuid); +CREATE INDEX index_virtual_machines_on_modified_at_and_uuid ON public.virtual_machines USING btree (modified_at, uuid); -- @@ -2766,10 +2752,17 @@ CREATE UNIQUE INDEX index_virtual_machines_on_uuid ON public.virtual_machines US -- --- Name: index_workflows_on_modified_at_uuid; Type: INDEX; Schema: public; Owner: - +-- Name: index_workflows_on_created_at_and_uuid; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_workflows_on_created_at_and_uuid ON public.workflows USING btree (created_at, uuid); + + +-- +-- Name: index_workflows_on_modified_at_and_uuid; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_workflows_on_modified_at_uuid ON public.workflows USING btree (modified_at DESC, uuid); +CREATE INDEX index_workflows_on_modified_at_and_uuid ON public.workflows USING btree (modified_at, uuid); -- @@ -3185,6 +3178,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20211027154300'), ('20220224203102'), ('20220301155729'), -('20220303204419'); +('20220303204419'), +('20220401153101'); diff --git a/services/api/test/fixtures/jobs.yml b/services/api/test/fixtures/jobs.yml index ab76417902..9280aeab93 100644 --- a/services/api/test/fixtures/jobs.yml +++ b/services/api/test/fixtures/jobs.yml @@ -8,8 +8,8 @@ running: cancelled_at: ~ cancelled_by_user_uuid: ~ cancelled_by_client_uuid: ~ - created_at: <%= 3.minute.ago.to_s(:db) %> - started_at: <%= 3.minute.ago.to_s(:db) %> + created_at: <%= 2.7.minute.ago.to_s(:db) %> + started_at: <%= 2.7.minute.ago.to_s(:db) %> finished_at: ~ script: hash repository: active/foo diff --git a/services/api/test/fixtures/pipeline_instances.yml b/services/api/test/fixtures/pipeline_instances.yml index 9621b3effc..a504c9fadd 100644 --- a/services/api/test/fixtures/pipeline_instances.yml +++ b/services/api/test/fixtures/pipeline_instances.yml @@ -97,7 +97,7 @@ has_job: state: Ready uuid: zzzzz-d1hrv-1yfj6xkidf2muk3 owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz - created_at: <%= 3.1.minute.ago.to_s(:db) %> + created_at: <%= 2.9.minute.ago.to_s(:db) %> components: foo: script: foo @@ -112,7 +112,7 @@ components_is_jobspec: # Helps test that clients cope with funny-shaped components. # For an example, see #3321. uuid: zzzzz-d1hrv-1yfj61234abcdk4 - created_at: <%= 2.minute.ago.to_s(:db) %> + created_at: <%= 4.minute.ago.to_s(:db) %> owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz modified_by_client_uuid: zzzzz-ozdt8-brczlopd8u8d0jr modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz @@ -132,7 +132,7 @@ pipeline_with_tagged_collection_input: state: Ready uuid: zzzzz-d1hrv-1yfj61234abcdk3 owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz - created_at: <%= 3.1.minute.ago.to_s(:db) %> + created_at: <%= 3.2.minute.ago.to_s(:db) %> components: part-one: script_parameters: @@ -145,7 +145,7 @@ pipeline_to_merge_params: uuid: zzzzz-d1hrv-1yfj6dcba4321k3 pipeline_template_uuid: zzzzz-p5p6p-aox0k0ofxrystgw owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz - created_at: <%= 3.1.minute.ago.to_s(:db) %> + created_at: <%= 3.3.minute.ago.to_s(:db) %> components: part-one: script_parameters: @@ -193,7 +193,7 @@ pipeline_instance_owned_by_fuse: uuid: zzzzz-d1hrv-ri9dvgkgqs9y09j owner_uuid: zzzzz-tpzed-0fusedrivertest pipeline_template_uuid: zzzzz-p5p6p-vq4wuvy84xvaq2r - created_at: 2014-09-15 12:00:00 + created_at: 2014-09-16 12:00:00 name: "pipeline instance owned by FUSE" components: foo: @@ -210,7 +210,7 @@ pipeline_instance_in_fuse_project: uuid: zzzzz-d1hrv-scarxiyajtshq3l owner_uuid: zzzzz-j7d0g-0000ownedbyfuse pipeline_template_uuid: zzzzz-p5p6p-vq4wuvy84xvaq2r - created_at: 2014-09-15 12:00:00 + created_at: 2014-09-17 12:00:00 name: "pipeline instance in FUSE project" components: foo: @@ -227,7 +227,7 @@ pipeline_owned_by_active_in_aproject: state: Complete uuid: zzzzz-d1hrv-ju5ghi0i9z2kqc6 owner_uuid: zzzzz-j7d0g-v955i6s2oi1cbso - created_at: 2014-09-15 12:00:00 + created_at: 2014-09-18 12:00:00 components: foo: script: foo @@ -243,7 +243,7 @@ pipeline_owned_by_active_in_home: state: Complete uuid: zzzzz-d1hrv-lihrbd0i9z2kqc6 owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz - created_at: 2014-09-15 12:00:00 + created_at: 2014-09-19 12:00:00 components: foo: script: foo @@ -287,7 +287,7 @@ pipeline_in_publicly_accessible_project_but_other_objects_elsewhere: name: Pipeline in public project with other objects elsewhere pipeline_template_uuid: zzzzz-p5p6p-aox0k0ofxrystgw state: Complete - created_at: 2014-09-15 12:00:00 + created_at: 2014-09-20 12:00:00 components: foo: script: foo @@ -314,7 +314,7 @@ new_pipeline_in_publicly_accessible_project: name: Pipeline in New state in publicly accessible project pipeline_template_uuid: zzzzz-p5p6p-tmpltpublicproj state: New - created_at: 2014-09-15 12:00:00 + created_at: 2014-09-21 12:00:00 components: foo: script: foo @@ -331,7 +331,7 @@ new_pipeline_in_publicly_accessible_project_but_other_objects_elsewhere: name: Pipeline in New state in public project with objects elsewhere pipeline_template_uuid: zzzzz-p5p6p-aox0k0ofxrystgw state: New - created_at: 2014-09-15 12:00:00 + created_at: 2014-09-22 12:00:00 components: foo: script: foo @@ -348,7 +348,7 @@ new_pipeline_in_publicly_accessible_project_with_dataclass_file_and_other_object name: Pipeline in public project in New state with file type data class with objects elsewhere pipeline_template_uuid: zzzzz-p5p6p-aox0k0ofxrystgw state: New - created_at: 2014-09-15 12:00:00 + created_at: 2014-09-23 12:00:00 components: foo: script: foo @@ -363,8 +363,8 @@ pipeline_in_running_state: name: running_with_job uuid: zzzzz-d1hrv-runningpipeline owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz - created_at: <%= 3.1.minute.ago.to_s(:db) %> - started_at: <%= 3.1.minute.ago.to_s(:db) %> + created_at: <%= 2.8.minute.ago.to_s(:db) %> + started_at: <%= 2.8.minute.ago.to_s(:db) %> state: RunningOnServer components: foo: @@ -393,7 +393,7 @@ complete_pipeline_with_two_jobs: uuid: zzzzz-d1hrv-twodonepipeline owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz state: Complete - created_at: <%= 3.minute.ago.to_s(:db) %> + created_at: <%= 2.5.minute.ago.to_s(:db) %> started_at: <%= 2.minute.ago.to_s(:db) %> finished_at: <%= 1.minute.ago.to_s(:db) %> components: diff --git a/services/api/test/functional/arvados/v1/query_test.rb b/services/api/test/functional/arvados/v1/query_test.rb index 9bba418578..fae9dc40c6 100644 --- a/services/api/test/functional/arvados/v1/query_test.rb +++ b/services/api/test/functional/arvados/v1/query_test.rb @@ -24,7 +24,7 @@ class Arvados::V1::QueryTest < ActionController::TestCase controller: 'logs', } assert_response :success - assert_equal('logs.event_type asc, logs.modified_at desc, logs.uuid', + assert_equal('logs.event_type asc, logs.modified_at desc, logs.uuid desc', assigns(:objects).order_values.join(', ')) end @@ -36,7 +36,7 @@ class Arvados::V1::QueryTest < ActionController::TestCase controller: 'logs', } assert_response :success - assert_equal('logs.modified_at asc, logs.uuid', + assert_equal('logs.modified_at asc, logs.uuid desc', assigns(:objects).order_values.join(', ')) end @@ -51,7 +51,7 @@ class Arvados::V1::QueryTest < ActionController::TestCase controller: 'logs', } assert_response :success - assert_equal('logs.modified_at asc, logs.event_type desc, logs.uuid', + assert_equal('logs.modified_at asc, logs.event_type desc, logs.uuid desc', assigns(:objects).order_values.join(', ')) end diff --git a/services/api/test/integration/select_test.rb b/services/api/test/integration/select_test.rb index 2ee3b3cf94..0548a767ba 100644 --- a/services/api/test/integration/select_test.rb +++ b/services/api/test/integration/select_test.rb @@ -62,7 +62,7 @@ class SelectTest < ActionDispatch::IntegrationTest headers: auth(:admin) assert_response :success uuids = json_response['items'].collect { |i| i['uuid'] } - assert_equal uuids, uuids.sort + assert_equal uuids, uuids.sort.reverse end def assert_link_classes_ascend(current_class, prev_class)