16663: Merge branch 'master'
authorTom Clegg <tom@tomclegg.ca>
Mon, 17 Aug 2020 14:17:28 +0000 (10:17 -0400)
committerTom Clegg <tom@tomclegg.ca>
Mon, 17 Aug 2020 14:17:28 +0000 (10:17 -0400)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@tomclegg.ca>

32 files changed:
apps/workbench/app/views/application/_show_sharing.html.erb
doc/install/install-keep-web.html.textile.liquid
doc/install/install-keepproxy.html.textile.liquid
doc/user/cwl/cwl-versions.html.textile.liquid
lib/config/deprecated_test.go
lib/config/load_test.go
lib/controller/federation/generated.go
lib/controller/federation/list.go
lib/controller/integration_test.go
lib/controller/localdb/login_ldap_test.go
lib/controller/router/router_test.go
lib/controller/rpc/conn_test.go
lib/pam/pam_arvados.go
lib/recovercollection/cmd_test.go
lib/service/cmd_test.go
sdk/cwl/arvados_cwl/__init__.py
sdk/cwl/arvados_cwl/arv-cwl-schema-v1.2.yml [new file with mode: 0644]
sdk/cwl/setup.py
sdk/go/arvados/api.go
sdk/go/arvados/duration_test.go
sdk/go/arvados/fs_project_test.go
sdk/go/arvados/fs_site_test.go
sdk/go/arvadosclient/arvadosclient_test.go
sdk/go/httpserver/logger_test.go
sdk/go/keepclient/collectionreader_test.go
sdk/go/keepclient/keepclient_test.go
sdk/python/tests/fed-migrate/check.py
services/api/app/models/arvados_model.rb
services/api/app/models/link.rb
services/api/test/unit/link_test.rb
services/keep-balance/main_test.go
services/keepstore/s3aws_volume_test.go

index 7877e60d3018096bdc3ad6b9ef4c4bd892631925..75773ab90082ba0a79a64ba49b497216e1087094 100644 (file)
@@ -8,6 +8,8 @@ SPDX-License-Identifier: AGPL-3.0 %>
      [User, Group].each do |type|
        type
          .filter([['uuid','in',@share_links.collect(&:tail_uuid)]])
+         .with_count("none")
+         .fetch_multiple_pages(false)
          .each do |o|
          uuid_map[o.uuid] = o
        end
index b31827bf70ed6c0a062cef1321cce68c393caaba..24f37bfb4f8ee25b3b32b691624e06586f9b42d1 100644 (file)
@@ -142,6 +142,7 @@ server {
     client_max_body_size    0;
     proxy_http_version      1.1;
     proxy_request_buffering off;
+    proxy_max_temp_file_size 0;
   }
 }
 </pre></notextile>
index ae6bd3989c340cbc64bb67932d9c1c3d8a8121e9..b4edd4f57b6e682560f8da16759b6042921dd0c3 100644 (file)
@@ -66,6 +66,7 @@ server {
   proxy_set_header        X-Real-IP $remote_addr;
   proxy_http_version      1.1;
   proxy_request_buffering off;
+  proxy_max_temp_file_size 0;
 
   ssl_certificate     <span class="userinput">/YOUR/PATH/TO/cert.pem</span>;
   ssl_certificate_key <span class="userinput">/YOUR/PATH/TO/cert.key</span>;
index 7bb9fdcbe602c5009242798295b043cfb2508204..5fcfcbe3bc3e8c00b3e4f20467ad224271e47c97 100644 (file)
@@ -9,7 +9,13 @@ Copyright (C) The Arvados Authors. All rights reserved.
 SPDX-License-Identifier: CC-BY-SA-3.0
 {% endcomment %}
 
-h2. Upgrading to CWL v1.1
+h2(#v12). Upgrading your workflows to CWL v1.2
+
+If you are starting from a CWL v1.0 document, see "Upgrading your workflows to CWL v1.1":#v11 below.
+
+If you are starting from a CWL v1.1 document, you should be able to trivially change @cwlVersion: v1.1@ to @cwlVersion: v1.2@ to be able to take advantage of the new features of v1.2, such as conditional workflow steps.
+
+h2(#v11). Upgrading your workflows to CWL v1.1
 
 CWL v1.1 introduces several features to the standard that were previously available as Arvados extensions.  CWL v1.1 syntax is backwards compatible with v1.0, so you can just change @cwlVersion: v1.0@ to @cwlVersion: v1.1@ and update your script to using the standard features.  On Arvados, there is only one behavior change between CWL v1.0 and v1.1 to be aware of: for performance reasons, Directory listings are no longer loaded by default.  To control loading Directory listings, use "loadListing":https://www.commonwl.org/v1.1/CommandLineTool.html#CommandInputParameter or "LoadListingRequirement":https://www.commonwl.org/v1.1/CommandLineTool.html#LoadListingRequirement (the extension @cwltool:LoadListingRequirement@ is deprecated.)
 
index 87e26fd09672805aa5bd840b757df71778477057..ca376ba0bb233f56f6606adb8404d1e39bffa4aa 100644 (file)
@@ -205,6 +205,7 @@ func (s *LoadSuite) TestLegacyKeepproxyConfig(c *check.C) {
 
        content = []byte(fmtKeepproxyConfig("", false))
        cluster, err = testLoadLegacyConfig(content, f, c)
+       c.Check(err, check.IsNil)
        c.Check(cluster.SystemLogs.LogLevel, check.Equals, "info")
 
        content = []byte(fmtKeepproxyConfig(`"DisableGet": true,`, true))
index 5e912f91aa835e51cec5210b1d6b52c1a9016e39..58ddf950efdd82d1f1a2f26b4d3b4a248f116764 100644 (file)
@@ -164,6 +164,7 @@ func (s *LoadSuite) TestSampleKeys(c *check.C) {
                cfg, err := testLoader(c, yaml, nil).Load()
                c.Assert(err, check.IsNil)
                cc, err := cfg.GetCluster("z1111")
+               c.Assert(err, check.IsNil)
                _, hasSample := cc.InstanceTypes["SAMPLE"]
                c.Check(hasSample, check.Equals, false)
                if strings.Contains(yaml, "Foo") {
index 20edd90b95dad70791b21cf4f19bfce6b496bff4..8745f3b9730b068faa2cc9e8a02d4c5638c7164a 100755 (executable)
@@ -23,6 +23,7 @@ func (conn *Conn) generated_ContainerList(ctx context.Context, options arvados.L
        var needSort atomic.Value
        needSort.Store(false)
        err := conn.splitListRequest(ctx, options, func(ctx context.Context, _ string, backend arvados.API, options arvados.ListOptions) ([]string, error) {
+               options.ForwardedFor = conn.cluster.ClusterID + "-" + options.ForwardedFor
                cl, err := backend.ContainerList(ctx, options)
                if err != nil {
                        return nil, err
@@ -63,6 +64,7 @@ func (conn *Conn) generated_SpecimenList(ctx context.Context, options arvados.Li
        var needSort atomic.Value
        needSort.Store(false)
        err := conn.splitListRequest(ctx, options, func(ctx context.Context, _ string, backend arvados.API, options arvados.ListOptions) ([]string, error) {
+               options.ForwardedFor = conn.cluster.ClusterID + "-" + options.ForwardedFor
                cl, err := backend.SpecimenList(ctx, options)
                if err != nil {
                        return nil, err
@@ -103,6 +105,7 @@ func (conn *Conn) generated_UserList(ctx context.Context, options arvados.ListOp
        var needSort atomic.Value
        needSort.Store(false)
        err := conn.splitListRequest(ctx, options, func(ctx context.Context, _ string, backend arvados.API, options arvados.ListOptions) ([]string, error) {
+               options.ForwardedFor = conn.cluster.ClusterID + "-" + options.ForwardedFor
                cl, err := backend.UserList(ctx, options)
                if err != nil {
                        return nil, err
index 0a596eb9cb6ac6aac690dc19a2e43ca3dc723340..bc6d3e00a493361b4d9897aeab77e3abf5cced27 100644 (file)
@@ -27,6 +27,7 @@ func (conn *Conn) generated_CollectionList(ctx context.Context, options arvados.
        var needSort atomic.Value
        needSort.Store(false)
        err := conn.splitListRequest(ctx, options, func(ctx context.Context, _ string, backend arvados.API, options arvados.ListOptions) ([]string, error) {
+               options.ForwardedFor = conn.cluster.ClusterID + "-" + options.ForwardedFor
                cl, err := backend.CollectionList(ctx, options)
                if err != nil {
                        return nil, err
@@ -107,7 +108,7 @@ func (conn *Conn) generated_CollectionList(ctx context.Context, options arvados.
 // backend.
 func (conn *Conn) splitListRequest(ctx context.Context, opts arvados.ListOptions, fn func(context.Context, string, arvados.API, arvados.ListOptions) ([]string, error)) error {
 
-       if opts.BypassFederation {
+       if opts.BypassFederation || opts.ForwardedFor != "" {
                // Client requested no federation.  Pass through.
                _, err := fn(ctx, conn.cluster.ClusterID, conn.local, opts)
                return err
@@ -249,7 +250,7 @@ func (conn *Conn) splitListRequest(ctx context.Context, opts arvados.ListOptions
 
                                done, err := fn(ctx, clusterID, backend, remoteOpts)
                                if err != nil {
-                                       errs <- httpErrorf(http.StatusBadGateway, err.Error())
+                                       errs <- httpErrorf(http.StatusBadGateway, "%s", err.Error())
                                        return
                                }
                                progress := false
index 3bf64771d70b30d08d6c53312384071bef14a259..a73f5f9f828574b1c234932432a2a4b63c769087 100644 (file)
@@ -300,6 +300,7 @@ func (s *IntegrationSuite) TestCreateContainerRequestWithFedToken(c *check.C) {
        resp, err = arvados.InsecureHTTPClient.Do(req)
        if c.Check(err, check.IsNil) {
                err = json.NewDecoder(resp.Body).Decode(&cr)
+               c.Check(err, check.IsNil)
                c.Check(cr.UUID, check.Matches, "z2222-.*")
        }
 }
index 0c94fa6c0e21be72949f6fd5b402ae252d7ce1cc..700d757c274d707c703ad0c58dbac812440a45a6 100644 (file)
@@ -49,6 +49,7 @@ func (s *LDAPSuite) SetUpSuite(c *check.C) {
        c.Assert(err, check.IsNil)
 
        ln, err := net.Listen("tcp", "127.0.0.1:0")
+       c.Assert(err, check.IsNil)
        s.ldap = &godap.LDAPServer{
                Listener: ln,
                Handlers: []godap.LDAPRequestHandler{
index c73bc64915f12aff293f23c803e25771669fe8a9..18fff7c9cc4f5d4a10f347c3da55ab79ca1bf38d 100644 (file)
@@ -273,7 +273,7 @@ func (s *RouterIntegrationSuite) TestContainerLock(c *check.C) {
        c.Check(rr.Code, check.Equals, http.StatusOK)
        c.Check(jresp["uuid"], check.HasLen, 27)
        c.Check(jresp["state"], check.Equals, "Locked")
-       _, rr, jresp = doRequest(c, s.rtr, token, "POST", "/arvados/v1/containers/"+uuid+"/lock", nil, nil)
+       _, rr, _ = doRequest(c, s.rtr, token, "POST", "/arvados/v1/containers/"+uuid+"/lock", nil, nil)
        c.Check(rr.Code, check.Equals, http.StatusUnprocessableEntity)
        c.Check(rr.Body.String(), check.Not(check.Matches), `.*"uuid":.*`)
        _, rr, jresp = doRequest(c, s.rtr, token, "POST", "/arvados/v1/containers/"+uuid+"/unlock", nil, nil)
index b97c0f87b85f6e4f8c2c0ee798256bde9fced23c..f43cc1ddee295d506854fc97447c0cfe46d868ab 100644 (file)
@@ -81,10 +81,12 @@ func (s *RPCSuite) TestSpecimenCRUD(c *check.C) {
        c.Check(sp.Properties["foo"], check.Equals, "bar")
 
        spGet, err := s.conn.SpecimenGet(s.ctx, arvados.GetOptions{UUID: sp.UUID})
+       c.Check(err, check.IsNil)
        c.Check(spGet.UUID, check.Equals, sp.UUID)
        c.Check(spGet.Properties["foo"], check.Equals, "bar")
 
        spList, err := s.conn.SpecimenList(s.ctx, arvados.ListOptions{Limit: -1, Filters: []arvados.Filter{{"uuid", "=", sp.UUID}}})
+       c.Check(err, check.IsNil)
        c.Check(spList.ItemsAvailable, check.Equals, 1)
        c.Assert(spList.Items, check.HasLen, 1)
        c.Check(spList.Items[0].UUID, check.Equals, sp.UUID)
@@ -92,9 +94,11 @@ func (s *RPCSuite) TestSpecimenCRUD(c *check.C) {
 
        anonCtx := context.WithValue(context.Background(), contextKeyTestTokens, []string{arvadostest.AnonymousToken})
        spList, err = s.conn.SpecimenList(anonCtx, arvados.ListOptions{Limit: -1, Filters: []arvados.Filter{{"uuid", "=", sp.UUID}}})
+       c.Check(err, check.IsNil)
        c.Check(spList.ItemsAvailable, check.Equals, 0)
        c.Check(spList.Items, check.HasLen, 0)
 
        spDel, err := s.conn.SpecimenDelete(s.ctx, arvados.DeleteOptions{UUID: sp.UUID})
+       c.Check(err, check.IsNil)
        c.Check(spDel.UUID, check.Equals, sp.UUID)
 }
index 34b90805363fc3230ef7f78f1bf3605ecebdfdea..ee967af6cc6f1f773d429b69a4999c051e22989e 100644 (file)
@@ -102,7 +102,7 @@ func authenticate(logger *logrus.Logger, username, token string, argv []string)
                } else if arg == "debug" {
                        logger.SetLevel(logrus.DebugLevel)
                } else {
-                       logger.Warnf("unkown option: %s\n", arg)
+                       logger.Warnf("unknown option: %s\n", arg)
                }
        }
        if hostname == "" || hostname == "-" {
index 57c2c64cdab01289911043c5767ed92edbcd8c36..7b3c8e1b4ed95b59f5e155fcb0392b7fe0d58a26 100644 (file)
@@ -90,6 +90,7 @@ func (*Suite) TestUntrashAndTouchBlock(c *check.C) {
                c.Assert(err, check.IsNil)
                t := time.Now().Add(-time.Hour * 24 * 365)
                err = os.Chtimes(trashfile, t, t)
+               c.Assert(err, check.IsNil)
        }
 
        var stdout, stderr bytes.Buffer
index ec7834972c2609aeb5e4cd14099d35367a7e3c09..4a984c9e780a9fba5bca0ff3d964e972ec2eb728 100644 (file)
@@ -107,6 +107,7 @@ Clusters:
                                continue
                        }
                        body, err := ioutil.ReadAll(resp.Body)
+                       c.Check(err, check.IsNil)
                        c.Logf("status %d, body %s", resp.StatusCode, string(body))
                        c.Check(resp.StatusCode, check.Equals, http.StatusOK)
                        break
index 341929454ad71a87912e566dfdd86153f7f0881e..f3629b68972650e90f06e772404b8c5b29a46f94 100644 (file)
@@ -226,15 +226,12 @@ def arg_parser():  # type: () -> argparse.ArgumentParser
 def add_arv_hints():
     cwltool.command_line_tool.ACCEPTLIST_EN_RELAXED_RE = re.compile(r".*")
     cwltool.command_line_tool.ACCEPTLIST_RE = cwltool.command_line_tool.ACCEPTLIST_EN_RELAXED_RE
-    res10 = pkg_resources.resource_stream(__name__, 'arv-cwl-schema-v1.0.yml')
-    res11 = pkg_resources.resource_stream(__name__, 'arv-cwl-schema-v1.1.yml')
-    customschema10 = res10.read().decode('utf-8')
-    customschema11 = res11.read().decode('utf-8')
-    use_custom_schema("v1.0", "http://arvados.org/cwl", customschema10)
-    use_custom_schema("v1.1.0-dev1", "http://arvados.org/cwl", customschema11)
-    use_custom_schema("v1.1", "http://arvados.org/cwl", customschema11)
-    res10.close()
-    res11.close()
+    supported_versions = ["v1.0", "v1.1", "v1.2"]
+    for s in supported_versions:
+        res = pkg_resources.resource_stream(__name__, 'arv-cwl-schema-%s.yml' % s)
+        customschema = res.read().decode('utf-8')
+        use_custom_schema(s, "http://arvados.org/cwl", customschema)
+        res.close()
     cwltool.process.supportedProcessRequirements.extend([
         "http://arvados.org/cwl#RunInSingleContainer",
         "http://arvados.org/cwl#OutputDirType",
diff --git a/sdk/cwl/arvados_cwl/arv-cwl-schema-v1.2.yml b/sdk/cwl/arvados_cwl/arv-cwl-schema-v1.2.yml
new file mode 100644 (file)
index 0000000..b9b9e61
--- /dev/null
@@ -0,0 +1,206 @@
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: Apache-2.0
+
+$base: "http://arvados.org/cwl#"
+$namespaces:
+  cwl: "https://w3id.org/cwl/cwl#"
+  cwltool: "http://commonwl.org/cwltool#"
+$graph:
+- $import: https://w3id.org/cwl/CommonWorkflowLanguage.yml
+
+- name: cwltool:Secrets
+  type: record
+  inVocab: false
+  extends: cwl:ProcessRequirement
+  fields:
+    class:
+      type: string
+      doc: "Always 'Secrets'"
+      jsonldPredicate:
+        "_id": "@type"
+        "_type": "@vocab"
+    secrets:
+      type: string[]
+      doc: |
+        List one or more input parameters that are sensitive (such as passwords)
+        which will be deliberately obscured from logging.
+      jsonldPredicate:
+        "_type": "@id"
+        refScope: 0
+
+- name: RunInSingleContainer
+  type: record
+  extends: cwl:ProcessRequirement
+  inVocab: false
+  doc: |
+    Indicates that a subworkflow should run in a single container
+    and not be scheduled as separate steps.
+  fields:
+    - name: class
+      type: string
+      doc: "Always 'arv:RunInSingleContainer'"
+      jsonldPredicate:
+        _id: "@type"
+        _type: "@vocab"
+
+- name: OutputDirType
+  type: enum
+  symbols:
+    - local_output_dir
+    - keep_output_dir
+  doc:
+    - |
+      local_output_dir: Use regular file system local to the compute node.
+      There must be sufficient local scratch space to store entire output;
+      specify this with `outdirMin` of `ResourceRequirement`.  Files are
+      batch uploaded to Keep when the process completes.  Most compatible, but
+      upload step can be time consuming for very large files.
+    - |
+      keep_output_dir: Use writable Keep mount.  Files are streamed to Keep as
+      they are written.  Does not consume local scratch space, but does consume
+      RAM for output buffers (up to 192 MiB per file simultaneously open for
+      writing.)  Best suited to processes which produce sequential output of
+      large files (non-sequential writes may produced fragmented file
+      manifests).  Supports regular files and directories, does not support
+      special files such as symlinks, hard links, named pipes, named sockets,
+      or device nodes.
+
+
+- name: RuntimeConstraints
+  type: record
+  extends: cwl:ProcessRequirement
+  inVocab: false
+  doc: |
+    Set Arvados-specific runtime hints.
+  fields:
+    - name: class
+      type: string
+      doc: "Always 'arv:RuntimeConstraints'"
+      jsonldPredicate:
+        _id: "@type"
+        _type: "@vocab"
+    - name: keep_cache
+      type: int?
+      doc: |
+        Size of file data buffer for Keep mount in MiB. Default is 256
+        MiB. Increase this to reduce cache thrashing in situations such as
+        accessing multiple large (64+ MiB) files at the same time, or
+        performing random access on a large file.
+    - name: outputDirType
+      type: OutputDirType?
+      doc: |
+        Preferred backing store for output staging.  If not specified, the
+        system may choose which one to use.
+
+- name: PartitionRequirement
+  type: record
+  extends: cwl:ProcessRequirement
+  inVocab: false
+  doc: |
+    Select preferred compute partitions on which to run jobs.
+  fields:
+    - name: class
+      type: string
+      doc: "Always 'arv:PartitionRequirement'"
+      jsonldPredicate:
+        _id: "@type"
+        _type: "@vocab"
+    - name: partition
+      type:
+        - string
+        - string[]
+
+- name: APIRequirement
+  type: record
+  extends: cwl:ProcessRequirement
+  inVocab: false
+  doc: |
+    Indicates that process wants to access to the Arvados API.  Will be granted
+    limited network access and have ARVADOS_API_HOST and ARVADOS_API_TOKEN set
+    in the environment.
+  fields:
+    - name: class
+      type: string
+      doc: "Always 'arv:APIRequirement'"
+      jsonldPredicate:
+        _id: "@type"
+        _type: "@vocab"
+
+- name: IntermediateOutput
+  type: record
+  extends: cwl:ProcessRequirement
+  inVocab: false
+  doc: |
+    Specify desired handling of intermediate output collections.
+  fields:
+    class:
+      type: string
+      doc: "Always 'arv:IntermediateOutput'"
+      jsonldPredicate:
+        _id: "@type"
+        _type: "@vocab"
+    outputTTL:
+      type: int
+      doc: |
+        If the value is greater than zero, consider intermediate output
+        collections to be temporary and should be automatically
+        trashed. Temporary collections will be trashed `outputTTL` seconds
+        after creation.  A value of zero means intermediate output should be
+        retained indefinitely (this is the default behavior).
+
+        Note: arvados-cwl-runner currently does not take workflow dependencies
+        into account when setting the TTL on an intermediate output
+        collection. If the TTL is too short, it is possible for a collection to
+        be trashed before downstream steps that consume it are started.  The
+        recommended minimum value for TTL is the expected duration of the
+        entire the workflow.
+
+- name: WorkflowRunnerResources
+  type: record
+  extends: cwl:ProcessRequirement
+  inVocab: false
+  doc: |
+    Specify memory or cores resource request for the CWL runner process itself.
+  fields:
+    class:
+      type: string
+      doc: "Always 'arv:WorkflowRunnerResources'"
+      jsonldPredicate:
+        _id: "@type"
+        _type: "@vocab"
+    ramMin:
+      type: int?
+      doc: Minimum RAM, in mebibytes (2**20)
+      jsonldPredicate: "https://w3id.org/cwl/cwl#ResourceRequirement/ramMin"
+    coresMin:
+      type: int?
+      doc: Minimum cores allocated to cwl-runner
+      jsonldPredicate: "https://w3id.org/cwl/cwl#ResourceRequirement/coresMin"
+    keep_cache:
+      type: int?
+      doc: |
+        Size of collection metadata cache for the workflow runner, in
+        MiB.  Default 256 MiB.  Will be added on to the RAM request
+        when determining node size to request.
+      jsonldPredicate: "http://arvados.org/cwl#RuntimeConstraints/keep_cache"
+
+- name: ClusterTarget
+  type: record
+  extends: cwl:ProcessRequirement
+  inVocab: false
+  doc: |
+    Specify where a workflow step should run
+  fields:
+    class:
+      type: string
+      doc: "Always 'arv:ClusterTarget'"
+      jsonldPredicate:
+        _id: "@type"
+        _type: "@vocab"
+    cluster_id:
+      type: string?
+      doc: The cluster to run the container
+    project_uuid:
+      type: string?
+      doc: The project that will own the container requests and intermediate collections
index d703fcbc55fdec7889108ca01c898365117733cd..c8ab71e50b3dd5bc3cfd2e6f08fa03cdb46f3100 100644 (file)
@@ -30,7 +30,7 @@ setup(name='arvados-cwl-runner',
       download_url="https://github.com/arvados/arvados.git",
       license='Apache 2.0',
       packages=find_packages(),
-      package_data={'arvados_cwl': ['arv-cwl-schema-v1.0.yml', 'arv-cwl-schema-v1.1.yml']},
+      package_data={'arvados_cwl': ['arv-cwl-schema-v1.0.yml', 'arv-cwl-schema-v1.1.yml', 'arv-cwl-schema-v1.2.yml']},
       scripts=[
           'bin/cwl-runner',
           'bin/arvados-cwl-runner',
@@ -39,7 +39,7 @@ setup(name='arvados-cwl-runner',
       # file to determine what version of cwltool and schema-salad to
       # build.
       install_requires=[
-          'cwltool==3.0.20200720165847',
+          'cwltool==3.0.20200807132242',
           'schema-salad==7.0.20200612160654',
           'arvados-python-client{}'.format(pysdk_dep),
           'setuptools',
index c32f88864f88750c00fe896286e147ccd9d061ce..5a2cfb8800402496f3f8fe400cf38c786e57d6eb 100644 (file)
@@ -86,6 +86,7 @@ type ListOptions struct {
        IncludeTrash       bool                   `json:"include_trash"`
        IncludeOldVersions bool                   `json:"include_old_versions"`
        BypassFederation   bool                   `json:"bypass_federation"`
+       ForwardedFor       string                 `json:"forwarded_for,omitempty"`
 }
 
 type CreateOptions struct {
index 257a2b4ef54156d65b22bafb3152cc067de6cd13..86fe218c3361a1b986e0cd38ab09a39eac1ec9bc 100644 (file)
@@ -23,6 +23,7 @@ func (s *DurationSuite) TestMarshalJSON(c *check.C) {
        c.Check(err, check.IsNil)
        c.Check(d.D, check.Equals, Duration(time.Second+234*time.Millisecond))
        buf, err := json.Marshal(d)
+       c.Check(err, check.IsNil)
        c.Check(string(buf), check.Equals, `{"D":"1.234s"}`)
 
        for _, trial := range []struct {
index 5628dcc9c43b42ef6560ddfa1eba2bc0482001d3..61d82c7fa9f4e442d6492ba8fc0f285df76bd5f2 100644 (file)
@@ -52,6 +52,7 @@ func (s *SiteFSSuite) testHomeProject(c *check.C, path string) {
        f, err := s.fs.Open(path)
        c.Assert(err, check.IsNil)
        fis, err := f.Readdir(-1)
+       c.Assert(err, check.IsNil)
        c.Check(len(fis), check.Not(check.Equals), 0)
 
        ok := false
index fff0b7e010b22b1811991ce3b6249093c50b616b..80cc03df37b88ad82ad246db6d4d7bce68dd68a2 100644 (file)
@@ -79,6 +79,7 @@ func (s *SiteFSSuite) TestByUUIDAndPDH(c *check.C) {
                f, err = s.fs.Open("/by_id/" + path)
                c.Assert(err, check.IsNil)
                fis, err = f.Readdir(-1)
+               c.Assert(err, check.IsNil)
                var names []string
                for _, fi := range fis {
                        names = append(names, fi.Name())
@@ -89,6 +90,7 @@ func (s *SiteFSSuite) TestByUUIDAndPDH(c *check.C) {
        f, err = s.fs.Open("/by_id/" + fixtureAProjectUUID + "/A Subproject/baz_file")
        c.Assert(err, check.IsNil)
        fis, err = f.Readdir(-1)
+       c.Assert(err, check.IsNil)
        var names []string
        for _, fi := range fis {
                names = append(names, fi.Name())
index e0a41c924bb3de6a0f9ae7826fd4abd2febfd5eb..fc686ad63739e51340d5e254f8f68d65ac4db3e7 100644 (file)
@@ -63,6 +63,7 @@ func (s *ServerRequiredSuite) TestMakeArvadosClientInsecure(c *C) {
 
 func (s *ServerRequiredSuite) TestGetInvalidUUID(c *C) {
        arv, err := MakeArvadosClient()
+       c.Assert(err, IsNil)
 
        getback := make(Dict)
        err = arv.Get("collections", "", nil, &getback)
@@ -80,6 +81,7 @@ func (s *ServerRequiredSuite) TestGetInvalidUUID(c *C) {
 
 func (s *ServerRequiredSuite) TestGetValidUUID(c *C) {
        arv, err := MakeArvadosClient()
+       c.Assert(err, IsNil)
 
        getback := make(Dict)
        err = arv.Get("collections", "zzzzz-4zz18-abcdeabcdeabcde", nil, &getback)
@@ -95,6 +97,7 @@ func (s *ServerRequiredSuite) TestGetValidUUID(c *C) {
 
 func (s *ServerRequiredSuite) TestInvalidResourceType(c *C) {
        arv, err := MakeArvadosClient()
+       c.Assert(err, IsNil)
 
        getback := make(Dict)
        err = arv.Get("unicorns", "zzzzz-zebra-unicorn7unicorn", nil, &getback)
@@ -141,6 +144,7 @@ func (s *ServerRequiredSuite) TestErrorResponse(c *C) {
 
 func (s *ServerRequiredSuite) TestAPIDiscovery_Get_defaultCollectionReplication(c *C) {
        arv, err := MakeArvadosClient()
+       c.Assert(err, IsNil)
        value, err := arv.Discovery("defaultCollectionReplication")
        c.Assert(err, IsNil)
        c.Assert(value, NotNil)
@@ -148,6 +152,7 @@ func (s *ServerRequiredSuite) TestAPIDiscovery_Get_defaultCollectionReplication(
 
 func (s *ServerRequiredSuite) TestAPIDiscovery_Get_noSuchParameter(c *C) {
        arv, err := MakeArvadosClient()
+       c.Assert(err, IsNil)
        value, err := arv.Discovery("noSuchParameter")
        c.Assert(err, NotNil)
        c.Assert(value, IsNil)
index 32802b6a9e00f341195712284b897e1dc083eb48..7d5eb2b64f326e2cd10b41bbeacd147a2bff682a 100644 (file)
@@ -58,6 +58,7 @@ func (s *Suite) TestLogRequests(c *check.C) {
 
        gotReq := make(map[string]interface{})
        err = dec.Decode(&gotReq)
+       c.Check(err, check.IsNil)
        c.Logf("%#v", gotReq)
        c.Check(gotReq["RequestID"], check.Matches, "req-[a-z0-9]{20}")
        c.Check(gotReq["reqForwardedFor"], check.Equals, "1.2.3.4:12345")
@@ -65,6 +66,7 @@ func (s *Suite) TestLogRequests(c *check.C) {
 
        gotResp := make(map[string]interface{})
        err = dec.Decode(&gotResp)
+       c.Check(err, check.IsNil)
        c.Logf("%#v", gotResp)
        c.Check(gotResp["RequestID"], check.Equals, gotReq["RequestID"])
        c.Check(gotResp["reqForwardedFor"], check.Equals, "1.2.3.4:12345")
@@ -111,9 +113,11 @@ func (s *Suite) TestLogErrorBody(c *check.C) {
 
                gotReq := make(map[string]interface{})
                err = dec.Decode(&gotReq)
+               c.Check(err, check.IsNil)
                c.Logf("%#v", gotReq)
                gotResp := make(map[string]interface{})
                err = dec.Decode(&gotResp)
+               c.Check(err, check.IsNil)
                c.Logf("%#v", gotResp)
                if trial.expectLog {
                        c.Check(gotResp["respBody"], check.Equals, trial.expectBody, comment)
index c6c9f044416a7fb93c4b898dfcafcdc121dfc1e4..75603f1baa2bcd59f3af7249e7fc540a06d63dae 100644 (file)
@@ -134,11 +134,11 @@ func (s *CollectionReaderUnit) TestCollectionReaderContent(c *check.C) {
                        c.Check(err, check.Equals, want)
                case string:
                        buf := make([]byte, len(want))
-                       n, err := io.ReadFull(rdr, buf)
+                       _, err := io.ReadFull(rdr, buf)
                        c.Check(err, check.IsNil)
                        for i := 0; i < 4; i++ {
                                c.Check(string(buf), check.Equals, want)
-                               n, err = rdr.Read(buf)
+                               n, err := rdr.Read(buf)
                                c.Check(n, check.Equals, 0)
                                c.Check(err, check.Equals, io.EOF)
                        }
@@ -173,6 +173,7 @@ func (s *CollectionReaderUnit) TestCollectionReaderManyBlocks(c *check.C) {
        filesize := 0
        for i := range locs {
                _, err := rand.Read(buf[:i])
+               c.Assert(err, check.IsNil)
                h.Write(buf[:i])
                locs[i], _, err = s.kc.PutB(buf[:i])
                c.Assert(err, check.IsNil)
@@ -202,9 +203,9 @@ func (s *CollectionReaderUnit) TestCollectionReaderManyBlocks(c *check.C) {
                offset := rand.Intn(len(buf) - 1)
                count := rand.Intn(len(buf) - offset)
                if rand.Intn(2) == 0 {
-                       curPos, err = rdr.Seek(int64(offset)-curPos, io.SeekCurrent)
+                       curPos, _ = rdr.Seek(int64(offset)-curPos, io.SeekCurrent)
                } else {
-                       curPos, err = rdr.Seek(int64(offset), io.SeekStart)
+                       curPos, _ = rdr.Seek(int64(offset), io.SeekStart)
                }
                c.Check(curPos, check.Equals, int64(offset))
                for count > 0 {
@@ -215,6 +216,7 @@ func (s *CollectionReaderUnit) TestCollectionReaderManyBlocks(c *check.C) {
                        count -= n
                }
                curPos, err = rdr.Seek(0, io.SeekCurrent)
+               c.Check(err, check.IsNil)
                c.Check(curPos, check.Equals, int64(offset))
        }
        c.Check(md5.Sum(buf), check.DeepEquals, md5.Sum(testdata))
index e25faed33c1d8c44341e88ec2938948f64140117..a1801b21456b9a6d8bbb716f4db19eaa78feaa4a 100644 (file)
@@ -80,10 +80,12 @@ func (s *ServerRequiredSuite) TestDefaultReplications(c *C) {
        c.Assert(err, Equals, nil)
 
        kc, err := MakeKeepClient(arv)
+       c.Check(err, IsNil)
        c.Assert(kc.Want_replicas, Equals, 2)
 
        arv.DiscoveryDoc["defaultCollectionReplication"] = 3.0
        kc, err = MakeKeepClient(arv)
+       c.Check(err, IsNil)
        c.Assert(kc.Want_replicas, Equals, 3)
 
        arv.DiscoveryDoc["defaultCollectionReplication"] = 1.0
@@ -367,6 +369,7 @@ func (s *StandaloneSuite) TestPutWithFail(c *C) {
                make(chan string, 1)}
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
 
        kc.Want_replicas = 2
@@ -426,6 +429,7 @@ func (s *StandaloneSuite) TestPutWithTooManyFail(c *C) {
                make(chan string, 4)}
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
 
        kc.Want_replicas = 2
@@ -487,6 +491,7 @@ func (s *StandaloneSuite) TestGet(c *C) {
        defer ks.listener.Close()
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
        arv.ApiToken = "abc123"
        kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
@@ -511,6 +516,7 @@ func (s *StandaloneSuite) TestGet404(c *C) {
        defer ks.listener.Close()
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
        arv.ApiToken = "abc123"
        kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
@@ -552,6 +558,7 @@ func (s *StandaloneSuite) TestGetFail(c *C) {
        defer ks.listener.Close()
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
        arv.ApiToken = "abc123"
        kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
@@ -583,6 +590,7 @@ func (s *StandaloneSuite) TestGetFailRetry(c *C) {
        defer ks.listener.Close()
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
        arv.ApiToken = "abc123"
        kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
@@ -609,6 +617,7 @@ func (s *StandaloneSuite) TestGetNetError(c *C) {
        hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
        arv.ApiToken = "abc123"
        kc.SetServiceRoots(map[string]string{"x": "http://localhost:62222"}, nil, nil)
@@ -645,6 +654,7 @@ func (s *StandaloneSuite) TestGetWithServiceHint(c *C) {
        defer ks.listener.Close()
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
        arv.ApiToken = "abc123"
        kc.SetServiceRoots(
@@ -688,6 +698,7 @@ func (s *StandaloneSuite) TestGetWithLocalServiceHint(c *C) {
        defer ks.listener.Close()
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
        arv.ApiToken = "abc123"
        kc.SetServiceRoots(
@@ -735,6 +746,7 @@ func (s *StandaloneSuite) TestGetWithServiceHintFailoverToLocals(c *C) {
        defer ksGateway.listener.Close()
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
        arv.ApiToken = "abc123"
        kc.SetServiceRoots(
@@ -772,11 +784,13 @@ func (s *StandaloneSuite) TestChecksum(c *C) {
        defer ks.listener.Close()
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
        arv.ApiToken = "abc123"
        kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
 
        r, n, _, err := kc.Get(barhash)
+       c.Check(err, IsNil)
        _, err = ioutil.ReadAll(r)
        c.Check(n, Equals, int64(3))
        c.Check(err, Equals, nil)
@@ -784,6 +798,7 @@ func (s *StandaloneSuite) TestChecksum(c *C) {
        <-st.handled
 
        r, n, _, err = kc.Get(foohash)
+       c.Check(err, IsNil)
        _, err = ioutil.ReadAll(r)
        c.Check(n, Equals, int64(3))
        c.Check(err, Equals, BadChecksum)
@@ -806,6 +821,7 @@ func (s *StandaloneSuite) TestGetWithFailures(c *C) {
                content}
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
        arv.ApiToken = "abc123"
        localRoots := make(map[string]string)
@@ -852,6 +868,7 @@ func (s *ServerRequiredSuite) TestPutGetHead(c *C) {
        content := []byte("TestPutGetHead")
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, err := MakeKeepClient(arv)
        c.Assert(err, Equals, nil)
 
@@ -912,6 +929,7 @@ func (s *StandaloneSuite) TestPutProxy(c *C) {
        st := StubProxyHandler{make(chan string, 1)}
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
 
        kc.Want_replicas = 2
@@ -940,6 +958,7 @@ func (s *StandaloneSuite) TestPutProxyInsufficientReplicas(c *C) {
        st := StubProxyHandler{make(chan string, 1)}
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
 
        kc.Want_replicas = 3
@@ -1133,6 +1152,7 @@ func (s *StandaloneSuite) TestGetIndexWithPrefix(c *C) {
        defer ks.listener.Close()
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
        arv.ApiToken = "abc123"
        kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
@@ -1159,6 +1179,7 @@ func (s *StandaloneSuite) TestGetIndexIncomplete(c *C) {
        defer ks.listener.Close()
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
        arv.ApiToken = "abc123"
        kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
@@ -1181,6 +1202,7 @@ func (s *StandaloneSuite) TestGetIndexWithNoSuchServer(c *C) {
        defer ks.listener.Close()
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
        arv.ApiToken = "abc123"
        kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
@@ -1201,6 +1223,7 @@ func (s *StandaloneSuite) TestGetIndexWithNoSuchPrefix(c *C) {
        defer ks.listener.Close()
 
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Check(err, IsNil)
        kc, _ := MakeKeepClient(arv)
        arv.ApiToken = "abc123"
        kc.SetServiceRoots(map[string]string{"x": ks.url}, nil, nil)
index c231cc0735795cae9577f9e52f7e5f4bae449bb3..e31ac05418a1154a14f87fc7ed4298e283564e3d 100644 (file)
@@ -3,6 +3,7 @@
 # SPDX-License-Identifier: Apache-2.0
 
 import arvados
+import arvados.errors
 import json
 import sys
 
@@ -113,4 +114,64 @@ for i in (3, 5, 9):
 users = apiC.users().list().execute()
 check_A(users)
 
+
+####
+# bug 16683 tests
+
+# Check that this query returns empty, instead of returning a 500 or
+# 502 error.
+# Yes, we're asking for a group from the users endpoint.  This is not a
+# mistake, this is something workbench does to populate the sharing
+# dialog.
+clusterID_B = apiB.configs().get().execute()["ClusterID"]
+i = apiB.users().list(filters=[["uuid", "in", ["%s-j7d0g-fffffffffffffff" % clusterID_B]]], count="none").execute()
+assert len(i["items"]) == 0
+
+# Check that we can create a project and give a remote user access to it
+
+tok3 = apiA.api_client_authorizations().create(body={"api_client_authorization": {"owner_uuid": by_username["case3"]}}).execute()
+tok4 = apiA.api_client_authorizations().create(body={"api_client_authorization": {"owner_uuid": by_username["case4"]}}).execute()
+
+v2_token3 = "v2/%s/%s" % (tok3["uuid"], tok3["api_token"])
+v2_token4 = "v2/%s/%s" % (tok4["uuid"], tok4["api_token"])
+
+apiB_3 = arvados.api(host=j["arvados_api_hosts"][1], token=v2_token3, insecure=True)
+apiB_4 = arvados.api(host=j["arvados_api_hosts"][1], token=v2_token4, insecure=True)
+
+assert apiB_3.users().current().execute()["uuid"] == by_username["case3"]
+assert apiB_4.users().current().execute()["uuid"] == by_username["case4"]
+
+newproject = apiB_3.groups().create(body={"group_class": "project",
+                                           "name":"fed test project"},
+                                    ensure_unique_name=True).execute()
+
+try:
+    # Expect to fail
+    apiB_4.groups().get(uuid=newproject["uuid"]).execute()
+except arvados.errors.ApiError as e:
+    if e.resp['status'] == '404':
+        pass
+    else:
+        raise
+
+l = apiB_3.links().create(body={"link_class": "permission",
+                            "name":"can_read",
+                            "tail_uuid": by_username["case4"],
+                            "head_uuid": newproject["uuid"]}).execute()
+
+# Expect to succeed
+apiB_4.groups().get(uuid=newproject["uuid"]).execute()
+
+# remove permission
+apiB_3.links().delete(uuid=l["uuid"]).execute()
+
+try:
+    # Expect to fail again
+    apiB_4.groups().get(uuid=newproject["uuid"]).execute()
+except arvados.errors.ApiError as e:
+    if e.resp['status'] == '404':
+        pass
+    else:
+        raise
+
 print("Passed checks")
index 01a31adb91967c0cb3648e364b3af7c891fd28f0..67794208de7c999c7b8b0b3a8c451f2b7bb36c57 100644 (file)
@@ -749,6 +749,20 @@ class ArvadosModel < ApplicationRecord
     %r/[a-z0-9]{5}-#{uuid_prefix}-[a-z0-9]{15}/
   end
 
+  def check_readable_uuid attr, attr_value
+    return if attr_value.nil?
+    if (r = ArvadosModel::resource_class_for_uuid attr_value)
+      unless skip_uuid_read_permission_check.include? attr
+        r = r.readable_by(current_user)
+      end
+      if r.where(uuid: attr_value).count == 0
+        errors.add(attr, "'#{attr_value}' not found")
+      end
+    else
+      # Not a valid uuid or PDH, but that (currently) is not an error.
+    end
+  end
+
   def ensure_valid_uuids
     specials = [system_user_uuid]
 
@@ -757,16 +771,7 @@ class ArvadosModel < ApplicationRecord
         next if skip_uuid_existence_check.include? attr
         attr_value = send attr
         next if specials.include? attr_value
-        if attr_value
-          if (r = ArvadosModel::resource_class_for_uuid attr_value)
-            unless skip_uuid_read_permission_check.include? attr
-              r = r.readable_by(current_user)
-            end
-            if r.where(uuid: attr_value).count == 0
-              errors.add(attr, "'#{attr_value}' not found")
-            end
-          end
-        end
+        check_readable_uuid attr, attr_value
       end
     end
   end
index e4ba7f3de1ef8f20833355efb0dae1a153b05113..0d7334e44e85440d37a530e6316d338f125b92aa 100644 (file)
@@ -43,6 +43,28 @@ class Link < ArvadosModel
 
   protected
 
+  def check_readable_uuid attr, attr_value
+    if attr == 'tail_uuid' &&
+       !attr_value.nil? &&
+       self.link_class == 'permission' &&
+       attr_value[0..4] != Rails.configuration.ClusterID &&
+       ApiClientAuthorization.remote_host(uuid_prefix: attr_value[0..4]) &&
+       ArvadosModel::resource_class_for_uuid(attr_value) == User
+      # Permission link tail is a remote user (the user permissions
+      # are being granted to), so bypass the standard check that a
+      # referenced object uuid is readable by current user.
+      #
+      # We could do a call to the remote cluster to check if the user
+      # in tail_uuid exists.  This would detect copy-and-paste errors,
+      # but add another way for the request to fail, and I don't think
+      # it would improve security.  It doesn't seem to be worth the
+      # complexity tradeoff.
+      true
+    else
+      super
+    end
+  end
+
   def permission_to_attach_to_objects
     # Anonymous users cannot write links
     return false if !current_user
@@ -76,6 +98,11 @@ class Link < ArvadosModel
 
     head_obj = ArvadosModel.find_by_uuid(head_uuid)
 
+    if head_obj.nil?
+      errors.add(:head_uuid, "does not exist")
+      return false
+    end
+
     # No permission links can be pointed to past collection versions
     if head_obj.is_a?(Collection) && head_obj.current_version_uuid != head_uuid
       errors.add(:head_uuid, "cannot point to a past version of a collection")
index 00f3cc291352493b11258aa0f9750fc883a263ff..c7d21bdc4da721d51f40c0cb235a15a8e3c3db96 100644 (file)
@@ -58,6 +58,14 @@ class LinkTest < ActiveSupport::TestCase
                                   users(:active).uuid.sub(/-\w+$/, "-#{'z' * 15}"))
   end
 
+  test "link granting permission to remote user is valid" do
+    refute new_active_link_valid?(tail_uuid:
+                                  users(:active).uuid.sub(/^\w+-/, "foooo-"))
+    Rails.configuration.RemoteClusters = Rails.configuration.RemoteClusters.merge({foooo: ActiveSupport::InheritableOptions.new({Host: "bar.com"})})
+    assert new_active_link_valid?(tail_uuid:
+                                  users(:active).uuid.sub(/^\w+-/, "foooo-"))
+  end
+
   test "link granting non-project permission to unreadable user is invalid" do
     refute new_active_link_valid?(tail_uuid: users(:admin).uuid,
                                   head_uuid: collections(:bar_file).uuid)
index a6445506e5fd3b3c1500caf6d3d8cb98d63b5f08..b154f6e99848a3623b167726412ce5b48a59c715 100644 (file)
@@ -31,6 +31,7 @@ func (s *mainSuite) TestHTTPServer(c *check.C) {
                c.Fatal(err)
        }
        _, p, err := net.SplitHostPort(ln.Addr().String())
+       c.Check(err, check.IsNil)
        ln.Close()
        config := "Clusters:\n zzzzz:\n  ManagementToken: abcdefg\n  Services: {Keepbalance: {InternalURLs: {'http://localhost:" + p + "/': {}}}}\n"
 
index 97045a660394fe6533fee5d6a444ce07915757ea..d9886c07f317904ea141343d2f26554ecae10b3a 100644 (file)
@@ -166,7 +166,9 @@ func (s *StubbedS3AWSSuite) TestIAMRoleCredentials(c *check.C) {
                metrics: newVolumeMetricsVecs(prometheus.NewRegistry()),
        }
        err := v.check(s.metadata.URL + "/latest")
+       c.Check(err, check.IsNil)
        creds, err := v.bucket.svc.Client.Config.Credentials.Retrieve(context.Background())
+       c.Check(err, check.IsNil)
        c.Check(creds.AccessKeyID, check.Equals, "ASIAIOSFODNN7EXAMPLE")
        c.Check(creds.SecretAccessKey, check.Equals, "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY")
 
@@ -185,6 +187,7 @@ func (s *StubbedS3AWSSuite) TestIAMRoleCredentials(c *check.C) {
                metrics: newVolumeMetricsVecs(prometheus.NewRegistry()),
        }
        err = deadv.check(s.metadata.URL + "/latest")
+       c.Check(err, check.IsNil)
        _, err = deadv.bucket.svc.Client.Config.Credentials.Retrieve(context.Background())
        c.Check(err, check.ErrorMatches, `(?s).*EC2RoleRequestError: no EC2 instance role found.*`)
        c.Check(err, check.ErrorMatches, `(?s).*404.*`)