Merge branch '17344-easy-demo'
authorTom Clegg <tom@curii.com>
Thu, 8 Sep 2022 15:05:51 +0000 (11:05 -0400)
committerTom Clegg <tom@curii.com>
Thu, 8 Sep 2022 15:05:51 +0000 (11:05 -0400)
closes #17344

Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@curii.com>

19 files changed:
cmd/arvados-package/build.go
cmd/arvados-package/fpm.go
lib/boot/nginx.go
lib/boot/supervisor.go
lib/cloud/loopback/loopback.go
sdk/go/arvados/client.go
sdk/go/arvadosclient/arvadosclient.go
sdk/python/arvados/api.py
sdk/python/arvados/keep.py
sdk/python/tests/nginx.conf
sdk/python/tests/run_test_server.py
sdk/python/tests/test_keep_client.py
services/crunch-dispatch-local/crunch-dispatch-local.go
services/crunch-dispatch-slurm/crunch-dispatch-slurm.go
services/keepproxy/keepproxy_test.go
tools/keep-block-check/keep-block-check.go
tools/keep-block-check/keep-block-check_test.go
tools/keep-rsync/keep-rsync.go
tools/keep-rsync/keep-rsync_test.go

index 9841c890b78a9f8363817d135e915bea29c6b472..2ce8a674322dedf410b331b496a7e31987ff01a1 100644 (file)
@@ -133,6 +133,13 @@ func build(ctx context.Context, opts opts, stdin io.Reader, stdout, stderr io.Wr
        if err != nil {
                return err
        }
+       cmd = exec.CommandContext(ctx, "ls", "-l", opts.PackageDir+"/"+packageFilename)
+       cmd.Stdout = stdout
+       cmd.Stderr = stderr
+       err = cmd.Run()
+       if err != nil {
+               return err
+       }
 
        return nil
 }
index 64d0adabe39190452891db68ee6eeb91d20717ee..0b13b15c1e2df4047bf6782b383c62d06af1c8e2 100644 (file)
@@ -142,10 +142,5 @@ func fpm(ctx context.Context, opts opts, stdin io.Reader, stdout, stderr io.Writ
                }
        }
 
-       cmd = exec.Command("ls", "-l", pkgfile)
-       cmd.Stdout = stdout
-       cmd.Stderr = stderr
-       _ = cmd.Run()
-
        return nil
 }
index b391c4dc8c93f61f50d221bb116cf71da3c10960..9f1091eac39177f15855de7b7e8ccf2b0ac443f3 100644 (file)
@@ -5,6 +5,7 @@
 package boot
 
 import (
+       "bytes"
        "context"
        "fmt"
        "io/ioutil"
@@ -17,6 +18,7 @@ import (
        "strings"
 
        "git.arvados.org/arvados.git/sdk/go/arvados"
+       "github.com/sirupsen/logrus"
 )
 
 // Run an Nginx process that proxies the supervisor's configured
@@ -46,6 +48,7 @@ func (runNginx) Run(ctx context.Context, fail func(error), super *Supervisor) er
        vars := map[string]string{
                "LISTENHOST":       extListenHost,
                "UPSTREAMHOST":     super.ListenHost,
+               "INTERNALSUBNETS":  internalSubnets(super.logger),
                "SSLCERT":          filepath.Join(super.tempdir, "server.crt"),
                "SSLKEY":           filepath.Join(super.tempdir, "server.key"),
                "ACCESSLOG":        filepath.Join(super.tempdir, "nginx_access.log"),
@@ -150,3 +153,27 @@ func (runNginx) Run(ctx context.Context, fail func(error), super *Supervisor) er
        }
        return waitForConnect(ctx, testurl.Host)
 }
+
+// Return 0 or more local subnets as "geo" fragments for Nginx config,
+// e.g., "1.2.3.0/24 0; 10.1.0.0/16 0;".
+func internalSubnets(logger logrus.FieldLogger) string {
+       iproutes, err := exec.Command("ip", "route").CombinedOutput()
+       if err != nil {
+               logger.Warnf("treating all clients as external because `ip route` failed: %s (%q)", err, iproutes)
+               return ""
+       }
+       subnets := ""
+       for _, line := range bytes.Split(iproutes, []byte("\n")) {
+               fields := strings.Fields(string(line))
+               if len(fields) > 2 && fields[1] == "dev" {
+                       // lan example:
+                       // 192.168.86.0/24 dev ens3 proto kernel scope link src 192.168.86.196
+                       // gcp example (private subnet):
+                       // 10.47.0.0/24 dev eth0 proto kernel scope link src 10.47.0.5
+                       // gcp example (no private subnet):
+                       // 10.128.0.1 dev ens4 scope link
+                       subnets += fields[0] + " 0; "
+               }
+       }
+       return subnets
+}
index ddc17953d2363d020d6aa37332c97c36c5b48646..ca88653fa643e56a93cdb8eb2136cacbf403044f 100644 (file)
@@ -282,7 +282,7 @@ func (super *Supervisor) runCluster() error {
        if err != nil {
                return err
        }
-       conffile, err := os.OpenFile(filepath.Join(super.wwwtempdir, "config.yml"), os.O_CREATE|os.O_WRONLY, 0644)
+       conffile, err := os.OpenFile(filepath.Join(super.wwwtempdir, "config.yml"), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
        if err != nil {
                return err
        }
@@ -308,6 +308,7 @@ func (super *Supervisor) runCluster() error {
        if super.ClusterType != "production" {
                super.prependEnv("PATH", super.tempdir+"/bin:")
        }
+       super.setEnv("ARVADOS_SERVER_ADDRESS", super.ListenHost)
 
        // Now that we have the config, replace the bootstrap logger
        // with a new one according to the logging config.
index 6ad4f876d99cb908c6d95fca7ebb0ecf6d03492e..fb7a35beae154cb384e60e1b130d76970ad23d8a 100644 (file)
@@ -11,6 +11,7 @@ import (
        "encoding/json"
        "errors"
        "io"
+       "os"
        "os/exec"
        "os/user"
        "strings"
@@ -58,6 +59,16 @@ func (is *instanceSet) Create(it arvados.InstanceType, _ cloud.ImageID, tags clo
        if len(is.instances) > 0 {
                return nil, errQuota
        }
+       // A crunch-run process running in a previous instance may
+       // have marked the node as broken. In the loopback scenario a
+       // destroy+create cycle doesn't fix whatever was broken -- but
+       // nothing else will either, so the best we can do is remove
+       // the "broken" flag and try again.
+       if err := os.Remove("/var/lock/crunch-run-broken"); err == nil {
+               is.logger.Info("removed /var/lock/crunch-run-broken")
+       } else if !errors.Is(err, os.ErrNotExist) {
+               return nil, err
+       }
        u, err := user.Current()
        if err != nil {
                return nil, err
index 24d5ac3e335c824f5ea4a444c6066ce37f3cc86f..cdc07bb0afd2c80b09985ad28f18c6c0fa1abcde 100644 (file)
@@ -15,6 +15,7 @@ import (
        "io/fs"
        "io/ioutil"
        "log"
+       "net"
        "net/http"
        "net/url"
        "os"
@@ -94,7 +95,40 @@ func NewClientFromConfig(cluster *Cluster) (*Client, error) {
        if ctrlURL.Host == "" {
                return nil, fmt.Errorf("no host in config Services.Controller.ExternalURL: %v", ctrlURL)
        }
+       var hc *http.Client
+       if srvaddr := os.Getenv("ARVADOS_SERVER_ADDRESS"); srvaddr != "" {
+               // When this client is used to make a request to
+               // https://{ctrlhost}:port/ (any port), it dials the
+               // indicated port on ARVADOS_SERVER_ADDRESS instead.
+               //
+               // This is invoked by arvados-server boot to ensure
+               // that server->server traffic (e.g.,
+               // keepproxy->controller) only hits local interfaces,
+               // even if the Controller.ExternalURL host is a load
+               // balancer / gateway and not a local interface
+               // address (e.g., when running on a cloud VM).
+               //
+               // This avoids unnecessary delay/cost of routing
+               // external traffic, and also allows controller to
+               // recognize other services as internal clients based
+               // on the connection source address.
+               divertedHost := (*url.URL)(&cluster.Services.Controller.ExternalURL).Hostname()
+               var dialer net.Dialer
+               hc = &http.Client{
+                       Transport: &http.Transport{
+                               TLSClientConfig: &tls.Config{InsecureSkipVerify: cluster.TLS.Insecure},
+                               DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
+                                       host, port, err := net.SplitHostPort(addr)
+                                       if err == nil && network == "tcp" && host == divertedHost {
+                                               addr = net.JoinHostPort(srvaddr, port)
+                                       }
+                                       return dialer.DialContext(ctx, network, addr)
+                               },
+                       },
+               }
+       }
        return &Client{
+               Client:   hc,
                Scheme:   ctrlURL.Scheme,
                APIHost:  ctrlURL.Host,
                Insecure: cluster.TLS.Insecure,
index 24070c5b0658d61f53104d9351352f8654611c27..13b3a30ac40d8c9f21f5a39434164f34d353d270 100644 (file)
@@ -103,10 +103,6 @@ type ArvadosClient struct {
        // Client object shared by client requests.  Supports HTTP KeepAlive.
        Client *http.Client
 
-       // If true, sets the X-External-Client header to indicate
-       // the client is outside the cluster.
-       External bool
-
        // Base URIs of Keep services, e.g., {"https://host1:8443",
        // "https://host2:8443"}.  If this is nil, Keep clients will
        // use the arvados.v1.keep_services.accessible API to discover
@@ -166,17 +162,20 @@ func MakeTLSConfig(insecure bool) *tls.Config {
 // fields from configuration files but still need to use the
 // arvadosclient.ArvadosClient package.
 func New(c *arvados.Client) (*ArvadosClient, error) {
-       ac := &ArvadosClient{
-               Scheme:      "https",
-               ApiServer:   c.APIHost,
-               ApiToken:    c.AuthToken,
-               ApiInsecure: c.Insecure,
-               Client: &http.Client{
+       hc := c.Client
+       if hc == nil {
+               hc = &http.Client{
                        Timeout: 5 * time.Minute,
                        Transport: &http.Transport{
                                TLSClientConfig: MakeTLSConfig(c.Insecure)},
-               },
-               External:          false,
+               }
+       }
+       ac := &ArvadosClient{
+               Scheme:            "https",
+               ApiServer:         c.APIHost,
+               ApiToken:          c.AuthToken,
+               ApiInsecure:       c.Insecure,
+               Client:            hc,
                Retries:           2,
                KeepServiceURIs:   c.KeepServiceURIs,
                lastClosedIdlesAt: time.Now(),
@@ -187,15 +186,9 @@ func New(c *arvados.Client) (*ArvadosClient, error) {
 
 // MakeArvadosClient creates a new ArvadosClient using the standard
 // environment variables ARVADOS_API_HOST, ARVADOS_API_TOKEN,
-// ARVADOS_API_HOST_INSECURE, ARVADOS_EXTERNAL_CLIENT, and
-// ARVADOS_KEEP_SERVICES.
-func MakeArvadosClient() (ac *ArvadosClient, err error) {
-       ac, err = New(arvados.NewClientFromEnv())
-       if err != nil {
-               return
-       }
-       ac.External = StringBool(os.Getenv("ARVADOS_EXTERNAL_CLIENT"))
-       return
+// ARVADOS_API_HOST_INSECURE, and ARVADOS_KEEP_SERVICES.
+func MakeArvadosClient() (*ArvadosClient, error) {
+       return New(arvados.NewClientFromEnv())
 }
 
 // CallRaw is the same as Call() but returns a Reader that reads the
@@ -276,9 +269,6 @@ func (c *ArvadosClient) CallRaw(method string, resourceType string, uuid string,
                if c.RequestID != "" {
                        req.Header.Add("X-Request-Id", c.RequestID)
                }
-               if c.External {
-                       req.Header.Add("X-External-Client", "1")
-               }
 
                resp, err = c.Client.Do(req)
                if err != nil {
index db1d0f4e1296bab02a2ecda9ff00377ca9636b24..85d419758820617b7bbdecd980e1a8f49e7cb009 100644 (file)
@@ -66,9 +66,6 @@ def _intercept_http_request(self, uri, method="GET", headers={}, **kwargs):
             self.max_request_size < len(kwargs['body'])):
             raise apiclient_errors.MediaUploadSizeError("Request size %i bytes exceeds published limit of %i bytes" % (len(kwargs['body']), self.max_request_size))
 
-        if config.get("ARVADOS_EXTERNAL_CLIENT", "") == "true":
-            headers['X-External-Client'] = '1'
-
         headers['Authorization'] = 'OAuth2 %s' % self.arvados_api_token
 
         retryable = method in [
index 7c05cc0a6a2c72ca818686b6eea5c6f0a4874d3d..44e915776734fe87020ba46b5d95d9985f8e8dfe 100644 (file)
@@ -159,7 +159,6 @@ class Keep(object):
                config.get('ARVADOS_API_TOKEN'),
                config.flag_is_true('ARVADOS_API_HOST_INSECURE'),
                config.get('ARVADOS_KEEP_PROXY'),
-               config.get('ARVADOS_EXTERNAL_CLIENT') == 'true',
                os.environ.get('KEEP_LOCAL_STORE'))
         if (global_client_object is None) or (cls._last_key != key):
             global_client_object = KeepClient()
index 4ad3eda42008b4c7f5ddd200dca9ca14336a436a..1716291fe828c3ec824b2b0cc56206de5fde3371 100644 (file)
@@ -15,6 +15,13 @@ http {
   fastcgi_temp_path "{{TMPDIR}}";
   uwsgi_temp_path "{{TMPDIR}}";
   scgi_temp_path "{{TMPDIR}}";
+  geo $external_client {
+    default 1;
+    127.0.0.0/8 0;
+    ::1 0;
+    fd00::/8 0;
+    {{INTERNALSUBNETS}}
+  }
   upstream controller {
     server {{UPSTREAMHOST}}:{{CONTROLLERPORT}};
   }
@@ -26,7 +33,10 @@ http {
     client_max_body_size 0;
     location  / {
       proxy_pass http://controller;
+      proxy_set_header Upgrade $http_upgrade;
+      proxy_set_header Connection "upgrade";
       proxy_set_header Host $http_host;
+      proxy_set_header X-External-Client $external_client;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Proto https;
       proxy_redirect off;
index e32d385f73fc0849c30d4a730cb3b83c6a4425c6..e5d1d8fa380fb49513452d7555618c5410993764 100644 (file)
@@ -660,6 +660,7 @@ def run_nginx():
     nginxconf['ACCESSLOG'] = _logfilename('nginx_access')
     nginxconf['ERRORLOG'] = _logfilename('nginx_error')
     nginxconf['TMPDIR'] = TEST_TMPDIR + '/nginx'
+    nginxconf['INTERNALSUBNETS'] = '169.254.0.0/16 0;'
 
     conftemplatefile = os.path.join(MY_DIRNAME, 'nginx.conf')
     conffile = os.path.join(TEST_TMPDIR, 'nginx.conf')
@@ -925,7 +926,6 @@ class TestCaseWithServers(unittest.TestCase):
         cls._orig_config = arvados.config.settings().copy()
         cls._cleanup_funcs = []
         os.environ.pop('ARVADOS_KEEP_SERVICES', None)
-        os.environ.pop('ARVADOS_EXTERNAL_CLIENT', None)
         for server_kwargs, start_func, stop_func in (
                 (cls.MAIN_SERVER, run, reset),
                 (cls.WS_SERVER, run_ws, stop_ws),
index 605b90301cd0bd78133a7ece408b6138b3aba864..87e4eefb29d666b4f3fa724151ba8cf268f7d20b 100644 (file)
@@ -184,7 +184,6 @@ class KeepProxyTestCase(run_test_server.TestCaseWithServers):
         cls.api_client = arvados.api('v1')
 
     def tearDown(self):
-        arvados.config.settings().pop('ARVADOS_EXTERNAL_CLIENT', None)
         super(KeepProxyTestCase, self).tearDown()
 
     def test_KeepProxyTest1(self):
@@ -202,22 +201,6 @@ class KeepProxyTestCase(run_test_server.TestCaseWithServers):
                          'wrong content from Keep.get(md5("baz"))')
         self.assertTrue(keep_client.using_proxy)
 
-    def test_KeepProxyTest2(self):
-        # Don't instantiate the proxy directly, but set the X-External-Client
-        # header.  The API server should direct us to the proxy.
-        arvados.config.settings()['ARVADOS_EXTERNAL_CLIENT'] = 'true'
-        keep_client = arvados.KeepClient(api_client=self.api_client,
-                                         proxy='', local_store='')
-        baz_locator = keep_client.put('baz2')
-        self.assertRegex(
-            baz_locator,
-            '^91f372a266fe2bf2823cb8ec7fda31ce\+4',
-            'wrong md5 hash from Keep.put("baz2"): ' + baz_locator)
-        self.assertEqual(keep_client.get(baz_locator),
-                         b'baz2',
-                         'wrong content from Keep.get(md5("baz2"))')
-        self.assertTrue(keep_client.using_proxy)
-
     def test_KeepProxyTestMultipleURIs(self):
         # Test using ARVADOS_KEEP_SERVICES env var overriding any
         # existing proxy setting and setting multiple proxies
@@ -254,6 +237,17 @@ class KeepClientServiceTestCase(unittest.TestCase, tutil.ApiClientMock):
         self.assertEqual('100::1', service.hostname)
         self.assertEqual(10, service.port)
 
+    def test_recognize_proxy_services_in_controller_response(self):
+        keep_client = arvados.KeepClient(api_client=self.mock_keep_services(
+            service_type='proxy', service_host='localhost', service_port=9, count=1))
+        try:
+            # this will fail, but it ensures we get the service
+            # discovery response
+            keep_client.put('baz2')
+        except:
+            pass
+        self.assertTrue(keep_client.using_proxy)
+
     def test_insecure_disables_tls_verify(self):
         api_client = self.mock_keep_services(count=1)
         force_timeout = socket.timeout("timed out")
index c33c2358ca3b7612ef92498edbef9a5562d6b9f5..e45598189107261401930126cc1e04235211b798 100644 (file)
@@ -102,7 +102,6 @@ func main() {
                if client.Insecure {
                        os.Setenv("ARVADOS_API_HOST_INSECURE", "1")
                }
-               os.Setenv("ARVADOS_EXTERNAL_CLIENT", "")
        } else {
                logger.Warnf("Client credentials missing from config, so falling back on environment variables (deprecated).")
        }
index c774584d683c338e70629320d9d602b9fea30814..ac394e114962ddf05d2e71e94cc4bb1ff46c4780 100644 (file)
@@ -101,7 +101,6 @@ func (disp *Dispatcher) configure() error {
                if disp.Client.Insecure {
                        os.Setenv("ARVADOS_API_HOST_INSECURE", "1")
                }
-               os.Setenv("ARVADOS_EXTERNAL_CLIENT", "")
                for k, v := range disp.cluster.Containers.SLURM.SbatchEnvironmentVariables {
                        os.Setenv(k, v)
                }
index 8242f5b2b56868b23dfaecf4aefe814100e682ee..2eaea278162c9c4d2fb308b30d27b38e8ea5b639 100644 (file)
@@ -146,7 +146,6 @@ func runProxy(c *C, bogusClientToken bool, loadKeepstoresFromConfig bool, kp *ar
                TestProxyUUID: "http://" + srv.Addr,
        }
        kc.SetServiceRoots(sr, sr, sr)
-       kc.Arvados.External = true
        return srv, kc, logbuf
 }
 
index 995a1fd559a396c9b364a0bea6adcf40b66176d0..6127485835388d359b64e5ffae4cd2607c298cc6 100644 (file)
@@ -108,7 +108,6 @@ type apiConfig struct {
        APIToken        string
        APIHost         string
        APIHostInsecure bool
-       ExternalClient  bool
 }
 
 // Load config from given file
@@ -152,8 +151,6 @@ func readConfigFromFile(filename string) (config apiConfig, blobSigningKey strin
                                config.APIHost = value
                        case "ARVADOS_API_HOST_INSECURE":
                                config.APIHostInsecure = arvadosclient.StringBool(value)
-                       case "ARVADOS_EXTERNAL_CLIENT":
-                               config.ExternalClient = arvadosclient.StringBool(value)
                        case "ARVADOS_BLOB_SIGNING_KEY":
                                blobSigningKey = value
                        }
@@ -171,7 +168,6 @@ func setupKeepClient(config apiConfig, keepServicesJSON string, blobSignatureTTL
                ApiInsecure: config.APIHostInsecure,
                Client: &http.Client{Transport: &http.Transport{
                        TLSClientConfig: &tls.Config{InsecureSkipVerify: config.APIHostInsecure}}},
-               External: config.ExternalClient,
        }
 
        // If keepServicesJSON is provided, use it instead of service discovery
index d973e06027c6ed2b707fce39a4f2ab00fcc51a11..4dcb47a8da02e3eea9edddf5e612dff660076147 100644 (file)
@@ -118,7 +118,6 @@ func setupConfigFile(c *C, fileName string) string {
        fileContent += "ARVADOS_API_TOKEN=" + arvadostest.DataManagerToken + "\n"
        fileContent += "\n"
        fileContent += "ARVADOS_API_HOST_INSECURE=" + os.Getenv("ARVADOS_API_HOST_INSECURE") + "\n"
-       fileContent += " ARVADOS_EXTERNAL_CLIENT = false \n"
        fileContent += " NotANameValuePairAndShouldGetIgnored \n"
        fileContent += "ARVADOS_BLOB_SIGNING_KEY=abcdefg\n"
 
@@ -291,7 +290,6 @@ func (s *ServerRequiredSuite) TestLoadConfig(c *C) {
        c.Assert(config.APIHost, Equals, os.Getenv("ARVADOS_API_HOST"))
        c.Assert(config.APIToken, Equals, arvadostest.DataManagerToken)
        c.Assert(config.APIHostInsecure, Equals, arvadosclient.StringBool(os.Getenv("ARVADOS_API_HOST_INSECURE")))
-       c.Assert(config.ExternalClient, Equals, false)
        c.Assert(blobSigningKey, Equals, "abcdefg")
 }
 
index 98c9609cb3c522f9524084194ecab1bd68531b79..7e519f775ba9bb4d500e578c891a55d50f1fae34 100644 (file)
@@ -118,7 +118,6 @@ type apiConfig struct {
        APIToken        string
        APIHost         string
        APIHostInsecure bool
-       ExternalClient  bool
 }
 
 // Load src and dst config from given files
@@ -164,8 +163,6 @@ func readConfigFromFile(filename string) (config apiConfig, blobSigningKey strin
                        config.APIHost = value
                case "ARVADOS_API_HOST_INSECURE":
                        config.APIHostInsecure = arvadosclient.StringBool(value)
-               case "ARVADOS_EXTERNAL_CLIENT":
-                       config.ExternalClient = arvadosclient.StringBool(value)
                case "ARVADOS_BLOB_SIGNING_KEY":
                        blobSigningKey = value
                }
@@ -181,7 +178,6 @@ func setupKeepClient(config apiConfig, keepServicesJSON string, isDst bool, repl
                ApiInsecure: config.APIHostInsecure,
                Client: &http.Client{Transport: &http.Transport{
                        TLSClientConfig: &tls.Config{InsecureSkipVerify: config.APIHostInsecure}}},
-               External: config.ExternalClient,
        }
 
        // If keepServicesJSON is provided, use it instead of service discovery
index 45ed3f67f52cc41e16782bd3a6c6144e3d64ecad..dc5b957125c731d13ae51969b7a47ec765ffcf33 100644 (file)
@@ -367,7 +367,6 @@ func (s *ServerNotRequiredSuite) TestLoadConfig(c *C) {
        c.Assert(srcConfig.APIHost, Equals, os.Getenv("ARVADOS_API_HOST"))
        c.Assert(srcConfig.APIToken, Equals, arvadostest.SystemRootToken)
        c.Assert(srcConfig.APIHostInsecure, Equals, arvadosclient.StringBool(os.Getenv("ARVADOS_API_HOST_INSECURE")))
-       c.Assert(srcConfig.ExternalClient, Equals, false)
 
        dstConfig, _, err := loadConfig(dstConfigFile)
        c.Check(err, IsNil)
@@ -375,7 +374,6 @@ func (s *ServerNotRequiredSuite) TestLoadConfig(c *C) {
        c.Assert(dstConfig.APIHost, Equals, os.Getenv("ARVADOS_API_HOST"))
        c.Assert(dstConfig.APIToken, Equals, arvadostest.SystemRootToken)
        c.Assert(dstConfig.APIHostInsecure, Equals, arvadosclient.StringBool(os.Getenv("ARVADOS_API_HOST_INSECURE")))
-       c.Assert(dstConfig.ExternalClient, Equals, false)
 
        c.Assert(srcBlobSigningKey, Equals, "abcdefg")
 }
@@ -412,7 +410,6 @@ func setupConfigFile(c *C, name string) *os.File {
        fileContent := "ARVADOS_API_HOST=" + os.Getenv("ARVADOS_API_HOST") + "\n"
        fileContent += "ARVADOS_API_TOKEN=" + arvadostest.SystemRootToken + "\n"
        fileContent += "ARVADOS_API_HOST_INSECURE=" + os.Getenv("ARVADOS_API_HOST_INSECURE") + "\n"
-       fileContent += "ARVADOS_EXTERNAL_CLIENT=false\n"
        fileContent += "ARVADOS_BLOB_SIGNING_KEY=abcdefg"
 
        _, err = file.Write([]byte(fileContent))