Skip to content
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

Validate stack during analyze phase #617

Merged
merged 3 commits into from
Jun 16, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
199 changes: 198 additions & 1 deletion acceptance/analyzer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,36 @@ func TestAnalyzer(t *testing.T) {
h.AssertNil(t, os.RemoveAll(filepath.Join(targetDockerConfig, "config.json")))
h.RecursiveCopy(t, authRegistry.DockerDirectory, targetDockerConfig)

// build run-images into test registry
runImageContext := filepath.Join("testdata", "analyzer", "run-image")
buildAuthRegistryImage(
t,
"company/stack:bionic",
runImageContext,
"-f", filepath.Join(runImageContext, dockerfileName),
"--build-arg", "stackid=io.buildpacks.stacks.bionic",
)
buildAuthRegistryImage(
t,
"company/stack:centos",
runImageContext,
"-f", filepath.Join(runImageContext, dockerfileName),
"--build-arg", "stackid=io.company.centos",
)

jabrown85 marked this conversation as resolved.
Show resolved Hide resolved
// build run-image into daemon
h.DockerBuild(
t,
"localcompany/stack:bionic",
runImageContext,
h.WithArgs(
"-f", filepath.Join(runImageContext, dockerfileName),
"--build-arg", "stackid=io.buildpacks.stacks.bionic",
),
)

defer h.DockerImageRemove(t, "localcompany/stack:bionic")

// Setup test container

h.MakeAndCopyLifecycle(t, daemonOS, analyzerBinaryDir)
Expand All @@ -81,6 +111,7 @@ func TestAnalyzer(t *testing.T) {
analyzeDockerContext,
h.WithFlags(
"-f", filepath.Join(analyzeDockerContext, dockerfileName),
"--build-arg", "registry="+noAuthRegistry.Host+":"+noAuthRegistry.Port,
),
)
defer h.DockerImageRemove(t, analyzeImage)
Expand Down Expand Up @@ -253,7 +284,10 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe
copyDir,
ctrPath("/some-dir/some-analyzed.toml"),
analyzeImage,
h.WithFlags("--env", "CNB_PLATFORM_API="+platformAPI),
h.WithFlags(
"--network", registryNetwork,
"--env", "CNB_PLATFORM_API="+platformAPI,
),
h.WithArgs(execArgs...),
)

Expand All @@ -277,6 +311,7 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe
h.WithFlags(append(
dockerSocketMount,
"--env", "CNB_PLATFORM_API="+platformAPI,
"--env", "CNB_STACK_PATH=/cnb/local-bionic-stack.toml", // /cnb/local-bionic-stack.toml has `io.buildpacks.stacks.bionic` and points to run image `localcompany/stack:bionic` with same stack id
)...),
h.WithArgs(execArgs...),
)
Expand Down Expand Up @@ -316,6 +351,7 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe
h.WithFlags(append(
dockerSocketMount,
"--env", "CNB_PLATFORM_API="+platformAPI,
"--env", "CNB_STACK_PATH=/cnb/local-bionic-stack.toml", // /cnb/local-bionic-stack.toml has `io.buildpacks.stacks.bionic` and points to run image `localcompany/stack:bionic` with same stack id
)...),
h.WithArgs(
ctrPath(analyzerPath),
Expand Down Expand Up @@ -624,6 +660,7 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe
ctrPath("/layers/analyzed.toml"),
analyzeImage,
h.WithFlags(
"--network", registryNetwork,
"--env", "CNB_PLATFORM_API="+platformAPI,
),
h.WithArgs(ctrPath(analyzerPath), "some-image"),
Expand Down Expand Up @@ -1065,6 +1102,166 @@ func testAnalyzerFunc(platformAPI string) func(t *testing.T, when spec.G, it spe
assertAnalyzedMetadata(t, filepath.Join(copyDir, "some-other-layers", "analyzed.toml")) // analyzed.toml is written at the provided -layers directory: /some-other-layers
})
})

when("validating stack", func() {
it.Before(func() {
h.SkipIf(t, api.MustParse(platformAPI).Compare(api.MustParse("0.7")) < 0, "Platform API < 0.7 does not validate stack")
natalieparellano marked this conversation as resolved.
Show resolved Hide resolved
})

when("stack metadata is present", func() {
jabrown85 marked this conversation as resolved.
Show resolved Hide resolved
when("stacks match", func() {
it("passes validation", func() {
execArgs := []string{ctrPath(analyzerPath), "some-image"}
h.DockerRun(t,
analyzeImage, // /cnb/stack.toml has `io.buildpacks.stacks.bionic` and points to run image `company/stack:bionic` with same stack id
h.WithFlags(
"--network", registryNetwork,
"--env", "CNB_PLATFORM_API="+platformAPI,
),
h.WithArgs(execArgs...),
)
})
})

when("CNB_RUN_IMAGE is present", func() {
it("uses CNB_RUN_IMAGE for validation", func() {
execArgs := []string{ctrPath(analyzerPath), "some-image"}

h.DockerRun(t,
analyzeImage,
h.WithFlags(
"--network", registryNetwork,
"--env", "CNB_PLATFORM_API="+platformAPI,
"--env", "CNB_STACK_PATH=/cnb/mismatch-stack.toml", // /cnb/mismatch-stack.toml points to run image `company/stack:centos`
"--env", "CNB_RUN_IMAGE="+noAuthRegistry.RepoName("company/stack:bionic"),
),
h.WithArgs(execArgs...),
)
})
})

when("stack metadata file is invalid", func() {
it("fails validation", func() {
cmd := exec.Command(
natalieparellano marked this conversation as resolved.
Show resolved Hide resolved
"docker", "run", "--rm",
"--network", registryNetwork,
"--env", "CNB_PLATFORM_API="+platformAPI,
"--env", "CNB_STACK_PATH=/cnb/bad-stack.toml",
jabrown85 marked this conversation as resolved.
Show resolved Hide resolved
analyzeImage,
ctrPath(analyzerPath),
"some-image",
) // #nosec G204
output, err := cmd.CombinedOutput()

h.AssertNotNil(t, err)
expected := "get stack metadata"
h.AssertStringContains(t, string(output), expected)
})
})

when("run image inaccessible", func() {
it("fails validation", func() {
cmd := exec.Command(
natalieparellano marked this conversation as resolved.
Show resolved Hide resolved
"docker", "run", "--rm",
"--network", registryNetwork,
"--env", "CNB_PLATFORM_API="+platformAPI,
"--env", "CNB_RUN_IMAGE=fake.example.com/company/example:20",
analyzeImage,
ctrPath(analyzerPath),
"some-image",
) // #nosec G204
output, err := cmd.CombinedOutput()

h.AssertNotNil(t, err)
expected := "failed to resolve run image"
h.AssertStringContains(t, string(output), expected)
})
})

when("run image has mirrors", func() {
it("uses expected mirror for run-image", func() {
execArgs := []string{ctrPath(analyzerPath), noAuthRegistry.RepoName("apprepo/myapp")} // image located on same registry as mirror

h.DockerRunAndCopy(t,
containerName,
copyDir,
ctrPath("/layers/analyzed.toml"),
analyzeImage,
h.WithFlags(
"--network", registryNetwork,
"--env", "CNB_PLATFORM_API="+platformAPI,
"--env", "CNB_STACK_PATH=/cnb/run-mirror-stack.toml", // /cnb/run-mirror-stack.toml points to run image on gcr.io and mirror on test registry
),
h.WithArgs(execArgs...),
)
})
})

when("daemon case", func() {
when("stacks match", func() {
it("passes validation", func() {
execArgs := []string{ctrPath(analyzerPath), "-daemon", "some-image"}

h.DockerRunAndCopy(t,
containerName,
copyDir,
ctrPath("/layers/analyzed.toml"),
analyzeImage,
h.WithFlags(append(
dockerSocketMount,
"--network", registryNetwork,
"--env", "CNB_PLATFORM_API="+platformAPI,
"--env", "CNB_STACK_PATH=/cnb/local-bionic-stack.toml", // /cnb/local-bionic-stack.toml has `io.buildpacks.stacks.bionic` and points to run image `localcompany/stack:bionic` with same stack id
)...),
h.WithArgs(execArgs...),
)
})
})
})
})

when("stack metadata is not present", func() {
when("CNB_RUN_IMAGE and CNB_STACK_ID are set", func() {
it("passes validation", func() {
execArgs := []string{ctrPath(analyzerPath), "some-image"}

h.DockerRunAndCopy(t,
containerName,
copyDir,
ctrPath("/layers/analyzed.toml"),
analyzeImage,
h.WithFlags(
"--network", registryNetwork,
"--env", "CNB_PLATFORM_API="+platformAPI,
"--env", "CNB_STACK_PATH=/cnb/file-does-not-exist.toml",
"--env", "CNB_RUN_IMAGE="+noAuthRegistry.RepoName("company/stack:bionic"),
"--env", "CNB_STACK_ID=io.buildpacks.stacks.bionic",
),
h.WithArgs(execArgs...),
)
})
})

when("run image and stack id are not provided as arguments or in the environment", func() {
it("fails validation", func() {
cmd := exec.Command(
"docker", "run", "--rm",
"--network", registryNetwork,
"--env", "CNB_PLATFORM_API="+platformAPI,
"--env", "CNB_STACK_PATH=/cnb/file-does-not-exist.toml",
analyzeImage,
ctrPath(analyzerPath),
"some-image",
) // #nosec G204
output, err := cmd.CombinedOutput()

h.AssertNotNil(t, err)
expected := "a run image must be specified when there is no stack metadata available"
h.AssertStringContains(t, string(output), expected)
})
})
})
})
}
}

Expand Down
41 changes: 41 additions & 0 deletions acceptance/testdata/analyzer/analyze-image/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,44 @@ RUN chown -R $CNB_USER_ID:$CNB_GROUP_ID /layers

# ensure docker config directory is root owned and NOT world readable
RUN chown -R root /docker-config; chmod -R 700 /docker-config

ARG registry
jabrown85 marked this conversation as resolved.
Show resolved Hide resolved

# write some stack.toml files to use in tests
RUN echo "\
[run-image]\n\
image = \"${registry}/company/stack:bionic\"\n\
mirrors = []\n\
[build-image]\n\
stack-id = \"io.buildpacks.stacks.bionic\"\n\
mixins = []\n\
" > /cnb/stack.toml

RUN echo "\
[run-image]\n\
image = \"${registry}/company/stack:centos\"\n\
mirrors = []\n\
[build-image]\n\
stack-id = \"io.buildpacks.stacks.bionic\"\n\
mixins = []\n\
" > /cnb/mismatch-stack.toml

RUN echo "\
[run-image]\n\
image = \"gcr.io/paketobuildpacks/invalidimg:20\"\n\
mirrors = [\"${registry}/company/stack:bionic\"]\n\
[build-image]\n\
stack-id = \"io.buildpacks.stacks.bionic\"\n\
mixins = []\n\
" > /cnb/run-mirror-stack.toml

RUN echo "\
[run-image]\n\
image = \"localcompany/stack:bionic\"\n\
mirrors = []\n\
[build-image]\n\
stack-id = \"io.buildpacks.stacks.bionic\"\n\
mixins = []\n\
" > /cnb/local-bionic-stack.toml

RUN echo "[run-images" > /cnb/bad-stack.toml
33 changes: 33 additions & 0 deletions acceptance/testdata/analyzer/analyze-image/Dockerfile.windows
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,36 @@ ENV CNB_USER_ID=1
ENV CNB_GROUP_ID=1

ENV CNB_PLATFORM_API=${cnb_platform_api}

ARG registry

# write some stack.toml files to use in tests
RUN echo [run-image] > /cnb/stack.toml &\
echo image = "%registry%/company/stack:bionic" >> /cnb/stack.toml &\
echo mirrors = [] >> /cnb/stack.toml &\
echo [build-image] >> /cnb/stack.toml &\
echo stack-id = "io.buildpacks.stacks.bionic" >> /cnb/stack.toml &\
echo mixins = [] >> /cnb/stack.toml

RUN echo [run-image] > /cnb/mismatch-stack.toml &\
echo image = "%registry%/company/stack:centos" >> /cnb/mismatch-stack.toml &\
echo mirrors = [] >> /cnb/mismatch-stack.toml &\
echo [build-image] >> /cnb/mismatch-stack.toml &\
echo stack-id = "io.buildpacks.stacks.bionic" >> /cnb/mismatch-stack.toml &\
echo mixins = [] >> /cnb/mismatch-stack.toml

RUN echo [run-image] > /cnb/run-mirror-stack.toml &\
echo image = "gcr.io/paketobuildpacks/invalidimg:20" >> /cnb/run-mirror-stack.toml &\
echo mirrors = ["%registry%/company/stack:bionic"] >> /cnb/run-mirror-stack.toml &\
echo [build-image] >> /cnb/run-mirror-stack.toml &\
echo stack-id = "io.buildpacks.stacks.bionic" >> /cnb/run-mirror-stack.toml &\
echo mixins = [] >> /cnb/run-mirror-stack.toml

RUN echo [run-image] > /cnb/local-bionic-stack.toml &\
echo image = "localcompany/stack:bionic" >> /cnb/local-bionic-stack.toml &\
echo mirrors = [] >> /cnb/local-bionic-stack.toml &\
echo [build-image] >> /cnb/local-bionic-stack.toml &\
echo stack-id = "io.buildpacks.stacks.bionic" >> /cnb/local-bionic-stack.toml &\
echo mixins = [] >> /cnb/local-bionic-stack.toml

RUN echo [run-images > /cnb/bad-stack.toml
4 changes: 4 additions & 0 deletions acceptance/testdata/analyzer/run-image/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM scratch

ARG stackid
LABEL io.buildpacks.stack.id=${stackid}
5 changes: 5 additions & 0 deletions acceptance/testdata/analyzer/run-image/Dockerfile.windows
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM mcr.microsoft.com/windows/nanoserver:1809
USER ContainerAdministrator

ARG stackid
LABEL io.buildpacks.stack.id=${stackid}
1 change: 1 addition & 0 deletions cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const (
EnvSkipLayers = "CNB_ANALYZE_SKIP_LAYERS" // defaults to false
EnvSkipRestore = "CNB_SKIP_RESTORE" // defaults to false
EnvStackPath = "CNB_STACK_PATH"
EnvStackID = "CNB_STACK_ID"
EnvUID = "CNB_USER_ID"
EnvUseDaemon = "CNB_USE_DAEMON" // defaults to false
)
Expand Down