From 7086181cbd9ec3419ff2e29de48e55293564f837 Mon Sep 17 00:00:00 2001 From: Srdjan Petrovic Date: Mon, 24 Jul 2023 12:17:32 -0700 Subject: [PATCH] Use access token to authenticate with the Google Cloud. When using GitHub actions or other CI/CD platform, the user may not be able to run `gcloud init` interactively. The recommended login for those kinds of deployments is to get an access token from Google Cloud, store it as a secret and use it for deployments. This change adds support for using such tokens for deployment, either by passing an "access_token" flag to the `weaver-gke` commands, or by setting the CLOUDSDK_AUTH_ACCESS_TOKEN variable when invoking the commands. Other changes: * Unify flag handling for the cloud flags across all commands. * Remove project and account fields from the `GKEConfig` proto. * Minor cleanups. --- cmd/weaver-gke-local/deploy.go | 4 +- cmd/weaver-gke/dashboard.go | 39 +++------ cmd/weaver-gke/deploy.go | 65 +++++++------- cmd/weaver-gke/flags.go | 59 +++++++++++++ cmd/weaver-gke/kill.go | 10 +-- cmd/weaver-gke/logs.go | 11 ++- cmd/weaver-gke/profile.go | 10 +-- cmd/weaver-gke/purge.go | 8 +- cmd/weaver-gke/status.go | 10 +-- cmd/weaver-gke/store.go | 14 +-- internal/babysitter/babysitter.go | 7 +- internal/config/config.pb.go | 137 ++++++++++++------------------ internal/config/config.proto | 18 +--- internal/gke/babysitter.go | 6 +- internal/gke/cloud_config.go | 88 ++++++++++++------- internal/gke/cluster_info.go | 22 +---- internal/gke/cmd.go | 8 +- internal/gke/deploy.go | 4 - internal/gke/token_source.go | 25 ++++-- internal/local/babysitter.go | 6 +- internal/local/tool.go | 2 - internal/tool/deploy.go | 23 ++--- internal/tool/deploy_test.go | 9 +- 23 files changed, 302 insertions(+), 283 deletions(-) create mode 100644 cmd/weaver-gke/flags.go diff --git a/cmd/weaver-gke-local/deploy.go b/cmd/weaver-gke-local/deploy.go index 4927f14..343092c 100644 --- a/cmd/weaver-gke-local/deploy.go +++ b/cmd/weaver-gke-local/deploy.go @@ -16,6 +16,7 @@ package main import ( "context" + "flag" "net/http" "github.com/ServiceWeaver/weaver-gke/internal/config" @@ -25,7 +26,8 @@ import ( ) var deploySpec = tool.DeploySpec{ - Tool: "weaver gke-local", + Tool: "weaver gke-local", + Flags: flag.NewFlagSet("deploy", flag.ContinueOnError), Controller: func(ctx context.Context, _ *config.GKEConfig) (string, *http.Client, error) { return local.Controller(ctx) }, diff --git a/cmd/weaver-gke/dashboard.go b/cmd/weaver-gke/dashboard.go index 942bc21..e26f9f5 100644 --- a/cmd/weaver-gke/dashboard.go +++ b/cmd/weaver-gke/dashboard.go @@ -23,7 +23,6 @@ import ( "net/url" "os" "strings" - "sync" "github.com/ServiceWeaver/weaver-gke/internal/gke" "github.com/ServiceWeaver/weaver-gke/internal/tool" @@ -31,35 +30,18 @@ import ( ) var ( - dashboardFlags = flag.NewFlagSet("dashboard", flag.ContinueOnError) - dashboardProject = dashboardFlags.String("project", "", "Google Cloud project") - dashboardAccount = dashboardFlags.String("account", "", "Google Cloud user account") - - // See setupCloudConfig. - cloudConfig gke.CloudConfig - cloudConfigErr error - configInit sync.Once + dashboardFlags = newCloudFlagSet("dashboard", flag.ContinueOnError) ) -// setupCloudConfig caches and returns the cloud config returned by -// gke.SetupCloudConfig called on dashboardProject and dashboardAccount. -func setupCloudConfig() (gke.CloudConfig, error) { - configInit.Do(func() { - flag.Parse() - cloudConfig, cloudConfigErr = gke.SetupCloudConfig(*dashboardProject, *dashboardAccount) - }) - return cloudConfig, cloudConfigErr -} - var dashboardSpec = tool.DashboardSpec{ Tool: "weaver gke", - Flags: dashboardFlags, + Flags: dashboardFlags.FlagSet, Controller: func(ctx context.Context) (string, *http.Client, error) { - config, err := setupCloudConfig() + config, err := dashboardFlags.CloudConfig() if err != nil { return "", nil, err } - fmt.Fprintf(os.Stderr, "Using account %s in project %s", config.Account, config.Project) + fmt.Fprintf(os.Stderr, "Using project %s", config.Project) return gke.Controller(ctx, config) }, AppLinks: func(ctx context.Context, app string) (tool.Links, error) { @@ -90,11 +72,14 @@ var dashboardSpec = tool.DashboardSpec{ // links are provided for the app. func links(app, version string) (tool.Links, error) { // Get the account and project. - config, err := setupCloudConfig() + config, err := dashboardFlags.CloudConfig() if err != nil { return tool.Links{}, err } - account := url.QueryEscape(config.Account) + authuser := "0" + if config.Account != "" { + authuser = url.QueryEscape(config.Account) + } project := url.QueryEscape(config.Project) // Form a Google Cloud Logging query that matches this version's logs. @@ -126,9 +111,9 @@ func links(app, version string) (tool.Links, error) { } traceQuery := url.QueryEscape(fmt.Sprintf(`("traceFilter":("chips":"%s"))`, traceFilter)) return tool.Links{ - Metrics: fmt.Sprintf("https://console.cloud.google.com/monitoring/metrics-explorer?authuser=%s&project=%s", account, project), - Logs: fmt.Sprintf("https://console.cloud.google.com/logs/query?authuser=%s&project=%s&query=%s", account, project, logQuery), - Traces: fmt.Sprintf("https://console.cloud.google.com/traces/list?authuser=%s&project=%s&pageState=%s", account, project, traceQuery), + Metrics: fmt.Sprintf("https://console.cloud.google.com/monitoring/metrics-explorer?authuser=%s&project=%s", authuser, project), + Logs: fmt.Sprintf("https://console.cloud.google.com/logs/query?authuser=%s&project=%s&query=%s", authuser, project, logQuery), + Traces: fmt.Sprintf("https://console.cloud.google.com/traces/list?authuser=%s&project=%s&pageState=%s", authuser, project, traceQuery), }, nil } diff --git a/cmd/weaver-gke/deploy.go b/cmd/weaver-gke/deploy.go index 17f4503..a5270e6 100644 --- a/cmd/weaver-gke/deploy.go +++ b/cmd/weaver-gke/deploy.go @@ -16,6 +16,7 @@ package main import ( "context" + "flag" "fmt" "net/http" "os" @@ -29,36 +30,40 @@ import ( "github.com/ServiceWeaver/weaver/runtime/logging" ) -var deploySpec = tool.DeploySpec{ - Tool: "weaver gke", - Controller: func(ctx context.Context, cfg *config.GKEConfig) (string, *http.Client, error) { - config, err := gke.SetupCloudConfig(cfg.Project, cfg.Account) - if err != nil { - return "", nil, err - } - return gke.Controller(ctx, config) - }, - PrepareRollout: func(ctx context.Context, cfg *config.GKEConfig) (*controller.RolloutRequest, error) { - config, err := gke.SetupCloudConfig(cfg.Project, cfg.Account) - if err != nil { - return nil, err - } - fmt.Fprintf(os.Stderr, "Using account %s in project %s\n", - config.Account, config.Project) - toolBinVersion, err := getToolVersion() - if err != nil { - return nil, fmt.Errorf("error extracting the tool binary version: %w", err) - } - return gke.PrepareRollout(ctx, config, cfg, toolBinVersion) - }, - Source: func(ctx context.Context, cfg *config.GKEConfig) (logging.Source, error) { - config, err := gke.SetupCloudConfig(cfg.Project, cfg.Account) - if err != nil { - return nil, err - } - return gke.LogSource(config) - }, -} +var ( + deployFlags = newCloudFlagSet("deploy", flag.ContinueOnError) + + deploySpec = tool.DeploySpec{ + Tool: "weaver gke", + Flags: deployFlags.FlagSet, + Controller: func(ctx context.Context, cfg *config.GKEConfig) (string, *http.Client, error) { + config, err := deployFlags.CloudConfig() + if err != nil { + return "", nil, err + } + return gke.Controller(ctx, config) + }, + PrepareRollout: func(ctx context.Context, cfg *config.GKEConfig) (*controller.RolloutRequest, error) { + config, err := deployFlags.CloudConfig() + if err != nil { + return nil, err + } + fmt.Fprintf(os.Stderr, "Deploying to project %s\n", config.Project) + toolBinVersion, err := getToolVersion() + if err != nil { + return nil, fmt.Errorf("error extracting the tool binary version: %w", err) + } + return gke.PrepareRollout(ctx, config, cfg, toolBinVersion) + }, + Source: func(ctx context.Context, cfg *config.GKEConfig) (logging.Source, error) { + config, err := deployFlags.CloudConfig() + if err != nil { + return nil, err + } + return gke.LogSource(config) + }, + } +) // getToolVersion returns the version of the tool binary. func getToolVersion() (string, error) { diff --git a/cmd/weaver-gke/flags.go b/cmd/weaver-gke/flags.go new file mode 100644 index 0000000..d2ffc6d --- /dev/null +++ b/cmd/weaver-gke/flags.go @@ -0,0 +1,59 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "flag" + "sync" + + "github.com/ServiceWeaver/weaver-gke/internal/gke" +) + +type cloudFlagSet struct { + *flag.FlagSet + + // Predefined cloud flags. + projectFlag, accessTokenFlag, accountFlag *string + + // Initialized lazily. + configInit sync.Once + config gke.CloudConfig + configErr error +} + +func newCloudFlagSet(name string, errorHandling flag.ErrorHandling) *cloudFlagSet { + fset := &cloudFlagSet{FlagSet: flag.NewFlagSet(name, errorHandling)} + fset.projectFlag = fset.String("project", "", ` +Google Cloud project. If empty, the command will use the project name in the +active gcloud configuration on the local machine.`) + fset.accessTokenFlag = fset.String("access_token", "", ` +Google Cloud access token. If empty, the command will acquire cloud access +by using the account name.`) + fset.accountFlag = fset.String("account", "", ` +Google Cloud user account. If empty, the command will use the account name +in the active gcloud configuration on the local machine.`) + return fset +} + +// CloudConfig returns the cloud configuration file that corresponds to the +// predefined cloud flag values. +func (fs *cloudFlagSet) CloudConfig() (gke.CloudConfig, error) { + fs.configInit.Do(func() { + flag.Parse() + fs.config, fs.configErr = gke.SetupCloudConfig( + *fs.projectFlag, *fs.accessTokenFlag, *fs.accountFlag) + }) + return fs.config, fs.configErr +} diff --git a/cmd/weaver-gke/kill.go b/cmd/weaver-gke/kill.go index c9d8128..4f5955c 100644 --- a/cmd/weaver-gke/kill.go +++ b/cmd/weaver-gke/kill.go @@ -26,20 +26,18 @@ import ( ) var ( - killFlags = flag.NewFlagSet("kill", flag.ContinueOnError) - killProject = killFlags.String("project", "", "Google Cloud project") - killAccount = killFlags.String("account", "", "Google Cloud user account") + killFlags = newCloudFlagSet("kill", flag.ContinueOnError) ) var killSpec = tool.KillSpec{ Tool: "weaver gke", - Flags: killFlags, + Flags: killFlags.FlagSet, Controller: func(ctx context.Context) (string, *http.Client, error) { - config, err := gke.SetupCloudConfig(*killProject, *killAccount) + config, err := killFlags.CloudConfig() if err != nil { return "", nil, err } - fmt.Fprintf(os.Stderr, "Using account %s in project %s\n", config.Account, config.Project) + fmt.Fprintf(os.Stderr, "Using project %s\n", config.Project) return gke.Controller(ctx, config) }, } diff --git a/cmd/weaver-gke/logs.go b/cmd/weaver-gke/logs.go index 5b8b6c8..015c4fd 100644 --- a/cmd/weaver-gke/logs.go +++ b/cmd/weaver-gke/logs.go @@ -27,9 +27,8 @@ import ( ) var ( - logsFlags = flag.NewFlagSet("logs", flag.ContinueOnError) - logsProject = logsFlags.String("project", "", "Google Cloud project") - logsAccount = logsFlags.String("account", "", "Google Cloud user account") + logsFlags = newCloudFlagSet("logs", flag.ContinueOnError) + // NOTE(mwhittaker): The Cloud Logging team informed us that they're // working on speeding up queries over large time ranges, so in the future, // we may be able to remove this flag. @@ -39,7 +38,7 @@ var ( logsFreshness = logsFlags.String("freshness", "24h", "Only show logs that are this fresh (e.g., 300ms, 1.5h, 2h45m)") logsSpec = tool.LogsSpec{ Tool: "weaver gke", - Flags: logsFlags, + Flags: logsFlags.FlagSet, Rewrite: func(q logging.Query) (logging.Query, error) { hasTime, err := gke.HasTime(q) if err != nil { @@ -70,11 +69,11 @@ a time based predicate in your query to override this behavior. return q, nil }, Source: func(context.Context) (logging.Source, error) { - config, err := gke.SetupCloudConfig(*logsProject, *logsAccount) + config, err := logsFlags.CloudConfig() if err != nil { return nil, err } - fmt.Fprintf(os.Stderr, "Using account %s in project %s\n", config.Account, config.Project) + fmt.Fprintf(os.Stderr, "Using project %s\n", config.Project) return gke.LogSource(config) }, } diff --git a/cmd/weaver-gke/profile.go b/cmd/weaver-gke/profile.go index e839160..4cd55d9 100644 --- a/cmd/weaver-gke/profile.go +++ b/cmd/weaver-gke/profile.go @@ -26,20 +26,18 @@ import ( ) var ( - profileFlags = flag.NewFlagSet("profile", flag.ContinueOnError) - profileProject = profileFlags.String("project", "", "Google Cloud project") - profileAccount = profileFlags.String("account", "", "Google Cloud user account") + profileFlags = newCloudFlagSet("profile", flag.ContinueOnError) ) var profileSpec = tool.ProfileSpec{ Tool: "weaver gke", - Flags: profileFlags, + Flags: profileFlags.FlagSet, Controller: func(ctx context.Context) (string, *http.Client, error) { - config, err := gke.SetupCloudConfig(*profileProject, *profileAccount) + config, err := profileFlags.CloudConfig() if err != nil { return "", nil, err } - fmt.Fprintf(os.Stderr, "Using account %s in project %s\n", config.Account, config.Project) + fmt.Fprintf(os.Stderr, "Using project %s\n", config.Project) return gke.Controller(ctx, config) }, } diff --git a/cmd/weaver-gke/purge.go b/cmd/weaver-gke/purge.go index 10a268c..1ed128f 100644 --- a/cmd/weaver-gke/purge.go +++ b/cmd/weaver-gke/purge.go @@ -27,13 +27,13 @@ import ( ) var ( - purgeFlags = flag.NewFlagSet("purge", flag.ContinueOnError) + purgeFlags = newCloudFlagSet("purge", flag.ContinueOnError) purgeForce = purgeFlags.Bool("force", false, "Purge without prompt") ) var purgeCmd = tool.Command{ Name: "purge", - Flags: purgeFlags, + Flags: purgeFlags.FlagSet, Description: "Purge cloud resources", Help: fmt.Sprintf(`Usage: weaver gke purge [--force] @@ -45,7 +45,7 @@ Flags: Description: "weaver gke purge" deletes all cloud resources created by "weaver gke deploy". This terminates all running jobs and deletes all data.`, - tool.FlagsHelp(purgeFlags)), + tool.FlagsHelp(purgeFlags.FlagSet)), Fn: purge, // TODO(mwhittaker): Unhide the purge command when it's fully implemented. @@ -74,7 +74,7 @@ Enter (y)es to continue: `) } } - config, err := gke.SetupCloudConfig("", "") + config, err := purgeFlags.CloudConfig() if err != nil { return nil } diff --git a/cmd/weaver-gke/status.go b/cmd/weaver-gke/status.go index ab69c9c..b432fdd 100644 --- a/cmd/weaver-gke/status.go +++ b/cmd/weaver-gke/status.go @@ -26,20 +26,18 @@ import ( ) var ( - statusFlags = flag.NewFlagSet("status", flag.ContinueOnError) - statusProject = statusFlags.String("project", "", "Google Cloud project") - statusAccount = statusFlags.String("account", "", "Google Cloud user account") + statusFlags = newCloudFlagSet("status", flag.ContinueOnError) ) var statusSpec = tool.StatusSpec{ Tool: "weaver gke", - Flags: statusFlags, + Flags: statusFlags.FlagSet, Controller: func(ctx context.Context) (string, *http.Client, error) { - config, err := gke.SetupCloudConfig(*statusProject, *statusAccount) + config, err := statusFlags.CloudConfig() if err != nil { return "", nil, err } - fmt.Fprintf(os.Stderr, "Using account %s in project %s", config.Account, config.Project) + fmt.Fprintf(os.Stderr, "Using project %s", config.Project) return gke.Controller(ctx, config) }, } diff --git a/cmd/weaver-gke/store.go b/cmd/weaver-gke/store.go index 1d7c3c2..1fef1de 100644 --- a/cmd/weaver-gke/store.go +++ b/cmd/weaver-gke/store.go @@ -26,13 +26,7 @@ import ( ) var ( - storeFlags = flag.NewFlagSet("store", flag.ContinueOnError) - storeProject = storeFlags.String("project", "", - `GCP project where the store resides. If empty, a default cloud -project on the local machine is used.`) - storeAccount = storeFlags.String("account", "", - `GCP user account to use to access the store. If empty, a default cloud - account on the local machine is used.`) + storeFlags = newCloudFlagSet("store", flag.ContinueOnError) storeRegion = storeFlags.String("region", gke.ConfigClusterRegion, `Cloud region where the store resides. Default value is the region of the Service Weaver configuration cluster.`) @@ -42,13 +36,13 @@ Service Weaver configuration cluster.`) storeSpec = tool.StoreSpec{ Tool: "weaver gke", - Flags: storeFlags, + Flags: storeFlags.FlagSet, Store: func(ctx context.Context) (store.Store, error) { - config, err := gke.SetupCloudConfig(*storeProject, *storeAccount) + config, err := storeFlags.CloudConfig() if err != nil { return nil, err } - fmt.Fprintf(os.Stderr, "Using account %s in project %s\n", config.Account, config.Project) + fmt.Fprintf(os.Stderr, "Using project %s\n", config.Project) cluster, err := gke.GetClusterInfo(ctx, config, *storeCluster, *storeRegion) if err != nil { return nil, err diff --git a/internal/babysitter/babysitter.go b/internal/babysitter/babysitter.go index 2103bdb..3ba502f 100644 --- a/internal/babysitter/babysitter.go +++ b/internal/babysitter/babysitter.go @@ -51,6 +51,7 @@ type Babysitter struct { selfAddr string // HTTP address for the listener cfg *config.GKEConfig replicaSet string + projectName string podName string envelope *envelope.Envelope manager endpoints.Manager @@ -73,6 +74,7 @@ func Start( ctx context.Context, cfg *config.GKEConfig, replicaSet string, + projectName string, podName string, useLocalhost bool, mux *http.ServeMux, @@ -123,6 +125,7 @@ func Start( mux: mux, cfg: cfg, replicaSet: replicaSet, + projectName: projectName, podName: podName, envelope: e, selfAddr: selfAddr, @@ -374,7 +377,7 @@ func (b *Babysitter) GetSelfCertificate(context.Context, *protos.GetSelfCertific // VerifyClientCertificate implements the envelope.EnvelopeHandler interface. func (b *Babysitter) VerifyClientCertificate(_ context.Context, req *protos.VerifyClientCertificateRequest) (*protos.VerifyClientCertificateReply, error) { - identity, err := mtls.VerifyRawCertificateChain(b.cfg.Project, b.caCert, req.CertChain) + identity, err := mtls.VerifyRawCertificateChain(b.projectName, b.caCert, req.CertChain) if err != nil { return nil, err } @@ -384,7 +387,7 @@ func (b *Babysitter) VerifyClientCertificate(_ context.Context, req *protos.Veri // VerifyServerCertificate implements the envelope.EnvelopeHandler interface. func (b *Babysitter) VerifyServerCertificate(_ context.Context, req *protos.VerifyServerCertificateRequest) (*protos.VerifyServerCertificateReply, error) { - actual, err := mtls.VerifyRawCertificateChain(b.cfg.Project, b.caCert, req.CertChain) + actual, err := mtls.VerifyRawCertificateChain(b.projectName, b.caCert, req.CertChain) if err != nil { return nil, err } diff --git a/internal/config/config.pb.go b/internal/config/config.pb.go index 278d314..c3cf1cd 100644 --- a/internal/config/config.pb.go +++ b/internal/config/config.pb.go @@ -44,16 +44,8 @@ type GKEConfig struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Cloud project the application should be deployed to. If empty, the - // project value will be extracted from the active gcloud configuration - // on the deploying machine. - Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"` - // Cloud account that should be used to deploy the application. If empty, - // the account value will be extracted from the active gcloud - // configuration on the deploying machine. - Account string `protobuf:"bytes,2,opt,name=account,proto3" json:"account,omitempty"` - // List of unique regions to deploy the application to. Service Weaver will manage the - // clusters in the given regions. + // List of unique regions to deploy the application to. Service Weaver will + // manage the clusters in the given regions. // // If empty, Service Weaver will pick regions automatically. // @@ -74,8 +66,8 @@ type GKEConfig struct { // Note that enabling mTLS will likely increase the CPU usage of your // application. Mtls bool `protobuf:"varint,8,opt,name=mtls,proto3" json:"mtls,omitempty"` - // Address of the manager local to a Service Weaver process. This field is typically - // filled by the manager, before starting a Service Weaver process. + // Address of the manager local to a Service Weaver process. This field is + // typically filled by the manager, before starting a Service Weaver process. ManagerAddr string `protobuf:"bytes,5,opt,name=manager_addr,json=managerAddr,proto3" json:"manager_addr,omitempty"` // The URL of the container used to deploy the application (e.g., // us-docker.pkg.dev/my-project/serviceweaver-repo/todo:tag4df65e28), or the @@ -119,20 +111,6 @@ func (*GKEConfig) Descriptor() ([]byte, []int) { return file_internal_config_config_proto_rawDescGZIP(), []int{0} } -func (x *GKEConfig) GetProject() string { - if x != nil { - return x.Project - } - return "" -} - -func (x *GKEConfig) GetAccount() string { - if x != nil { - return x.Account - } - return "" -} - func (x *GKEConfig) GetRegions() []string { if x != nil { return x.Regions @@ -299,63 +277,60 @@ var file_internal_config_config_proto_rawDesc = []byte{ 0x67, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x1b, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0xc8, 0x06, 0x0a, 0x09, 0x47, 0x4b, 0x45, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x3e, 0x0a, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x47, 0x4b, 0x45, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, - 0x12, 0x0a, 0x04, 0x6d, 0x74, 0x6c, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x6d, - 0x74, 0x6c, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x6e, 0x61, 0x67, - 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, - 0x6d, 0x65, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x64, - 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x57, 0x0a, 0x12, 0x63, 0x6f, 0x6d, - 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, - 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x47, - 0x4b, 0x45, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, - 0x6e, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x11, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x12, 0x57, 0x0a, 0x12, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x61, - 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, + 0x6f, 0x74, 0x6f, 0x22, 0x94, 0x06, 0x0a, 0x09, 0x47, 0x4b, 0x45, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3e, 0x0a, 0x09, 0x6c, + 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x47, 0x4b, 0x45, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, - 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x1a, 0x3a, 0x0a, 0x0f, 0x4c, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x27, - 0x0a, 0x0f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x48, - 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x1a, 0x5f, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x65, - 0x6e, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x37, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x2e, 0x47, 0x4b, 0x45, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x44, 0x0a, 0x16, 0x43, 0x6f, 0x6d, 0x70, - 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x2a, - 0x0a, 0x0a, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, - 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x1a, 0x62, 0x0a, 0x16, 0x49, 0x64, + 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6d, + 0x74, 0x6c, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x6d, 0x74, 0x6c, 0x73, 0x12, + 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x41, 0x64, + 0x64, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x12, 0x33, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x44, + 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x57, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, + 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x47, 0x4b, 0x45, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x63, 0x6f, 0x6d, + 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x57, + 0x0a, 0x12, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, + 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x2e, 0x47, 0x4b, 0x45, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x47, - 0x4b, 0x45, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, - 0x6e, 0x74, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x35, - 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x57, 0x65, 0x61, 0x76, 0x65, 0x72, 0x2f, 0x77, 0x65, 0x61, 0x76, 0x65, - 0x72, 0x2d, 0x67, 0x6b, 0x65, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x6c, + 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x1a, 0x3a, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x65, + 0x6e, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x6e, + 0x61, 0x6d, 0x65, 0x1a, 0x5f, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x37, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, + 0x47, 0x4b, 0x45, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, + 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x44, 0x0a, 0x16, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, + 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x2a, 0x0a, 0x0a, 0x43, 0x6f, + 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, + 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, + 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x1a, 0x62, 0x0a, 0x16, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x47, 0x4b, 0x45, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x35, 0x5a, 0x33, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x57, 0x65, 0x61, 0x76, 0x65, 0x72, 0x2f, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x2d, 0x67, 0x6b, + 0x65, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/config/config.proto b/internal/config/config.proto index cc262b3..647bc8c 100644 --- a/internal/config/config.proto +++ b/internal/config/config.proto @@ -23,18 +23,8 @@ import "runtime/protos/config.proto"; // of user specified configuration and Service Weaver provided information // specific to a particular execution. message GKEConfig { - // Cloud project the application should be deployed to. If empty, the - // project value will be extracted from the active gcloud configuration - // on the deploying machine. - string project = 1; - - // Cloud account that should be used to deploy the application. If empty, - // the account value will be extracted from the active gcloud - // configuration on the deploying machine. - string account = 2; - - // List of unique regions to deploy the application to. Service Weaver will manage the - // clusters in the given regions. + // List of unique regions to deploy the application to. Service Weaver will + // manage the clusters in the given regions. // // If empty, Service Weaver will pick regions automatically. // @@ -67,8 +57,8 @@ message GKEConfig { // application. bool mtls = 8; - // Address of the manager local to a Service Weaver process. This field is typically - // filled by the manager, before starting a Service Weaver process. + // Address of the manager local to a Service Weaver process. This field is + // typically filled by the manager, before starting a Service Weaver process. string manager_addr = 5; // The URL of the container used to deploy the application (e.g., diff --git a/internal/gke/babysitter.go b/internal/gke/babysitter.go index 8339541..d3b719d 100644 --- a/internal/gke/babysitter.go +++ b/internal/gke/babysitter.go @@ -132,7 +132,7 @@ func RunBabysitter(ctx context.Context) error { m := &manager.HttpClient{ Addr: cfg.ManagerAddr, - TLSConfig: mtls.ClientTLSConfig(cfg.Project, caCert, getSelfCert, "manager"), + TLSConfig: mtls.ClientTLSConfig(meta.Project, caCert, getSelfCert, "manager"), } mux := http.NewServeMux() lis, err := net.Listen("tcp", "localhost:0") @@ -140,14 +140,14 @@ func RunBabysitter(ctx context.Context) error { return err } selfAddr := fmt.Sprintf("https://%s", lis.Addr()) - _, err = babysitter.Start(ctx, cfg, replicaSet, meta.PodName, false /*useLocalhost*/, mux, selfAddr, m, caCert, getSelfCert, logSaver, traceSaver, metricSaver) + _, err = babysitter.Start(ctx, cfg, replicaSet, meta.Project, meta.PodName, false /*useLocalhost*/, mux, selfAddr, m, caCert, getSelfCert, logSaver, traceSaver, metricSaver) if err != nil { return err } server := &http.Server{ Handler: mux, - TLSConfig: mtls.ServerTLSConfig(cfg.Project, caCert, getSelfCert, "manager", "distributor"), + TLSConfig: mtls.ServerTLSConfig(meta.Project, caCert, getSelfCert, "manager", "distributor"), } return server.ServeTLS(lis, "", "") } diff --git a/internal/gke/cloud_config.go b/internal/gke/cloud_config.go index 9a4da76..0c07661 100644 --- a/internal/gke/cloud_config.go +++ b/internal/gke/cloud_config.go @@ -17,6 +17,7 @@ package gke import ( "errors" "fmt" + "os" "strings" "cloud.google.com/go/compute/metadata" @@ -24,32 +25,42 @@ import ( "google.golang.org/api/option" ) +const cloudTokenEnvVar = "CLOUDSDK_AUTH_ACCESS_TOKEN" + // CloudConfig stores the configuration information for a cloud project. type CloudConfig struct { Project string // Cloud project. - Account string // Cloud user account. ProjectNumber string // Cloud project number - // TokenSource associated with the account and project. - tokenSource oauth2.TokenSource + // TokenSource used for accessing the cloud project. + TokenSource oauth2.TokenSource + + // Account name associated with the project. This value is filled as + // best-effort and may be empty (e.g., if token is used for access). + Account string } // ClientOptions returns the client options that should be passed to // cloud clients for proper authentication. func (c *CloudConfig) ClientOptions() []option.ClientOption { var opt []option.ClientOption - if c.tokenSource != nil { - opt = append(opt, option.WithTokenSource(c.tokenSource)) + if c.TokenSource != nil { + opt = append(opt, option.WithTokenSource(c.TokenSource)) } return opt } -// SetupCloudConfig sets up the cloud configuration with the given project and -// account names. If a project or an account name is empty, their values -// are retrieved from the active gcloud configuration on the local -// machine. +// SetupCloudConfig sets up the cloud configuration for the given project, +// using the provided account name and access token. If the project name is +// empty, its value is retrieved from the active gcloud configuration on the +// local machine. If access token is empty, and if the +// CLOUDSDK_AUTH_ACCESS_TOKEN environment variable is set, the environment +// variable value is used. Otherwise, a new access token is generated +// for the provided account name. If the account name is also empty, its +// value is retrieved from the active gcloud configuration on the local machine. +// // REQUIRES: The caller is running on a user machine. -func SetupCloudConfig(project, account string) (CloudConfig, error) { +func SetupCloudConfig(project, token, account string) (CloudConfig, error) { // Check that google cloud SDK is installed. if err := checkSDK(); err != nil { return CloudConfig{}, err @@ -62,37 +73,56 @@ func SetupCloudConfig(project, account string) (CloudConfig, error) { project, err = runCmd( "", cmdOptions{}, "gcloud", "config", "get-value", "project") if err != nil { - return CloudConfig{}, fmt.Errorf("couldn't find an active cloud project: "+ - "please run \"gcloud init\": %w", err) + return CloudConfig{}, fmt.Errorf("couldn't find an active cloud "+ + "project: please run \"gcloud init\": %w", err) } project = strings.TrimSuffix(project, "\n") // remove trailing newline + if project == "" { + return CloudConfig{}, fmt.Errorf( + "empty active cloud project: please run \"gcloud init\"") + } } + var accountErr error if account == "" { - var err error - account, err = runCmd( + account, accountErr = runCmd( "", cmdOptions{}, "gcloud", "config", "get-value", "account") - if err != nil { - return CloudConfig{}, fmt.Errorf( - "couldn't find an active cloud account: please run "+ - "\"gcloud init\": %w", err) + if accountErr != nil { + account = "" + } else { + account = strings.TrimSuffix(account, "\n") // remove trailing newline + if account == "" { + accountErr = fmt.Errorf("empty account name in gcloud configuration") + } } - account = strings.TrimSuffix(account, "\n") // remove trailing newline } - number, err := runCmd( - "", cmdOptions{}, "gcloud", "projects", "describe", project, - "--format=value(projectNumber)", "--project", project, "--account", - account) + + // Create the token source. + var source oauth2.TokenSource + if token != "" { + source = &fixedTokenSource{token: token} + } else if os.Getenv(cloudTokenEnvVar) != "" { + source = &fixedTokenSource{token: os.Getenv(cloudTokenEnvVar)} + } else if account != "" { + source = &refreshingTokenSource{account: account} + } else { + return CloudConfig{}, fmt.Errorf("empty token and account error: %w", accountErr) + } + config := CloudConfig{ + Project: project, + Account: account, + TokenSource: source, + } + + number, err := runGcloud( + config, "", cmdOptions{}, "projects", "describe", project, + "--format=value(projectNumber)", "--project", project) if err != nil { return CloudConfig{}, fmt.Errorf("couldn't find the numeric project "+ "id for project %q: %w", project, err) } number = strings.TrimSuffix(number, "\n") // remove trailing newline - return CloudConfig{ - Project: project, - Account: account, - ProjectNumber: number, - tokenSource: &tokenSource{project: project, account: account}, - }, nil + config.ProjectNumber = number + return config, nil } // checkSDK checks that Google Cloud SDK is installed. diff --git a/internal/gke/cluster_info.go b/internal/gke/cluster_info.go index ec16770..3fd39e7 100644 --- a/internal/gke/cluster_info.go +++ b/internal/gke/cluster_info.go @@ -15,8 +15,6 @@ package gke import ( - "bufio" - "bytes" "context" "encoding/json" "errors" @@ -88,7 +86,6 @@ func GetClusterInfo(ctx context.Context, config CloudConfig, cluster, region str os.TempDir(), fmt.Sprintf("serviceweaver_%s_%s", cluster, uuid.New().String())) if _, err := runGcloud(config, "", cmdOptions{ EnvOverrides: []string{ - "USE_GKE_GCLOUD_AUTH_PLUGIN=False", fmt.Sprintf("KUBECONFIG=%s", kubeFileName), }}, "container", "clusters", "get-credentials", cluster, "--region", region, @@ -96,28 +93,13 @@ func GetClusterInfo(ctx context.Context, config CloudConfig, cluster, region str return nil, err } defer os.Remove(kubeFileName) - kubeFile, err := os.Open(kubeFileName) + contents, err := os.ReadFile(kubeFileName) if err != nil { return nil, err } - // Manually add the --account and --project flags to the gcloud command in - // the kubernetes config. These are dropped by the 'get-credentials' command - // above, which causes the account and project from the currently active - // gcloud config to be used. - var contents bytes.Buffer - scanner := bufio.NewScanner(kubeFile) - for scanner.Scan() { - line := scanner.Text() - contents.Write([]byte(line)) - if strings.Contains(line, "cmd-args:") { - contents.Write([]byte(fmt.Sprintf(" --account %s --project %s", config.Account, config.Project))) - } - contents.WriteRune('\n') - } - // Parse the config and fill the cluster info. - kubeConfig, err := clientcmd.RESTConfigFromKubeConfig(contents.Bytes()) + kubeConfig, err := clientcmd.RESTConfigFromKubeConfig(contents) if err != nil { return nil, fmt.Errorf("internal error: error creating kube config: %w", err) } diff --git a/internal/gke/cmd.go b/internal/gke/cmd.go index fa3cd48..007806f 100644 --- a/internal/gke/cmd.go +++ b/internal/gke/cmd.go @@ -31,9 +31,11 @@ type cmdOptions struct { // the given arguments, using the account and the project specified // in the given config. func runGcloud(config CloudConfig, msg string, opts cmdOptions, args ...string) (string, error) { - args = append([]string{ - "--project", config.Project, "--account", config.Account, - }, args...) + token, err := config.TokenSource.Token() + if err != nil { + return "", fmt.Errorf("cannot get cloud access token: %w", err) + } + opts.EnvOverrides = append(opts.EnvOverrides, fmt.Sprintf("CLOUDSDK_AUTH_ACCESS_TOKEN=%s", token.AccessToken)) return runCmd(msg, opts, "gcloud", args...) } diff --git a/internal/gke/deploy.go b/internal/gke/deploy.go index 385b8ac..42a37e5 100644 --- a/internal/gke/deploy.go +++ b/internal/gke/deploy.go @@ -342,10 +342,6 @@ func enableMultiClusterServices(config CloudConfig) error { } func finalizeConfig(cloudConfig CloudConfig, gkeConfig *config.GKEConfig) error { - // Override the project and account values in the app config. - gkeConfig.Project = cloudConfig.Project - gkeConfig.Account = cloudConfig.Account - // Finalize the rollout duration. if gkeConfig.Deployment.App.RolloutNanos == 0 { scanner := bufio.NewScanner(os.Stdin) diff --git a/internal/gke/token_source.go b/internal/gke/token_source.go index e4a98d7..f35adf1 100644 --- a/internal/gke/token_source.go +++ b/internal/gke/token_source.go @@ -22,11 +22,10 @@ import ( "golang.org/x/oauth2" ) -// tokenSource is an oauth2.TokenSource that generates access tokens using -// the gcloud command. -type tokenSource struct { +// refreshingTokenSource is an oauth2.TokenSource that generates the access +// token using the gcloud command and refreshes the token if needed. +type refreshingTokenSource struct { // These fields are immutable after construction. - project string account string mu sync.Mutex @@ -34,9 +33,9 @@ type tokenSource struct { expiry time.Time } -var _ oauth2.TokenSource = &tokenSource{} +var _ oauth2.TokenSource = &refreshingTokenSource{} -func (s *tokenSource) Token() (*oauth2.Token, error) { +func (s *refreshingTokenSource) Token() (*oauth2.Token, error) { s.mu.Lock() defer s.mu.Unlock() @@ -49,7 +48,7 @@ func (s *tokenSource) Token() (*oauth2.Token, error) { token, err := runCmd( "", cmdOptions{}, "gcloud", "auth", "--format", "value(token)", "print-access-token", - "--project", s.project, "--account", s.account, + s.account, ) if err != nil { return nil, err @@ -67,3 +66,15 @@ func (s *tokenSource) Token() (*oauth2.Token, error) { s.expiry = time.Now().Add(tokenValidity) return s.token, nil } + +// fixedTokenSource is a oauth2.TokenSource that returns a fixed token +// value. +type fixedTokenSource struct { + token string +} + +var _ oauth2.TokenSource = &fixedTokenSource{} + +func (s *fixedTokenSource) Token() (*oauth2.Token, error) { + return &oauth2.Token{AccessToken: s.token}, nil +} diff --git a/internal/local/babysitter.go b/internal/local/babysitter.go index 25cdeb4..e98abe4 100644 --- a/internal/local/babysitter.go +++ b/internal/local/babysitter.go @@ -92,7 +92,7 @@ func startBabysitter(ctx context.Context, cfg *config.GKEConfig, replicaSet stri // Connection to the manager. m := &manager.HttpClient{ Addr: cfg.ManagerAddr, - TLSConfig: mtls.ClientTLSConfig(cfg.Project, caCert, selfCertGetter, "manager"), + TLSConfig: mtls.ClientTLSConfig(projectName, caCert, selfCertGetter, "manager"), } mux := http.NewServeMux() hostname, err := os.Hostname() @@ -104,7 +104,7 @@ func startBabysitter(ctx context.Context, cfg *config.GKEConfig, replicaSet stri return nil, err } selfAddr := fmt.Sprintf("https://%s", lis.Addr().String()) - b, err := babysitter.Start(ctx, cfg, replicaSet, podName, true /*useLocalhost*/, mux, selfAddr, m, caCert, selfCertGetter, logSaver, traceSaver, metricExporter) + b, err := babysitter.Start(ctx, cfg, replicaSet, projectName, podName, true /*useLocalhost*/, mux, selfAddr, m, caCert, selfCertGetter, logSaver, traceSaver, metricExporter) if err != nil { return nil, err } @@ -112,7 +112,7 @@ func startBabysitter(ctx context.Context, cfg *config.GKEConfig, replicaSet stri // Start the server without blocking. server := &http.Server{ Handler: mux, - TLSConfig: mtls.ServerTLSConfig(cfg.Project, caCert, selfCertGetter, "manager", "distributor"), + TLSConfig: mtls.ServerTLSConfig(projectName, caCert, selfCertGetter, "manager", "distributor"), } go server.ServeTLS(lis, "", "") diff --git a/internal/local/tool.go b/internal/local/tool.go index 5d2ae02..e71c78e 100644 --- a/internal/local/tool.go +++ b/internal/local/tool.go @@ -41,8 +41,6 @@ const ( // PrepareRollout returns a new rollout request for the given application // version. This call may mutate the passed-in config. func PrepareRollout(ctx context.Context, cfg *config.GKEConfig) (*controller.RolloutRequest, error) { - cfg.Project = projectName - // Ensure all Service Weaver service processes (i.e., controller, // distributor/manager) are running. distributorPorts, err := ensureWeaverServices(ctx, cfg) diff --git a/internal/tool/deploy.go b/internal/tool/deploy.go index c1a9c2c..27dbc31 100644 --- a/internal/tool/deploy.go +++ b/internal/tool/deploy.go @@ -54,13 +54,11 @@ const ( deployTimeout = 8 * time.Minute ) -var ( - deployFlags = flag.NewFlagSet("deploy", flag.ContinueOnError) - detach = deployFlags.Bool("detach", false, "Don't follow logs after deploying") -) - type DeploySpec struct { - Tool string // e.g., weaver-gke, weaver-gke-local + Tool string // e.g., weaver-gke, weaver-gke-local + Flags *flag.FlagSet // command line flags + detach *bool // detach flag value + // Controller returns the HTTP address of the controller and an HTTP client // that we can use to contact the controller. Controller func(context.Context, *config.GKEConfig) (string, *http.Client, error) @@ -71,16 +69,17 @@ type DeploySpec struct { // DeployCmd returns the "deploy" command. func DeployCmd(spec *DeploySpec) *tool.Command { + spec.detach = spec.Flags.Bool("detach", false, "Don't follow logs after deploying") return &tool.Command{ Name: "deploy", - Flags: deployFlags, + Flags: spec.Flags, Description: "Deploy a Service Weaver app", Help: fmt.Sprintf(`Usage: %s deploy Flags: -h, --help Print this help message. -%s`, spec.Tool, tool.FlagsHelp(deployFlags)), +%s`, spec.Tool, tool.FlagsHelp(spec.Flags)), Fn: spec.deployFn, } } @@ -117,8 +116,6 @@ func makeGKEConfig(app *protos.AppConfig) (*config.GKEConfig, error) { PublicHostname string `toml:"public_hostname"` } type gkeConfigSchema struct { - Project string - Account string Regions []string Listeners map[string]lisOpts MTLS bool @@ -153,8 +150,6 @@ func makeGKEConfig(app *protos.AppConfig) (*config.GKEConfig, error) { depID := uuid.New() cfg := &config.GKEConfig{ - Project: parsed.Project, - Account: parsed.Account, Regions: parsed.Regions, Listeners: listeners, Deployment: &protos.Deployment{ @@ -223,12 +218,12 @@ persists, please file an issue at https://github.com/ServiceWeaver/weaver/issues return err } fmt.Printf("Version %q of app %q started successfully.\n", deployment.Id, deployment.App.Name) - if !*detach { + if !*d.detach { fmt.Println("Note that stopping this binary will not affect the app in any way.") } query := fmt.Sprintf(`version == %q`, logging.Shorten(deployment.Id)) - if *detach { + if *d.detach { fmt.Printf(`To watch the version's logs, run the following command: %s logs --follow '%s' diff --git a/internal/tool/deploy_test.go b/internal/tool/deploy_test.go index d615650..16cb32d 100644 --- a/internal/tool/deploy_test.go +++ b/internal/tool/deploy_test.go @@ -52,18 +52,17 @@ func TestMakeGKEConfig(t *testing.T) { name: "simple", config: ` [gke] -project = "foo" -account = "bar" +mtls = true `, - expect: &config.GKEConfig{Project: "foo", Account: "bar"}, + expect: &config.GKEConfig{Mtls: true}, }, { name: "long-key", config: ` ["github.com/ServiceWeaver/weaver-gke/internal/gke"] -project = "bar" +mtls = true `, - expect: &config.GKEConfig{Project: "bar"}, + expect: &config.GKEConfig{Mtls: true}, }, { name: "listeners",