[ARVADOS] created: 1.3.0-1543-g82ef8e6c9

Git user git at public.curoverse.com
Fri Aug 16 19:47:43 UTC 2019


        at  82ef8e6c9b95804159e199d7dd9128da82366a50 (commit)


commit 82ef8e6c9b95804159e199d7dd9128da82366a50
Author: Eric Biagiotti <ebiagiotti at veritasgenetics.com>
Date:   Thu Aug 15 14:25:29 2019 -0400

    14715: Fixes install and config migration docs
    
    Arvados-DCO-1.1-Signed-off-by: Eric Biagiotti <ebiagiotti at veritasgenetics.com>

diff --git a/doc/admin/config-migration.html.textile.liquid b/doc/admin/config-migration.html.textile.liquid
index 8bb108371..ae85876fd 100644
--- a/doc/admin/config-migration.html.textile.liquid
+++ b/doc/admin/config-migration.html.textile.liquid
@@ -64,19 +64,19 @@ Currently only reads @RemoteClusters@ from centralized configuration.  Still req
 
 h2(#keepproxy). keepproxy
 
-The legacy keepproxy config is stored at @/etc/arvados/keepproxy/keepproxy.yml@ and can still be used with the @-config=path/to/legacy/config@ keepproxy command line argument. If migrated to the centralized config at @/etc/arvados/config.yml@, @keepproxy.yml@ should be moved out of the way and/or deleted.
+The legacy keepproxy config is stored at @/etc/arvados/keepproxy/keepproxy.yml@ by default and will continue to take precedence over the cluster config, unless removed. Also, a legacy keepproxy config in a different path can still be used with the @-legacy-keepproxy-config=path/to/legacy/config@ keepproxy command line argument. If the @-legacy-keepproxy-config@ command line argument is provided, this will take precedence over @/etc/arvados/keepproxy/keepproxy.yml@ and the cluster config. If migrating to the centralized config, @keepproxy.yml@ should be moved out of the way and/or deleted and the @-legacy-keepproxy-config@ command line argument should not be used.
 
 Configuration via individual command line arguments is no longer available. The following table maps former keepproxy command line arguments and legacy config values to their equivalent representation in the centralized config, which may need to be set manually.
 
 table(table table-bordered table-condensed).
 |*Command Line*|*Legacy keepproxy.yml*|*Centralized config.yml*|
-|-listen|Listen|Services:Keepproxy:InternalURLs|
+|-listen|Listen|Services.Keepproxy.InternalURLs|
 |-no-get|DisableGet|N/A|
 |-no-put|DisablePut|N/A|
-|-default-replicas|DefaultReplicas|Collections:DefaultReplication|
+|-default-replicas|DefaultReplicas|Collections.DefaultReplication|
 |-pid|PIDFile|N/A|
-|N/A|Debug|SystemLogs:LogLevel|
-|-timeout|Timeout|API:KeepServiceRequestTimeout|
+|N/A|Debug|SystemLogs.LogLevel|
+|-timeout|Timeout|API.KeepServiceRequestTimeout|
 |-management-token|ManagementToken|ManagementToken|
 
 Note that some options are no longer supported. If you are still using the legacy config at @/etc/arvados/keepproxy/keepproxy.yml@ and @DisableGet@ or @DisablePut@ are set to true or @PIDFile@ has a value, keepproxy will produce an error and fail to start.
diff --git a/doc/admin/upgrading.html.textile.liquid b/doc/admin/upgrading.html.textile.liquid
index 28f08db4d..28a6ef89e 100644
--- a/doc/admin/upgrading.html.textile.liquid
+++ b/doc/admin/upgrading.html.textile.liquid
@@ -53,7 +53,7 @@ So that older Arvados sites don't lose access to legacy records, the API has bee
 
 h4. Keepproxy configuration migration
 
-Keepproxy can now be configured using the centralized config at @/etc/arvados/config.yml at . Some configuration options are no longer supported. Please see "keepproxy's config migration guide":{{site.baseurl}}/admin/config-migration.html#keepproxy for more details.
+(feature "#14715":https://dev.arvados.org/issues/14715 ) Keepproxy can now be configured using the centralized config at @/etc/arvados/config.yml at . Some configuration options are no longer supported. Please see "keepproxy's config migration guide":{{site.baseurl}}/admin/config-migration.html#keepproxy for more details.
 
 h4. No longer stripping ':' from strings in serialized database columns
 
diff --git a/doc/install/install-keepproxy.html.textile.liquid b/doc/install/install-keepproxy.html.textile.liquid
index 738cd523e..910e47e0e 100644
--- a/doc/install/install-keepproxy.html.textile.liquid
+++ b/doc/install/install-keepproxy.html.textile.liquid
@@ -44,9 +44,14 @@ Verify that Keepproxy is functional:
 
 <notextile>
 <pre><code>~$ <span class="userinput">keepproxy -h</span>
-...
-Usage: keepproxy [-config path/to/keepproxy.yml]
-...
+Usage of keepproxy:
+  -config file
+    	Site configuration file (default may be overridden by setting an ARVADOS_CONFIG environment variable) (default "/etc/arvados/config.yml")
+  -dump-config
+    	write current configuration to stdout and exit
+[...]
+  -version
+    	print version information and exit.
 </code></pre>
 </notextile>
 
@@ -56,7 +61,7 @@ Edit the cluster config at @/etc/arvados/config.yml@ and set @Services.Keepproxy
 
 <notextile>
 <pre><code>Clusters:
-  zzzzz:
+  <span class="userinput">uuid_prefix</span>:
     Services:
       <span class="userinput">Keepproxy:
         ExternalURL: https://keep.uuid_prefix.your.domain
@@ -65,17 +70,6 @@ Edit the cluster config at @/etc/arvados/config.yml@ and set @Services.Keepproxy
 </span></code></pre>
 </notextile>
 
-h3. Set up the Keepproxy service
-
-Install runit to supervise the keepproxy daemon.  {% include 'install_runit' %}
-
-The keepproxy command to run is:
-
-<notextile>
-<pre><code>~$ <span class="userinput">exec keepproxy
-</code></pre>
-</notextile>
-
 h3. Set up a reverse proxy with SSL support
 
 Because the Keepproxy is intended for access from anywhere on the internet, it is recommended to use SSL for transport encryption.
@@ -140,6 +134,32 @@ export ARVADOS_API_TOKEN=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
 EOF</span>
 </code></pre></notextile>
 
+h2. Run Keepproxy
+
+h3. Start the service (option 1: systemd)
+
+If your system does not use systemd, skip this section and follow the "runit instructions":#runit instead.
+
+If your system uses systemd, the keepproxy service should already be set up. Start it and check its status:
+
+<notextile>
+<pre><code>~$ <span class="userinput">sudo systemctl restart keepproxy</span>
+~$ <span class="userinput">sudo systemctl status keepproxy</span>
+&#x25cf; keepproxy.service - Arvados Keep Proxy
+   Loaded: loaded (/lib/systemd/system/keepproxy.service; enabled)
+   Active: active (running) since Tue 2019-07-23 09:33:47 EDT; 3 weeks 1 days ago
+     Docs: https://doc.arvados.org/
+ Main PID: 1150 (Keepproxy)
+   CGroup: /system.slice/keepproxy.service
+           └─1150 /usr/bin/keepproxy
+[...]
+</code></pre>
+</notextile>
+
+h3(#runit). Start the service (option 2: runit)
+
+Install runit to supervise the Keep-web daemon.  {% include 'install_runit' %}
+
 h3. Testing keepproxy
 
 Log into a host that is on an external network from your private Arvados network.  The host should be able to contact your keepproxy server (eg keep.$uuid_prefix.arvadosapi.com), but not your keepstore servers (eg keep[0-9].$uuid_prefix.arvadosapi.com).
diff --git a/services/keepproxy/keepproxy.go b/services/keepproxy/keepproxy.go
index 685007481..9244fe00c 100644
--- a/services/keepproxy/keepproxy.go
+++ b/services/keepproxy/keepproxy.go
@@ -43,7 +43,6 @@ const rfc3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00"
 
 func configure(logger log.FieldLogger, args []string) (*arvados.Cluster, error) {
 	flags := flag.NewFlagSet(args[0], flag.ExitOnError)
-	flags.Usage = usage
 
 	dumpConfig := flags.Bool("dump-config", false, "write current configuration to stdout and exit")
 	getVersion := flags.Bool("version", false, "Print version information and exit.")
diff --git a/services/keepproxy/usage.go b/services/keepproxy/usage.go
deleted file mode 100644
index 4eeb55065..000000000
--- a/services/keepproxy/usage.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-package main
-
-import (
-	"fmt"
-	"os"
-)
-
-func usage() {
-	fmt.Fprintf(os.Stderr, `
-Keepproxy forwards GET and PUT requests to keepstore servers. See
-http://doc.arvados.org/install/install-keepproxy.html
-
-Usage: keepproxy [-config path/to/keepproxy.yml]
-
-DEPRECATION WARNING: The -config parameter is deprecated. Use the
-cluster config instead.
-
-`)
-}

commit 5ae0a422e60788a4039d17d2d8dfb60f250329c7
Author: Eric Biagiotti <ebiagiotti at veritasgenetics.com>
Date:   Wed Aug 14 15:23:12 2019 -0400

    14715: Moves legacy config test to lib/config
    
    Arvados-DCO-1.1-Signed-off-by: Eric Biagiotti <ebiagiotti at veritasgenetics.com>

diff --git a/lib/config/deprecated_test.go b/lib/config/deprecated_test.go
index 8479842be..76313ebb1 100644
--- a/lib/config/deprecated_test.go
+++ b/lib/config/deprecated_test.go
@@ -6,6 +6,7 @@ package config
 
 import (
 	"flag"
+	"fmt"
 	"io/ioutil"
 	"os"
 	"time"
@@ -14,6 +15,35 @@ import (
 	check "gopkg.in/check.v1"
 )
 
+func testLoadLegacyConfig(content []byte, mungeFlag string, c *check.C) (*arvados.Cluster, error) {
+	tmpfile, err := ioutil.TempFile("", "example")
+	if err != nil {
+		return nil, err
+	}
+	defer os.Remove(tmpfile.Name())
+
+	if _, err := tmpfile.Write(content); err != nil {
+		return nil, err
+	}
+	if err := tmpfile.Close(); err != nil {
+		return nil, err
+	}
+	flags := flag.NewFlagSet("test", flag.ExitOnError)
+	ldr := testLoader(c, "Clusters: {zzzzz: {}}", nil)
+	ldr.SetupFlags(flags)
+	args := ldr.MungeLegacyConfigArgs(ldr.Logger, []string{"-config", tmpfile.Name()}, mungeFlag)
+	flags.Parse(args)
+	cfg, err := ldr.Load()
+	if err != nil {
+		return nil, err
+	}
+	cluster, err := cfg.GetCluster("")
+	if err != nil {
+		return nil, err
+	}
+	return cluster, nil
+}
+
 func (s *LoadSuite) TestDeprecatedNodeProfilesToServices(c *check.C) {
 	hostname, err := os.Hostname()
 	c.Assert(err, check.IsNil)
@@ -81,33 +111,8 @@ func (s *LoadSuite) TestLegacyKeepWebConfig(c *check.C) {
 	"ManagementToken": "xyzzy"
 }
 `)
-	tmpfile, err := ioutil.TempFile("", "example")
-	if err != nil {
-		c.Error(err)
-	}
-	defer os.Remove(tmpfile.Name())
-
-	if _, err := tmpfile.Write(content); err != nil {
-		c.Error(err)
-	}
-	if err := tmpfile.Close(); err != nil {
-		c.Error(err)
-	}
-	flags := flag.NewFlagSet("keep-web", flag.ExitOnError)
-	ldr := testLoader(c, "Clusters: {zzzzz: {}}", nil)
-	ldr.SetupFlags(flags)
-	args := ldr.MungeLegacyConfigArgs(ldr.Logger, []string{"-config", tmpfile.Name()}, "-legacy-keepweb-config")
-	flags.Parse(args)
-	cfg, err := ldr.Load()
-	if err != nil {
-		c.Error(err)
-	}
-	c.Check(cfg, check.NotNil)
-	cluster, err := cfg.GetCluster("")
-	if err != nil {
-		c.Error(err)
-	}
-	c.Check(cluster, check.NotNil)
+	cluster, err := testLoadLegacyConfig(content, "-legacy-keepweb-config", c)
+	c.Check(err, check.IsNil)
 
 	c.Check(cluster.Services.Controller.ExternalURL, check.Equals, arvados.URL{Scheme: "https", Host: "example.com"})
 	c.Check(cluster.SystemRootToken, check.Equals, "abcdefg")
@@ -127,3 +132,58 @@ func (s *LoadSuite) TestLegacyKeepWebConfig(c *check.C) {
 	c.Check(cluster.Users.AnonymousUserToken, check.Equals, "anonusertoken")
 	c.Check(cluster.ManagementToken, check.Equals, "xyzzy")
 }
+
+func (s *LoadSuite) TestLegacyKeepproxyConfig(c *check.C) {
+	f := "-legacy-keepproxy-config"
+	content := []byte(fmtKeepproxyConfig("", true))
+	cluster, err := testLoadLegacyConfig(content, f, c)
+
+	c.Check(err, check.IsNil)
+	c.Check(cluster, check.NotNil)
+	c.Check(cluster.Services.Controller.ExternalURL, check.Equals, arvados.URL{Scheme: "https", Host: "example.com"})
+	c.Check(cluster.SystemRootToken, check.Equals, "abcdefg")
+	c.Check(cluster.ManagementToken, check.Equals, "xyzzy")
+	c.Check(cluster.Services.Keepproxy.InternalURLs[arvados.URL{Host: ":80"}], check.Equals, arvados.ServiceInstance{})
+	c.Check(cluster.Collections.DefaultReplication, check.Equals, 0)
+	c.Check(cluster.API.KeepServiceRequestTimeout.String(), check.Equals, "15s")
+	c.Check(cluster.SystemLogs.LogLevel, check.Equals, "debug")
+
+	content = []byte(fmtKeepproxyConfig("", false))
+	cluster, err = testLoadLegacyConfig(content, f, c)
+	c.Check(cluster.SystemLogs.LogLevel, check.Equals, "info")
+
+	content = []byte(fmtKeepproxyConfig(`"DisableGet": true,`, true))
+	_, err = testLoadLegacyConfig(content, f, c)
+	c.Check(err, check.NotNil)
+
+	content = []byte(fmtKeepproxyConfig(`"DisablePut": true,`, true))
+	_, err = testLoadLegacyConfig(content, f, c)
+	c.Check(err, check.NotNil)
+
+	content = []byte(fmtKeepproxyConfig(`"PIDFile": "test",`, true))
+	_, err = testLoadLegacyConfig(content, f, c)
+	c.Check(err, check.NotNil)
+
+	content = []byte(fmtKeepproxyConfig(`"DisableGet": false, "DisablePut": false, "PIDFile": "",`, true))
+	_, err = testLoadLegacyConfig(content, f, c)
+	c.Check(err, check.IsNil)
+}
+
+func fmtKeepproxyConfig(param string, debugLog bool) string {
+	return fmt.Sprintf(`
+{
+	"Client": {
+		"Scheme": "",
+		"APIHost": "example.com",
+		"AuthToken": "abcdefg",
+		"Insecure": false
+	},
+	"Listen": ":80",
+	"DefaultReplicas": 0,
+	"Timeout": "15s",
+	"Debug": %t,
+	%s
+	"ManagementToken": "xyzzy"
+}
+`, debugLog, param)
+}
diff --git a/services/keepproxy/keepproxy_test.go b/services/keepproxy/keepproxy_test.go
index 609da4f70..d2758cc25 100644
--- a/services/keepproxy/keepproxy_test.go
+++ b/services/keepproxy/keepproxy_test.go
@@ -13,7 +13,6 @@ import (
 	"math/rand"
 	"net/http"
 	"net/http/httptest"
-	"os"
 	"strings"
 	"sync"
 	"testing"
@@ -640,74 +639,3 @@ func (s *ServerRequiredSuite) TestPing(c *C) {
 	c.Check(resp.Code, Equals, 200)
 	c.Assert(resp.Body.String(), Matches, `{"health":"OK"}\n?`)
 }
-
-func (s *NoKeepServerSuite) TestLegacyConfig(c *C) {
-	content := []byte(fmtConfig("", true))
-	cluster, err := loadLegacyConfig(content, c)
-
-	c.Check(err, IsNil)
-	c.Check(cluster, NotNil)
-	c.Check(cluster.Services.Controller.ExternalURL, Equals, arvados.URL{Scheme: "https", Host: "example.com"})
-	c.Check(cluster.SystemRootToken, Equals, "abcdefg")
-	c.Check(cluster.ManagementToken, Equals, "xyzzy")
-	c.Check(cluster.Services.Keepproxy.InternalURLs[arvados.URL{Host: ":80"}], Equals, arvados.ServiceInstance{})
-	c.Check(cluster.Collections.DefaultReplication, Equals, 0)
-	c.Check(cluster.API.KeepServiceRequestTimeout.String(), Equals, "15s")
-	c.Check(cluster.SystemLogs.LogLevel, Equals, "debug")
-
-	content = []byte(fmtConfig("", false))
-	cluster, err = loadLegacyConfig(content, c)
-	c.Check(cluster.SystemLogs.LogLevel, Equals, "info")
-
-	content = []byte(fmtConfig(`"DisableGet": true,`, true))
-	_, err = loadLegacyConfig(content, c)
-	c.Check(err, NotNil)
-
-	content = []byte(fmtConfig(`"DisablePut": true,`, true))
-	_, err = loadLegacyConfig(content, c)
-	c.Check(err, NotNil)
-
-	content = []byte(fmtConfig(`"PIDFile": "test",`, true))
-	_, err = loadLegacyConfig(content, c)
-	c.Check(err, NotNil)
-
-	content = []byte(fmtConfig(`"DisableGet": false, "DisablePut": false, "PIDFile": "",`, true))
-	_, err = loadLegacyConfig(content, c)
-	c.Check(err, IsNil)
-
-}
-
-func loadLegacyConfig(content []byte, c *C) (*arvados.Cluster, error) {
-	tmpfile, err := ioutil.TempFile("", "example")
-	if err != nil {
-		c.Error(err)
-	}
-	defer os.Remove(tmpfile.Name())
-
-	if _, err := tmpfile.Write(content); err != nil {
-		c.Error(err)
-	}
-	if err := tmpfile.Close(); err != nil {
-		c.Error(err)
-	}
-	return configure(log.New(), []string{"keepproxy", "-config", tmpfile.Name()})
-}
-
-func fmtConfig(param string, debugLog bool) string {
-	return fmt.Sprintf(`
-{
-	"Client": {
-		"Scheme": "",
-		"APIHost": "example.com",
-		"AuthToken": "abcdefg",
-		"Insecure": false
-	},
-	"Listen": ":80",
-	"DefaultReplicas": 0,
-	"Timeout": "15s",
-	"Debug": %t,
-	%s
-	"ManagementToken": "xyzzy"
-}
-`, debugLog, param)
-}

commit 729c7c95d0d9c8d0357143717d5f2bb8cdd743de
Author: Eric Biagiotti <ebiagiotti at veritasgenetics.com>
Date:   Wed Aug 14 14:35:45 2019 -0400

    14715: Fixes error handling
    
    Also removes the path assertion from the service file and fixes copy/paste typo
    
    Arvados-DCO-1.1-Signed-off-by: Eric Biagiotti <ebiagiotti at veritasgenetics.com>

diff --git a/lib/config/load.go b/lib/config/load.go
index c0b44c17e..84de9b60e 100644
--- a/lib/config/load.go
+++ b/lib/config/load.go
@@ -141,7 +141,7 @@ func (ldr *Loader) MungeLegacyConfigArgs(lgr logrus.FieldLogger, args []string,
 		ldr.KeepWebPath = ""
 	}
 	if legacyConfigArg != "-legacy-keepproxy-config" {
-		ldr.WebsocketPath = ""
+		ldr.KeepproxyPath = ""
 	}
 
 	return munged
diff --git a/services/keepproxy/keepproxy.go b/services/keepproxy/keepproxy.go
index 824b748bc..685007481 100644
--- a/services/keepproxy/keepproxy.go
+++ b/services/keepproxy/keepproxy.go
@@ -108,13 +108,13 @@ func main() {
 func run(logger log.FieldLogger, cluster *arvados.Cluster) error {
 	client, err := arvados.NewClientFromConfig(cluster)
 	if err != nil {
-		log.Fatal(err)
+		return err
 	}
 	client.AuthToken = cluster.SystemRootToken
 
 	arv, err := arvadosclient.New(client)
 	if err != nil {
-		log.Fatalf("Error setting up arvados client %s", err.Error())
+		return fmt.Errorf("Error setting up arvados client %v", err)
 	}
 
 	if cluster.SystemLogs.LogLevel == "debug" {
@@ -122,7 +122,7 @@ func run(logger log.FieldLogger, cluster *arvados.Cluster) error {
 	}
 	kc, err := keepclient.MakeKeepClient(arv)
 	if err != nil {
-		log.Fatalf("Error setting up keep client %s", err.Error())
+		return fmt.Errorf("Error setting up keep client %v", err)
 	}
 	keepclient.RefreshServiceDiscoveryOnSIGHUP()
 
@@ -138,13 +138,13 @@ func run(logger log.FieldLogger, cluster *arvados.Cluster) error {
 	var lErr error
 	listener, lErr = net.Listen("tcp", listen.Host)
 	if lErr != nil {
-		log.Fatalf("listen(%s): %s", listen.Host, lErr)
+		return fmt.Errorf("listen(%s): %v", listen.Host, lErr)
 	}
 
 	if _, err := daemon.SdNotify(false, "READY=1"); err != nil {
 		log.Printf("Error notifying init daemon: %v", err)
 	}
-	log.Println("Listening at", listener.Addr())
+	log.Println("listening at", listener.Addr())
 
 	// Shut down the server gracefully (by closing the listener)
 	// if SIGTERM is received.
diff --git a/services/keepproxy/keepproxy.service b/services/keepproxy/keepproxy.service
index 817aec6c4..1d0113e0e 100644
--- a/services/keepproxy/keepproxy.service
+++ b/services/keepproxy/keepproxy.service
@@ -6,7 +6,6 @@
 Description=Arvados Keep Proxy
 Documentation=https://doc.arvados.org/
 After=network.target
-AssertPathExists=/etc/arvados/config.yml
 
 # systemd==229 (ubuntu:xenial) obeys StartLimitInterval in the [Unit] section
 StartLimitInterval=0

commit d4ed3e6460469f2766e1f1676c538d6c86e000b6
Merge: 1166aeb60 86b790311
Author: Eric Biagiotti <ebiagiotti at veritasgenetics.com>
Date:   Wed Aug 14 10:49:48 2019 -0400

    Merge branch 'master' into 14715-keepprox-config
    
    refs #14715
    
    Arvados-DCO-1.1-Signed-off-by: Eric Biagiotti <ebiagiotti at veritasgenetics.com>

diff --cc doc/admin/upgrading.html.textile.liquid
index 7ea1b10fa,8c2ca7657..28f08db4d
--- a/doc/admin/upgrading.html.textile.liquid
+++ b/doc/admin/upgrading.html.textile.liquid
@@@ -39,15 -39,21 +39,25 @@@ table(table table-bordered table-conden
  |"v1.1.4":#v1_1_4|"v1.1.3":#v1_1_3|"v1.1.2":#v1_1_2|"v1.1.1":#v1_1_1|"v1.1.0":#v1_1_0|
  |\5. "older":#older|
  
- h3(#master). development master (as of 2019-06-07)
+ h3(#master). development master (as of 2019-08-12)
+ 
+ h4. Keep-web dropped support on command line flags configuration
+ 
+ As we're migrating to a central cluster configuration file, the already deprecated way of getting configurations via environment variables and command line flags isn't valid anymore. Current keep-web supports both the now legacy @keep-web.yml@ config format (used by Arvados 1.4) and the new cluster config file format. Please check "keep-web's install guide":{{site.baseurl}}/install/install-keep-web.html for more details.
+ 
+ h4. Jobs API is read-only
+ 
+ (task "#15133":https://dev.arvados.org/issues/15133 ) The legacy 'jobs' API is now read-only.  It has long been superceded by containers / container_requests (aka crunch v2).  Arvados installations since the end of 2017 (v1.1.0) have probably only used containers, and are unaffected by this change.
+ 
+ So that older Arvados sites don't lose access to legacy records, the API has been converted to read-only.  Creating and updating jobs (and related types job_task, pipeline_template and pipeline_instance) is disabled and much of the business logic related has been removed, along with various other code specific to the jobs API.  Specifically, the following programs associated with the jobs API have been removed: @crunch-dispatch.rb@, @crunch-job@, @crunchrunner@, @arv-run-pipeline-instance@, @arv-run at .
  
 +h4. Keepproxy configuration migration
 +
 +Keepproxy can now be configured using the centralized config at @/etc/arvados/config.yml at . Some configuration options are no longer supported. Please see "keepproxy's config migration guide":{{site.baseurl}}/admin/config-migration.html#keepproxy for more details.
 +
  h4. No longer stripping ':' from strings in serialized database columns
  
-  (bug #15311) Strings read from serialized columns in the database with a leading ':' would have the ':' stripped after loading the record.  This behavior existed due to legacy serialization behavior which stored Ruby symbols with a leading ':'.  Unfortunately this corrupted fields where the leading ":" was intentional.  This behavior has been removed.
+ (bug "#15311":https://dev.arvados.org/issues/15311 ) Strings read from serialized columns in the database with a leading ':' would have the ':' stripped after loading the record.  This behavior existed due to legacy serialization behavior which stored Ruby symbols with a leading ':'.  Unfortunately this corrupted fields where the leading ":" was intentional.  This behavior has been removed.
  
  You can test if any records in your database are affected by going to the API server directory and running @bundle exec rake symbols:check at .  This will report which records contain fields with a leading ':' that would previously have been stripped.  If there are records to be updated, you can update the database using @bundle exec rake symbols:stringify at .
  
diff --cc lib/config/deprecated.go
index 4e7b85ec5,019979d39..df872111d
--- a/lib/config/deprecated.go
+++ b/lib/config/deprecated.go
@@@ -327,74 -327,72 +327,144 @@@ func (ldr *Loader) loadOldWebsocketConf
  	return nil
  }
  
 +type oldKeepProxyConfig struct {
 +	Client          *arvados.Client
 +	Listen          *string
 +	DisableGet      *bool
 +	DisablePut      *bool
 +	DefaultReplicas *int
 +	Timeout         *arvados.Duration
 +	PIDFile         *string
 +	Debug           *bool
 +	ManagementToken *string
 +}
 +
 +const defaultKeepproxyConfigPath = "/etc/arvados/keepproxy/keepproxy.yml"
 +
 +func (ldr *Loader) loadOldKeepproxyConfig(cfg *arvados.Config) error {
 +	if ldr.KeepproxyPath == "" {
 +		return nil
 +	}
 +	var oc oldKeepProxyConfig
 +	err := ldr.loadOldConfigHelper("keepproxy", ldr.KeepproxyPath, &oc)
 +	if os.IsNotExist(err) && ldr.KeepproxyPath == defaultKeepproxyConfigPath {
 +		return nil
 +	} else if err != nil {
 +		return err
 +	}
 +
 +	cluster, err := cfg.GetCluster("")
 +	if err != nil {
 +		return err
 +	}
 +
 +	loadOldClientConfig(cluster, oc.Client)
 +
 +	if oc.Listen != nil {
 +		cluster.Services.Keepproxy.InternalURLs[arvados.URL{Host: *oc.Listen}] = arvados.ServiceInstance{}
 +	}
 +	if oc.DefaultReplicas != nil {
 +		cluster.Collections.DefaultReplication = *oc.DefaultReplicas
 +	}
 +	if oc.Timeout != nil {
 +		cluster.API.KeepServiceRequestTimeout = *oc.Timeout
 +	}
 +	if oc.Debug != nil {
 +		if *oc.Debug && cluster.SystemLogs.LogLevel != "debug" {
 +			cluster.SystemLogs.LogLevel = "debug"
 +		} else if !*oc.Debug && cluster.SystemLogs.LogLevel != "info" {
 +			cluster.SystemLogs.LogLevel = "info"
 +		}
 +	}
 +	if oc.ManagementToken != nil {
 +		cluster.ManagementToken = *oc.ManagementToken
 +	}
 +
 +	// The following legacy options are no longer supported. If they are set to
 +	// true or PIDFile has a value, error out and notify the user
 +	unsupportedEntry := func(cfgEntry string) error {
 +		return fmt.Errorf("the keepproxy %s configuration option is no longer supported, please remove it from your configuration file", cfgEntry)
 +	}
 +	if oc.DisableGet != nil && *oc.DisableGet {
 +		return unsupportedEntry("DisableGet")
 +	}
 +	if oc.DisablePut != nil && *oc.DisablePut {
 +		return unsupportedEntry("DisablePut")
 +	}
 +	if oc.PIDFile != nil && *oc.PIDFile != "" {
 +		return unsupportedEntry("PIDFile")
 +	}
 +
 +	cfg.Clusters[cluster.ClusterID] = *cluster
 +	return nil
 +}
++
+ const defaultKeepWebConfigPath = "/etc/arvados/keep-web/keep-web.yml"
+ 
+ type oldKeepWebConfig struct {
+ 	Client *arvados.Client
+ 
+ 	Listen string
+ 
+ 	AnonymousTokens    []string
+ 	AttachmentOnlyHost string
+ 	TrustAllContent    bool
+ 
+ 	Cache struct {
+ 		TTL                  arvados.Duration
+ 		UUIDTTL              arvados.Duration
+ 		MaxCollectionEntries int
+ 		MaxCollectionBytes   int64
+ 		MaxPermissionEntries int
+ 		MaxUUIDEntries       int
+ 	}
+ 
+ 	// Hack to support old command line flag, which is a bool
+ 	// meaning "get actual token from environment".
+ 	deprecatedAllowAnonymous bool
+ 
+ 	// Authorization token to be included in all health check requests.
+ 	ManagementToken string
+ }
+ 
+ func (ldr *Loader) loadOldKeepWebConfig(cfg *arvados.Config) error {
+ 	if ldr.KeepWebPath == "" {
+ 		return nil
+ 	}
+ 	var oc oldKeepWebConfig
+ 	err := ldr.loadOldConfigHelper("keep-web", ldr.KeepWebPath, &oc)
+ 	if os.IsNotExist(err) && ldr.KeepWebPath == defaultKeepWebConfigPath {
+ 		return nil
+ 	} else if err != nil {
+ 		return err
+ 	}
+ 
+ 	cluster, err := cfg.GetCluster("")
+ 	if err != nil {
+ 		return err
+ 	}
+ 
+ 	loadOldClientConfig(cluster, oc.Client)
+ 
+ 	cluster.Services.WebDAV.InternalURLs[arvados.URL{Host: oc.Listen}] = arvados.ServiceInstance{}
+ 	cluster.Services.WebDAVDownload.InternalURLs[arvados.URL{Host: oc.Listen}] = arvados.ServiceInstance{}
+ 	cluster.Services.WebDAVDownload.ExternalURL = arvados.URL{Host: oc.AttachmentOnlyHost}
+ 	cluster.TLS.Insecure = oc.Client.Insecure
+ 	cluster.ManagementToken = oc.ManagementToken
+ 	cluster.Collections.TrustAllContent = oc.TrustAllContent
+ 	cluster.Collections.WebDAVCache.TTL = oc.Cache.TTL
+ 	cluster.Collections.WebDAVCache.UUIDTTL = oc.Cache.UUIDTTL
+ 	cluster.Collections.WebDAVCache.MaxCollectionEntries = oc.Cache.MaxCollectionEntries
+ 	cluster.Collections.WebDAVCache.MaxCollectionBytes = oc.Cache.MaxCollectionBytes
+ 	cluster.Collections.WebDAVCache.MaxPermissionEntries = oc.Cache.MaxPermissionEntries
+ 	cluster.Collections.WebDAVCache.MaxUUIDEntries = oc.Cache.MaxUUIDEntries
+ 	if len(oc.AnonymousTokens) > 0 {
+ 		cluster.Users.AnonymousUserToken = oc.AnonymousTokens[0]
+ 		if len(oc.AnonymousTokens) > 1 {
+ 			ldr.Logger.Warn("More than 1 anonymous tokens configured, using only the first and discarding the rest.")
+ 		}
+ 	}
+ 
+ 	cfg.Clusters[cluster.ClusterID] = *cluster
+ 	return nil
+ }
diff --cc lib/config/load.go
index 309c0a615,3413e3bec..c0b44c17e
--- a/lib/config/load.go
+++ b/lib/config/load.go
@@@ -31,9 -31,9 +31,10 @@@ type Loader struct 
  
  	Path                    string
  	KeepstorePath           string
+ 	KeepWebPath             string
  	CrunchDispatchSlurmPath string
  	WebsocketPath           string
 +	KeepproxyPath           string
  
  	configdata []byte
  }
@@@ -61,9 -61,9 +62,10 @@@ func NewLoader(stdin io.Reader, logger 
  func (ldr *Loader) SetupFlags(flagset *flag.FlagSet) {
  	flagset.StringVar(&ldr.Path, "config", arvados.DefaultConfigFile, "Site configuration `file` (default may be overridden by setting an ARVADOS_CONFIG environment variable)")
  	flagset.StringVar(&ldr.KeepstorePath, "legacy-keepstore-config", defaultKeepstoreConfigPath, "Legacy keepstore configuration `file`")
+ 	flagset.StringVar(&ldr.KeepWebPath, "legacy-keepweb-config", defaultKeepWebConfigPath, "Legacy keep-web configuration `file`")
  	flagset.StringVar(&ldr.CrunchDispatchSlurmPath, "legacy-crunch-dispatch-slurm-config", defaultCrunchDispatchSlurmConfigPath, "Legacy crunch-dispatch-slurm configuration `file`")
  	flagset.StringVar(&ldr.WebsocketPath, "legacy-ws-config", defaultWebsocketConfigPath, "Legacy arvados-ws configuration `file`")
 +	flagset.StringVar(&ldr.KeepproxyPath, "legacy-keepproxy-config", defaultKeepproxyConfigPath, "Legacy keepproxy configuration `file`")
  	flagset.BoolVar(&ldr.SkipLegacy, "skip-legacy", false, "Don't load legacy config files")
  }
  
@@@ -135,9 -135,9 +137,12 @@@ func (ldr *Loader) MungeLegacyConfigArg
  	if legacyConfigArg != "-legacy-ws-config" {
  		ldr.WebsocketPath = ""
  	}
+ 	if legacyConfigArg != "-legacy-keepweb-config" {
+ 		ldr.KeepWebPath = ""
+ 	}
 +	if legacyConfigArg != "-legacy-keepproxy-config" {
 +		ldr.WebsocketPath = ""
 +	}
  
  	return munged
  }
@@@ -235,9 -235,9 +240,10 @@@ func (ldr *Loader) Load() (*arvados.Con
  		// legacy config file for the current component
  		for _, err := range []error{
  			ldr.loadOldKeepstoreConfig(&cfg),
+ 			ldr.loadOldKeepWebConfig(&cfg),
  			ldr.loadOldCrunchDispatchSlurmConfig(&cfg),
  			ldr.loadOldWebsocketConfig(&cfg),
 +			ldr.loadOldKeepproxyConfig(&cfg),
  		} {
  			if err != nil {
  				return nil, err
diff --cc tools/arvbox/lib/arvbox/docker/cluster-config.sh
index 3444e61e1,58bedd284..34a0c2d75
--- a/tools/arvbox/lib/arvbox/docker/cluster-config.sh
+++ b/tools/arvbox/lib/arvbox/docker/cluster-config.sh
@@@ -76,12 -79,10 +79,14 @@@ Clusters
          ExternalURL: "https://$localip:${services[workbench2-ssl]}"
        SSO:
          ExternalURL: "https://$localip:${services[sso]}"
 +      Keepproxy:
 +        InternalURLs:
 +          "http://localhost:${services[keepproxy]}/": {}
 +        ExternalURL: "http://$localip:${services[keepproxy-ssl]}/"
        Websocket:
          ExternalURL: "wss://$localip:${services[websockets-ssl]}/websocket"
+         InternalURLs:
+           "http://localhost:${services[websockets]}": {}
        GitSSH:
          ExternalURL: "ssh://git@$localip:"
        GitHTTP:

commit 1166aeb6033725709ded753a0c00f69320a9a873
Author: Eric Biagiotti <ebiagiotti at veritasgenetics.com>
Date:   Mon Aug 12 15:41:00 2019 -0400

    14715: keepproxy.service checks for cluster config
    
    Arvados-DCO-1.1-Signed-off-by: Eric Biagiotti <ebiagiotti at veritasgenetics.com>

diff --git a/services/keepproxy/keepproxy.service b/services/keepproxy/keepproxy.service
index 96dec25ec..817aec6c4 100644
--- a/services/keepproxy/keepproxy.service
+++ b/services/keepproxy/keepproxy.service
@@ -6,7 +6,7 @@
 Description=Arvados Keep Proxy
 Documentation=https://doc.arvados.org/
 After=network.target
-AssertPathExists=/etc/arvados/keepproxy/keepproxy.yml
+AssertPathExists=/etc/arvados/config.yml
 
 # systemd==229 (ubuntu:xenial) obeys StartLimitInterval in the [Unit] section
 StartLimitInterval=0

commit 8f9f169bf7d53ecaaa076bf4fbf60fa0f0016af4
Author: Eric Biagiotti <ebiagiotti at veritasgenetics.com>
Date:   Mon Aug 12 15:40:26 2019 -0400

    14715: Updates keepproxy documentation
    
    Arvados-DCO-1.1-Signed-off-by: Eric Biagiotti <ebiagiotti at veritasgenetics.com>

diff --git a/doc/admin/config-migration.html.textile.liquid b/doc/admin/config-migration.html.textile.liquid
index 3f10a87fe..8bb108371 100644
--- a/doc/admin/config-migration.html.textile.liquid
+++ b/doc/admin/config-migration.html.textile.liquid
@@ -62,6 +62,25 @@ h2. keepstore
 
 Currently only reads @RemoteClusters@ from centralized configuration.  Still requires component-specific configuration file.
 
+h2(#keepproxy). keepproxy
+
+The legacy keepproxy config is stored at @/etc/arvados/keepproxy/keepproxy.yml@ and can still be used with the @-config=path/to/legacy/config@ keepproxy command line argument. If migrated to the centralized config at @/etc/arvados/config.yml@, @keepproxy.yml@ should be moved out of the way and/or deleted.
+
+Configuration via individual command line arguments is no longer available. The following table maps former keepproxy command line arguments and legacy config values to their equivalent representation in the centralized config, which may need to be set manually.
+
+table(table table-bordered table-condensed).
+|*Command Line*|*Legacy keepproxy.yml*|*Centralized config.yml*|
+|-listen|Listen|Services:Keepproxy:InternalURLs|
+|-no-get|DisableGet|N/A|
+|-no-put|DisablePut|N/A|
+|-default-replicas|DefaultReplicas|Collections:DefaultReplication|
+|-pid|PIDFile|N/A|
+|N/A|Debug|SystemLogs:LogLevel|
+|-timeout|Timeout|API:KeepServiceRequestTimeout|
+|-management-token|ManagementToken|ManagementToken|
+
+Note that some options are no longer supported. If you are still using the legacy config at @/etc/arvados/keepproxy/keepproxy.yml@ and @DisableGet@ or @DisablePut@ are set to true or @PIDFile@ has a value, keepproxy will produce an error and fail to start.
+
 h2. arvados-controller
 
 Already uses centralized config exclusively.  No migration needed.
diff --git a/doc/admin/upgrading.html.textile.liquid b/doc/admin/upgrading.html.textile.liquid
index da37d743d..7ea1b10fa 100644
--- a/doc/admin/upgrading.html.textile.liquid
+++ b/doc/admin/upgrading.html.textile.liquid
@@ -41,6 +41,10 @@ table(table table-bordered table-condensed).
 
 h3(#master). development master (as of 2019-06-07)
 
+h4. Keepproxy configuration migration
+
+Keepproxy can now be configured using the centralized config at @/etc/arvados/config.yml at . Some configuration options are no longer supported. Please see "keepproxy's config migration guide":{{site.baseurl}}/admin/config-migration.html#keepproxy for more details.
+
 h4. No longer stripping ':' from strings in serialized database columns
 
  (bug #15311) Strings read from serialized columns in the database with a leading ':' would have the ':' stripped after loading the record.  This behavior existed due to legacy serialization behavior which stored Ruby symbols with a leading ':'.  Unfortunately this corrupted fields where the leading ":" was intentional.  This behavior has been removed.
diff --git a/doc/install/install-keepproxy.html.textile.liquid b/doc/install/install-keepproxy.html.textile.liquid
index db24953fc..738cd523e 100644
--- a/doc/install/install-keepproxy.html.textile.liquid
+++ b/doc/install/install-keepproxy.html.textile.liquid
@@ -50,20 +50,29 @@ Usage: keepproxy [-config path/to/keepproxy.yml]
 </code></pre>
 </notextile>
 
-h3. Create an API token for the Keepproxy server
+h3. Update the cluster config
 
-{% assign railscmd = "bundle exec ./script/get_anonymous_user_token.rb --get" %}
-{% assign railsout = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" %}
-The Keepproxy server needs a token to talk to the API server.  On the <strong>API server</strong>, use the following command to create the token.  {% include 'install_rails_command' %}
+Edit the cluster config at @/etc/arvados/config.yml@ and set @Services.Keepproxy.ExternalURL@ and @Services.Keepproxy.InternalURLs at .  Replace @zzzzz@ with your cluster id.
+
+<notextile>
+<pre><code>Clusters:
+  zzzzz:
+    Services:
+      <span class="userinput">Keepproxy:
+        ExternalURL: https://keep.uuid_prefix.your.domain
+        InternalURLs:
+	  "http://localhost:25107": {}
+</span></code></pre>
+</notextile>
 
 h3. Set up the Keepproxy service
 
 Install runit to supervise the keepproxy daemon.  {% include 'install_runit' %}
 
-The run script for the keepproxy service should set the environment variables @ARVADOS_API_TOKEN@ (with the token you just generated), @ARVADOS_API_HOST@, and, if needed, @ARVADOS_API_HOST_INSECURE at .  The core keepproxy command to run is:
+The keepproxy command to run is:
 
 <notextile>
-<pre><code>ARVADOS_API_TOKEN=<span class="userinput">{{railsout}}</span> ARVADOS_API_HOST=<span class="userinput">uuid_prefix.your.domain</span> exec keepproxy
+<pre><code>~$ <span class="userinput">exec keepproxy
 </code></pre>
 </notextile>
 

commit e7374a8dbe6467add8506d52a8d25b9f0eee16dd
Author: Eric Biagiotti <ebiagiotti at veritasgenetics.com>
Date:   Mon Aug 12 09:06:29 2019 -0400

    14715: Adds legacy config test
    
    Arvados-DCO-1.1-Signed-off-by: Eric Biagiotti <ebiagiotti at veritasgenetics.com>

diff --git a/services/keepproxy/keepproxy.go b/services/keepproxy/keepproxy.go
index f2a89e58e..824b748bc 100644
--- a/services/keepproxy/keepproxy.go
+++ b/services/keepproxy/keepproxy.go
@@ -41,7 +41,7 @@ var (
 
 const rfc3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00"
 
-func configure(logger log.FieldLogger, args []string) *arvados.Cluster {
+func configure(logger log.FieldLogger, args []string) (*arvados.Cluster, error) {
 	flags := flag.NewFlagSet(args[0], flag.ExitOnError)
 	flags.Usage = usage
 
@@ -57,31 +57,29 @@ func configure(logger log.FieldLogger, args []string) *arvados.Cluster {
 	// Print version information if requested
 	if *getVersion {
 		fmt.Printf("keepproxy %s\n", version)
-		return nil
+		return nil, nil
 	}
 
 	cfg, err := loader.Load()
 	if err != nil {
-		log.Fatal(err)
+		return nil, err
 	}
-
 	cluster, err := cfg.GetCluster("")
 	if err != nil {
-		log.Fatal(err)
+		return nil, err
 	}
 
 	if *dumpConfig {
 		out, err := yaml.Marshal(cfg)
 		if err != nil {
-			log.Fatal(err)
+			return nil, err
 		}
-		_, err = os.Stdout.Write(out)
-		if err != nil {
-			log.Fatal(err)
+		if _, err := os.Stdout.Write(out); err != nil {
+			return nil, err
 		}
-		return nil
+		return nil, nil
 	}
-	return cluster
+	return cluster, nil
 }
 
 func main() {
@@ -90,7 +88,10 @@ func main() {
 		TimestampFormat: rfc3339NanoFixed,
 	}
 
-	cluster := configure(logger, os.Args)
+	cluster, err := configure(logger, os.Args)
+	if err != nil {
+		log.Fatal(err)
+	}
 	if cluster == nil {
 		return
 	}
diff --git a/services/keepproxy/keepproxy_test.go b/services/keepproxy/keepproxy_test.go
index 5f19c8c1f..609da4f70 100644
--- a/services/keepproxy/keepproxy_test.go
+++ b/services/keepproxy/keepproxy_test.go
@@ -13,6 +13,7 @@ import (
 	"math/rand"
 	"net/http"
 	"net/http/httptest"
+	"os"
 	"strings"
 	"sync"
 	"testing"
@@ -107,7 +108,10 @@ func runProxy(c *C, bogusClientToken bool) *keepclient.KeepClient {
 	cluster.Services.Keepproxy.InternalURLs = map[arvados.URL]arvados.ServiceInstance{arvados.URL{Host: ":0"}: arvados.ServiceInstance{}}
 
 	listener = nil
-	go run(log.New(), cluster)
+	go func() {
+		run(log.New(), cluster)
+		defer closeListener()
+	}()
 	waitForListener()
 
 	client := arvados.NewClientFromEnv()
@@ -636,3 +640,74 @@ func (s *ServerRequiredSuite) TestPing(c *C) {
 	c.Check(resp.Code, Equals, 200)
 	c.Assert(resp.Body.String(), Matches, `{"health":"OK"}\n?`)
 }
+
+func (s *NoKeepServerSuite) TestLegacyConfig(c *C) {
+	content := []byte(fmtConfig("", true))
+	cluster, err := loadLegacyConfig(content, c)
+
+	c.Check(err, IsNil)
+	c.Check(cluster, NotNil)
+	c.Check(cluster.Services.Controller.ExternalURL, Equals, arvados.URL{Scheme: "https", Host: "example.com"})
+	c.Check(cluster.SystemRootToken, Equals, "abcdefg")
+	c.Check(cluster.ManagementToken, Equals, "xyzzy")
+	c.Check(cluster.Services.Keepproxy.InternalURLs[arvados.URL{Host: ":80"}], Equals, arvados.ServiceInstance{})
+	c.Check(cluster.Collections.DefaultReplication, Equals, 0)
+	c.Check(cluster.API.KeepServiceRequestTimeout.String(), Equals, "15s")
+	c.Check(cluster.SystemLogs.LogLevel, Equals, "debug")
+
+	content = []byte(fmtConfig("", false))
+	cluster, err = loadLegacyConfig(content, c)
+	c.Check(cluster.SystemLogs.LogLevel, Equals, "info")
+
+	content = []byte(fmtConfig(`"DisableGet": true,`, true))
+	_, err = loadLegacyConfig(content, c)
+	c.Check(err, NotNil)
+
+	content = []byte(fmtConfig(`"DisablePut": true,`, true))
+	_, err = loadLegacyConfig(content, c)
+	c.Check(err, NotNil)
+
+	content = []byte(fmtConfig(`"PIDFile": "test",`, true))
+	_, err = loadLegacyConfig(content, c)
+	c.Check(err, NotNil)
+
+	content = []byte(fmtConfig(`"DisableGet": false, "DisablePut": false, "PIDFile": "",`, true))
+	_, err = loadLegacyConfig(content, c)
+	c.Check(err, IsNil)
+
+}
+
+func loadLegacyConfig(content []byte, c *C) (*arvados.Cluster, error) {
+	tmpfile, err := ioutil.TempFile("", "example")
+	if err != nil {
+		c.Error(err)
+	}
+	defer os.Remove(tmpfile.Name())
+
+	if _, err := tmpfile.Write(content); err != nil {
+		c.Error(err)
+	}
+	if err := tmpfile.Close(); err != nil {
+		c.Error(err)
+	}
+	return configure(log.New(), []string{"keepproxy", "-config", tmpfile.Name()})
+}
+
+func fmtConfig(param string, debugLog bool) string {
+	return fmt.Sprintf(`
+{
+	"Client": {
+		"Scheme": "",
+		"APIHost": "example.com",
+		"AuthToken": "abcdefg",
+		"Insecure": false
+	},
+	"Listen": ":80",
+	"DefaultReplicas": 0,
+	"Timeout": "15s",
+	"Debug": %t,
+	%s
+	"ManagementToken": "xyzzy"
+}
+`, debugLog, param)
+}

commit f248e19664fec1268e2a736d698acfbd6147016e
Author: Eric Biagiotti <ebiagiotti at veritasgenetics.com>
Date:   Fri Aug 9 15:27:38 2019 -0400

    14715: Fixes keepproxy tests
    
    Arvados-DCO-1.1-Signed-off-by: Eric Biagiotti <ebiagiotti at veritasgenetics.com>

diff --git a/services/keepproxy/keepproxy.go b/services/keepproxy/keepproxy.go
index f75079565..f2a89e58e 100644
--- a/services/keepproxy/keepproxy.go
+++ b/services/keepproxy/keepproxy.go
@@ -27,9 +27,9 @@ import (
 	"git.curoverse.com/arvados.git/sdk/go/httpserver"
 	"git.curoverse.com/arvados.git/sdk/go/keepclient"
 	"github.com/coreos/go-systemd/daemon"
+	"github.com/ghodss/yaml"
 	"github.com/gorilla/mux"
 	log "github.com/sirupsen/logrus"
-	"gopkg.in/yaml.v2"
 )
 
 var version = "dev"
@@ -97,6 +97,14 @@ func main() {
 
 	log.Printf("keepproxy %s started", version)
 
+	if err := run(logger, cluster); err != nil {
+		log.Fatal(err)
+	}
+
+	log.Println("shutting down")
+}
+
+func run(logger log.FieldLogger, cluster *arvados.Cluster) error {
 	client, err := arvados.NewClientFromConfig(cluster)
 	if err != nil {
 		log.Fatal(err)
@@ -125,9 +133,11 @@ func main() {
 	for listen = range cluster.Services.Keepproxy.InternalURLs {
 		break
 	}
-	listener, err := net.Listen("tcp", listen.Host)
-	if err != nil {
-		log.Fatalf("listen(%s): %s", listen.Host, err)
+
+	var lErr error
+	listener, lErr = net.Listen("tcp", listen.Host)
+	if lErr != nil {
+		log.Fatalf("listen(%s): %s", listen.Host, lErr)
 	}
 
 	if _, err := daemon.SdNotify(false, "READY=1"); err != nil {
@@ -148,9 +158,7 @@ func main() {
 
 	// Start serving requests.
 	router = MakeRESTRouter(kc, time.Duration(cluster.API.KeepServiceRequestTimeout), cluster.SystemRootToken)
-	http.Serve(listener, httpserver.AddRequestIDs(httpserver.LogRequests(router)))
-
-	log.Println("shutting down")
+	return http.Serve(listener, httpserver.AddRequestIDs(httpserver.LogRequests(router)))
 }
 
 type ApiTokenCache struct {
diff --git a/services/keepproxy/keepproxy_test.go b/services/keepproxy/keepproxy_test.go
index 440bf5b8a..5f19c8c1f 100644
--- a/services/keepproxy/keepproxy_test.go
+++ b/services/keepproxy/keepproxy_test.go
@@ -13,15 +13,17 @@ import (
 	"math/rand"
 	"net/http"
 	"net/http/httptest"
-	"os"
 	"strings"
 	"sync"
 	"testing"
 	"time"
 
+	"git.curoverse.com/arvados.git/lib/config"
+	"git.curoverse.com/arvados.git/sdk/go/arvados"
 	"git.curoverse.com/arvados.git/sdk/go/arvadosclient"
 	"git.curoverse.com/arvados.git/sdk/go/arvadostest"
 	"git.curoverse.com/arvados.git/sdk/go/keepclient"
+	log "github.com/sirupsen/logrus"
 
 	. "gopkg.in/check.v1"
 )
@@ -96,14 +98,20 @@ func (s *NoKeepServerSuite) TearDownSuite(c *C) {
 	arvadostest.StopAPI()
 }
 
-func runProxy(c *C, args []string, bogusClientToken bool) *keepclient.KeepClient {
-	args = append([]string{"keepproxy"}, args...)
-	os.Args = append(args, "-listen=:0")
+func runProxy(c *C, bogusClientToken bool) *keepclient.KeepClient {
+	cfg, err := config.NewLoader(nil, nil).Load()
+	c.Assert(err, Equals, nil)
+	cluster, err := cfg.GetCluster("")
+	c.Assert(err, Equals, nil)
+
+	cluster.Services.Keepproxy.InternalURLs = map[arvados.URL]arvados.ServiceInstance{arvados.URL{Host: ":0"}: arvados.ServiceInstance{}}
+
 	listener = nil
-	go main()
+	go run(log.New(), cluster)
 	waitForListener()
 
-	arv, err := arvadosclient.MakeArvadosClient()
+	client := arvados.NewClientFromEnv()
+	arv, err := arvadosclient.New(client)
 	c.Assert(err, Equals, nil)
 	if bogusClientToken {
 		arv.ApiToken = "bogus-token"
@@ -119,7 +127,7 @@ func runProxy(c *C, args []string, bogusClientToken bool) *keepclient.KeepClient
 }
 
 func (s *ServerRequiredSuite) TestResponseViaHeader(c *C) {
-	runProxy(c, nil, false)
+	runProxy(c, false)
 	defer closeListener()
 
 	req, err := http.NewRequest("POST",
@@ -145,7 +153,7 @@ func (s *ServerRequiredSuite) TestResponseViaHeader(c *C) {
 }
 
 func (s *ServerRequiredSuite) TestLoopDetection(c *C) {
-	kc := runProxy(c, nil, false)
+	kc := runProxy(c, false)
 	defer closeListener()
 
 	sr := map[string]string{
@@ -163,7 +171,7 @@ func (s *ServerRequiredSuite) TestLoopDetection(c *C) {
 }
 
 func (s *ServerRequiredSuite) TestStorageClassesHeader(c *C) {
-	kc := runProxy(c, nil, false)
+	kc := runProxy(c, false)
 	defer closeListener()
 
 	// Set up fake keepstore to record request headers
@@ -190,7 +198,7 @@ func (s *ServerRequiredSuite) TestStorageClassesHeader(c *C) {
 }
 
 func (s *ServerRequiredSuite) TestDesiredReplicas(c *C) {
-	kc := runProxy(c, nil, false)
+	kc := runProxy(c, false)
 	defer closeListener()
 
 	content := []byte("TestDesiredReplicas")
@@ -207,7 +215,7 @@ func (s *ServerRequiredSuite) TestDesiredReplicas(c *C) {
 }
 
 func (s *ServerRequiredSuite) TestPutWrongContentLength(c *C) {
-	kc := runProxy(c, nil, false)
+	kc := runProxy(c, false)
 	defer closeListener()
 
 	content := []byte("TestPutWrongContentLength")
@@ -246,7 +254,7 @@ func (s *ServerRequiredSuite) TestPutWrongContentLength(c *C) {
 }
 
 func (s *ServerRequiredSuite) TestManyFailedPuts(c *C) {
-	kc := runProxy(c, nil, false)
+	kc := runProxy(c, false)
 	defer closeListener()
 	router.(*proxyHandler).timeout = time.Nanosecond
 
@@ -273,7 +281,7 @@ func (s *ServerRequiredSuite) TestManyFailedPuts(c *C) {
 }
 
 func (s *ServerRequiredSuite) TestPutAskGet(c *C) {
-	kc := runProxy(c, nil, false)
+	kc := runProxy(c, false)
 	defer closeListener()
 
 	hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
@@ -350,7 +358,7 @@ func (s *ServerRequiredSuite) TestPutAskGet(c *C) {
 }
 
 func (s *ServerRequiredSuite) TestPutAskGetForbidden(c *C) {
-	kc := runProxy(c, nil, true)
+	kc := runProxy(c, true)
 	defer closeListener()
 
 	hash := fmt.Sprintf("%x+3", md5.Sum([]byte("bar")))
@@ -376,7 +384,7 @@ func (s *ServerRequiredSuite) TestPutAskGetForbidden(c *C) {
 }
 
 func (s *ServerRequiredSuite) TestCorsHeaders(c *C) {
-	runProxy(c, nil, false)
+	runProxy(c, false)
 	defer closeListener()
 
 	{
@@ -407,7 +415,7 @@ func (s *ServerRequiredSuite) TestCorsHeaders(c *C) {
 }
 
 func (s *ServerRequiredSuite) TestPostWithoutHash(c *C) {
-	runProxy(c, nil, false)
+	runProxy(c, false)
 	defer closeListener()
 
 	{
@@ -450,7 +458,7 @@ func (s *ServerRequiredSuite) TestStripHint(c *C) {
 //   With a valid but non-existing prefix (expect "\n")
 //   With an invalid prefix (expect error)
 func (s *ServerRequiredSuite) TestGetIndex(c *C) {
-	kc := runProxy(c, nil, false)
+	kc := runProxy(c, false)
 	defer closeListener()
 
 	// Put "index-data" blocks
@@ -513,7 +521,7 @@ func (s *ServerRequiredSuite) TestGetIndex(c *C) {
 }
 
 func (s *ServerRequiredSuite) TestCollectionSharingToken(c *C) {
-	kc := runProxy(c, nil, false)
+	kc := runProxy(c, false)
 	defer closeListener()
 	hash, _, err := kc.PutB([]byte("shareddata"))
 	c.Check(err, IsNil)
@@ -526,7 +534,7 @@ func (s *ServerRequiredSuite) TestCollectionSharingToken(c *C) {
 }
 
 func (s *ServerRequiredSuite) TestPutAskGetInvalidToken(c *C) {
-	kc := runProxy(c, nil, false)
+	kc := runProxy(c, false)
 	defer closeListener()
 
 	// Put a test block
@@ -563,7 +571,7 @@ func (s *ServerRequiredSuite) TestPutAskGetInvalidToken(c *C) {
 }
 
 func (s *ServerRequiredSuite) TestAskGetKeepProxyConnectionError(c *C) {
-	kc := runProxy(c, nil, false)
+	kc := runProxy(c, false)
 	defer closeListener()
 
 	// Point keepproxy at a non-existent keepstore
@@ -589,7 +597,7 @@ func (s *ServerRequiredSuite) TestAskGetKeepProxyConnectionError(c *C) {
 }
 
 func (s *NoKeepServerSuite) TestAskGetNoKeepServerError(c *C) {
-	kc := runProxy(c, nil, false)
+	kc := runProxy(c, false)
 	defer closeListener()
 
 	hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
@@ -612,7 +620,7 @@ func (s *NoKeepServerSuite) TestAskGetNoKeepServerError(c *C) {
 }
 
 func (s *ServerRequiredSuite) TestPing(c *C) {
-	kc := runProxy(c, nil, false)
+	kc := runProxy(c, false)
 	defer closeListener()
 
 	rtr := MakeRESTRouter(kc, 10*time.Second, arvadostest.ManagementToken)

commit 47d4b25da3ee62b641aa3026adf38adc22b3b65c
Author: Eric Biagiotti <ebiagiotti at veritasgenetics.com>
Date:   Fri Aug 9 15:24:54 2019 -0400

    14715: Updates arvbox with new keepproxy cluster config
    
    Arvados-DCO-1.1-Signed-off-by: Eric Biagiotti <ebiagiotti at veritasgenetics.com>

diff --git a/tools/arvbox/lib/arvbox/docker/cluster-config.sh b/tools/arvbox/lib/arvbox/docker/cluster-config.sh
index 801787e6a..3444e61e1 100755
--- a/tools/arvbox/lib/arvbox/docker/cluster-config.sh
+++ b/tools/arvbox/lib/arvbox/docker/cluster-config.sh
@@ -76,6 +76,10 @@ Clusters:
         ExternalURL: "https://$localip:${services[workbench2-ssl]}"
       SSO:
         ExternalURL: "https://$localip:${services[sso]}"
+      Keepproxy:
+        InternalURLs:
+          "http://localhost:${services[keepproxy]}/": {}
+        ExternalURL: "http://$localip:${services[keepproxy-ssl]}/"
       Websocket:
         ExternalURL: "wss://$localip:${services[websockets-ssl]}/websocket"
       GitSSH:
diff --git a/tools/arvbox/lib/arvbox/docker/common.sh b/tools/arvbox/lib/arvbox/docker/common.sh
index 8e4e74ca0..218727495 100644
--- a/tools/arvbox/lib/arvbox/docker/common.sh
+++ b/tools/arvbox/lib/arvbox/docker/common.sh
@@ -37,6 +37,7 @@ services=(
   [keep-web]=9003
   [keep-web-ssl]=9002
   [keepproxy]=25100
+  [keepproxy-ssl]=25101
   [keepstore0]=25107
   [keepstore1]=25108
   [ssh]=22
diff --git a/tools/arvbox/lib/arvbox/docker/service/keepproxy/run-service b/tools/arvbox/lib/arvbox/docker/service/keepproxy/run-service
index bf802d45f..55c647d5b 100755
--- a/tools/arvbox/lib/arvbox/docker/service/keepproxy/run-service
+++ b/tools/arvbox/lib/arvbox/docker/service/keepproxy/run-service
@@ -40,4 +40,4 @@ else
     echo $UUID > /var/lib/arvados/keepproxy-uuid
 fi
 
-exec /usr/local/bin/keepproxy -listen=:${services[keepproxy]}
+exec /usr/local/bin/keepproxy
diff --git a/tools/arvbox/lib/arvbox/docker/service/nginx/run b/tools/arvbox/lib/arvbox/docker/service/nginx/run
index 18c56ce9d..b17eeea04 100755
--- a/tools/arvbox/lib/arvbox/docker/service/nginx/run
+++ b/tools/arvbox/lib/arvbox/docker/service/nginx/run
@@ -123,6 +123,23 @@ server {
     }
   }
 
+  upstream keepproxy {
+    server localhost:${services[keepproxy]};
+  }
+  server {
+    listen *:${services[keepproxy-ssl]} ssl default_server;
+    server_name keepproxy;
+    ssl_certificate "${server_cert}";
+    ssl_certificate_key "${server_cert_key}";
+    location  / {
+      proxy_pass http://keepproxy;
+      proxy_set_header Host \$http_host;
+      proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
+      proxy_set_header X-Forwarded-Proto https;
+      proxy_redirect off;
+    }
+  }
+
 }
 
 EOF

commit 100ae537a8329048452c656229750b97c78a3296
Author: Eric Biagiotti <ebiagiotti at veritasgenetics.com>
Date:   Wed Aug 7 15:10:39 2019 -0400

    14715: Fixes tests and removes PID creation
    
    Arvados-DCO-1.1-Signed-off-by: Eric Biagiotti <ebiagiotti at veritasgenetics.com>

diff --git a/sdk/python/tests/run_test_server.py b/sdk/python/tests/run_test_server.py
index 0f8f1c5f8..cde0cefb6 100644
--- a/sdk/python/tests/run_test_server.py
+++ b/sdk/python/tests/run_test_server.py
@@ -544,10 +544,11 @@ def run_keep_proxy():
     env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
     logf = open(_logfilename('keepproxy'), 'a')
     kp = subprocess.Popen(
-        ['keepproxy',
-         '-pid='+_pidfile('keepproxy'),
-         '-listen=:{}'.format(port)],
-        env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
+        ['keepproxy'], env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
+
+    with open(_pidfile('keepproxy'), 'w') as f:
+        f.write(str(kp.pid))
+    _wait_until_port_listens(port)
 
     print("Using API %s token %s" % (os.environ['ARVADOS_API_HOST'], auth_token('admin')), file=sys.stdout)
     api = arvados.api(
diff --git a/services/keepproxy/keepproxy.go b/services/keepproxy/keepproxy.go
index e4e54040f..f75079565 100644
--- a/services/keepproxy/keepproxy.go
+++ b/services/keepproxy/keepproxy.go
@@ -117,30 +117,6 @@ func main() {
 	}
 	keepclient.RefreshServiceDiscoveryOnSIGHUP()
 
-	pidFile := "keepproxy"
-	f, err := os.Create(pidFile)
-	if err != nil {
-		log.Fatal(err)
-	}
-	defer f.Close()
-	err = syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
-	if err != nil {
-		log.Fatalf("flock(%s): %s", pidFile, err)
-	}
-	defer os.Remove(pidFile)
-	err = f.Truncate(0)
-	if err != nil {
-		log.Fatalf("truncate(%s): %s", pidFile, err)
-	}
-	_, err = fmt.Fprint(f, os.Getpid())
-	if err != nil {
-		log.Fatalf("write(%s): %s", pidFile, err)
-	}
-	err = f.Sync()
-	if err != nil {
-		log.Fatalf("sync(%s): %s", pidFile, err)
-	}
-
 	if cluster.Collections.DefaultReplication > 0 {
 		kc.Want_replicas = cluster.Collections.DefaultReplication
 	}
@@ -151,7 +127,7 @@ func main() {
 	}
 	listener, err := net.Listen("tcp", listen.Host)
 	if err != nil {
-		log.Fatalf("listen(%s): %s", listen, err)
+		log.Fatalf("listen(%s): %s", listen.Host, err)
 	}
 
 	if _, err := daemon.SdNotify(false, "READY=1"); err != nil {
diff --git a/services/keepproxy/keepproxy_test.go b/services/keepproxy/keepproxy_test.go
index dc70d968e..440bf5b8a 100644
--- a/services/keepproxy/keepproxy_test.go
+++ b/services/keepproxy/keepproxy_test.go
@@ -218,7 +218,7 @@ func (s *ServerRequiredSuite) TestPutWrongContentLength(c *C) {
 	// fixes the invalid Content-Length header. In order to test
 	// our server behavior, we have to call the handler directly
 	// using an httptest.ResponseRecorder.
-	rtr := MakeRESTRouter(true, true, kc, 10*time.Second, "")
+	rtr := MakeRESTRouter(kc, 10*time.Second, "")
 
 	type testcase struct {
 		sendLength   string
@@ -375,57 +375,6 @@ func (s *ServerRequiredSuite) TestPutAskGetForbidden(c *C) {
 
 }
 
-func (s *ServerRequiredSuite) TestGetDisabled(c *C) {
-	kc := runProxy(c, []string{"-no-get"}, false)
-	defer closeListener()
-
-	hash := fmt.Sprintf("%x", md5.Sum([]byte("baz")))
-
-	{
-		_, _, err := kc.Ask(hash)
-		errNotFound, _ := err.(keepclient.ErrNotFound)
-		c.Check(errNotFound, NotNil)
-		c.Assert(err, ErrorMatches, `.*HTTP 405.*`)
-		c.Log("Ask 1")
-	}
-
-	{
-		hash2, rep, err := kc.PutB([]byte("baz"))
-		c.Check(hash2, Matches, fmt.Sprintf(`^%s\+3(\+.+)?$`, hash))
-		c.Check(rep, Equals, 2)
-		c.Check(err, Equals, nil)
-		c.Log("PutB")
-	}
-
-	{
-		blocklen, _, err := kc.Ask(hash)
-		errNotFound, _ := err.(keepclient.ErrNotFound)
-		c.Check(errNotFound, NotNil)
-		c.Assert(err, ErrorMatches, `.*HTTP 405.*`)
-		c.Check(blocklen, Equals, int64(0))
-		c.Log("Ask 2")
-	}
-
-	{
-		_, blocklen, _, err := kc.Get(hash)
-		errNotFound, _ := err.(keepclient.ErrNotFound)
-		c.Check(errNotFound, NotNil)
-		c.Assert(err, ErrorMatches, `.*HTTP 405.*`)
-		c.Check(blocklen, Equals, int64(0))
-		c.Log("Get")
-	}
-}
-
-func (s *ServerRequiredSuite) TestPutDisabled(c *C) {
-	kc := runProxy(c, []string{"-no-put"}, false)
-	defer closeListener()
-
-	hash2, rep, err := kc.PutB([]byte("quux"))
-	c.Check(hash2, Equals, "")
-	c.Check(rep, Equals, 0)
-	c.Check(err, FitsTypeOf, keepclient.InsufficientReplicasError(errors.New("")))
-}
-
 func (s *ServerRequiredSuite) TestCorsHeaders(c *C) {
 	runProxy(c, nil, false)
 	defer closeListener()
@@ -666,7 +615,7 @@ func (s *ServerRequiredSuite) TestPing(c *C) {
 	kc := runProxy(c, nil, false)
 	defer closeListener()
 
-	rtr := MakeRESTRouter(true, true, kc, 10*time.Second, arvadostest.ManagementToken)
+	rtr := MakeRESTRouter(kc, 10*time.Second, arvadostest.ManagementToken)
 
 	req, err := http.NewRequest("GET",
 		"http://"+listener.Addr().String()+"/_health/ping",

commit aabdf0fec790f9dd341af07013cc1c47ae04b876
Author: Eric Biagiotti <ebiagiotti at veritasgenetics.com>
Date:   Tue Aug 6 18:00:36 2019 -0400

    14715: Keepproxy uses cluster config
    
    Arvados-DCO-1.1-Signed-off-by: Eric Biagiotti <ebiagiotti at veritasgenetics.com>

diff --git a/lib/config/deprecated.go b/lib/config/deprecated.go
index dcfdd8b74..4e7b85ec5 100644
--- a/lib/config/deprecated.go
+++ b/lib/config/deprecated.go
@@ -380,10 +380,11 @@ func (ldr *Loader) loadOldKeepproxyConfig(cfg *arvados.Config) error {
 		cluster.ManagementToken = *oc.ManagementToken
 	}
 
+	// The following legacy options are no longer supported. If they are set to
+	// true or PIDFile has a value, error out and notify the user
 	unsupportedEntry := func(cfgEntry string) error {
 		return fmt.Errorf("the keepproxy %s configuration option is no longer supported, please remove it from your configuration file", cfgEntry)
 	}
-
 	if oc.DisableGet != nil && *oc.DisableGet {
 		return unsupportedEntry("DisableGet")
 	}
diff --git a/services/keepproxy/keepproxy.go b/services/keepproxy/keepproxy.go
index f8aa6c4aa..e4e54040f 100644
--- a/services/keepproxy/keepproxy.go
+++ b/services/keepproxy/keepproxy.go
@@ -20,39 +20,20 @@ import (
 	"syscall"
 	"time"
 
+	"git.curoverse.com/arvados.git/lib/config"
 	"git.curoverse.com/arvados.git/sdk/go/arvados"
 	"git.curoverse.com/arvados.git/sdk/go/arvadosclient"
-	"git.curoverse.com/arvados.git/sdk/go/config"
 	"git.curoverse.com/arvados.git/sdk/go/health"
 	"git.curoverse.com/arvados.git/sdk/go/httpserver"
 	"git.curoverse.com/arvados.git/sdk/go/keepclient"
 	"github.com/coreos/go-systemd/daemon"
-	"github.com/ghodss/yaml"
 	"github.com/gorilla/mux"
 	log "github.com/sirupsen/logrus"
+	"gopkg.in/yaml.v2"
 )
 
 var version = "dev"
 
-type Config struct {
-	Client          arvados.Client
-	Listen          string
-	DisableGet      bool
-	DisablePut      bool
-	DefaultReplicas int
-	Timeout         arvados.Duration
-	PIDFile         string
-	Debug           bool
-	ManagementToken string
-}
-
-func DefaultConfig() *Config {
-	return &Config{
-		Listen:  ":25107",
-		Timeout: arvados.Duration(15 * time.Second),
-	}
-}
-
 var (
 	listener net.Listener
 	router   http.Handler
@@ -60,69 +41,74 @@ var (
 
 const rfc3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00"
 
-func main() {
-	log.SetFormatter(&log.JSONFormatter{
-		TimestampFormat: rfc3339NanoFixed,
-	})
-
-	cfg := DefaultConfig()
+func configure(logger log.FieldLogger, args []string) *arvados.Cluster {
+	flags := flag.NewFlagSet(args[0], flag.ExitOnError)
+	flags.Usage = usage
 
-	flagset := flag.NewFlagSet("keepproxy", flag.ExitOnError)
-	flagset.Usage = usage
+	dumpConfig := flags.Bool("dump-config", false, "write current configuration to stdout and exit")
+	getVersion := flags.Bool("version", false, "Print version information and exit.")
 
-	const deprecated = " (DEPRECATED -- use config file instead)"
-	flagset.StringVar(&cfg.Listen, "listen", cfg.Listen, "Local port to listen on."+deprecated)
-	flagset.BoolVar(&cfg.DisableGet, "no-get", cfg.DisableGet, "Disable GET operations."+deprecated)
-	flagset.BoolVar(&cfg.DisablePut, "no-put", cfg.DisablePut, "Disable PUT operations."+deprecated)
-	flagset.IntVar(&cfg.DefaultReplicas, "default-replicas", cfg.DefaultReplicas, "Default number of replicas to write if not specified by the client. If 0, use site default."+deprecated)
-	flagset.StringVar(&cfg.PIDFile, "pid", cfg.PIDFile, "Path to write pid file."+deprecated)
-	timeoutSeconds := flagset.Int("timeout", int(time.Duration(cfg.Timeout)/time.Second), "Timeout (in seconds) on requests to internal Keep services."+deprecated)
-	flagset.StringVar(&cfg.ManagementToken, "management-token", cfg.ManagementToken, "Authorization token to be included in all health check requests.")
+	loader := config.NewLoader(os.Stdin, logger)
+	loader.SetupFlags(flags)
 
-	var cfgPath string
-	const defaultCfgPath = "/etc/arvados/keepproxy/keepproxy.yml"
-	flagset.StringVar(&cfgPath, "config", defaultCfgPath, "Configuration file `path`")
-	dumpConfig := flagset.Bool("dump-config", false, "write current configuration to stdout and exit")
-	getVersion := flagset.Bool("version", false, "Print version information and exit.")
-	flagset.Parse(os.Args[1:])
+	args = loader.MungeLegacyConfigArgs(logger, args[1:], "-legacy-keepproxy-config")
+	flags.Parse(args)
 
 	// Print version information if requested
 	if *getVersion {
 		fmt.Printf("keepproxy %s\n", version)
-		return
+		return nil
 	}
 
-	err := config.LoadFile(cfg, cfgPath)
+	cfg, err := loader.Load()
 	if err != nil {
-		h := os.Getenv("ARVADOS_API_HOST")
-		t := os.Getenv("ARVADOS_API_TOKEN")
-		if h == "" || t == "" || !os.IsNotExist(err) || cfgPath != defaultCfgPath {
+		log.Fatal(err)
+	}
+
+	cluster, err := cfg.GetCluster("")
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	if *dumpConfig {
+		out, err := yaml.Marshal(cfg)
+		if err != nil {
 			log.Fatal(err)
 		}
-		log.Print("DEPRECATED: No config file found, but ARVADOS_API_HOST and ARVADOS_API_TOKEN environment variables are set. Please use a config file instead.")
-		cfg.Client.APIHost = h
-		cfg.Client.AuthToken = t
-		if regexp.MustCompile("^(?i:1|yes|true)$").MatchString(os.Getenv("ARVADOS_API_HOST_INSECURE")) {
-			cfg.Client.Insecure = true
-		}
-		if y, err := yaml.Marshal(cfg); err == nil && !*dumpConfig {
-			log.Print("Current configuration:\n", string(y))
+		_, err = os.Stdout.Write(out)
+		if err != nil {
+			log.Fatal(err)
 		}
-		cfg.Timeout = arvados.Duration(time.Duration(*timeoutSeconds) * time.Second)
+		return nil
 	}
+	return cluster
+}
 
-	if *dumpConfig {
-		log.Fatal(config.DumpAndExit(cfg))
+func main() {
+	logger := log.New()
+	logger.Formatter = &log.JSONFormatter{
+		TimestampFormat: rfc3339NanoFixed,
+	}
+
+	cluster := configure(logger, os.Args)
+	if cluster == nil {
+		return
 	}
 
 	log.Printf("keepproxy %s started", version)
 
-	arv, err := arvadosclient.New(&cfg.Client)
+	client, err := arvados.NewClientFromConfig(cluster)
+	if err != nil {
+		log.Fatal(err)
+	}
+	client.AuthToken = cluster.SystemRootToken
+
+	arv, err := arvadosclient.New(client)
 	if err != nil {
 		log.Fatalf("Error setting up arvados client %s", err.Error())
 	}
 
-	if cfg.Debug {
+	if cluster.SystemLogs.LogLevel == "debug" {
 		keepclient.DebugPrintf = log.Printf
 	}
 	kc, err := keepclient.MakeKeepClient(arv)
@@ -131,39 +117,43 @@ func main() {
 	}
 	keepclient.RefreshServiceDiscoveryOnSIGHUP()
 
-	if cfg.PIDFile != "" {
-		f, err := os.Create(cfg.PIDFile)
-		if err != nil {
-			log.Fatal(err)
-		}
-		defer f.Close()
-		err = syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
-		if err != nil {
-			log.Fatalf("flock(%s): %s", cfg.PIDFile, err)
-		}
-		defer os.Remove(cfg.PIDFile)
-		err = f.Truncate(0)
-		if err != nil {
-			log.Fatalf("truncate(%s): %s", cfg.PIDFile, err)
-		}
-		_, err = fmt.Fprint(f, os.Getpid())
-		if err != nil {
-			log.Fatalf("write(%s): %s", cfg.PIDFile, err)
-		}
-		err = f.Sync()
-		if err != nil {
-			log.Fatalf("sync(%s): %s", cfg.PIDFile, err)
-		}
+	pidFile := "keepproxy"
+	f, err := os.Create(pidFile)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer f.Close()
+	err = syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
+	if err != nil {
+		log.Fatalf("flock(%s): %s", pidFile, err)
+	}
+	defer os.Remove(pidFile)
+	err = f.Truncate(0)
+	if err != nil {
+		log.Fatalf("truncate(%s): %s", pidFile, err)
+	}
+	_, err = fmt.Fprint(f, os.Getpid())
+	if err != nil {
+		log.Fatalf("write(%s): %s", pidFile, err)
+	}
+	err = f.Sync()
+	if err != nil {
+		log.Fatalf("sync(%s): %s", pidFile, err)
 	}
 
-	if cfg.DefaultReplicas > 0 {
-		kc.Want_replicas = cfg.DefaultReplicas
+	if cluster.Collections.DefaultReplication > 0 {
+		kc.Want_replicas = cluster.Collections.DefaultReplication
 	}
 
-	listener, err = net.Listen("tcp", cfg.Listen)
+	var listen arvados.URL
+	for listen = range cluster.Services.Keepproxy.InternalURLs {
+		break
+	}
+	listener, err := net.Listen("tcp", listen.Host)
 	if err != nil {
-		log.Fatalf("listen(%s): %s", cfg.Listen, err)
+		log.Fatalf("listen(%s): %s", listen, err)
 	}
+
 	if _, err := daemon.SdNotify(false, "READY=1"); err != nil {
 		log.Printf("Error notifying init daemon: %v", err)
 	}
@@ -181,7 +171,7 @@ func main() {
 	signal.Notify(term, syscall.SIGINT)
 
 	// Start serving requests.
-	router = MakeRESTRouter(!cfg.DisableGet, !cfg.DisablePut, kc, time.Duration(cfg.Timeout), cfg.ManagementToken)
+	router = MakeRESTRouter(kc, time.Duration(cluster.API.KeepServiceRequestTimeout), cluster.SystemRootToken)
 	http.Serve(listener, httpserver.AddRequestIDs(httpserver.LogRequests(router)))
 
 	log.Println("shutting down")
@@ -292,7 +282,7 @@ type proxyHandler struct {
 
 // MakeRESTRouter returns an http.Handler that passes GET and PUT
 // requests to the appropriate handlers.
-func MakeRESTRouter(enable_get bool, enable_put bool, kc *keepclient.KeepClient, timeout time.Duration, mgmtToken string) http.Handler {
+func MakeRESTRouter(kc *keepclient.KeepClient, timeout time.Duration, mgmtToken string) http.Handler {
 	rest := mux.NewRouter()
 
 	transport := defaultTransport
@@ -315,24 +305,20 @@ func MakeRESTRouter(enable_get bool, enable_put bool, kc *keepclient.KeepClient,
 		},
 	}
 
-	if enable_get {
-		rest.HandleFunc(`/{locator:[0-9a-f]{32}\+.*}`, h.Get).Methods("GET", "HEAD")
-		rest.HandleFunc(`/{locator:[0-9a-f]{32}}`, h.Get).Methods("GET", "HEAD")
+	rest.HandleFunc(`/{locator:[0-9a-f]{32}\+.*}`, h.Get).Methods("GET", "HEAD")
+	rest.HandleFunc(`/{locator:[0-9a-f]{32}}`, h.Get).Methods("GET", "HEAD")
 
-		// List all blocks
-		rest.HandleFunc(`/index`, h.Index).Methods("GET")
+	// List all blocks
+	rest.HandleFunc(`/index`, h.Index).Methods("GET")
 
-		// List blocks whose hash has the given prefix
-		rest.HandleFunc(`/index/{prefix:[0-9a-f]{0,32}}`, h.Index).Methods("GET")
-	}
+	// List blocks whose hash has the given prefix
+	rest.HandleFunc(`/index/{prefix:[0-9a-f]{0,32}}`, h.Index).Methods("GET")
 
-	if enable_put {
-		rest.HandleFunc(`/{locator:[0-9a-f]{32}\+.*}`, h.Put).Methods("PUT")
-		rest.HandleFunc(`/{locator:[0-9a-f]{32}}`, h.Put).Methods("PUT")
-		rest.HandleFunc(`/`, h.Put).Methods("POST")
-		rest.HandleFunc(`/{any}`, h.Options).Methods("OPTIONS")
-		rest.HandleFunc(`/`, h.Options).Methods("OPTIONS")
-	}
+	rest.HandleFunc(`/{locator:[0-9a-f]{32}\+.*}`, h.Put).Methods("PUT")
+	rest.HandleFunc(`/{locator:[0-9a-f]{32}}`, h.Put).Methods("PUT")
+	rest.HandleFunc(`/`, h.Put).Methods("POST")
+	rest.HandleFunc(`/{any}`, h.Options).Methods("OPTIONS")
+	rest.HandleFunc(`/`, h.Options).Methods("OPTIONS")
 
 	rest.Handle("/_health/{check}", &health.Handler{
 		Token:  mgmtToken,
diff --git a/services/keepproxy/usage.go b/services/keepproxy/usage.go
index 6d3d21e6f..4eeb55065 100644
--- a/services/keepproxy/usage.go
+++ b/services/keepproxy/usage.go
@@ -5,86 +5,19 @@
 package main
 
 import (
-	"encoding/json"
-	"flag"
 	"fmt"
 	"os"
 )
 
 func usage() {
-	c := DefaultConfig()
-	c.Client.APIHost = "zzzzz.arvadosapi.com:443"
-	exampleConfigFile, err := json.MarshalIndent(c, "    ", "  ")
-	if err != nil {
-		panic(err)
-	}
 	fmt.Fprintf(os.Stderr, `
-
-Keepproxy forwards GET and PUT requests to keepstore servers.  See
+Keepproxy forwards GET and PUT requests to keepstore servers. See
 http://doc.arvados.org/install/install-keepproxy.html
 
 Usage: keepproxy [-config path/to/keepproxy.yml]
 
-Options:
-`)
-	flag.PrintDefaults()
-	fmt.Fprintf(os.Stderr, `
-Example config file:
-    %s
-
-Client.APIHost:
-
-    Address (or address:port) of the Arvados API endpoint.
-
-Client.AuthToken:
-
-    Anonymous API token.
-
-Client.Insecure:
-
-    True if your Arvados API endpoint uses an unverifiable SSL/TLS
-    certificate.
-
-Listen:
-
-    Local port to listen on. Can be "address:port" or ":port", where
-    "address" is a host IP address or name and "port" is a port number
-    or name.
-
-DisableGet:
-
-    Respond 404 to GET and HEAD requests.
+DEPRECATION WARNING: The -config parameter is deprecated. Use the
+cluster config instead.
 
-DisablePut:
-
-    Respond 404 to PUT, POST, and OPTIONS requests.
-
-DefaultReplicas:
-
-    Default number of replicas to write if not specified by the
-    client. If this is zero or omitted, the site-wide
-    defaultCollectionReplication configuration will be used.
-
-Timeout:
-
-    Timeout for requests to keep services, with units (e.g., "120s",
-    "2m").
-
-PIDFile:
-
-    Path to PID file. During startup this file will be created if
-    needed, and locked using flock() until keepproxy exits. If it is
-    already locked, or any error is encountered while writing to it,
-    keepproxy will exit immediately. If omitted or empty, no PID file
-    will be used.
-
-Debug:
-
-    Enable debug logging.
-
-ManagementToken:
-
-    Authorization token to be included in all health check requests.
-
-`, exampleConfigFile)
+`)
 }

commit 1cce0422dfc66a02e59f0c3a783562c90d0931d9
Author: Eric Biagiotti <ebiagiotti at veritasgenetics.com>
Date:   Fri Aug 2 15:47:02 2019 -0400

    14715: Adds keepproxy to cluster config loading
    
    Arvados-DCO-1.1-Signed-off-by: Eric Biagiotti <ebiagiotti at veritasgenetics.com>

diff --git a/lib/config/config.default.yml b/lib/config/config.default.yml
index 9ac4aeeb9..6da5344fa 100644
--- a/lib/config/config.default.yml
+++ b/lib/config/config.default.yml
@@ -206,6 +206,9 @@ Clusters:
       WebsocketClientEventQueue: 64
       WebsocketServerEventQueue: 4
 
+      # Timeout on requests to internal Keep services.
+      KeepServiceRequestTimeout: 15s
+
     Users:
       # Config parameters to automatically setup new users.  If enabled,
       # this users will be able to self-activate.  Enable this if you want
diff --git a/lib/config/deprecated.go b/lib/config/deprecated.go
index 12581ddff..dcfdd8b74 100644
--- a/lib/config/deprecated.go
+++ b/lib/config/deprecated.go
@@ -326,3 +326,74 @@ func (ldr *Loader) loadOldWebsocketConfig(cfg *arvados.Config) error {
 	cfg.Clusters[cluster.ClusterID] = *cluster
 	return nil
 }
+
+type oldKeepProxyConfig struct {
+	Client          *arvados.Client
+	Listen          *string
+	DisableGet      *bool
+	DisablePut      *bool
+	DefaultReplicas *int
+	Timeout         *arvados.Duration
+	PIDFile         *string
+	Debug           *bool
+	ManagementToken *string
+}
+
+const defaultKeepproxyConfigPath = "/etc/arvados/keepproxy/keepproxy.yml"
+
+func (ldr *Loader) loadOldKeepproxyConfig(cfg *arvados.Config) error {
+	if ldr.KeepproxyPath == "" {
+		return nil
+	}
+	var oc oldKeepProxyConfig
+	err := ldr.loadOldConfigHelper("keepproxy", ldr.KeepproxyPath, &oc)
+	if os.IsNotExist(err) && ldr.KeepproxyPath == defaultKeepproxyConfigPath {
+		return nil
+	} else if err != nil {
+		return err
+	}
+
+	cluster, err := cfg.GetCluster("")
+	if err != nil {
+		return err
+	}
+
+	loadOldClientConfig(cluster, oc.Client)
+
+	if oc.Listen != nil {
+		cluster.Services.Keepproxy.InternalURLs[arvados.URL{Host: *oc.Listen}] = arvados.ServiceInstance{}
+	}
+	if oc.DefaultReplicas != nil {
+		cluster.Collections.DefaultReplication = *oc.DefaultReplicas
+	}
+	if oc.Timeout != nil {
+		cluster.API.KeepServiceRequestTimeout = *oc.Timeout
+	}
+	if oc.Debug != nil {
+		if *oc.Debug && cluster.SystemLogs.LogLevel != "debug" {
+			cluster.SystemLogs.LogLevel = "debug"
+		} else if !*oc.Debug && cluster.SystemLogs.LogLevel != "info" {
+			cluster.SystemLogs.LogLevel = "info"
+		}
+	}
+	if oc.ManagementToken != nil {
+		cluster.ManagementToken = *oc.ManagementToken
+	}
+
+	unsupportedEntry := func(cfgEntry string) error {
+		return fmt.Errorf("the keepproxy %s configuration option is no longer supported, please remove it from your configuration file", cfgEntry)
+	}
+
+	if oc.DisableGet != nil && *oc.DisableGet {
+		return unsupportedEntry("DisableGet")
+	}
+	if oc.DisablePut != nil && *oc.DisablePut {
+		return unsupportedEntry("DisablePut")
+	}
+	if oc.PIDFile != nil && *oc.PIDFile != "" {
+		return unsupportedEntry("PIDFile")
+	}
+
+	cfg.Clusters[cluster.ClusterID] = *cluster
+	return nil
+}
diff --git a/lib/config/export.go b/lib/config/export.go
index b125d7dc9..82b48b36b 100644
--- a/lib/config/export.go
+++ b/lib/config/export.go
@@ -72,6 +72,7 @@ var whitelist = map[string]bool{
 	"API.WebsocketClientEventQueue":                false,
 	"API.SendTimeout":                              true,
 	"API.WebsocketServerEventQueue":                false,
+	"API.KeepServiceRequestTimeout":                false,
 	"AuditLogs":                                    false,
 	"AuditLogs.MaxAge":                             false,
 	"AuditLogs.MaxDeleteBatch":                     false,
diff --git a/lib/config/generated_config.go b/lib/config/generated_config.go
index 602f30e1d..ffcdddfe2 100644
--- a/lib/config/generated_config.go
+++ b/lib/config/generated_config.go
@@ -212,6 +212,9 @@ Clusters:
       WebsocketClientEventQueue: 64
       WebsocketServerEventQueue: 4
 
+      # Timeout on requests to internal Keep services.
+      KeepServiceRequestTimeout: 15s
+
     Users:
       # Config parameters to automatically setup new users.  If enabled,
       # this users will be able to self-activate.  Enable this if you want
diff --git a/lib/config/load.go b/lib/config/load.go
index 33d31f71c..309c0a615 100644
--- a/lib/config/load.go
+++ b/lib/config/load.go
@@ -33,6 +33,7 @@ type Loader struct {
 	KeepstorePath           string
 	CrunchDispatchSlurmPath string
 	WebsocketPath           string
+	KeepproxyPath           string
 
 	configdata []byte
 }
@@ -62,6 +63,7 @@ func (ldr *Loader) SetupFlags(flagset *flag.FlagSet) {
 	flagset.StringVar(&ldr.KeepstorePath, "legacy-keepstore-config", defaultKeepstoreConfigPath, "Legacy keepstore configuration `file`")
 	flagset.StringVar(&ldr.CrunchDispatchSlurmPath, "legacy-crunch-dispatch-slurm-config", defaultCrunchDispatchSlurmConfigPath, "Legacy crunch-dispatch-slurm configuration `file`")
 	flagset.StringVar(&ldr.WebsocketPath, "legacy-ws-config", defaultWebsocketConfigPath, "Legacy arvados-ws configuration `file`")
+	flagset.StringVar(&ldr.KeepproxyPath, "legacy-keepproxy-config", defaultKeepproxyConfigPath, "Legacy keepproxy configuration `file`")
 	flagset.BoolVar(&ldr.SkipLegacy, "skip-legacy", false, "Don't load legacy config files")
 }
 
@@ -133,6 +135,9 @@ func (ldr *Loader) MungeLegacyConfigArgs(lgr logrus.FieldLogger, args []string,
 	if legacyConfigArg != "-legacy-ws-config" {
 		ldr.WebsocketPath = ""
 	}
+	if legacyConfigArg != "-legacy-keepproxy-config" {
+		ldr.WebsocketPath = ""
+	}
 
 	return munged
 }
@@ -232,6 +237,7 @@ func (ldr *Loader) Load() (*arvados.Config, error) {
 			ldr.loadOldKeepstoreConfig(&cfg),
 			ldr.loadOldCrunchDispatchSlurmConfig(&cfg),
 			ldr.loadOldWebsocketConfig(&cfg),
+			ldr.loadOldKeepproxyConfig(&cfg),
 		} {
 			if err != nil {
 				return nil, err
diff --git a/sdk/go/arvados/config.go b/sdk/go/arvados/config.go
index f6b736d58..bc434a203 100644
--- a/sdk/go/arvados/config.go
+++ b/sdk/go/arvados/config.go
@@ -79,6 +79,7 @@ type Cluster struct {
 		SendTimeout                    Duration
 		WebsocketClientEventQueue      int
 		WebsocketServerEventQueue      int
+		KeepServiceRequestTimeout      Duration
 	}
 	AuditLogs struct {
 		MaxAge             Duration

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list