From 4a89a4435fe4e7bcfaed53c3320f2705811f7eed Mon Sep 17 00:00:00 2001 From: Jordan Keister Date: Fri, 31 May 2024 15:41:36 -0500 Subject: [PATCH] generate binary-less dockerfiles Signed-off-by: Jordan Keister --- alpha/action/generate_dockerfile.go | 35 +++++++++- alpha/action/generate_dockerfile_test.go | 83 ++++++++++++++++++++++++ cmd/opm/generate/cmd.go | 3 + 3 files changed, 120 insertions(+), 1 deletion(-) diff --git a/alpha/action/generate_dockerfile.go b/alpha/action/generate_dockerfile.go index 4d2a3ddfc..7c33a87c3 100644 --- a/alpha/action/generate_dockerfile.go +++ b/alpha/action/generate_dockerfile.go @@ -13,6 +13,7 @@ type GenerateDockerfile struct { IndexDir string ExtraLabels map[string]string Writer io.Writer + Lite bool } func (i GenerateDockerfile) Run() error { @@ -20,7 +21,14 @@ func (i GenerateDockerfile) Run() error { return err } - t, err := template.New("dockerfile").Parse(dockerfileTmpl) + var dockerfileTemplate string + if i.Lite { + dockerfileTemplate = binlessDockerfileTmpl + } else { + dockerfileTemplate = dockerfileTmpl + } + + t, err := template.New("dockerfile").Parse(dockerfileTemplate) if err != nil { // The template is hardcoded in the binary, so if // there is a parse error, it was a programmer error. @@ -39,6 +47,31 @@ func (i GenerateDockerfile) validate() error { return nil } +const binlessDockerfileTmpl = `# The builder image is expected to contain +# /bin/opm (with serve subcommand) +FROM {{.BaseImage}} as builder + +# Copy FBC root into image at /configs and pre-populate serve cache +ADD {{.IndexDir}} /configs +RUN ["/bin/opm", "serve", "/configs", "--cache-dir=/tmp/cache", "--cache-only"] + +FROM scratch + +COPY --from=builder /configs /configs +COPY --from=builder /tmp/cache /tmp/cache + +# Set FBC-specific label for the location of the FBC root directory +# in the image +LABEL ` + containertools.ConfigsLocationLabel + `=/configs +{{- if .ExtraLabels }} + +# Set other custom labels +{{- range $key, $value := .ExtraLabels }} +LABEL "{{ $key }}"="{{ $value }}" +{{- end }} +{{- end }} +` + const dockerfileTmpl = `# The base image is expected to contain # /bin/opm (with a serve subcommand) and /bin/grpc_health_probe FROM {{.BaseImage}} diff --git a/alpha/action/generate_dockerfile_test.go b/alpha/action/generate_dockerfile_test.go index d5a76516c..54d805f4a 100644 --- a/alpha/action/generate_dockerfile_test.go +++ b/alpha/action/generate_dockerfile_test.go @@ -87,6 +87,89 @@ RUN ["/bin/opm", "serve", "/configs", "--cache-dir=/tmp/cache", "--cache-only"] # in the image LABEL operators.operatorframework.io.index.configs.v1=/configs +# Set other custom labels +LABEL "key1"="value1" +LABEL "key2"="value2" +`, + }, + + { + name: "Lite/Fail/EmptyBaseImage", + gen: GenerateDockerfile{ + IndexDir: "bar", + ExtraLabels: map[string]string{ + "key1": "value1", + "key2": "value2", + }, + Lite: true, + }, + expectedErr: "base image is unset", + }, + { + name: "Lite/Fail/EmptyFromDir", + gen: GenerateDockerfile{ + BaseImage: "foo", + ExtraLabels: map[string]string{ + "key1": "value1", + "key2": "value2", + }, + Lite: true, + }, + expectedErr: "index directory is unset", + }, + { + name: "Lite/Success/WithoutExtraLabels", + gen: GenerateDockerfile{ + BaseImage: "foo", + IndexDir: "bar", + Lite: true, + }, + expectedDockerfile: `# The builder image is expected to contain +# /bin/opm (with serve subcommand) +FROM foo as builder + +# Copy FBC root into image at /configs and pre-populate serve cache +ADD bar /configs +RUN ["/bin/opm", "serve", "/configs", "--cache-dir=/tmp/cache", "--cache-only"] + +FROM scratch + +COPY --from=builder /configs /configs +COPY --from=builder /tmp/cache /tmp/cache + +# Set FBC-specific label for the location of the FBC root directory +# in the image +LABEL operators.operatorframework.io.index.configs.v1=/configs +`, + }, + { + name: "Lite/Success/WithExtraLabels", + gen: GenerateDockerfile{ + BaseImage: "foo", + IndexDir: "bar", + ExtraLabels: map[string]string{ + "key1": "value1", + "key2": "value2", + }, + Lite: true, + }, + expectedDockerfile: `# The builder image is expected to contain +# /bin/opm (with serve subcommand) +FROM foo as builder + +# Copy FBC root into image at /configs and pre-populate serve cache +ADD bar /configs +RUN ["/bin/opm", "serve", "/configs", "--cache-dir=/tmp/cache", "--cache-only"] + +FROM scratch + +COPY --from=builder /configs /configs +COPY --from=builder /tmp/cache /tmp/cache + +# Set FBC-specific label for the location of the FBC root directory +# in the image +LABEL operators.operatorframework.io.index.configs.v1=/configs + # Set other custom labels LABEL "key1"="value1" LABEL "key2"="value2" diff --git a/cmd/opm/generate/cmd.go b/cmd/opm/generate/cmd.go index 7871a7f52..0e3c80df4 100644 --- a/cmd/opm/generate/cmd.go +++ b/cmd/opm/generate/cmd.go @@ -29,6 +29,7 @@ func newDockerfileCmd() *cobra.Command { var ( baseImage string extraLabelStrs []string + lite bool ) cmd := &cobra.Command{ Use: "dockerfile ", @@ -75,6 +76,7 @@ value of each duplicate key will be added to the generated Dockerfile. IndexDir: indexName, ExtraLabels: extraLabels, Writer: f, + Lite: lite, } if err := gen.Run(); err != nil { log.Fatal(err) @@ -83,6 +85,7 @@ value of each duplicate key will be added to the generated Dockerfile. }, } cmd.Flags().StringVarP(&baseImage, "binary-image", "i", containertools.DefaultBinarySourceImage, "Image in which to build catalog.") + cmd.Flags().BoolVarP(&lite, "lite", "t", false, "Generate a smaller, binary-less Dockerfile.") cmd.Flags().StringSliceVarP(&extraLabelStrs, "extra-labels", "l", []string{}, "Extra labels to include in the generated Dockerfile. Labels should be of the form 'key=value'.") return cmd }