Skip to content

chore: improve logging around lifecycle scripts (#420) #427

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ test-registry-container: .registry-cache

# Pulls images referenced in integration tests and pushes them to the local cache.
.PHONY: test-images-push
test-images-push: .registry-cache/docker/registry/v2/repositories/envbuilder-test-alpine .registry-cache/docker/registry/v2/repositories/envbuilder-test-ubuntu .registry-cache/docker/registry/v2/repositories/envbuilder-test-codercom-code-server
test-images-push: .registry-cache/docker/registry/v2/repositories/envbuilder-test-alpine .registry-cache/docker/registry/v2/repositories/envbuilder-test-ubuntu .registry-cache/docker/registry/v2/repositories/envbuilder-test-codercom-code-server .registry-cache/docker/registry/v2/repositories/envbuilder-test-blob-unknown

.PHONY: test-images-pull
test-images-pull:
Expand All @@ -77,6 +77,7 @@ test-images-pull:
docker tag ubuntu:latest localhost:5000/envbuilder-test-ubuntu:latest
docker pull codercom/code-server:latest
docker tag codercom/code-server:latest localhost:5000/envbuilder-test-codercom-code-server:latest
docker build -t localhost:5000/envbuilder-test-blob-unknown:latest -f integration/testdata/blob-unknown/Dockerfile integration/testdata/blob-unknown

.registry-cache:
mkdir -p .registry-cache && chmod -R ag+w .registry-cache
Expand All @@ -89,3 +90,6 @@ test-images-pull:

.registry-cache/docker/registry/v2/repositories/envbuilder-test-codercom-code-server:
docker push localhost:5000/envbuilder-test-codercom-code-server:latest

.registry-cache/docker/registry/v2/repositories/envbuilder-test-blob-unknown:
docker push localhost:5000/envbuilder-test-blob-unknown:latest
6 changes: 3 additions & 3 deletions devcontainer/devcontainer.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,11 +400,11 @@ func ImageFromDockerfile(dockerfileContent string) (name.Reference, error) {
arg = strings.TrimSpace(arg)
if strings.Contains(arg, "=") {
parts := strings.SplitN(arg, "=", 2)
key, err := lexer.ProcessWord(parts[0], args)
key, _, err := lexer.ProcessWord(parts[0], shell.EnvsFromSlice(args))
if err != nil {
return nil, fmt.Errorf("processing %q: %w", line, err)
}
val, err := lexer.ProcessWord(parts[1], args)
val, _, err := lexer.ProcessWord(parts[1], shell.EnvsFromSlice(args))
if err != nil {
return nil, fmt.Errorf("processing %q: %w", line, err)
}
Expand All @@ -421,7 +421,7 @@ func ImageFromDockerfile(dockerfileContent string) (name.Reference, error) {
if imageRef == "" {
return nil, fmt.Errorf("no FROM directive found")
}
imageRef, err := lexer.ProcessWord(imageRef, args)
imageRef, _, err := lexer.ProcessWord(imageRef, shell.EnvsFromSlice(args))
if err != nil {
return nil, fmt.Errorf("processing %q: %w", imageRef, err)
}
Expand Down
4 changes: 3 additions & 1 deletion docs/env-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
| `--docker-config-base64` | `ENVBUILDER_DOCKER_CONFIG_BASE64` | | The base64 encoded Docker config file that will be used to pull images from private container registries. When this is set, Docker configuration set via the DOCKER_CONFIG environment variable is ignored. |
| `--fallback-image` | `ENVBUILDER_FALLBACK_IMAGE` | | Specifies an alternative image to use when neither an image is declared in the devcontainer.json file nor a Dockerfile is present. If there's a build failure (from a faulty Dockerfile) or a misconfiguration, this image will be the substitute. Set ExitOnBuildFailure to true to halt the container if the build faces an issue. |
| `--exit-on-build-failure` | `ENVBUILDER_EXIT_ON_BUILD_FAILURE` | | Terminates the container upon a build failure. This is handy when preferring the FALLBACK_IMAGE in cases where no devcontainer.json or image is provided. However, it ensures that the container stops if the build process encounters an error. |
| `--exit-on-push-failure` | `ENVBUILDER_EXIT_ON_PUSH_FAILURE` | | ExitOnPushFailure terminates the container upon a push failure. This is useful if failure to push the built image should abort execution and result in an error. |
| `--force-safe` | `ENVBUILDER_FORCE_SAFE` | | Ignores any filesystem safety checks. This could cause serious harm to your system! This is used in cases where bypass is needed to unblock customers. |
| `--insecure` | `ENVBUILDER_INSECURE` | | Bypass TLS verification when cloning and pulling from container registries. |
| `--ignore-paths` | `ENVBUILDER_IGNORE_PATHS` | | The comma separated list of paths to ignore when building the workspace. |
Expand All @@ -30,7 +31,8 @@
| `--git-ssh-private-key-path` | `ENVBUILDER_GIT_SSH_PRIVATE_KEY_PATH` | | Path to an SSH private key to be used for Git authentication. If this is set, then GIT_SSH_PRIVATE_KEY_BASE64 cannot be set. |
| `--git-ssh-private-key-base64` | `ENVBUILDER_GIT_SSH_PRIVATE_KEY_BASE64` | | Base64 encoded SSH private key to be used for Git authentication. If this is set, then GIT_SSH_PRIVATE_KEY_PATH cannot be set. |
| `--git-http-proxy-url` | `ENVBUILDER_GIT_HTTP_PROXY_URL` | | The URL for the HTTP proxy. This is optional. |
| `--workspace-folder` | `ENVBUILDER_WORKSPACE_FOLDER` | | The path to the workspace folder that will be built. This is optional. |
| `--workspace-base-dir` | `ENVBUILDER_WORKSPACE_BASE_DIR` | `/workspaces` | The path under which workspaces will be placed when workspace folder option is not given. |
| `--workspace-folder` | `ENVBUILDER_WORKSPACE_FOLDER` | | The path to the workspace folder that will be built. This is optional. Defaults to `[workspace base dir]/[name]` where name is the name of the repository or `empty`. |
| `--ssl-cert-base64` | `ENVBUILDER_SSL_CERT_BASE64` | | The content of an SSL cert file. This is useful for self-signed certificates. |
| `--export-env-file` | `ENVBUILDER_EXPORT_ENV_FILE` | | Optional file path to a .env file where envbuilder will dump environment variables from devcontainer.json and the built container image. |
| `--post-start-script-path` | `ENVBUILDER_POST_START_SCRIPT_PATH` | | The path to a script that will be created by envbuilder based on the postStartCommand in devcontainer.json, if any is specified (otherwise the script is not created). If this is set, the specified InitCommand should check for the presence of this script and execute it after successful startup. |
Expand Down
25 changes: 23 additions & 2 deletions envbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ func run(ctx context.Context, opts options.Options, execArgs *execArgsInfo) erro
RemoteEnv: make(map[string]string),
}
if fileExists(opts.Filesystem, workingDir.Image()) {
opts.Logger(log.LevelInfo, "Found magic image file at %s", workingDir.Image())
if err = parseMagicImageFile(opts.Filesystem, workingDir.Image(), &runtimeData); err != nil {
return fmt.Errorf("parse magic image file: %w", err)
}
Expand Down Expand Up @@ -288,6 +289,7 @@ func run(ctx context.Context, opts options.Options, execArgs *execArgsInfo) erro

var buildParams *devcontainer.Compiled
if opts.DockerfilePath == "" {
opts.Logger(log.LevelInfo, "No Dockerfile specified, looking for a devcontainer.json...")
// Only look for a devcontainer if a Dockerfile wasn't specified.
// devcontainer is a standard, so it's reasonable to be the default.
var devcontainerDir string
Expand All @@ -297,6 +299,7 @@ func run(ctx context.Context, opts options.Options, execArgs *execArgsInfo) erro
opts.Logger(log.LevelError, "Failed to locate devcontainer.json: %s", err.Error())
opts.Logger(log.LevelError, "Falling back to the default image...")
} else {
opts.Logger(log.LevelInfo, "Building in Devcontainer mode using %s", strings.TrimPrefix(runtimeData.DevcontainerPath, buildTimeWorkspaceFolder))
// We know a devcontainer exists.
// Let's parse it and use it!
file, err := opts.Filesystem.Open(runtimeData.DevcontainerPath)
Expand Down Expand Up @@ -335,6 +338,7 @@ func run(ctx context.Context, opts options.Options, execArgs *execArgsInfo) erro
} else {
// If a Dockerfile was specified, we use that.
dockerfilePath := filepath.Join(buildTimeWorkspaceFolder, opts.DockerfilePath)
opts.Logger(log.LevelInfo, "Building in Dockerfile-only mode using %s", opts.DockerfilePath)

// If the dockerfilePath is specified and deeper than the base of WorkspaceFolder AND the BuildContextPath is
// not defined, show a warning
Expand Down Expand Up @@ -582,10 +586,23 @@ func run(ctx context.Context, opts options.Options, execArgs *execArgsInfo) erro
endStage("🏗️ Built image!")
if opts.PushImage {
endStage = startStage("🏗️ Pushing image...")
if err := executor.DoPush(image, kOpts); err != nil {

// To debug registry issues, enable logging:
//
// import (
// stdlog "log"
// reglogs "github.com/google/go-containerregistry/pkg/logs"
// )
// reglogs.Debug = stdlog.New(os.Stderr, "", 0)
// reglogs.Warn = stdlog.New(os.Stderr, "", 0)
// reglogs.Progress = stdlog.New(os.Stderr, "", 0)
if err := executor.DoPush(image, kOpts); err == nil {
endStage("🏗️ Pushed image!")
} else if !opts.ExitOnPushFailure {
endStage("⚠️️ Failed to push image!")
} else {
return nil, xerrors.Errorf("do push: %w", err)
}
endStage("🏗️ Pushed image!")
}

return image, err
Expand Down Expand Up @@ -1398,6 +1415,7 @@ func execOneLifecycleScript(
userInfo userInfo,
) error {
if s.IsEmpty() {
logf(log.LevelInfo, "=== No %s script specified", scriptName)
return nil
}
logf(log.LevelInfo, "=== Running %s as the %q user...", scriptName, userInfo.user.Username)
Expand All @@ -1416,6 +1434,7 @@ func execLifecycleScripts(
userInfo userInfo,
) error {
if options.PostStartScriptPath != "" {
options.Logger(log.LevelDebug, "Removing postStartScriptPath %s", options.PostStartScriptPath)
_ = os.Remove(options.PostStartScriptPath)
}

Expand All @@ -1424,6 +1443,8 @@ func execLifecycleScripts(
// skip remaining lifecycle commands
return nil
}
} else {
options.Logger(log.LevelDebug, "Skipping onCreateCommand for subsequent starts...")
}
if err := execOneLifecycleScript(ctx, options.Logger, scripts.UpdateContentCommand, "updateContentCommand", userInfo); err != nil {
// skip remaining lifecycle commands
Expand Down
29 changes: 14 additions & 15 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.22.4

// There are a few options we need added to Kaniko!
// See: https://github.com/GoogleContainerTools/kaniko/compare/main...coder:kaniko:main
replace github.com/GoogleContainerTools/kaniko => github.com/coder/kaniko v0.0.0-20240925122543-caa18967f374
replace github.com/GoogleContainerTools/kaniko => github.com/coder/kaniko v0.0.0-20241120132148-131d6094d781

// Required to import codersdk due to gvisor dependency.
replace tailscale.com => github.com/coder/tailscale v1.1.1-0.20240702054557-aa558fbe5374
Expand All @@ -19,8 +19,8 @@ require (
github.com/coder/serpent v0.7.0
github.com/containerd/platforms v0.2.1
github.com/distribution/distribution/v3 v3.0.0-alpha.1
github.com/docker/cli v27.2.0+incompatible
github.com/docker/docker v26.1.5+incompatible
github.com/docker/cli v27.2.1+incompatible
github.com/docker/docker v27.3.1+incompatible
github.com/fatih/color v1.17.0
github.com/gliderlabs/ssh v0.3.7
github.com/go-git/go-billy/v5 v5.5.0
Expand All @@ -31,7 +31,7 @@ require (
github.com/hashicorp/go-multierror v1.1.1
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/mattn/go-isatty v0.0.20
github.com/moby/buildkit v0.13.1
github.com/moby/buildkit v0.16.0
github.com/otiai10/copy v1.14.0
github.com/prometheus/procfs v0.15.1
github.com/sirupsen/logrus v1.9.3
Expand Down Expand Up @@ -100,25 +100,22 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/charmbracelet/lipgloss v0.8.0 // indirect
github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 // indirect
github.com/cilium/ebpf v0.12.3 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0 // indirect
github.com/coder/quartz v0.1.0 // indirect
github.com/coder/terraform-provider-coder v0.23.0 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/containerd/cgroups/v3 v3.0.2 // indirect
github.com/containerd/containerd v1.7.19 // indirect
github.com/containerd/containerd v1.7.21 // indirect
github.com/containerd/containerd/api v1.7.19 // indirect
github.com/containerd/continuity v0.4.3 // indirect
github.com/containerd/errdefs v0.1.0 // indirect
github.com/containerd/fifo v1.1.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
github.com/containerd/ttrpc v1.2.5 // indirect
github.com/containerd/typeurl/v2 v2.1.1 // indirect
github.com/containerd/typeurl/v2 v2.2.0 // indirect
github.com/coreos/go-iptables v0.6.0 // indirect
github.com/coreos/go-oidc/v3 v3.10.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
Expand Down Expand Up @@ -146,12 +143,12 @@ require (
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/nftables v0.2.0 // indirect
github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect
github.com/gorilla/handlers v1.5.1 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect
Expand All @@ -164,7 +161,7 @@ require (
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/hashicorp/golang-lru/arc/v2 v2.0.5 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl/v2 v2.21.0 // indirect
github.com/hashicorp/logutils v1.0.0 // indirect
github.com/hashicorp/terraform-plugin-go v0.12.0 // indirect
Expand Down Expand Up @@ -202,11 +199,12 @@ require (
github.com/moby/patternmatcher v0.6.0 // indirect
github.com/moby/swarmkit/v2 v2.0.0-20230315203717-e28e8ba9bc83 // indirect
github.com/moby/sys/mount v0.3.3 // indirect
github.com/moby/sys/mountinfo v0.7.1 // indirect
github.com/moby/sys/mountinfo v0.7.2 // indirect
github.com/moby/sys/sequential v0.5.0 // indirect
github.com/moby/sys/signal v0.7.0 // indirect
github.com/moby/sys/signal v0.7.1 // indirect
github.com/moby/sys/symlink v0.2.0 // indirect
github.com/moby/sys/user v0.1.0 // indirect
github.com/moby/sys/user v0.3.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/muesli/reflow v0.3.0 // indirect
Expand Down Expand Up @@ -245,6 +243,7 @@ require (
github.com/tailscale/wireguard-go v0.0.0-20231121184858-cc193a0b3272 // indirect
github.com/tcnksm/go-httpstat v0.2.0 // indirect
github.com/tinylib/msgp v1.1.8 // indirect
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 // indirect
github.com/twpayne/go-vfs/v5 v5.0.4 // indirect
github.com/u-root/uio v0.0.0-20240209044354-b3d14b93376a // indirect
github.com/valyala/fasthttp v1.55.0 // indirect
Expand Down
Loading