Skip to content

Commit

Permalink
feat: define build_args in ImageBuildSpec (#2257)
Browse files Browse the repository at this point in the history
## Description:

- [x] Add a new parameter `build_args` in `ImageBuildSpec`.
- [x] Update the logic of the image builder to take into accounts the
build arguments.
- [x] Implement tests (unit + e2e).
- [x] Update docs.
- [x] Test in a real scenario.

### Tests in a real scenario

I updated the `Dockerfile` under
`internal_testsuites/starlark_image-build-package` to expect a build
argument called `BUILD_ARG` and equal to `VALUE`.

```Dockerfile
FROM alpine:latest

WORKDIR /app

COPY . .


# The idea is to test if the build argument has been provided.
# The following commands would not work:

# $ docker build -t image-build-package-test .
# Error: the build argument BUILD_ARG has not been provided or is not equal to VALUE

# $ docker build -t image-build-package-test --build-arg "BUILD_ARG=WRONG_VALUE" .
# Error: the build argument BUILD_ARG has not been provided or is not equal to VALUE

# But this command would work:
# $ docker build -t image-build-package-test --build-arg "BUILD_ARG=VALUE" .

ARG BUILD_ARG="DEFAULT_VALUE"
RUN if [ "$BUILD_ARG" != "VALUE" ]; then \
  echo "Error: the build argument BUILD_ARG has not been provided or is not equal to VALUE"; \
  exit 1; \
fi

CMD ["echo", "Hello, Kurtosis!"]
```

I then performed three tests to check that the feature was implemented
correctly:
- Test without any build arguments defined.
- Test with the correct build argument defined but with a wrong value.
- Test with the correct build argument defined with the correct value.

For the first two tests, as expected, they fail because the image can't
be built.

```bash
$ ktdebug run --enclave test internal_testsuites/starlark/image-build-package
WARN[2024-03-08T12:48:16+01:00] An error occurred getting the running engine's version; you may be running an out-of-date engine version 
WARN[2024-03-08T12:48:16+01:00] We expected the running engine version to match format X.Y.Z, but instead got '386fd4-dirty'; this means that we can't verify the API library and engine versions match so you may encounter runtime errors 
INFO[2024-03-08T12:48:16+01:00] Creating a new enclave for Starlark to run inside... 
INFO[2024-03-08T12:48:18+01:00] Enclave 'test' created successfully          
INFO[2024-03-08T12:48:18+01:00] Executing Starlark package at '/Users/leovct/Documents/opensource/kurtosis/internal_testsuites/starlark/image-build-package' as the passed argument 'internal_testsuites/starlark/image-build-package' looks like a directory 
INFO[2024-03-08T12:48:18+01:00] Compressing package 'github.com/kurtosis-tech/kurtosis/internal_testsuites/starlark/image-build-package' at 'internal_testsuites/starlark/image-build-package' for upload 
INFO[2024-03-08T12:48:18+01:00] Uploading and executing package 'github.com/kurtosis-tech/kurtosis/internal_testsuites/starlark/image-build-package' 
There was an error validating Starlark code 
Error while validating final environment of script
	Caused by: Failed to build the required image 'kurtosistech/service'.
	Caused by: Image build for 'kurtosistech/service' failed with the following output:
{"id":"moby.buildkit.trace","aux":"Cm8KR3NoYTI1NjpkYzExOGIxMmZmMmY2MTE4Y2EwNjY2NjhhNmNjOGQ3ZjQyYmYzZWEwYzg3YWY2YTNjZDExNmI4Y2UzMmNkY2ExGiRbaW50ZXJuYWxdIGxvYWQgcmVtb3RlIGJ1aWxkIGNvbnRleHQ="}
{"id":"moby.buildkit.trace","aux":"Cn0KR3NoYTI1NjpkYzExOGIxMmZmMmY2MTE4Y2EwNjY2NjhhNmNjOGQ3ZjQyYmYzZWEwYzg3YWY2YTNjZDExNmI4Y2UzMmNkY2ExGiRbaW50ZXJuYWxdIGxvYWQgcmVtb3RlIGJ1aWxkIGNvbnRleHQqDAiE9quvBhD/qsaLAw=="}
{"id":"moby.buildkit.trace","aux":"CosBCkdzaGEyNTY6ZGMxMThiMTJmZjJmNjExOGNhMDY2NjY4YTZjYzhkN2Y0MmJmM2VhMGM4N2FmNmEzY2QxMTZiOGNlMzJjZGNhMRokW2ludGVybmFsXSBsb2FkIHJlbW90ZSBidWlsZCBjb250ZXh0KgwIhParrwYQ/6rGiwMyDAiE9quvBhD6gMSPAw=="}
{"id":"moby.buildkit.trace","aux":"CosBCkdzaGEyNTY6ZGMxMThiMTJmZjJmNjExOGNhMDY2NjY4YTZjYzhkN2Y0MmJmM2VhMGM4N2FmNmEzY2QxMTZiOGNlMzJjZGNhMRokW2ludGVybmFsXSBsb2FkIHJlbW90ZSBidWlsZCBjb250ZXh0KgwIhParrwYQyv7JjwMyDAiE9quvBhDF0MuPAw=="}
{"id":"moby.buildkit.trace","aux":"CqMBCkdzaGEyNTY6MTY1ZDBjMTIwNmI3ZDMwMzRkYzllMzE2M2QwNmE5Y2UzYjE4NGI3ZTcxNmU1MzliM2UwZjY0ZTQwZTBkYTBmMxJHc2hhMjU2OmRjMTE4YjEyZmYyZjYxMThjYTA2NjY2OGE2Y2M4ZDdmNDJiZjNlYTBjODdhZjZhM2NkMTE2YjhjZTMyY2RjYTEaD2NvcHkgL2NvbnRleHQgLw=="}
{"id":"moby.buildkit.trace","aux":"CrEBCkdzaGEyNTY6MTY1ZDBjMTIwNmI3ZDMwMzRkYzllMzE2M2QwNmE5Y2UzYjE4NGI3ZTcxNmU1MzliM2UwZjY0ZTQwZTBkYTBmMxJHc2hhMjU2OmRjMTE4YjEyZmYyZjYxMThjYTA2NjY2OGE2Y2M4ZDdmNDJiZjNlYTBjODdhZjZhM2NkMTE2YjhjZTMyY2RjYTEaD2NvcHkgL2NvbnRleHQgLyoMCIT2q68GEJXyjJED"}
{"id":"moby.buildkit.trace","aux":"Cr8BCkdzaGEyNTY6MTY1ZDBjMTIwNmI3ZDMwMzRkYzllMzE2M2QwNmE5Y2UzYjE4NGI3ZTcxNmU1MzliM2UwZjY0ZTQwZTBkYTBmMxJHc2hhMjU2OmRjMTE4YjEyZmYyZjYxMThjYTA2NjY2OGE2Y2M4ZDdmNDJiZjNlYTBjODdhZjZhM2NkMTE2YjhjZTMyY2RjYTEaD2NvcHkgL2NvbnRleHQgLyoMCIT2q68GEJXyjJEDMgwIhParrwYQ6JOHlAM="}
{"id":"moby.buildkit.trace","aux":"CpUBCkdzaGEyNTY6MTM1NDljNThhNzZiY2I1ZGFjOWQ1MmJjMzY4YThmYjZiNWNmNzY1OWY5NGUzZmE2Mjk0OTE3Yjg1NTQ2OTc4ZBo8W2ludGVybmFsXSBsb2FkIG1ldGFkYXRhIGZvciBkb2NrZXIuaW8vbGlicmFyeS9hbHBpbmU6bGF0ZXN0KgwIhParrwYQ25TglAM="}
{"id":"moby.buildkit.trace","aux":"CqMBCkdzaGEyNTY6MTM1NDljNThhNzZiY2I1ZGFjOWQ1MmJjMzY4YThmYjZiNWNmNzY1OWY5NGUzZmE2Mjk0OTE3Yjg1NTQ2OTc4ZBo8W2ludGVybmFsXSBsb2FkIG1ldGFkYXRhIGZvciBkb2NrZXIuaW8vbGlicmFyeS9hbHBpbmU6bGF0ZXN0KgwIhParrwYQ25TglAMyDAiF9quvBhCl+4CKAQ=="}
{"id":"moby.buildkit.trace","aux":"CrACCkdzaGEyNTY6MWFhZWYxZjViNTc0YzNhNmU3MzdhODFjZTMxZmI1YzRmOGNmYWZlNTg5ZDkwNWMwZWQ2YjYzMmZmYzMwNzM5NhJHc2hhMjU2OjE0MjBiNTM5NzFkODkzOTE2YzRlMGU4ZDVlZDRlMjRlNjlkMmE0ODFlNzRiNDcxM2M0NzBhYzczNDU1NDU4YTIamwFbNC80XSBSVU4gaWYgWyAiREVGQVVMVF9WQUxVRSIgIT0gIlZBTFVFIiBdOyB0aGVuICAgZWNobyAiRXJyb3I6IHRoZSBidWlsZCBhcmd1bWVudCBCVUlMRF9BUkcgaGFzIG5vdCBiZWVuIHByb3ZpZGVkIG9yIGlzIG5vdCBlcXVhbCB0byBWQUxVRSI7ICAgZXhpdCAxOyBmaQrrAQpHc2hhMjU2OjE0MjBiNTM5NzFkODkzOTE2YzRlMGU4ZDVlZDRlMjRlNjlkMmE0ODFlNzRiNDcxM2M0NzBhYzczNDU1NDU4YTISR3NoYTI1Njo0M2Q4OWU2YzU4NGQyM2U1YjM1ODU2MzQ5ODQxZDBmN2M1NmRlMTA3NDQ3YjNhZjdiY2I4ODEwNjBlMGM1ZjNlEkdzaGEyNTY6MTY1ZDBjMTIwNmI3ZDMwMzRkYzllMzE2M2QwNmE5Y2UzYjE4NGI3ZTcxNmU1MzliM2UwZjY0ZTQwZTBkYTBmMxoOWzMvNF0gQ09QWSAuIC4KpgEKR3NoYTI1Njo0M2Q4OWU2YzU4NGQyM2U1YjM1ODU2MzQ5ODQxZDBmN2M1NmRlMTA3NDQ3YjNhZjdiY2I4ODEwNjBlMGM1ZjNlEkdzaGEyNTY6OWVmN2JlYWVhMDQ3MzA5MTg1MDQ3NzY0ZTNhYTBkNGYyOTk3OWRhY2M4OGU1NzNkYWE5ZDBmODIwNTBiNGFiMRoSWzIvNF0gV09SS0RJUiAvYXBwCr0BCkdzaGEyNTY6OWVmN2JlYWVhMDQ3MzA5MTg1MDQ3NzY0ZTNhYTBkNGYyOTk3OWRhY2M4OGU1NzNkYWE5ZDBmODIwNTBiNGFiMRpyWzEvNF0gRlJPTSBkb2NrZXIuaW8vbGlicmFyeS9hbHBpbmU6bGF0ZXN0QHNoYTI1NjpjNWIxMjYxZDZkM2U0MzA3MTYyNjkzMWZjMDA0ZjcwMTQ5YmFlYmEyYzhlYzY3MmJkNGYyNzc2MWY4ZTFhZDZiCtkBCkdzaGEyNTY6OWVmN2JlYWVhMDQ3MzA5MTg1MDQ3NzY0ZTNhYTBkNGYyOTk3OWRhY2M4OGU1NzNkYWE5ZDBmODIwNTBiNGFiMRpyWzEvNF0gRlJPTSBkb2NrZXIuaW8vbGlicmFyeS9hbHBpbmU6bGF0ZXN0QHNoYTI1NjpjNWIxMjYxZDZkM2U0MzA3MTYyNjkzMWZjMDA0ZjcwMTQ5YmFlYmEyYzhlYzY3MmJkNGYyNzc2MWY4ZTFhZDZiKgwIhfarrwYQ0v3JigEyDAiF9quvBhDz1teKAQ=="}
{"id":"moby.buildkit.trace","aux":"CsQBCkdzaGEyNTY6NDNkODllNmM1ODRkMjNlNWIzNTg1NjM0OTg0MWQwZjdjNTZkZTEwNzQ0N2IzYWY3YmNiODgxMDYwZTBjNWYzZRJHc2hhMjU2OjllZjdiZWFlYTA0NzMwOTE4NTA0Nzc2NGUzYWEwZDRmMjk5NzlkYWNjODhlNTczZGFhOWQwZjgyMDUwYjRhYjEaElsyLzRdIFdPUktESVIgL2FwcCABKgwIhfarrwYQ7PyxiwEyDAiF9quvBhDAsLiLAQ=="}
{"id":"moby.buildkit.trace","aux":"CvkBCkdzaGEyNTY6MTQyMGI1Mzk3MWQ4OTM5MTZjNGUwZThkNWVkNGUyNGU2OWQyYTQ4MWU3NGI0NzEzYzQ3MGFjNzM0NTU0NThhMhJHc2hhMjU2OjQzZDg5ZTZjNTg0ZDIzZTViMzU4NTYzNDk4NDFkMGY3YzU2ZGUxMDc0NDdiM2FmN2JjYjg4MTA2MGUwYzVmM2USR3NoYTI1NjoxNjVkMGMxMjA2YjdkMzAzNGRjOWUzMTYzZDA2YTljZTNiMTg0YjdlNzE2ZTUzOWIzZTBmNjRlNDBlMGRhMGYzGg5bMy80XSBDT1BZIC4gLioMCIX2q68GEN6wvosB"}
{"id":"moby.buildkit.trace","aux":"CocCCkdzaGEyNTY6MTQyMGI1Mzk3MWQ4OTM5MTZjNGUwZThkNWVkNGUyNGU2OWQyYTQ4MWU3NGI0NzEzYzQ3MGFjNzM0NTU0NThhMhJHc2hhMjU2OjQzZDg5ZTZjNTg0ZDIzZTViMzU4NTYzNDk4NDFkMGY3YzU2ZGUxMDc0NDdiM2FmN2JjYjg4MTA2MGUwYzVmM2USR3NoYTI1NjoxNjVkMGMxMjA2YjdkMzAzNGRjOWUzMTYzZDA2YTljZTNiMTg0YjdlNzE2ZTUzOWIzZTBmNjRlNDBlMGRhMGYzGg5bMy80XSBDT1BZIC4gLioMCIX2q68GEN6wvosBMgwIhfarrwYQyOfrlAE="}
{"id":"moby.buildkit.trace","aux":"Cr4CCkdzaGEyNTY6MWFhZWYxZjViNTc0YzNhNmU3MzdhODFjZTMxZmI1YzRmOGNmYWZlNTg5ZDkwNWMwZWQ2YjYzMmZmYzMwNzM5NhJHc2hhMjU2OjE0MjBiNTM5NzFkODkzOTE2YzRlMGU4ZDVlZDRlMjRlNjlkMmE0ODFlNzRiNDcxM2M0NzBhYzczNDU1NDU4YTIamwFbNC80XSBSVU4gaWYgWyAiREVGQVVMVF9WQUxVRSIgIT0gIlZBTFVFIiBdOyB0aGVuICAgZWNobyAiRXJyb3I6IHRoZSBidWlsZCBhcmd1bWVudCBCVUlMRF9BUkcgaGFzIG5vdCBiZWVuIHByb3ZpZGVkIG9yIGlzIG5vdCBlcXVhbCB0byBWQUxVRSI7ICAgZXhpdCAxOyBmaSoMCIX2q68GEPmv7JUB"}
{"id":"moby.buildkit.trace","aux":"Gq4BCkdzaGEyNTY6MWFhZWYxZjViNTc0YzNhNmU3MzdhODFjZTMxZmI1YzRmOGNmYWZlNTg5ZDkwNWMwZWQ2YjYzMmZmYzMwNzM5NhIMCIX2q68GEI710M8BGAEiU0Vycm9yOiB0aGUgYnVpbGQgYXJndW1lbnQgQlVJTERfQVJHIGhhcyBub3QgYmVlbiBwcm92aWRlZCBvciBpcyBub3QgZXF1YWwgdG8gVkFMVUUK"}
{"id":"moby.buildkit.trace","aux":"CqQECkdzaGEyNTY6MWFhZWYxZjViNTc0YzNhNmU3MzdhODFjZTMxZmI1YzRmOGNmYWZlNTg5ZDkwNWMwZWQ2YjYzMmZmYzMwNzM5NhJHc2hhMjU2OjE0MjBiNTM5NzFkODkzOTE2YzRlMGU4ZDVlZDRlMjRlNjlkMmE0ODFlNzRiNDcxM2M0NzBhYzczNDU1NDU4YTIamwFbNC80XSBSVU4gaWYgWyAiREVGQVVMVF9WQUxVRSIgIT0gIlZBTFVFIiBdOyB0aGVuICAgZWNobyAiRXJyb3I6IHRoZSBidWlsZCBhcmd1bWVudCBCVUlMRF9BUkcgaGFzIG5vdCBiZWVuIHByb3ZpZGVkIG9yIGlzIG5vdCBlcXVhbCB0byBWQUxVRSI7ICAgZXhpdCAxOyBmaSoMCIX2q68GEPmv7JUBMgwIhfarrwYQn6i91AE61QFwcm9jZXNzICIvYmluL3NoIC1jIGlmIFsgXCIkQlVJTERfQVJHXCIgIT0gXCJWQUxVRVwiIF07IHRoZW4gICBlY2hvIFwiRXJyb3I6IHRoZSBidWlsZCBhcmd1bWVudCBCVUlMRF9BUkcgaGFzIG5vdCBiZWVuIHByb3ZpZGVkIG9yIGlzIG5vdCBlcXVhbCB0byBWQUxVRVwiOyAgIGV4aXQgMTsgZmkiIGRpZCBub3QgY29tcGxldGUgc3VjY2Vzc2Z1bGx5OiBleGl0IGNvZGU6IDE="}
{"errorDetail":{"message":"process \"/bin/sh -c if [ \\\"$BUILD_ARG\\\" != \\\"VALUE\\\" ]; then   echo \\\"Error: the build argument BUILD_ARG has not been provided or is not equal to VALUE\\\";   exit 1; fi\" did not complete successfully: exit code: 1"},"error":"process \"/bin/sh -c if [ \\\"$BUILD_ARG\\\" != \\\"VALUE\\\" ]; then   echo \\\"Error: the build argument BUILD_ARG has not been provided or is not equal to VALUE\\\";   exit 1; fi\" did not complete successfully: exit code: 1"}
 --- at /Users/leovct/Documents/opensource/kurtosis/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go:1479 (DockerManager.BuildImage) ---

Container images used in this run:
> kurtosistech/service - locally built

Error encountered running Starlark code.

Made with Kurtosis - https://kurtosis.com
INFO[2024-03-08T12:48:21+01:00] ============================================= 
INFO[2024-03-08T12:48:21+01:00] ||          Created enclave: test          || 
INFO[2024-03-08T12:48:21+01:00] ============================================= 
Name:            test
UUID:            fc14d605d775
Status:          RUNNING
Creation Time:   Fri, 08 Mar 2024 12:48:16 CET
Flags:           

========================================= Files Artifacts =========================================
UUID   Name

========================================== User Services ==========================================
UUID   Name   Ports   Status
```

For the last test, it succeeds, meaning the feature has been correctly
implemented! 🥳

```bash
$ ktdebug run --enclave test internal_testsuites/starlark/image-build-package
WARN[2024-03-08T12:49:39+01:00] An error occurred getting the running engine's version; you may be running an out-of-date engine version 
WARN[2024-03-08T12:49:39+01:00] We expected the running engine version to match format X.Y.Z, but instead got '386fd4-dirty'; this means that we can't verify the API library and engine versions match so you may encounter runtime errors 
INFO[2024-03-08T12:49:39+01:00] Executing Starlark package at '/Users/leovct/Documents/opensource/kurtosis/internal_testsuites/starlark/image-build-package' as the passed argument 'internal_testsuites/starlark/image-build-package' looks like a directory 
INFO[2024-03-08T12:49:39+01:00] Compressing package 'github.com/kurtosis-tech/kurtosis/internal_testsuites/starlark/image-build-package' at 'internal_testsuites/starlark/image-build-package' for upload 
INFO[2024-03-08T12:49:39+01:00] Uploading and executing package 'github.com/kurtosis-tech/kurtosis/internal_testsuites/starlark/image-build-package' 

Container images used in this run:
> kurtosistech/service - locally built

WARNING: Container images with different architecture than expected(amd64):
> kurtosistech/service - arm64

Adding service with name 'service' and image 'kurtosistech/service'
Service 'service' added with service UUID '30bd3754ec864729bf11e2ed9154b4f6'

Starlark code successfully run. No output was returned.

Made with Kurtosis - https://kurtosis.com
Name:            test
UUID:            fc14d605d775
Status:          RUNNING
Creation Time:   Fri, 08 Mar 2024 12:48:16 CET
Flags:           

========================================= Files Artifacts =========================================
UUID   Name

========================================== User Services ==========================================
UUID           Name      Ports    Status
30bd3754ec86   service   <none>   STOPPED
```


## Is this change user facing?
YES
<!-- If yes, please add the "user facing" label to the PR -->
<!-- If yes, don't forget to include docs changes where relevant -->

## References (if applicable):
<!-- Add relevant Github Issues, Discord threads, or other helpful
information. -->

Resolves #2214

---------

Co-authored-by: Tedi Mitiku <tedi.m52@gmail.com>
  • Loading branch information
leovct and tedim52 committed Mar 12, 2024
1 parent 9697eb9 commit 9812375
Show file tree
Hide file tree
Showing 12 changed files with 168 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1408,6 +1408,12 @@ func (manager *DockerManager) BuildImage(ctx context.Context, imageName string,
}()
defer buildkitSession.Close() //nolint

buildArgs := imageBuildSpec.GetBuildArgs()
buildArgsMapStringStringPtr := map[string]*string{}
for k, v := range buildArgs {
value := v // Go uses a single variable for loop iterations which lead to unexpected behaviours.
buildArgsMapStringStringPtr[k] = &value
}
imageBuildOpts := types.ImageBuildOptions{
Tags: []string{imageName},
SuppressOutput: false,
Expand All @@ -1429,7 +1435,7 @@ func (manager *DockerManager) BuildImage(ctx context.Context, imageName string,
ShmSize: 0,
Dockerfile: defaultContainerImageFile,
Ulimits: []*units.Ulimit{},
BuildArgs: map[string]*string{},
BuildArgs: buildArgsMapStringStringPtr,
AuthConfigs: map[string]registry.AuthConfig{},
Context: buildContextTarReader,
// 0.0.0 label is a hack so that images by internal testsuite are cleaned up by kurtosis clean/PruneUnusedImages
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package image_build_spec

import (
"encoding/json"

"github.com/kurtosis-tech/stacktrace"
)

Expand Down Expand Up @@ -37,13 +38,17 @@ type privateImageBuildSpec struct {
// Default value is the empty string if the image build is not multi-stage.
//
TargetStage string

// Dockerfile build args
BuildArgs map[string]string
}

func NewImageBuildSpec(contextDirPath string, containerImageFilePath string, targetStage string) *ImageBuildSpec {
func NewImageBuildSpec(contextDirPath string, containerImageFilePath string, targetStage string, buildArgs map[string]string) *ImageBuildSpec {
internalImageBuildSpec := &privateImageBuildSpec{
ContainerImageFilePath: containerImageFilePath,
ContextDirPath: contextDirPath,
TargetStage: targetStage,
BuildArgs: buildArgs,
}
return &ImageBuildSpec{internalImageBuildSpec}
}
Expand All @@ -60,6 +65,10 @@ func (imageBuildSpec *ImageBuildSpec) GetTargetStage() string {
return imageBuildSpec.privateImageBuildSpec.TargetStage
}

func (imageBuildSpec *ImageBuildSpec) GetBuildArgs() map[string]string {
return imageBuildSpec.privateImageBuildSpec.BuildArgs
}

func (imageBuildSpec *ImageBuildSpec) MarshalJSON() ([]byte, error) {
return json.Marshal(imageBuildSpec.privateImageBuildSpec)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package service

import (
"encoding/json"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_registry_spec"
"testing"
"time"

"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_build_spec"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_registry_spec"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/nix_build_spec"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/port_spec"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service_directory"
Expand Down Expand Up @@ -185,7 +185,8 @@ func testImageBuildSpec() *image_build_spec.ImageBuildSpec {
return image_build_spec.NewImageBuildSpec(
"test-image",
"path",
"")
"",
nil)
}

func testImageRegistrySpec() *image_registry_spec.ImageRegistrySpec {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package test_engine

import (
"fmt"
"testing"

"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/service_config"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_packages"
"github.com/stretchr/testify/require"
)

type imageBuildSpecWithBuildArgsTest struct {
*testing.T

packageContentProvider *startosis_packages.MockPackageContentProvider
}

func (suite *KurtosisTypeConstructorTestSuite) TestImageBuildSpecWithBuildArgsTest() {
suite.packageContentProvider.EXPECT().
GetAbsoluteLocator(testModulePackageId, testModuleMainFileLocator, testBuildContextDir, testNoPackageReplaceOptions).
Times(1).
Return(testBuildContextLocator, nil)

suite.packageContentProvider.EXPECT().
GetOnDiskAbsolutePackageFilePath(testContainerImageLocator).
Times(1).
Return(testOnDiskContainerImagePath, nil)

suite.run(&imageBuildSpecWithBuildArgsTest{
T: suite.T(),
packageContentProvider: suite.packageContentProvider,
})
}

func (t *imageBuildSpecWithBuildArgsTest) GetStarlarkCode() string {
return fmt.Sprintf("%s(%s=%q, %s=%q, %s=%s)",
service_config.ImageBuildSpecTypeName,
service_config.BuiltImageNameAttr,
testContainerImageName,
service_config.BuildContextAttr,
testBuildContextDir,
service_config.BuildArgsAttr,
fmt.Sprintf("{%q: %q, %q: %q}", testBuildArgName1, testBuildArgValue1, testBuildArgName2, testBuildArgValue2))
}

func (t *imageBuildSpecWithBuildArgsTest) Assert(typeValue builtin_argument.KurtosisValueType) {
imageBuildSpecStarlark, ok := typeValue.(*service_config.ImageBuildSpec)
require.True(t, ok)

imageBuildSpec, err := imageBuildSpecStarlark.ToKurtosisType(
testModuleMainFileLocator,
testModulePackageId,
t.packageContentProvider,
testNoPackageReplaceOptions)
require.Nil(t, err)
require.Equal(t, testOnDiskContainerImagePath, imageBuildSpec.GetContainerImageFilePath())
require.Equal(t, testOnDiskContextDirPath, imageBuildSpec.GetBuildContextDir())

expectedBuildArgs := map[string]string{
testBuildArgName1: testBuildArgValue1,
testBuildArgName2: testBuildArgValue2,
}
require.Equal(t, expectedBuildArgs, imageBuildSpec.GetBuildArgs())
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,16 @@ func (suite *KurtosisTypeConstructorTestSuite) TestServiceConfigWithImageBuildSp
}

func (t *serviceConfigImageBuildSpecTestCase) GetStarlarkCode() string {
imageBuildSpec := fmt.Sprintf("%s(%s=%q, %s=%q, %s=%q)",
imageBuildSpec := fmt.Sprintf("%s(%s=%q, %s=%q, %s=%q, %s=%s)",
service_config.ImageBuildSpecTypeName,
service_config.BuiltImageNameAttr,
testContainerImageName,
service_config.BuildContextAttr,
testBuildContextDir,
service_config.TargetStageAttr,
testTargetStage)
testTargetStage,
service_config.BuildArgsAttr,
fmt.Sprintf("{%q: %q, %q: %q}", testBuildArgName1, testBuildArgValue1, testBuildArgName2, testBuildArgValue2))
return fmt.Sprintf("%s(%s=%s)",
service_config.ServiceConfigTypeName,
service_config.ImageAttr, imageBuildSpec)
Expand All @@ -66,10 +68,15 @@ func (t *serviceConfigImageBuildSpecTestCase) Assert(typeValue builtin_argument.
image_download_mode.ImageDownloadMode_Missing)
require.Nil(t, interpretationErr)

expectedBuildArgs := map[string]string{
testBuildArgName1: testBuildArgValue1,
testBuildArgName2: testBuildArgValue2,
}
expectedImageBuildSpec := image_build_spec.NewImageBuildSpec(
testOnDiskContextDirPath,
testOnDiskContainerImagePath,
testTargetStage)
testTargetStage,
expectedBuildArgs)
expectedServiceConfig, err := service.CreateServiceConfig(
testContainerImageName,
expectedImageBuildSpec,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ var (
testBuildContextDir = "./"
testBuildFile = "foo.Dockerfile"
testTargetStage = "builder"
testBuildArgName1 = "BUILD_ARG_1"
testBuildArgValue1 = "VALUE_1"
testBuildArgName2 = "BUILD_ARG_2"
testBuildArgValue2 = "VALUE_2"
testBuildContextLocator = testModulePackageId
testContainerImageLocator = "github.com/kurtosistech/test-package/Dockerfile"
testContainerImageLocatorWithBuildFile = "github.com/kurtosistech/test-package/foo.Dockerfile"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package kurtosis_types

import (
"fmt"
"reflect"

"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors"
"github.com/kurtosis-tech/stacktrace"
"go.starlark.net/starlark"
"reflect"
)

func MakeOptional(argName string) string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_constants"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_packages"
Expand All @@ -21,6 +22,7 @@ const (
BuildContextAttr = "build_context_dir"
BuildFileAttr = "build_file"
TargetStageAttr = "target_stage"
BuildArgsAttr = "build_args"

defaultContainerImageFileName = "Dockerfile"
)
Expand Down Expand Up @@ -62,6 +64,12 @@ func NewImageBuildSpecType() *kurtosis_type_constructor.KurtosisTypeConstructor
return builtin_argument.NonEmptyString(value, TargetStageAttr)
},
},
{
Name: BuildArgsAttr,
IsOptional: true,
ZeroValueProvider: builtin_argument.ZeroValueProvider[*starlark.Dict],
Validator: nil,
},
},
},
Instantiate: instantiateImageBuildSpec,
Expand Down Expand Up @@ -149,6 +157,22 @@ func (imageBuildSpec *ImageBuildSpec) GetTargetStage() (string, *startosis_error
return targetStageStr, nil
}

// Dockerfile build-time variables
func (imageBuildSpec *ImageBuildSpec) GetBuildArgs() (map[string]string, *startosis_errors.InterpretationError) {
buildArgsStarlark, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[*starlark.Dict](imageBuildSpec.KurtosisValueTypeDefault, BuildArgsAttr)
if interpretationErr != nil {
return nil, interpretationErr
}
if !found || buildArgsStarlark.Len() == 0 {
return nil, nil
}
buildArgs, interpretationErr := kurtosis_types.SafeCastToMapStringString(buildArgsStarlark, BuildArgsAttr)
if interpretationErr != nil {
return nil, interpretationErr
}
return buildArgs, nil
}

func (imageBuildSpec *ImageBuildSpec) ToKurtosisType(
locatorOfModuleInWhichThisBuiltInIsBeingCalled string,
packageId string,
Expand Down Expand Up @@ -181,7 +205,12 @@ func (imageBuildSpec *ImageBuildSpec) ToKurtosisType(
return nil, interpretationErr
}

return image_build_spec.NewImageBuildSpec(buildContextDirPathOnDisk, containerImageFilePathOnDisk, targetStageStr), nil
buildArgs, interpretationErr := imageBuildSpec.GetBuildArgs()
if interpretationErr != nil {
return nil, interpretationErr
}

return image_build_spec.NewImageBuildSpec(buildContextDirPathOnDisk, containerImageFilePathOnDisk, targetStageStr, buildArgs), nil
}

// Returns the filepath of the build context directory and container image on APIC based on package info
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ Kurtosis starts services based on a provided image definition in the `image` arg
# Stage of image build to target for multi-stage container image
# OPTIONAL
target_stage=""

# Arguments passed at build-time
# OPTIONAL (Default: {})
build_args={
"BUILD_ARG_1": "VALUE_1",
"BUILD_ARG_2": "VALUE_2",
}
)
```
:::info
Expand Down
7 changes: 7 additions & 0 deletions docs/docs/api-reference/starlark-reference/service-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ config = ServiceConfig(
# Stage of image build to target for multi-stage container image
# OPTIONAL
target_stage=""

# Arguments passed at build-time
# OPTIONAL (Default: {})
build_args={
"BUILD_ARG_1": "VALUE_1",
"BUILD_ARG_2": "VALUE_2",
}
)

OR
Expand Down
19 changes: 19 additions & 0 deletions internal_testsuites/starlark/image-build-package/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,23 @@ WORKDIR /app

COPY . .


# The idea is to test if the build argument has been provided.
# The following commands would not work:

# $ docker build -t image-build-package-test .
# Error: the build argument BUILD_ARG has not been provided or is not equal to VALUE

# $ docker build -t image-build-package-test --build-arg "BUILD_ARG=WRONG_VALUE" .
# Error: the build argument BUILD_ARG has not been provided or is not equal to VALUE

# But this command would work:
# $ docker build -t image-build-package-test --build-arg "BUILD_ARG=VALUE" .

ARG BUILD_ARG="DEFAULT_VALUE"
RUN if [ "$BUILD_ARG" != "VALUE" ]; then \
echo "Error: the build argument BUILD_ARG has not been provided or is not equal to VALUE"; \
exit 1; \
fi

CMD ["echo", "Hello, Kurtosis!"]
3 changes: 3 additions & 0 deletions internal_testsuites/starlark/image-build-package/main.star
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ def run(plan, args):
image=ImageBuildSpec(
image_name="kurtosistech/service",
build_context_dir="./",
build_args={
"BUILD_ARG": "VALUE",
}
),
)
)

0 comments on commit 9812375

Please sign in to comment.