forked from shipwright-io/build
-
Notifications
You must be signed in to change notification settings - Fork 1
/
buildstrategy_buildkit_cr.yaml
174 lines (161 loc) · 7.42 KB
/
buildstrategy_buildkit_cr.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
---
apiVersion: shipwright.io/v1beta1
kind: ClusterBuildStrategy
metadata:
name: buildkit
annotations:
# See https://github.com/moby/buildkit/blob/master/docs/rootless.md#about---oci-worker-no-process-sandbox for more information
container.apparmor.security.beta.kubernetes.io/step-build-and-push: unconfined
# The usage of seccomp annotation will be deprecate in k8s v1.22.0, see
# https://kubernetes.io/docs/tutorials/clusters/seccomp/#create-a-pod-with-a-seccomp-profile-for-syscall-auditing for more information
container.seccomp.security.alpha.kubernetes.io/step-build-and-push: unconfined
spec:
parameters:
- name: build-args
description: "The values for the ARGs in the Dockerfile. Values must be in the format KEY=VALUE."
type: array
defaults: []
- name: cache
description: "Configure BuildKit's cache usage. Allowed values are 'disabled' and 'registry'. The default is 'registry'."
type: string
default: registry
- name: platforms
description: "Build the image for different platforms. By default, the image is built for the platform used by the FROM image. If that is present for multiple platforms, then it is built for the environment's platform."
type: array
defaults: []
- name: secrets
description: "The secrets to pass to the build. Values must be in the format ID=FILE_CONTENT."
type: array
defaults: []
- name: dockerfile
description: The path to the Dockerfile to be used for building the image.
type: string
default: "Dockerfile"
steps:
- name: build-and-push
image: moby/buildkit:nightly-rootless
imagePullPolicy: Always
securityContext:
allowPrivilegeEscalation: true
capabilities:
add:
- SETGID
- SETUID
workingDir: $(params.shp-source-root)
env:
- name: DOCKER_CONFIG
value: /tekton/home/.docker
- name: HOME
value: /tekton/home
# See https://github.com/moby/buildkit/blob/master/docs/rootless.md#about---oci-worker-no-process-sandbox for more information
- name: BUILDKITD_FLAGS
value: --oci-worker-no-process-sandbox
- name: PARAM_SOURCE_CONTEXT
value: $(params.shp-source-context)
- name: PARAM_DOCKERFILE
value: $(params.dockerfile)
- name: PARAM_OUTPUT_DIRECTORY
value: $(params.shp-output-directory)
- name: PARAM_OUTPUT_IMAGE
value: $(params.shp-output-image)
- name: PARAM_OUTPUT_INSECURE
value: $(params.shp-output-insecure)
- name: PARAM_CACHE
value: $(params.cache)
command:
- /bin/ash
args:
- -c
- |
set -euo pipefail
# Verify the existence of the context directory
if [ ! -d "${PARAM_SOURCE_CONTEXT}" ]; then
echo -e "The context directory '${PARAM_SOURCE_CONTEXT}' does not exist."
echo -n "ContextDirNotFound" > '$(results.shp-error-reason.path)'
echo -n "The context directory '${PARAM_SOURCE_CONTEXT}' does not exist." > '$(results.shp-error-message.path)'
exit 1
fi
# Prepare the file arguments
DOCKERFILE_PATH="${PARAM_SOURCE_CONTEXT}/${PARAM_DOCKERFILE}"
DOCKERFILE_DIR="$(dirname "${DOCKERFILE_PATH}")"
DOCKERFILE_NAME="$(basename "${DOCKERFILE_PATH}")"
# Verify the existence of the Dockerfile
if [ ! -f "${DOCKERFILE_PATH}" ]; then
echo -e "The Dockerfile '${DOCKERFILE_PATH}' does not exist."
echo -n "DockerfileNotFound" > '$(results.shp-error-reason.path)'
echo -n "The Dockerfile '${DOCKERFILE_PATH}' does not exist." > '$(results.shp-error-message.path)'
exit 1
fi
# We only have ash here and therefore no bash arrays to help add dynamic arguments (the build-args) to the build command.
echo "#!/bin/ash" > /tmp/run.sh
echo "set -euo pipefail" >> /tmp/run.sh
echo "buildctl-daemonless.sh \\" >> /tmp/run.sh
echo "build \\" >> /tmp/run.sh
echo "--frontend=dockerfile.v0 \\" >> /tmp/run.sh
echo "--opt=filename=\"${DOCKERFILE_NAME}\" \\" >> /tmp/run.sh
echo "--local=context=\"${PARAM_SOURCE_CONTEXT}\" \\" >> /tmp/run.sh
echo "--local=dockerfile=\"${DOCKERFILE_DIR}\" \\" >> /tmp/run.sh
echo "--output=type=oci,tar=false,dest=\"${PARAM_OUTPUT_DIRECTORY}\" \\" >> /tmp/run.sh
if [ "${PARAM_CACHE}" == "registry" ]; then
echo "--export-cache=type=inline \\" >> /tmp/run.sh
echo "--import-cache=type=registry,ref=\"${PARAM_OUTPUT_IMAGE}\",registry.insecure=\"${PARAM_OUTPUT_INSECURE}\" \\" >> /tmp/run.sh
elif [ "${PARAM_CACHE}" == "disabled" ]; then
echo "--no-cache \\" >> /tmp/run.sh
else
echo -e "An invalid value for the parameter 'cache' has been provided: '${PARAM_CACHE}'. Allowed values are 'disabled' and 'registry'."
echo -n "InvalidParameterValue" > '$(results.shp-error-reason.path)'
echo -n "An invalid value for the parameter 'cache' has been provided: '${PARAM_CACHE}'. Allowed values are 'disabled' and 'registry'." > '$(results.shp-error-message.path)'
exit 1
fi
stage=""
platforms=""
for a in "$@"
do
if [ "${a}" == "--build-args" ]; then
stage=build-args
elif [ "${a}" == "--platforms" ]; then
stage=platforms
elif [ "${a}" == "--secrets" ]; then
stage=secrets
elif [ "${stage}" == "build-args" ]; then
echo "--opt=\"build-arg:${a}\" \\" >> /tmp/run.sh
elif [ "${stage}" == "platforms" ]; then
if [ "${platforms}" == "" ]; then
platforms="${a}"
else
platforms="${platforms},${a}"
fi
elif [ "${stage}" == "secrets" ]; then
# Split ID=FILE_CONTENT into variables id and data
# using head because the data could be multiline
id="$(echo "${a}" | head -1 | sed 's/=.*//')"
# This is hacky, we remove the suffix ${id}= from all lines of the data.
# If the data would be multiple lines and a line would start with ${id}=
# then we would remove it. We could force users to give us the secret
# base64 encoded. But ultimately, the best solution might be if the user
# mounts the secret and just gives us the path here.
data="$(echo "${a}" | sed "s/^${id}=//")"
# Write the secret data into a temporary file, once we have volume support
# in the build strategy, we should use a memory based emptyDir for this.
echo -n "${data}" > "/tmp/secret_${id}"
# Add the secret argument
echo "--secret id=${id},src="/tmp/secret_${id}" \\" >> /tmp/run.sh
fi
done
if [ "${platforms}" != "" ]; then
echo "--opt=\"platform=${platforms}\" \\" >> /tmp/run.sh
fi
echo "--progress=plain" >> /tmp/run.sh
chmod +x /tmp/run.sh
/tmp/run.sh
# That's the separator between the shell script and its args
- --
- --build-args
- $(params.build-args[*])
- --platforms
- $(params.platforms[*])
- --secrets
- $(params.secrets[*])
securityContext:
runAsUser: 1000
runAsGroup: 1000