Skip to content

Commit 7461ace

Browse files
author
Simon Emms
committed
[installer]: move the kots install script into a bash file in Installer
1 parent 30b274a commit 7461ace

9 files changed

+443
-339
lines changed

install/installer/BUILD.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ packages:
1212
- "pkg/components/**/*.key"
1313
- "pkg/components/**/*.pem"
1414
- "pkg/components/**/*.sql"
15+
- "scripts/*.sh"
1516
- "third_party/**/*"
1617
deps:
1718
- components/blobserve:lib
@@ -51,6 +52,8 @@ packages:
5152
- ["objcopy", "--add-section", "versionManifest=components--all-docker/versions.yaml", "install-installer--raw-app/installer", "installer"]
5253
- name: docker
5354
type: docker
55+
srcs:
56+
- "scripts/*.sh"
5457
deps:
5558
- :app
5659
argdeps:

install/installer/leeway.Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
FROM alpine:3.16
66
COPY --from=alpine/helm:3.8.0 /usr/bin/helm /usr/bin/helm
77
COPY install-installer--app/installer install-installer--app/provenance-bundle.jsonl /app/
8+
COPY scripts/*.sh /app/scripts/
89
RUN apk add --no-cache curl jq openssh-keygen yq \
910
&& curl -L "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" -o /usr/local/bin/kubectl \
1011
&& chmod +x /usr/local/bin/kubectl
+345
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,345 @@
1+
#!/bin/sh
2+
# Copyright (c) 2022 Gitpod GmbH. All rights reserved.
3+
# Licensed under the MIT License. See License-MIT.txt in the project root for license information.
4+
5+
# shellcheck disable=SC2050,SC2153
6+
7+
set -e
8+
9+
echo "Gitpod: Killing any in-progress installations"
10+
11+
kubectl delete jobs.batch -n "${NAMESPACE}" -l component="gitpod-installer,cursor!=${CURSOR}" --force --grace-period 0 || true
12+
kubectl delete pod -n "${NAMESPACE}" -l component="gitpod-installer,cursor!=${CURSOR}" --force --grace-period 0 || true
13+
14+
if [ "$(helm status -n "${NAMESPACE}" gitpod -o json | jq '.info.status == "deployed"')" = "false" ];
15+
then
16+
echo "Gitpod: Deployment in-progress - clearing"
17+
18+
VERSION="$(helm status -n "${NAMESPACE}" gitpod -o json | jq '.version')"
19+
if [ "${VERSION}" -le 1 ];
20+
then
21+
echo "Gitpod: Uninstall application"
22+
helm uninstall -n "${NAMESPACE}" gitpod --wait || true
23+
else
24+
echo "Gitpod: Rolling back application"
25+
helm rollback -n "${NAMESPACE}" gitpod --wait || true
26+
fi
27+
fi
28+
29+
echo "Gitpod: Create a Helm template directory"
30+
rm -Rf "${GITPOD_OBJECTS}"
31+
mkdir -p "${GITPOD_OBJECTS}/templates"
32+
cat <<EOF >> "${GITPOD_OBJECTS}/Chart.yaml"
33+
apiVersion: v2
34+
name: gitpod-kots
35+
description: Always ready-to-code
36+
version: "1.0.0"
37+
appVersion: "$(/app/installer version | yq e '.version' -)"
38+
EOF
39+
40+
echo "Gitpod: Generate the base Installer config"
41+
/app/installer init > "${CONFIG_FILE}"
42+
43+
echo "Gitpod: auto-detecting ShiftFS support on host machine"
44+
kubectl wait job -n "${NAMESPACE}" --for=condition=complete -l component=shiftfs-module-loader --timeout=30s || true
45+
ENABLE_SHIFTFS=$(kubectl get jobs.batch -n "${NAMESPACE}" -l component=shiftfs-module-loader -o jsonpath='{.items[0].status.succeeded}')
46+
47+
if [ "${ENABLE_SHIFTFS}" = "1" ]; then
48+
echo "Gitpod: enabling ShiftFS support"
49+
50+
yq e -i '.workspace.runtime.fsShiftMethod = "shiftfs"' "${CONFIG_FILE}"
51+
fi
52+
53+
echo "Gitpod: auto-detecting containerd location on host machine"
54+
if [ -d "/mnt/node0${CONTAINERD_DIR_K3S}" ]; then
55+
echo "Gitpod: containerd dir detected as k3s"
56+
57+
yq e -i ".workspace.runtime.containerdRuntimeDir = \"${CONTAINERD_DIR_K3S}\"" "${CONFIG_FILE}"
58+
elif [ -d "/mnt/node0${CONTAINERD_DIR_AL}" ]; then
59+
echo "Gitpod: containerd dir detected as ${CONTAINERD_DIR_AL}"
60+
61+
yq e -i ".workspace.runtime.containerdRuntimeDir = \"${CONTAINERD_DIR_AL}\"" "${CONFIG_FILE}"
62+
fi
63+
64+
if [ -S "/mnt/node0${CONTAINERD_SOCKET_K3S}" ]; then
65+
echo "Gitpod: containerd socket detected as k3s"
66+
67+
yq e -i ".workspace.runtime.containerdSocket = \"${CONTAINERD_SOCKET_K3S}\"" "${CONFIG_FILE}"
68+
elif [ -S "/mnt/node0${CONTAINERD_SOCKET_AL}" ]; then
69+
echo "Gitpod: containerd socket detected as ${CONTAINERD_SOCKET_AL}"
70+
71+
yq e -i ".workspace.runtime.containerdSocket = \"${CONTAINERD_SOCKET_AL}\"" "${CONFIG_FILE}"
72+
fi
73+
74+
echo "Gitpod: Inject the Replicated variables into the config"
75+
yq e -i ".domain = \"${DOMAIN}\"" "${CONFIG_FILE}"
76+
yq e -i '.license.kind = "secret"' "${CONFIG_FILE}"
77+
yq e -i '.license.name = "gitpod-license"' "${CONFIG_FILE}"
78+
79+
if [ "${OPEN_VSX_URL}" != "" ];
80+
then
81+
echo "Gitpod: Setting Open VSX Registry URL"
82+
yq e -i ".openVSX.url = \"${OPEN_VSX_URL}\"" "${CONFIG_FILE}"
83+
fi
84+
85+
if [ "${DB_INCLUSTER_ENABLED}" = "0" ] && [ "${DB_CLOUDSQL_INSTANCE}" != "" ];
86+
then
87+
echo "Gitpod: configuring CloudSQLProxy"
88+
89+
yq e -i ".database.inCluster = false" "${CONFIG_FILE}"
90+
yq e -i ".database.cloudSQL.instance = \"${DB_CLOUDSQL_INSTANCE}\"" "${CONFIG_FILE}"
91+
yq e -i ".database.cloudSQL.serviceAccount.kind = \"secret\"" "${CONFIG_FILE}"
92+
yq e -i ".database.cloudSQL.serviceAccount.name = \"cloudsql\"" "${CONFIG_FILE}"
93+
fi
94+
95+
if [ "${DB_INCLUSTER_ENABLED}" = "0" ] && [ "${DB_CLOUDSQL_INSTANCE}" = "" ];
96+
then
97+
echo "Gitpod: configuring external database"
98+
99+
yq e -i ".database.inCluster = false" "${CONFIG_FILE}"
100+
yq e -i ".database.external.certificate.kind = \"secret\"" "${CONFIG_FILE}"
101+
yq e -i ".database.external.certificate.name = \"database\"" "${CONFIG_FILE}"
102+
fi
103+
104+
if [ "${HAS_LOCAL_REGISTRY}" = "true" ];
105+
then
106+
echo "Gitpod: configuring mirrored container registry for airgapped installation"
107+
108+
yq e -i ".repository = \"${LOCAL_REGISTRY_ADDRESS}\"" "${CONFIG_FILE}"
109+
yq e -i ".imagePullSecrets[0].kind = \"secret\"" "${CONFIG_FILE}"
110+
yq e -i ".imagePullSecrets[0].name = \"${IMAGE_PULL_SECRET_NAME}\"" "${CONFIG_FILE}"
111+
yq e -i '.dropImageRepo = true' "${CONFIG_FILE}"
112+
113+
# Add the registry to the server allowlist - keep docker.io in case it's just using the mirrored registry functionality without being airgapped
114+
yq e -i ".containerRegistry.privateBaseImageAllowList += \"${LOCAL_REGISTRY_HOST}\"" "${CONFIG_FILE}"
115+
yq e -i ".containerRegistry.privateBaseImageAllowList += \"docker.io\"" "${CONFIG_FILE}"
116+
fi
117+
118+
if [ "${REG_DOCKER_CONFIG_ENABLED}" = "1" ];
119+
then
120+
echo "Gitpod: extracting servers from the custom registry authentication"
121+
122+
kubectl get secret \
123+
-n "${NAMESPACE}" \
124+
custom-registry-credentials \
125+
-o jsonpath="{.data.\.dockerconfigjson}" | base64 -d > /tmp/userconfig.json
126+
127+
# Add the registries to the server allowlist
128+
yq e -i ".containerRegistry.privateBaseImageAllowList += $(jq '.auths' /tmp/userconfig.json | jq -rc 'keys')" "${CONFIG_FILE}"
129+
yq e -i ".containerRegistry.privateBaseImageAllowList += \"docker.io\"" "${CONFIG_FILE}"
130+
fi
131+
132+
# Output the local registry secret - this is proxy.replicated.com if user hasn't set their own
133+
echo "${LOCAL_REGISTRY_IMAGE_PULL_SECRET}" | base64 -d > /tmp/kotsregistry.json
134+
135+
if [ "${REG_INCLUSTER_ENABLED}" = "0" ];
136+
then
137+
echo "Gitpod: configuring external container registry"
138+
139+
# Get the external-container-registry secret so we can merge the external registry and KOTS registry keys
140+
kubectl get secret external-container-registry \
141+
--namespace "${NAMESPACE}" \
142+
-o jsonpath='{.data.\.dockerconfigjson}' | base64 -d > /tmp/gitpodregistry.json
143+
144+
cat /tmp/kotsregistry.json /tmp/gitpodregistry.json | jq -s '.[0] * .[1]' - - > /tmp/container-registry-secret
145+
146+
echo "Gitpod: create the container-registry secret"
147+
kubectl create secret docker-registry container-registry \
148+
--namespace "${NAMESPACE}" \
149+
--from-file=.dockerconfigjson=/tmp/container-registry-secret \
150+
-o yaml --dry-run=client > "${GITPOD_OBJECTS}/templates/gitpod.yaml"
151+
152+
yq e -i ".containerRegistry.inCluster = false" "${CONFIG_FILE}"
153+
yq e -i ".containerRegistry.external.url = \"${REG_URL}\"" "${CONFIG_FILE}"
154+
yq e -i ".containerRegistry.external.certificate.kind = \"secret\"" "${CONFIG_FILE}"
155+
yq e -i ".containerRegistry.external.certificate.name = \"container-registry\"" "${CONFIG_FILE}"
156+
else
157+
if [ "${REG_INCLUSTER_STORAGE}" = "s3" ];
158+
then
159+
echo "Gitpod: configuring container registry S3 backend"
160+
161+
yq e -i ".containerRegistry.s3storage.region = \"${REG_INCLUSTER_STORAGE_S3_REGION}\"" "${CONFIG_FILE}"
162+
yq e -i ".containerRegistry.s3storage.endpoint = \"${REG_INCLUSTER_STORAGE_S3_ENDPOINT}\"" "${CONFIG_FILE}"
163+
yq e -i ".containerRegistry.s3storage.bucket = \"${REG_INCLUSTER_STORAGE_S3_BUCKETNAME}\"" "${CONFIG_FILE}"
164+
yq e -i ".containerRegistry.s3storage.certificate.kind = \"secret\"" "${CONFIG_FILE}"
165+
yq e -i ".containerRegistry.s3storage.certificate.name = \"container-registry-s3-backend\"" "${CONFIG_FILE}"
166+
fi
167+
fi
168+
169+
if [ "${STORE_PROVIDER}" != "incluster" ];
170+
then
171+
echo "Gitpod: configuring the storage"
172+
173+
yq e -i ".metadata.region = \"${STORE_REGION}\"" "${CONFIG_FILE}"
174+
yq e -i ".objectStorage.inCluster = false" "${CONFIG_FILE}"
175+
176+
if [ "${STORE_PROVIDER}" = "azure" ];
177+
then
178+
echo "Gitpod: configuring storage for Azure"
179+
180+
yq e -i ".objectStorage.azure.credentials.kind = \"secret\"" "${CONFIG_FILE}"
181+
yq e -i ".objectStorage.azure.credentials.name = \"storage-azure\"" "${CONFIG_FILE}"
182+
fi
183+
184+
if [ "${STORE_PROVIDER}" = "gcp" ];
185+
then
186+
echo "Gitpod: configuring storage for GCP"
187+
188+
yq e -i ".objectStorage.cloudStorage.project = \"${STORE_GCP_PROJECT}\"" "${CONFIG_FILE}"
189+
yq e -i ".objectStorage.cloudStorage.serviceAccount.kind = \"secret\"" "${CONFIG_FILE}"
190+
yq e -i ".objectStorage.cloudStorage.serviceAccount.name = \"storage-gcp\"" "${CONFIG_FILE}"
191+
fi
192+
193+
if [ "${STORE_PROVIDER}" = "s3" ];
194+
then
195+
echo "Gitpod: configuring storage for S3"
196+
197+
yq e -i ".objectStorage.s3.endpoint = \"${STORE_S3_ENDPOINT}\"" "${CONFIG_FILE}"
198+
yq e -i ".objectStorage.s3.bucket = \"${STORE_S3_BUCKET}\"" "${CONFIG_FILE}"
199+
yq e -i ".objectStorage.s3.credentials.kind = \"secret\"" "${CONFIG_FILE}"
200+
yq e -i ".objectStorage.s3.credentials.name = \"storage-s3\"" "${CONFIG_FILE}"
201+
fi
202+
fi
203+
204+
if [ "${SSH_GATEWAY}" = "1" ];
205+
then
206+
echo "Gitpod: Generate SSH host key"
207+
ssh-keygen -t rsa -q -N "" -f host.key
208+
kubectl create secret generic ssh-gateway-host-key --from-file=host.key -n "${NAMESPACE}" || echo "SSH Gateway Host Key secret has not been created. Does it exist already?"
209+
yq e -i '.sshGatewayHostKey.kind = "secret"' "${CONFIG_FILE}"
210+
yq e -i '.sshGatewayHostKey.name = "ssh-gateway-host-key"' "${CONFIG_FILE}"
211+
fi
212+
213+
if [ "${TLS_SELF_SIGNED_ENABLED}" = "1" ];
214+
then
215+
echo "Gitpod: Generating a self-signed certificate with the internal CA"
216+
yq e -i '.customCACert.kind = "secret"' "${CONFIG_FILE}"
217+
yq e -i '.customCACert.name = "ca-issuer-ca"' "${CONFIG_FILE}"
218+
elif [ "${TLS_SELF_SIGNED_ENABLED}" = "0" ] && [ "${CERT_MANAGER_ENABLED}" = "0" ] && [ "${TLS_CUSTOM_CA_CRT_ENABLED}" = "true" ];
219+
then
220+
echo "Gitpod: Setting CA to be used for certificate"
221+
yq e -i '.customCACert.kind = "secret"' "${CONFIG_FILE}"
222+
yq e -i '.customCACert.name = "ca-certificate"' "${CONFIG_FILE}"
223+
fi
224+
225+
if [ "${USER_MANAGEMENT_BLOCK_ENABLED}" = "1" ];
226+
then
227+
echo "Gitpod: Adding blockNewUsers to config"
228+
yq e -i '.blockNewUsers.enabled = true' "${CONFIG_FILE}"
229+
230+
for domain in ${USER_MANAGEMENT_BLOCK_PASSLIST}
231+
do
232+
echo "Gitpod: Adding domain \"${domain}\" to blockNewUsers config"
233+
yq e -i ".blockNewUsers.passlist += \"${domain}\"" "${CONFIG_FILE}"
234+
done
235+
fi
236+
237+
if [ "${ADVANCED_MODE_ENABLED}" = "1" ];
238+
then
239+
echo "Gitpod: Applying advanced configuration"
240+
241+
if [ "${COMPONENT_PROXY_SERVICE_SERVICETYPE}" != "" ];
242+
then
243+
# Empty string defaults to LoadBalancer. This maintains backwards compatibility with the deprecated experimental value
244+
echo "Gitpod: Applying Proxy service type"
245+
yq e -i ".components.proxy.service.serviceType = \"${COMPONENT_PROXY_SERVICE_SERVICETYPE}\"" "${CONFIG_FILE}"
246+
fi
247+
248+
if [ -s "${CUSTOMIZATION_PATCH_FILE}" ];
249+
then
250+
CUSTOMIZATION="$(base64 "${CUSTOMIZATION_PATCH_FILE}" -w 0)"
251+
echo "Gitpod: Applying customization patch ${CUSTOMIZATION}"
252+
253+
# Apply the customization property - if something else is set, this will be ignored
254+
yq e -i ".customization = $(echo "${CUSTOMIZATION}" | base64 -d | yq e -o json '.customization' - | jq -rc) // []" "${CONFIG_FILE}"
255+
fi
256+
else
257+
echo "Gitpod: No advanced configuration applied"
258+
fi
259+
260+
echo "Gitpod: Update platform telemetry value"
261+
yq eval-all --inplace ".experimental.telemetry.data.platform = \"${DISTRIBUTION}\"" "${CONFIG_FILE}"
262+
263+
echo "Gitpod: Patch Gitpod config"
264+
base64 -d "${CONFIG_PATCH_FILE}" > /tmp/patch.yaml
265+
config_patch=$(cat /tmp/patch.yaml)
266+
echo "Gitpod: ${CONFIG_PATCH_FILE}=${config_patch}"
267+
yq eval-all --inplace 'select(fileIndex == 0) * select(fileIndex == 1)' "${CONFIG_FILE}" /tmp/patch.yaml
268+
269+
echo "Gitpod: Generate the Kubernetes objects"
270+
config=$(cat "${CONFIG_FILE}")
271+
echo "Gitpod: ${CONFIG_FILE}=${config}"
272+
273+
echo "Gitpod: render Kubernetes manifests"
274+
/app/installer render -c "${CONFIG_FILE}" --namespace "${NAMESPACE}" --use-experimental-config >> "${GITPOD_OBJECTS}/templates/gitpod.yaml"
275+
276+
if [ "${REG_INCLUSTER_ENABLED}" = "1" ];
277+
then
278+
echo "Gitpod: Add the local registry secret to the in-cluster registry secret"
279+
280+
# Get the in-cluster registry secret
281+
yq eval-all '(select(.kind == "Secret" and .metadata.name == "builtin-registry-auth") | .data.".dockerconfigjson")' \
282+
"${GITPOD_OBJECTS}/templates/gitpod.yaml" \
283+
| base64 -d \
284+
> /tmp/gitpodregistry.json
285+
286+
REGISTRY_SECRET="$(cat /tmp/kotsregistry.json /tmp/gitpodregistry.json | jq -s '.[0] * .[1]' - - | base64 -w 0)"
287+
export REGISTRY_SECRET
288+
289+
echo "Gitpod: update the in-cluster registry secret"
290+
yq eval-all --inplace '(select(.kind == "Secret" and .metadata.name == "builtin-registry-auth") | .data.".dockerconfigjson") |= env(REGISTRY_SECRET)' \
291+
"${GITPOD_OBJECTS}/templates/gitpod.yaml"
292+
fi
293+
294+
if [ "${REG_DOCKER_CONFIG_ENABLED}" = "1" ];
295+
then
296+
# Work out the registry secret to use
297+
if [ "${REG_INCLUSTER_ENABLED}" = "0" ];
298+
then
299+
export REGISTRY_SECRET_NAME="container-registry"
300+
else
301+
export REGISTRY_SECRET_NAME="builtin-registry-auth"
302+
fi
303+
304+
echo "Gitpod: Add given extra docker config JSON file to ${REGISTRY_SECRET_NAME}"
305+
yq eval-all '(select(.kind == "Secret" and .metadata.name == env(REGISTRY_SECRET_NAME)) | .data.".dockerconfigjson")' \
306+
"${GITPOD_OBJECTS}/templates/gitpod.yaml" \
307+
| base64 -d \
308+
> /tmp/currentconfig.json
309+
310+
echo "Gitpod: update the in-cluster registry secret"
311+
REGISTRY_SECRET="$(jq -s '.[0] * .[1]' /tmp/userconfig.json /tmp/currentconfig.json | base64 -w 0)"
312+
export REGISTRY_SECRET
313+
yq eval-all --inplace '(select(.kind == "Secret" and .metadata.name == env(REGISTRY_SECRET_NAME)) | .data.".dockerconfigjson") |= env(REGISTRY_SECRET)' \
314+
"${GITPOD_OBJECTS}/templates/gitpod.yaml"
315+
fi
316+
317+
echo "Gitpod: Escape any Golang template values"
318+
# shellcheck disable=SC2016
319+
sed -i -r 's/(.*\{\{.*)/{{`\1`}}/' "${GITPOD_OBJECTS}/templates/gitpod.yaml"
320+
321+
# If certificate secret already exists, set the timeout to 5m
322+
CERT_SECRET=$(kubectl get secrets -n "${NAMESPACE}" https-certificates -o jsonpath='{.metadata.name}' || echo '')
323+
HELM_TIMEOUT="5m"
324+
if [ "${CERT_SECRET}" = "" ]; then
325+
HELM_TIMEOUT="1h"
326+
fi
327+
328+
# The long timeout is to ensure the TLS cert is created (if required)
329+
echo "Gitpod: Apply the Kubernetes objects with timeout of ${HELM_TIMEOUT}"
330+
helm upgrade \
331+
--atomic \
332+
--cleanup-on-fail \
333+
--create-namespace \
334+
--install \
335+
--namespace="${NAMESPACE}" \
336+
--reset-values \
337+
--timeout "${HELM_TIMEOUT}" \
338+
--wait \
339+
gitpod \
340+
"${GITPOD_OBJECTS}"
341+
342+
echo "Gitpod: Restarting installation status job"
343+
kubectl delete pod -n "${NAMESPACE}" -l component=gitpod-installer-status || true
344+
345+
echo "Gitpod: Installer job finished - goodbye"

install/kots/manifests/gitpod-config-patch.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ metadata:
1010
component: gitpod-installer
1111
data:
1212
gitpod-config-patch.yaml: '{{repl if and (ConfigOptionEquals "advanced_mode_enabled" "1") (ConfigOptionNotEquals "config_patch" "") }}{{repl ConfigOption "config_patch" }}{{repl else }}{{repl printf "{}" | Base64Encode }}{{repl end }}'
13+
customization-patch.yaml: |
14+
repl{{ ConfigOptionData "customization_patch" | default "" | nindent 4 }}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Copyright (c) 2022 Gitpod GmbH. All rights reserved.
2+
# Licensed under the MIT License. See License-MIT.txt in the project root for license information.
3+
4+
apiVersion: v1
5+
kind: Secret
6+
metadata:
7+
name: custom-registry-credentials
8+
annotations:
9+
kots.io/when: '{{repl ConfigOptionEquals "reg_docker_config_enable" "1" }}'
10+
type: kubernetes.io/dockerconfigjson
11+
data:
12+
.dockerconfigjson: repl{{ ConfigOptionData "reg_docker_config" | Base64Encode | quote }}

install/kots/manifests/gitpod-installation-status.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ spec:
3030
containers:
3131
- name: installation-status
3232
# This will normally be the release tag
33-
image: "eu.gcr.io/gitpod-core-dev/build/installer:sje-conditional-psp-removal.4"
33+
image: "eu.gcr.io/gitpod-core-dev/build/installer:sje-move-kots-bash-script.28"
3434
command:
3535
- /bin/sh
3636
- -c

0 commit comments

Comments
 (0)