From f336dc833173836a45890c6c7afb396436a37046 Mon Sep 17 00:00:00 2001 From: mpl Date: Wed, 15 Apr 2015 00:41:52 +0200 Subject: [PATCH] website: easier launcher dev workflow Use the website/launcher-config.json JSON config file to provide all the deploy handler parameters. Change-Id: I6156eaa80269ad3e70e9d48d7b8253a9a507036e --- pkg/deploy/gce/handler.go | 38 ++++++++++++++++++++++++++++++++++++-- website/.gitignore | 2 +- website/camweb.go | 36 +++++++++++++++++++++++++++--------- website/run.pl | 7 ++++++- 4 files changed, 70 insertions(+), 13 deletions(-) diff --git a/pkg/deploy/gce/handler.go b/pkg/deploy/gce/handler.go index 8b078b092..0b707a54b 100644 --- a/pkg/deploy/gce/handler.go +++ b/pkg/deploy/gce/handler.go @@ -129,10 +129,44 @@ type DeployHandler struct { *log.Logger } +// Config is the set of parameters to initialize the DeployHandler. +type Config struct { + ClientID string `json:"clientID"` // handler's credentials for OAuth. required. + ClientSecret string `json:"clientSecret"` // handler's credentials for OAuth. required. + Project string `json:"project"` // any Google Cloud project we can query to get the valid Google Cloud zones. optional. + ServiceAccount string `json:"serviceAccount"` // JSON file with credentials to Project. optional. + DataDir string `json:"dataDir"` // where to store the instances configurations and states. optional. +} + +// NewDeployHandlerFromConfig initializes a DeployHandler from the JSON config file. +// Host and prefix have the same meaning as for NewDeployHandler. +func NewDeployHandlerFromConfig(host, prefix, configFile string) (http.Handler, error) { + var cfg Config + data, err := ioutil.ReadFile(configFile) + if err != nil { + return nil, fmt.Errorf("Could not read handler's config at %v: %v", configFile, err) + } + if err := json.Unmarshal(data, &cfg); err != nil { + return nil, fmt.Errorf("Could not JSON decode config at %v: %v", configFile, err) + } + if cfg.ClientID == "" { + return nil, errors.New("oauth2 clientID required in config") + } + if cfg.ClientSecret == "" { + return nil, errors.New("oauth2 clientSecret required in config") + } + os.Setenv("CAMLI_GCE_CLIENTID", cfg.ClientID) + os.Setenv("CAMLI_GCE_CLIENTSECRET", cfg.ClientSecret) + os.Setenv("CAMLI_GCE_PROJECT", cfg.Project) + os.Setenv("CAMLI_GCE_SERVICE_ACCOUNT", cfg.ServiceAccount) + os.Setenv("CAMLI_GCE_DATA", cfg.DataDir) + return NewDeployHandler(host, prefix) +} + // NewDeployHandler initializes a DeployHandler that serves at https://host/prefix/ and returns it. // A Google account client ID should be set in CAMLI_GCE_CLIENTID with its corresponding client // secret in CAMLI_GCE_CLIENTSECRET. -func NewDeployHandler(host string, prefix string) (http.Handler, error) { +func NewDeployHandler(host, prefix string) (http.Handler, error) { clientID := os.Getenv("CAMLI_GCE_CLIENTID") if clientID == "" { return nil, errors.New("Need an oauth2 client ID defined in CAMLI_GCE_CLIENTID") @@ -791,7 +825,7 @@ func dataStores() (blobserver.Storage, sorted.KeyValue, error) { } dataDir := os.Getenv("CAMLI_GCE_DATA") if dataDir == "" { - dataDir = "camli-data" + dataDir = "camli-gce-data" log.Printf("data dir not provided as env var CAMLI_GCE_DATA, so defaulting to %v", dataDir) } blobsDir := filepath.Join(dataDir, "instance-conf") diff --git a/website/.gitignore b/website/.gitignore index c6c87396d..f6e4c7b39 100644 --- a/website/.gitignore +++ b/website/.gitignore @@ -1,3 +1,3 @@ camweb latestgits - +launcher-config.json diff --git a/website/camweb.go b/website/camweb.go index 8bc3614fc..f794e7e50 100644 --- a/website/camweb.go +++ b/website/camweb.go @@ -327,8 +327,30 @@ func runAsChild(res string) { }() } -func gceDeployHandler(host, prefix string) http.Handler { - gceh, err := gce.NewDeployHandler(host, prefix) +// gceDeployHandler conditionally returns an http.Handler for a GCE launcher, +// configured to run at /prefix/ (the trailing slash can be omitted). +// If CAMLI_GCE_CLIENTID is not set, the launcher-config.json file, if present, +// is used instead of environment variables to initialize the launcher. If a +// launcher isn't enabled, gceDeployHandler returns nil. If another error occurs, +// log.Fatal is called. +func gceDeployHandler(prefix string) http.Handler { + hostPort, err := netutil.HostPort("https://" + *httpsAddr) + if err != nil { + hostPort = "camlistore.org:443" + } + var gceh http.Handler + if e := os.Getenv("CAMLI_GCE_CLIENTID"); e != "" { + gceh, err = gce.NewDeployHandler(hostPort, prefix) + } else { + config := filepath.Join(*root, "launcher-config.json") + if _, err := os.Stat(config); err != nil { + if os.IsNotExist(err) { + return nil + } + log.Fatalf("Could not stat launcher-config.json: %v", err) + } + gceh, err = gce.NewDeployHandlerFromConfig(hostPort, prefix, config) + } if err != nil { log.Fatalf("Error initializing gce deploy handler: %v", err) } @@ -339,6 +361,7 @@ func gceDeployHandler(host, prefix string) http.Handler { if err := gceh.(*gce.DeployHandler).AddTemplateTheme(string(pageBytes)); err != nil { log.Fatalf("Error initializing gce deploy handler: %v", err) } + log.Printf("Starting Camlistore launcher on https://%s%s", hostPort, prefix) return gceh } @@ -382,13 +405,8 @@ func main() { } if *httpsAddr != "" { - if e := os.Getenv("CAMLI_GCE_CLIENTID"); e != "" { - hostPort, err := netutil.HostPort("https://" + *httpsAddr) - if err != nil { - hostPort = "camlistore.org:443" - } - log.Printf("Starting Camlistore launcher on https://%s/launch/", hostPort) - mux.Handle("/launch/", gceDeployHandler(hostPort, "/launch/")) + if launcher := gceDeployHandler("/launch/"); launcher != nil { + mux.Handle("/launch/", launcher) } } diff --git a/website/run.pl b/website/run.pl index 60bfb7cbe..61f3707e5 100755 --- a/website/run.pl +++ b/website/run.pl @@ -42,7 +42,12 @@ if ($in_prod) { print $fh "foo\n"; close($fh); } - push @args, "--http=127.0.0.1:8080"; # localhost avoids Mac firewall warning + # These https certificate and key are the default ones used by devcam server. + die "TLS cert or key not initialized; run devcam server --tls" unless -e "$Bin/../config/tls.crt" && -e "$Bin/../config/tls.key"; + push @args, "--tlscert=$Bin/../config/tls.crt"; + push @args, "--tlskey=$Bin/../config/tls.key"; + push @args, "--http=127.0.0.1:8080"; + push @args, "--https=127.0.0.1:4430"; push @args, @ARGV; exec(@args); die "Failed to exec: $!";