From b8235d20601b621bcea7be149edca6cd0e184dd6 Mon Sep 17 00:00:00 2001 From: Christopher Eaton Date: Thu, 15 Jun 2023 09:31:32 -0700 Subject: [PATCH] Add support for --no-cloud. --- README.md | 4 +- localbuilder_main.go | 113 ++++++++++++++++++++++++------------------- 2 files changed, 67 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 8599272..4583a04 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,14 @@ Google has been archived. This fork is an attempt to keep the project alive, at original, and maybe improve on it a bit. #### New Features -- Add support for loading `.env` file secrets for `secretEnv` replacements. +- Added support for loading `.env` file secrets for `secretEnv` replacements. This will convert only the matching `secretEnv` into a corresponding `env` with a value. To use this, just add the `--env=` argument with `envfilepath` as the path to the `.env` file. *This is not supported in the cloud, and only works for GCBL. Which means the cloud will simply treat a secretEnv as intended :)* - No contributor agreements. Just code! +- Added support for skipping cloud token gathering and metadata with argument `--no-cloud`. This let's you run + cloud-build-local *without* an active `gcloud` authentication token (which requires a GCP account). ## Usage To run a local build you should make sure you've got credentials to GCP if using any resources (`gcloud auth login`), diff --git a/localbuilder_main.go b/localbuilder_main.go index 4866ef9..6c180dd 100644 --- a/localbuilder_main.go +++ b/localbuilder_main.go @@ -59,6 +59,7 @@ var ( dryRun = flag.Bool("dryrun", true, "Lints the config file and prints but does not run the commands; Local Builder runs the commands only when dryrun is set to false") push = flag.Bool("push", false, "Pushes the images to the registry") noSource = flag.Bool("no-source", false, "Prevents Local Builder from using source for this build") + noCloud = flag.Bool("no-cloud", false, "Skip usage and checks for an active Google Cloud project/environment.") bindMountSource = flag.Bool("bind-mount-source", false, "Bind mounts the source directory under /workspace rather "+ " than copying its contents into /workspace. It is an error to use this flag with --noSource") writeWorkspace = flag.String("write-workspace", "", "Copies the workspace directory to this host directory") @@ -131,7 +132,7 @@ func run(ctx context.Context, source string) error { } // Check installed docker versions. - if !*dryRun { + if !*dryRun && !*noCloud { dockerServerVersion, dockerClientVersion, err := dockerVersions(ctx, r) if err != nil { return fmt.Errorf("Error getting local docker versions: %v", err) @@ -243,28 +244,9 @@ func run(ctx context.Context, source string) error { cancelableCtx, cancel := context.WithCancel(ctx) defer cancel() if !*dryRun { - // Set initial Docker credentials. - tok, err := gcloud.AccessToken(ctx, r) - if err != nil { - return fmt.Errorf("Error getting access token to set docker credentials: %v", err) - } - if err := b.SetDockerAccessToken(ctx, tok.AccessToken); err != nil { - return fmt.Errorf("Error setting docker credentials: %v", err) - } - b.TokenSource = oauth2.StaticTokenSource(&oauth2.Token{ - AccessToken: tok.AccessToken, - }) - - // On GCE, do not create a spoofed metadata server, use the existing one. - // The cloudbuild network is still needed, with a private subnet. var mdTokenSetter metadataTokenSetter - if computeMetadata.OnGCE() { - if err := metadata.CreateCloudbuildNetwork(ctx, r, "172.22.0.0/16"); err != nil { - return fmt.Errorf("Error creating network: %v", err) - } - defer metadata.CleanCloudbuildNetwork(ctx, r) - mdTokenSetter = nopTokenSetter{} - } else { + if *noCloud { + //start spoofed metadata server if err := metadata.StartLocalServer(ctx, r, metadataImageName); err != nil { return fmt.Errorf("Failed to start spoofed metadata server: %v", err) } @@ -275,38 +257,71 @@ func run(ctx context.Context, source string) error { // Feed the project info to the metadata server. metadataUpdater.SetProjectInfo(ctx, projectInfo) mdTokenSetter = metadataUpdater - } - - // Keep credentials up-to-date. - go func(ctx context.Context, tok *metadata.Token) { - var refresh time.Duration - for { - select { - case <-time.After(refresh): - case <-ctx.Done(): - return + } else { + // Set initial Docker credentials. + tok, err := gcloud.AccessToken(ctx, r) + if err != nil { + return fmt.Errorf("Error getting access token to set docker credentials: %v", err) + } + if err := b.SetDockerAccessToken(ctx, tok.AccessToken); err != nil { + return fmt.Errorf("Error setting docker credentials: %v", err) + } + b.TokenSource = oauth2.StaticTokenSource(&oauth2.Token{ + AccessToken: tok.AccessToken, + }) + + // On GCE, do not create a spoofed metadata server, use the existing one. + // The cloudbuild network is still needed, with a private subnet. + if computeMetadata.OnGCE() { + if err := metadata.CreateCloudbuildNetwork(ctx, r, "172.22.0.0/16"); err != nil { + return fmt.Errorf("Error creating network: %v", err) } - tok, err := gcloud.AccessToken(ctx, r) - if err != nil { - log.Printf("Error getting gcloud token: %v", err) - continue + defer metadata.CleanCloudbuildNetwork(ctx, r) + mdTokenSetter = nopTokenSetter{} + } else { + if err := metadata.StartLocalServer(ctx, r, metadataImageName); err != nil { + return fmt.Errorf("Failed to start spoofed metadata server: %v", err) } + log.Println("Started spoofed metadata server") + metadataUpdater := metadata.RealUpdater{Local: true} + defer metadataUpdater.Stop(ctx, r) - // Supply token to the metadata server. - if err := mdTokenSetter.SetToken(ctx, tok); err != nil { - log.Printf("Error updating token in metadata server: %v", err) - } + // Feed the project info to the metadata server. + metadataUpdater.SetProjectInfo(ctx, projectInfo) + mdTokenSetter = metadataUpdater + } + + // Keep credentials up-to-date. + go func(ctx context.Context, tok *metadata.Token) { + var refresh time.Duration + for { + select { + case <-time.After(refresh): + case <-ctx.Done(): + return + } + tok, err := gcloud.AccessToken(ctx, r) + if err != nil { + log.Printf("Error getting gcloud token: %v", err) + continue + } - // Keep a fresh token in ~/.docker/config.json, which in turn is - // available to build steps. Note that use of `gcloud auth` to switch - // accounts mid-build is not supported. - if err := b.UpdateDockerAccessToken(ctx, tok.AccessToken); err != nil { - log.Printf("Error updating docker credentials: %v", err) + // Supply token to the metadata server. + if err := mdTokenSetter.SetToken(ctx, tok); err != nil { + log.Printf("Error updating token in metadata server: %v", err) + } + + // Keep a fresh token in ~/.docker/config.json, which in turn is + // available to build steps. Note that use of `gcloud auth` to switch + // accounts mid-build is not supported. + if err := b.UpdateDockerAccessToken(ctx, tok.AccessToken); err != nil { + log.Printf("Error updating docker credentials: %v", err) + } + b.TokenSource = oauth2.StaticTokenSource(&oauth2.Token{AccessToken: tok.AccessToken}) + refresh = common.RefreshDuration(tok.Expiry) } - b.TokenSource = oauth2.StaticTokenSource(&oauth2.Token{AccessToken: tok.AccessToken}) - refresh = common.RefreshDuration(tok.Expiry) - } - }(cancelableCtx, tok) + }(cancelableCtx, tok) + } } b.Start(ctx)