Skip to content

Commit

Permalink
[werft]: pull provider secret into build and configure installer
Browse files Browse the repository at this point in the history
  • Loading branch information
Simon Emms committed Dec 14, 2021
1 parent 3e561c6 commit e92b27e
Showing 1 changed file with 54 additions and 42 deletions.
96 changes: 54 additions & 42 deletions .werft/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export async function build(context, version) {
const retag = ("with-retag" in buildConfig) ? "" : "--dont-retag";
const cleanSlateDeployment = mainBuild || ("with-clean-slate-deployment" in buildConfig);
const installEELicense = !("without-ee-license" in buildConfig);
const withPayment= "with-payment" in buildConfig;
const withPayment = "with-payment" in buildConfig;
const withObservability = "with-observability" in buildConfig;
const withHelm = "with-helm" in buildConfig;

Expand Down Expand Up @@ -238,7 +238,7 @@ export async function build(context, version) {
continue
}
let flag = file.substring(0, file.length - "-coverage.out".length);
exec(`codecov -N "${parent_commit}" --flags=${flag} --file "${coverageOutput}/${file}"`, {slice: "coverage"});
exec(`codecov -N "${parent_commit}" --flags=${flag} --file "${coverageOutput}/${file}"`, { slice: "coverage" });
}

werft.done('coverage');
Expand Down Expand Up @@ -285,8 +285,8 @@ export async function build(context, version) {

werft.phase(phases.PREDEPLOY, "Checking for existing installations...");
// the context namespace is not set at this point
const hasGitpodHelmInstall = exec(`helm status ${helmInstallName} -n ${deploymentConfig.namespace}`, {slice: "check for Helm install", dontCheckRc: true}).code === 0;
const hasGitpodInstallerInstall = exec(`kubectl get configmap gitpod-app -n ${deploymentConfig.namespace}`, {slice: "check for Installer install", dontCheckRc: true}).code === 0;
const hasGitpodHelmInstall = exec(`helm status ${helmInstallName} -n ${deploymentConfig.namespace}`, { slice: "check for Helm install", dontCheckRc: true }).code === 0;
const hasGitpodInstallerInstall = exec(`kubectl get configmap gitpod-app -n ${deploymentConfig.namespace}`, { slice: "check for Installer install", dontCheckRc: true }).code === 0;
werft.log("result of installation checks", `has Helm install: ${hasGitpodHelmInstall}, has Installer install: ${hasGitpodInstallerInstall}`);

if (withHelm) {
Expand Down Expand Up @@ -386,7 +386,7 @@ export async function deployToDevWithInstaller(deploymentConfig: DeploymentConfi
}

// add the image pull secret to the namespcae if it doesn't exist
const hasPullSecret = (exec(`kubectl get secret ${IMAGE_PULL_SECRET_NAME} -n ${namespace}`, {slice: installerSlices.IMAGE_PULL_SECRET, dontCheckRc: true, silent: true })).code === 0;
const hasPullSecret = (exec(`kubectl get secret ${IMAGE_PULL_SECRET_NAME} -n ${namespace}`, { slice: installerSlices.IMAGE_PULL_SECRET, dontCheckRc: true, silent: true })).code === 0;
if (!hasPullSecret) {
try {
werft.log(installerSlices.IMAGE_PULL_SECRET, "Adding the image pull secret to the namespace");
Expand All @@ -406,9 +406,9 @@ export async function deployToDevWithInstaller(deploymentConfig: DeploymentConfi
// download and init with the installer
try {
werft.log(installerSlices.INSTALLER_INIT, "Downloading installer and initializing config file");
exec(`docker run --entrypoint sh --rm eu.gcr.io/gitpod-core-dev/build/installer:${version} -c "cat /app/installer" > /tmp/installer`, {slice: installerSlices.INSTALLER_INIT});
exec(`chmod +x /tmp/installer`, {slice: installerSlices.INSTALLER_INIT});
exec(`/tmp/installer init > config.yaml`, {slice: installerSlices.INSTALLER_INIT});
exec(`docker run --entrypoint sh --rm eu.gcr.io/gitpod-core-dev/build/installer:${version} -c "cat /app/installer" > /tmp/installer`, { slice: installerSlices.INSTALLER_INIT });
exec(`chmod +x /tmp/installer`, { slice: installerSlices.INSTALLER_INIT });
exec(`/tmp/installer init > config.yaml`, { slice: installerSlices.INSTALLER_INIT });
werft.done(installerSlices.INSTALLER_INIT);
} catch (err) {
werft.fail(installerSlices.INSTALLER_INIT, err)
Expand All @@ -417,8 +417,8 @@ export async function deployToDevWithInstaller(deploymentConfig: DeploymentConfi
// prepare a proper config file
try {
werft.log(installerSlices.INSTALLER_RENDER, "Post process the base installer config file and render k8s manifests");
const PROJECT_NAME="gitpod-core-dev";
const CONTAINER_REGISTRY_URL=`eu.gcr.io/${PROJECT_NAME}/build/`;
const PROJECT_NAME = "gitpod-core-dev";
const CONTAINER_REGISTRY_URL = `eu.gcr.io/${PROJECT_NAME}/build/`;
const CONTAINERD_RUNTIME_DIR = "/var/lib/containerd/io.containerd.runtime.v2.task/k8s.io";

// get some values we need to customize the config and write them to file
Expand All @@ -431,47 +431,59 @@ export async function deployToDevWithInstaller(deploymentConfig: DeploymentConfi
exec(`yq m -i config.yaml ./workspaceSizing`, { slice: installerSlices.INSTALLER_RENDER });

// write some values inline
exec(`yq w -i config.yaml certificate.name ${PROXY_SECRET_NAME}`, {slice: installerSlices.INSTALLER_RENDER});
exec(`yq w -i config.yaml containerRegistry.inCluster false`, {slice: installerSlices.INSTALLER_RENDER});
exec(`yq w -i config.yaml containerRegistry.external.url ${CONTAINER_REGISTRY_URL}`, {slice: installerSlices.INSTALLER_RENDER});
exec(`yq w -i config.yaml containerRegistry.external.certificate.kind secret`, {slice: installerSlices.INSTALLER_RENDER});
exec(`yq w -i config.yaml containerRegistry.external.certificate.name ${IMAGE_PULL_SECRET_NAME}`, {slice: installerSlices.INSTALLER_RENDER});
exec(`yq w -i config.yaml domain ${deploymentConfig.domain}`, {slice: installerSlices.INSTALLER_RENDER});
exec(`yq w -i config.yaml jaegerOperator.inCluster false`, {slice: installerSlices.INSTALLER_RENDER});
exec(`yq w -i config.yaml workspace.runtime.containerdRuntimeDir ${CONTAINERD_RUNTIME_DIR}`, {slice: installerSlices.INSTALLER_RENDER});
exec(`yq w -i config.yaml certificate.name ${PROXY_SECRET_NAME}`, { slice: installerSlices.INSTALLER_RENDER });
exec(`yq w -i config.yaml containerRegistry.inCluster false`, { slice: installerSlices.INSTALLER_RENDER });
exec(`yq w -i config.yaml containerRegistry.external.url ${CONTAINER_REGISTRY_URL}`, { slice: installerSlices.INSTALLER_RENDER });
exec(`yq w -i config.yaml containerRegistry.external.certificate.kind secret`, { slice: installerSlices.INSTALLER_RENDER });
exec(`yq w -i config.yaml containerRegistry.external.certificate.name ${IMAGE_PULL_SECRET_NAME}`, { slice: installerSlices.INSTALLER_RENDER });
exec(`yq w -i config.yaml domain ${deploymentConfig.domain}`, { slice: installerSlices.INSTALLER_RENDER });
exec(`yq w -i config.yaml jaegerOperator.inCluster false`, { slice: installerSlices.INSTALLER_RENDER });
exec(`yq w -i config.yaml workspace.runtime.containerdRuntimeDir ${CONTAINERD_RUNTIME_DIR}`, { slice: installerSlices.INSTALLER_RENDER });

if ((deploymentConfig.analytics || "").startsWith("segment|")) {
exec(`yq w -i config.yaml analytics.writer segment`, {slice: installerSlices.INSTALLER_RENDER});
exec(`yq w -i config.yaml analytics.segmentKey ${deploymentConfig.analytics!.substring("segment|".length)}`, {slice: installerSlices.INSTALLER_RENDER});
exec(`yq w -i config.yaml analytics.writer segment`, { slice: installerSlices.INSTALLER_RENDER });
exec(`yq w -i config.yaml analytics.segmentKey ${deploymentConfig.analytics!.substring("segment|".length)}`, { slice: installerSlices.INSTALLER_RENDER });
} else if (!!deploymentConfig.analytics) {
exec(`yq w -i config.yaml analytics.writer ${deploymentConfig.analytics!}`, {slice: installerSlices.INSTALLER_RENDER});
exec(`yq w -i config.yaml analytics.writer ${deploymentConfig.analytics!}`, { slice: installerSlices.INSTALLER_RENDER });
}

if (withObservability) {
// TODO: there's likely more to do...
const tracingEndpoint = exec(`yq r ./.werft/values.tracing.yaml tracing.endpoint`,{slice: installerSlices.INSTALLER_RENDER}).stdout.trim();
exec(`yq w -i config.yaml observability.tracing.endpoint ${tracingEndpoint}`, {slice: installerSlices.INSTALLER_RENDER});
const tracingEndpoint = exec(`yq r ./.werft/values.tracing.yaml tracing.endpoint`, { slice: installerSlices.INSTALLER_RENDER }).stdout.trim();
exec(`yq w -i config.yaml observability.tracing.endpoint ${tracingEndpoint}`, { slice: installerSlices.INSTALLER_RENDER });
}

// TODO: Remove this after #6867 is done
werft.log("authProviders", "copy authProviders")
werft.log("authProviders", "copy authProviders from secret")
try {
exec(`kubectl get secret preview-envs-authproviders --namespace=keys -o yaml \
| yq r - data.authProviders \
exec(`for row in $(kubectl get secret preview-envs-authproviders --namespace=keys -o jsonpath="{.data.authProviders}" \
| base64 -d -w 0 \
> ./authProviders`, { silent: true });
exec(`yq merge --inplace config.yaml ./authProviders`, { silent: true })
| yq r - authProviders -j \
| jq -r 'to_entries | .[] | @base64'); do
key=$(echo $row | base64 -d | jq -r '.key')
providerId=$(echo $row | base64 -d | jq -r '.value.id')
data=$(echo $row | base64 -d | yq r - value --prettyPrint | )
yq w -i ./config.yaml authProviders[$key].kind "secret"
yq w -i ./config.yaml authProviders[$key].name "$providerId"
kubectl create secret generic "$providerId" \
--namespace ${namespace} \
--from-literal=provider="$data" \
--dry-run=client -o yaml |
kubectl replace --force -f -
done`, { silent: true })

werft.done('authProviders');
} catch (err) {
werft.fail('authProviders', err);
}

// validate the config and cluster
exec(`/tmp/installer validate config -c config.yaml`, {slice: installerSlices.INSTALLER_RENDER});
exec(`/tmp/installer validate config -c config.yaml`, { slice: installerSlices.INSTALLER_RENDER });

// TODO: Ignore cluster validation errors (our k8s version is too old in core-dev)
// consider removing '|| true' after we've left core-dev and are using K3s for preview envs
exec(`/tmp/installer validate cluster -c config.yaml || true`, {slice: installerSlices.INSTALLER_RENDER});
exec(`/tmp/installer validate cluster -c config.yaml || true`, { slice: installerSlices.INSTALLER_RENDER });

// render the k8s manifest
exec(`/tmp/installer render --namespace ${deploymentConfig.namespace} --config config.yaml > k8s.yaml`, { silent: true });
Expand All @@ -486,22 +498,22 @@ export async function deployToDevWithInstaller(deploymentConfig: DeploymentConfi

if (deploymentConfig.installEELicense) {
werft.log(installerSlices.INSTALLER_POST_PROCESSING, "Adding the EE License...");
exec(`cp /mnt/secrets/gpsh-coredev/license /tmp/license`, {slice: installerSlices.INSTALLER_POST_PROCESSING});
exec(`cp /mnt/secrets/gpsh-coredev/license /tmp/license`, { slice: installerSlices.INSTALLER_POST_PROCESSING });
// post-process.sh looks for /tmp/license, and if it exists, adds it to the configmap
} else {
exec(`touch /tmp/license`, {slice: installerSlices.INSTALLER_POST_PROCESSING});
exec(`touch /tmp/license`, { slice: installerSlices.INSTALLER_POST_PROCESSING });
}
exec(`touch /tmp/defaultFeatureFlags`, {slice: installerSlices.INSTALLER_POST_PROCESSING});
exec(`touch /tmp/defaultFeatureFlags`, { slice: installerSlices.INSTALLER_POST_PROCESSING });
if (workspaceFeatureFlags && workspaceFeatureFlags.length > 0) {
werft.log(installerSlices.INSTALLER_POST_PROCESSING, "Adding feature flags...");
workspaceFeatureFlags.forEach(featureFlag => {
exec(`echo \'"${featureFlag}"\' >> /tmp/defaultFeatureFlags`, {slice: installerSlices.INSTALLER_POST_PROCESSING});
exec(`echo \'"${featureFlag}"\' >> /tmp/defaultFeatureFlags`, { slice: installerSlices.INSTALLER_POST_PROCESSING });
})
// post-process.sh looks for /tmp/defaultFeatureFlags
// each "flag" string gets added to the configmap
}

exec(`./.werft/post-process.sh ${registryNodePortMeta} ${wsdaemonPortMeta} ${nodepoolIndex} ${deploymentConfig.destname}`, {slice: installerSlices.INSTALLER_POST_PROCESSING});
exec(`./.werft/post-process.sh ${registryNodePortMeta} ${wsdaemonPortMeta} ${nodepoolIndex} ${deploymentConfig.destname}`, { slice: installerSlices.INSTALLER_POST_PROCESSING });
werft.done(installerSlices.INSTALLER_POST_PROCESSING);
} catch (err) {
werft.fail(installerSlices.INSTALLER_POST_PROCESSING, err);
Expand All @@ -510,7 +522,7 @@ export async function deployToDevWithInstaller(deploymentConfig: DeploymentConfi
werft.log(installerSlices.APPLY_INSTALL_MANIFESTS, "Installing preview environment.");
try {
// errors could result in outputing a secret to the werft log when kubernetes patches existing objects...
exec(`kubectl apply -f k8s.yaml`,{ slice: installerSlices.APPLY_INSTALL_MANIFESTS, silent: true });
exec(`kubectl apply -f k8s.yaml`, { slice: installerSlices.APPLY_INSTALL_MANIFESTS, silent: true });
werft.done(installerSlices.APPLY_INSTALL_MANIFESTS);
} catch (err) {
werft.fail(installerSlices.APPLY_INSTALL_MANIFESTS, err);
Expand All @@ -521,7 +533,7 @@ export async function deployToDevWithInstaller(deploymentConfig: DeploymentConfi

try {
werft.log(installerSlices.DEPLOYMENT_WAITING, "Server not ready. Let the waiting...commence!");
exec(`kubectl rollout status deployment/server --timeout=5m`,{ slice: installerSlices.DEPLOYMENT_WAITING });
exec(`kubectl rollout status deployment/server --timeout=5m`, { slice: installerSlices.DEPLOYMENT_WAITING });
werft.done(installerSlices.DEPLOYMENT_WAITING);
} catch (err) {
werft.fail(installerSlices.DEPLOYMENT_WAITING, err);
Expand Down Expand Up @@ -566,7 +578,7 @@ export async function deployToDevWithInstaller(deploymentConfig: DeploymentConfi
// cleanup non-namespace objects
werft.log(installerSlices.CLEAN_ENV_STATE, "removing old unnamespaced objects - this might take a while");
try {
await deleteNonNamespaceObjects(namespace, destname, { ...shellOpts, slice: installerSlices.CLEAN_ENV_STATE });
await deleteNonNamespaceObjects(namespace, destname, { ...shellOpts, slice: installerSlices.CLEAN_ENV_STATE });
werft.done(installerSlices.CLEAN_ENV_STATE);
} catch (err) {
werft.fail(installerSlices.CLEAN_ENV_STATE, err);
Expand Down Expand Up @@ -662,8 +674,8 @@ export async function deployToDevWithHelm(deploymentConfig: DeploymentConfig, wo
exec(`werft log result -d "Monitoring Satellite - Grafana" -c github-check-Grafana url https://grafana-${monitoringDomain}/dashboards`);
exec(`werft log result -d "Monitoring Satellite - Prometheus" -c github-check-Prometheus url https://prometheus-${monitoringDomain}/graph`);
} else {
exec(`echo '"with-observability" annotation not set, skipping...'`, {slice: `observability`})
exec(`echo 'To deploy monitoring-satellite, please add "/werft with-observability" to your PR description.'`, {slice: `observability`})
exec(`echo '"with-observability" annotation not set, skipping...'`, { slice: `observability` })
exec(`echo 'To deploy monitoring-satellite, please add "/werft with-observability" to your PR description.'`, { slice: `observability` })
}
werft.done('observability');

Expand Down Expand Up @@ -902,7 +914,7 @@ async function publishHelmChart(imageRepoBase: string, version: string) {
function getNodePoolIndex(namespace: string): number {
const nodeAffinityValues = getNodeAffinities();

return parseInt(createHash('sha256').update(namespace).digest('hex').substring(0,5),16) % nodeAffinityValues.length;
return parseInt(createHash('sha256').update(namespace).digest('hex').substring(0, 5), 16) % nodeAffinityValues.length;
}

function getNodeAffinities(): string[] {
Expand Down

0 comments on commit e92b27e

Please sign in to comment.