From f34f9838a5789465254e6ad94ec4237b21220d23 Mon Sep 17 00:00:00 2001 From: zhenyus Date: Mon, 17 Feb 2025 18:14:40 +0800 Subject: [PATCH] chore(git): code staging Signed-off-by: zhenyus --- .../ArgoApplicationVersionUpdater.groovy | 33 +++ .../com/freeleaps/devops/ImageBuilder.groovy | 12 + .../vars/executeFreeleapsPipeline.groovy | 18 +- magicleaps/alpha/ci/Jenkinsfile | 193 ++++--------- magicleaps/helm-pkg/magicleaps/.helmignore | 23 -- magicleaps/helm-pkg/magicleaps/Chart.yaml | 6 +- .../magicleaps/templates/_helpers.tpl | 107 ------- .../templates/backend/deployment.yaml | 98 +++++++ .../backend/magicleaps-backend-config.yaml | 22 ++ .../magicleaps/templates/backend/service.yaml | 26 ++ .../templates/deployments/backend.yaml | 87 ------ .../templates/deployments/frontend.yaml | 41 --- .../templates/frontend/certificate.yaml | 27 ++ .../templates/frontend/deployment.yaml | 98 +++++++ .../templates/frontend/ingress.yaml | 38 +++ .../frontend/magicleaps-frontend-config.yaml | 10 + .../templates/frontend/service.yaml | 26 ++ .../templates/ingresses/backend.yaml | 24 -- .../templates/ingresses/frontend.yaml | 24 -- .../magicleaps/templates/secrets/backend.yaml | 16 -- .../templates/services/backend.yaml | 17 -- .../templates/services/frontend.yaml | 17 -- .../helm-pkg/magicleaps/values.alpha.yaml | 182 +++++++----- magicleaps/helm-pkg/magicleaps/values.yaml | 178 +++++++----- .../api/v1alpha1/projectinitialize_types.go | 2 + .../freeleaps-gitops-initializer/cmd/main.go | 46 ++- .../gitops_v1alpha1_projectinitialize.yaml | 2 +- .../projectinitialize_controller.go | 33 ++- .../internal/helm/generator.go | 29 ++ .../internal/helm/generator_test.go | 261 ++++++++++++++++++ .../internal/helm/metadata-values.yaml | 109 -------- .../internal/jenkins/generator.go | 96 +++++++ .../jenkins/templates/Jenkinsfile.tpl | 28 ++ .../internal/repo/plugin.go | 16 +- .../internal/repo/plugins/azure/azure.go | 4 +- 35 files changed, 1180 insertions(+), 769 deletions(-) create mode 100644 first-class-pipeline/src/com/freeleaps/devops/ArgoApplicationVersionUpdater.groovy delete mode 100644 magicleaps/helm-pkg/magicleaps/.helmignore delete mode 100644 magicleaps/helm-pkg/magicleaps/templates/_helpers.tpl create mode 100644 magicleaps/helm-pkg/magicleaps/templates/backend/deployment.yaml create mode 100644 magicleaps/helm-pkg/magicleaps/templates/backend/magicleaps-backend-config.yaml create mode 100644 magicleaps/helm-pkg/magicleaps/templates/backend/service.yaml delete mode 100644 magicleaps/helm-pkg/magicleaps/templates/deployments/backend.yaml delete mode 100644 magicleaps/helm-pkg/magicleaps/templates/deployments/frontend.yaml create mode 100644 magicleaps/helm-pkg/magicleaps/templates/frontend/certificate.yaml create mode 100644 magicleaps/helm-pkg/magicleaps/templates/frontend/deployment.yaml create mode 100644 magicleaps/helm-pkg/magicleaps/templates/frontend/ingress.yaml create mode 100644 magicleaps/helm-pkg/magicleaps/templates/frontend/magicleaps-frontend-config.yaml create mode 100644 magicleaps/helm-pkg/magicleaps/templates/frontend/service.yaml delete mode 100644 magicleaps/helm-pkg/magicleaps/templates/ingresses/backend.yaml delete mode 100644 magicleaps/helm-pkg/magicleaps/templates/ingresses/frontend.yaml delete mode 100644 magicleaps/helm-pkg/magicleaps/templates/secrets/backend.yaml delete mode 100644 magicleaps/helm-pkg/magicleaps/templates/services/backend.yaml delete mode 100644 magicleaps/helm-pkg/magicleaps/templates/services/frontend.yaml create mode 100644 operators/freeleaps-gitops-initializer/internal/helm/generator_test.go delete mode 100644 operators/freeleaps-gitops-initializer/internal/helm/metadata-values.yaml create mode 100644 operators/freeleaps-gitops-initializer/internal/jenkins/generator.go create mode 100644 operators/freeleaps-gitops-initializer/internal/jenkins/templates/Jenkinsfile.tpl diff --git a/first-class-pipeline/src/com/freeleaps/devops/ArgoApplicationVersionUpdater.groovy b/first-class-pipeline/src/com/freeleaps/devops/ArgoApplicationVersionUpdater.groovy new file mode 100644 index 00000000..82a2a0d2 --- /dev/null +++ b/first-class-pipeline/src/com/freeleaps/devops/ArgoApplicationVersionUpdater.groovy @@ -0,0 +1,33 @@ +package com.freeleaps.devops + +class ArgoApplicationVersionUpdater { + def steps + def workspace + + ArgoApplicationVersionUpdater(steps) { + this.steps = steps + } + + def update(environmentSlug, component) { + steps.log.info("ArgoApplicationVersionUpdater", "[${environmentSlug}] Update Argo application image version for ${component.name}...") + def valuesFile = "${workspace}/../helm/${component.name}/values-${environmentSlug}.yaml" + def data = steps.readYaml (file: valuesFile) + data.${component.name}.image.registry = steps.env.BUILD_IMAGE_REGISTRY + data.${component.name}.image.repository = steps.env.BUILD_IMAGE_REPOSITORY + data.${component.name}.image.tag = steps.env.BUILD_IMAGE_VERSION + data.${component.name}.image.name = steps.env.BUILD_IMAGE_NAME + steps.writeFile file: valuesFile, data: data, overwrite: true + + steps.withCredentials([steps.usernamePassword(credentialsId: 'freeleaps-ops-credentials', passwordVariable: 'OPS_GIT_PASSWORD', usernameVariable: 'OPS_GIT_USERNAME')]) { + steps.sh """ + git config user.name "freeleaps-gitops-bot" + git config user.email "gitops@mathmast.com" + git remote add ci_origin https://${OPS_GIT_USERNAME}:${OPS_GIT_PASSWORD}@dev.azure.com/freeleaps/freeleaps-ops/_git/freeleaps-ops + git add ${valuesFile} + git commit -m "ci(bump): bump ${component.name} image version for ${environmentSlug} to ${steps.env.BUILD_IMAGE_VERSION}" + git push ci_origin HEAD:master + """ + steps.log.info("ArgoApplicationVersionUpdater", "[${environmentSlug}] ${component.name} image version bump to ${steps.env.BUILD_IMAGE_VERSION}") + } + } +} \ No newline at end of file diff --git a/first-class-pipeline/src/com/freeleaps/devops/ImageBuilder.groovy b/first-class-pipeline/src/com/freeleaps/devops/ImageBuilder.groovy index cb6415b6..68ab3482 100644 --- a/first-class-pipeline/src/com/freeleaps/devops/ImageBuilder.groovy +++ b/first-class-pipeline/src/com/freeleaps/devops/ImageBuilder.groovy @@ -114,6 +114,10 @@ class ImageBuilder { steps.log.info("ImageBuilder", "Set builder timeout to 10min...") steps.env.BUILDKIT_TIMEOUT = "1800s" steps.sh "docker buildx build --builder ${buildxBuilderName} --platform ${architectures.join(",")} -t ${registry}/${repository}/${name}:${version} -f ${dockerfile} --push ${contextRoot}" + steps.env.BUILD_IMAGE_REGISTRY = "${registry}" + steps.env.BUILD_IMAGE_REPO = "${repository}" + steps.env.BUILD_IMAGE_NAME = "${name}" + steps.env.BUILD_IMAGE_VERSION = "${version}" } else { architectures.each { architecture -> def archTag = architecture.split("/")[1] @@ -121,6 +125,10 @@ class ImageBuilder { steps.sh "docker build -t ${registry}/${repository}/${name}:${version}-${archTag} --platform ${architecture} -f ${dockerfile} ${contextRoot}" steps.sh "docker push ${registry}/${repository}/${name}:${version}-${archTag}" } + steps.env.BUILD_IMAGE_REGISTRY = "${registry}" + steps.env.BUILD_IMAGE_REPO = "${repository}" + steps.env.BUILD_IMAGE_NAME = "${name}" + steps.env.BUILD_IMAGE_VERSION = "${version}-linux-amd64" } } break @@ -131,6 +139,10 @@ class ImageBuilder { steps.log.info("ImageBuilder", "Building image ${registry}/${repository}/${name} with architectures: ${architectures}, tag sets to ${version}-${archTag}") steps.sh "/kaniko/executor --log-format text --context ${contextRoot} --dockerfile ${dockerfile} --destination ${registry}/${repository}/${name}:${version}-${archTag} --custom-platform ${architecture}" } + steps.env.BUILD_IMAGE_REGISTRY = "${registry}" + steps.env.BUILD_IMAGE_REPO = "${repository}" + steps.env.BUILD_IMAGE_NAME = "${name}" + steps.env.BUILD_IMAGE_VERSION = "${version}-linux-amd64" } break default: diff --git a/first-class-pipeline/vars/executeFreeleapsPipeline.groovy b/first-class-pipeline/vars/executeFreeleapsPipeline.groovy index bfca10a0..37a99ac4 100644 --- a/first-class-pipeline/vars/executeFreeleapsPipeline.groovy +++ b/first-class-pipeline/vars/executeFreeleapsPipeline.groovy @@ -378,8 +378,9 @@ def generateComponentStages(component, configurations) { } } }}, - // Image Building & Publishing - {stage("${component.name} :: Image Building & Publishing") { + { + // Image Building & Publishing + stage("${component.name} :: Image Building & Publishing") { podTemplate( label: "image-builder-${component.name}", containers: [ @@ -448,7 +449,18 @@ def generateComponentStages(component, configurations) { } } } - }} + }, + { + stage("${component.name} :: Argo Application Version Updating") { + script { + if (env.executeMode == "fully" || env.changedComponents.contains(component.name)) { + def argoApplicationVersionUpdater = new ArgoApplicationVersionUpdater(this) + argoApplicationVersionUpdater.update(configurations.environmentSlug, component) + } + } + } + }, + } ]) return { stages.each { stageClosure -> diff --git a/magicleaps/alpha/ci/Jenkinsfile b/magicleaps/alpha/ci/Jenkinsfile index 9618456f..d00b0b26 100644 --- a/magicleaps/alpha/ci/Jenkinsfile +++ b/magicleaps/alpha/ci/Jenkinsfile @@ -1,141 +1,56 @@ -def REGISTRY_URL = 'docker.io' -def REPO_NAME = 'zhenyus' -def IMAGE_NAME = 'magicleaps' -def APP_NAME = 'magicleaps' -def TAG_PREFIX = 'snapshot' -def DOCKER_REGISTRY_SECRET = 'kaniko-secret' +library 'first-class-pipeline' -pipeline { - agent any - - stages { - stage('Checkout') { - steps { - git credentialsId: 'freeleaps-azure-dev', url: 'https://freeleaps@dev.azure.com/freeleaps/magicleaps/_git/magicleaps' - } - } - - stage('Set Commit Hash') { - steps { - script { - def commitHash = sh(script: 'git rev-parse HEAD', returnStdout: true).trim() - def shortCommitHash = commitHash.take(7) - env.COMMIT_HASH = shortCommitHash - echo "Commit Hash: ${env.COMMIT_HASH}" - env.TRIGGERED_BRANCH = "${GIT_BRANCH}" - echo "Triggered Branch: ${env.TRIGGERED_BRANCH}" - } - } - } - - stage('Build Docker Images For Each Components') { - matrix { - axes { - axis { - name 'COMPONENT' - values 'backend', 'frontend' - } - axis { - name 'ARCH' - values 'linux/amd64' - } - } - - agent { - kubernetes { - defaultContainer 'kaniko' - yaml """ - apiVersion: v1 - kind: Pod - metadata: - labels: - freeleaps-devops-job: magicleaps-app-build - freeleaps-devops-app: magicleaps - spec: - containers: - - name: kaniko - image: gcr.io/kaniko-project/executor:debug - command: - - cat - tty: true - volumeMounts: - - name: kaniko-secret - mountPath: /kaniko/.docker/config.json - subPath: .dockerconfigjson - - name: workspace - mountPath: /workspace - volumes: - - name: kaniko-secret - secret: - secretName: kaniko-secret - - name: workspace - emptyDir: {} - """ - } - } - - stages { - stage('Image Building') { - steps { - script { - def dockerfilePath = "${COMPONENT}/Dockerfile" - def arch = "${ARCH}" - def archTag = arch.replace('/', '-') - def targetImage = "${REGISTRY_URL}/${REPO_NAME}/${IMAGE_NAME}:${COMPONENT}-${TAG_PREFIX}-${COMMIT_HASH}-${archTag}" - echo "Building Docker image ${targetImage}..." - - sh """ - /kaniko/executor \ - --dockerfile=${dockerfilePath} \ - --context=${COMPONENT} \ - --destination=${targetImage} \ - --custom-platform=${ARCH} \ - --skip-tls-verify=true \ - --ignore-path=/product_uuid - """ - } - } - } - } - } - } - - stage('Deploy with Argo CD') { - stages { - stage('Clone GitOps Manifests Repo') { - steps { - git credentialsId: 'freeleaps-azure-dev', url: 'https://freeleaps@dev.azure.com/freeleaps/freeleaps-ops/_git/freeleaps-ops' - } - } - - stage('Automate Update Application Image Tag') { - steps { - script { - def triggeredBranch = "${TRIGGERED_BRANCH}" - if (triggeredBranch == 'origin/master') { - echo "Triggered branch is master, deploying to alpha..." - def valuesFile = APP_NAME + '/helm-pkg/' + APP_NAME + '/values.alpha.yaml' - def data = readYaml (file: valuesFile) - data.backend.image.tag = "backend-${TAG_PREFIX}-${env.COMMIT_HASH}-linux-amd64" - data.frontend.image.tag = "frontend-${TAG_PREFIX}-${env.COMMIT_HASH}-linux-amd64" - writeYaml file: valuesFile, data: data, overwrite: true - // git push - withCredentials([string(credentialsId: 'freeleaps-azure-dev-token-only', variable: 'GIT_CREDENTIALS')]) { - sh """ - git config user.name "zhenyus" - git config user.email "zhenyus@mathmast.com" - git remote add ci_origin https://zhenyus:${GIT_CREDENTIALS}@dev.azure.com/freeleaps/freeleaps-ops/_git/freeleaps-ops - git add ${valuesFile} - git commit -m "ci(bot-auto-bump): bump ${APP_NAME} image tags for alpha to ${TAG_PREFIX}-${env.COMMIT_HASH}-linux-amd64" - git push ci_origin HEAD:master - """ - } - echo "Update ${APP_NAME} image tags for alpha to ${TAG_PREFIX}-${env.COMMIT_HASH}-linux-amd64." - } - } - } - } - } - } - } +executeFreeleapsPipeline { + serviceName = 'magicleaps' + environmentSlug = 'alpha' + serviceGitBranch = 'master' + serviceGitRepo = "https://freeleaps@dev.azure.com/freeleaps/magicleaps/_git/magicleaps" + serviceGitRepoType = 'monorepo' + serviceGitCredentialsId = 'magicleaps-azure-devops-credentials' + executeMode = 'fully' + commitMessageLintEnabled = true + components = [ + [ + name: 'frontend', + root: 'frontend', + language: 'javascript', + dependenciesManager: 'npm', + npmPackageJsonFile: 'package.json', + buildCacheEnabled: true, + buildAgentImage: 'node:lts', + buildCommand: 'npm run build', + buildArtifacts: ['dist'], + lintEnabled: false, + sastEnabled: false, + imageRegistry: 'docker.io', + imageRepository: 'sunzhenyucn', + imageName: 'magicleaps-frontend', + imageBuilder: 'dind', + dockerfilePath: 'Dockerfile', + imageBuildRoot: '.', + imageReleaseArchitectures: ['linux/amd64', 'linux/arm64/v8'], + registryCredentialsId: 'magicleaps-dockerhub-credentials', + semanticReleaseEnabled: true + ], + [ + name: 'backend', + root: 'backend', + language: 'python', + dependenciesManager: 'pip', + buildAgentImage: 'python:3.8-slim-buster', + buildArtifacts: ['.'], + buildCacheEnabled: true, + lintEnabled: false, + sastEnabled: false, + imageRegistry: 'docker.io', + imageRepository: 'sunzhenyucn', + imageName: 'magicleaps-backend', + imageBuilder: 'dind', + dockerfilePath: 'Dockerfile', + imageBuildRoot: '.', + imageReleaseArchitectures: ['linux/amd64', 'linux/arm64/v8'], + registryCredentialsId: 'magicleaps-dockerhub-credentials', + semanticReleaseEnabled: true + ] + ] } \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/.helmignore b/magicleaps/helm-pkg/magicleaps/.helmignore deleted file mode 100644 index 0e8a0eb3..00000000 --- a/magicleaps/helm-pkg/magicleaps/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/magicleaps/helm-pkg/magicleaps/Chart.yaml b/magicleaps/helm-pkg/magicleaps/Chart.yaml index 0d1bc580..3356264f 100644 --- a/magicleaps/helm-pkg/magicleaps/Chart.yaml +++ b/magicleaps/helm-pkg/magicleaps/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: magicleaps -description: A Helm chart for Magic Leaps application. +description: A Helm Chart of magicleaps, powered by Freeleaps. type: application -version: 0.1.0 -appVersion: "0.1.0" +version: 0.0.1 +appVersion: "0.0.1" \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/templates/_helpers.tpl b/magicleaps/helm-pkg/magicleaps/templates/_helpers.tpl deleted file mode 100644 index a15ed866..00000000 --- a/magicleaps/helm-pkg/magicleaps/templates/_helpers.tpl +++ /dev/null @@ -1,107 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "magicleaps.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Expand the name of the frontend. -*/}} -{{- define "magicleaps.frontend.name" -}} -{{- default .Values.frontend.name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Expand the name of the backend. -*/}} -{{- define "magicleaps.backend.name" -}} -{{- default .Values.backend.name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "magicleaps.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "magicleaps.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Backend labels -*/}} -{{- define "magicleaps.backend.labels" -}} -helm.sh/chart: {{ include "magicleaps.chart" . }} -{{ include "magicleaps.backend.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Backend Selector labels -*/}} -{{- define "magicleaps.backend.selectorLabels" -}} -app.kubernetes.io/name: {{ include "magicleaps.backend.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Frontend labels -*/}} -{{- define "magicleaps.frontend.labels" -}} -helm.sh/chart: {{ include "magicleaps.chart" . }} -{{ include "magicleaps.frontend.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Frontend Selector labels -*/}} -{{- define "magicleaps.frontend.selectorLabels" -}} -app.kubernetes.io/name: {{ include "magicleaps.frontend.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Return the appropriate apiVersion for deployment. -*/}} -{{- define "magicleaps.deployment.apiVersion" -}} -{{- if semverCompare "<1.9-0" .Capabilities.KubeVersion.GitVersion -}} -{{- print "extensions/v1beta1" -}} -{{- else if semverCompare "^1.9-0" .Capabilities.KubeVersion.GitVersion -}} -{{- print "apps/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Define the magicleaps.namespace template if set with forceNamespace or .Release.Namespace is set -*/}} -{{- define "magicleaps.namespace" -}} -{{- if .Values.forceNamespace -}} -{{ printf "namespace: %s" .Values.forceNamespace }} -{{- else -}} -{{ printf "namespace: %s" .Release.Namespace }} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/templates/backend/deployment.yaml b/magicleaps/helm-pkg/magicleaps/templates/backend/deployment.yaml new file mode 100644 index 00000000..2294ace8 --- /dev/null +++ b/magicleaps/helm-pkg/magicleaps/templates/backend/deployment.yaml @@ -0,0 +1,98 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/name: "backend" + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + name: "backend" + namespace: {{ .Release.Namespace | quote }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: "backend" + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + replicas: {{ .Values.backend.replicas }} + template: + metadata: + labels: + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/name: "backend" + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + containers: + - name: "backend" + image: "{{ coalesce .Values.backend.image.registry .Values.global.registry "docker.io"}}/{{ coalesce .Values.backend.image.repository .Values.global.repository }}/{{ .Values.backend.image.name }}:{{ .Values.backend.image.tag | default "latest" }}" + imagePullPolicy: {{ .Values.backend.image.imagePullPolicy | default "IfNotPresent" }} + ports: + {{- range $port := .Values.backend.ports }} + - containerPort: {{ $port.containerPort }} + name: {{ $port.name }} + protocol: {{ $port.protocol }} + {{- end }} + {{- if .Values.backend.resources }} + resources: + {{- toYaml .Values.backend.resources | nindent 12 }} + {{- end }} + {{- if .Values.backend.probes }} + {{- if and (.Values.backend.probes.liveness) (eq .Values.backend.probes.liveness.type "httpGet") }} + livenessProbe: + httpGet: + path: {{ .Values.backend.probes.liveness.config.path }} + port: {{ .Values.backend.probes.liveness.config.port }} + {{- if .Values.backend.probes.liveness.config.initialDelaySeconds }} + initialDelaySeconds: {{ .Values.backend.probes.liveness.config.initialDelaySeconds }} + {{- end }} + {{- if .Values.backend.probes.liveness.config.periodSeconds }} + periodSeconds: {{ .Values.backend.probes.liveness.config.periodSeconds }} + {{- end }} + {{- if .Values.backend.probes.liveness.config.timeoutSeconds }} + timeoutSeconds: {{ .Values.backend.probes.liveness.config.timeoutSeconds }} + {{- end }} + {{- if .Values.backend.probes.liveness.config.successThreshold }} + successThreshold: {{ .Values.backend.probes.liveness.config.successThreshold }} + {{- end }} + {{- if .Values.backend.probes.liveness.config.failureThreshold }} + failureThreshold: {{ .Values.backend.probes.liveness.config.failureThreshold }} + {{- end }} + {{- if .Values.backend.probes.liveness.config.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.backend.probes.liveness.config.terminationGracePeriodSeconds }} + {{- end }} + {{- end }} + {{- if and (.Values.backend.probes.readiness) (eq .Values.backend.probes.readiness.type "httpGet") }} + readinessProbe: + httpGet: + path: {{ .Values.backend.probes.readiness.config.path }} + port: {{ .Values.backend.probes.readiness.config.port }} + {{- if .Values.backend.probes.readiness.config.initialDelaySeconds }} + initialDelaySeconds: {{ .Values.backend.probes.readiness.config.initialDelaySeconds }} + {{- end }} + {{- if .Values.backend.probes.readiness.config.periodSeconds }} + periodSeconds: {{ .Values.backend.probes.readiness.config.periodSeconds }} + {{- end }} + {{- if .Values.backend.probes.readiness.config.timeoutSeconds }} + timeoutSeconds: {{ .Values.backend.probes.readiness.config.timeoutSeconds }} + {{- end }} + {{- if .Values.backend.probes.readiness.config.successThreshold }} + successThreshold: {{ .Values.backend.probes.readiness.config.successThreshold }} + {{- end }} + {{- if .Values.backend.probes.readiness.config.failureThreshold }} + failureThreshold: {{ .Values.backend.probes.readiness.config.failureThreshold }} + {{- end }} + {{- if .Values.backend.probes.readiness.config.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.backend.probes.readiness.config.terminationGracePeriodSeconds }} + {{- end }} + {{- end }} + {{- end}} + env: + {{- range $key, $value := .Values.backend.configs }} + - name: {{ $key | snakecase | upper }} + valueFrom: + secretKeyRef: + name: magicleaps-backend-config + key: {{ $key | snakecase | upper }} + {{- end }} \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/templates/backend/magicleaps-backend-config.yaml b/magicleaps/helm-pkg/magicleaps/templates/backend/magicleaps-backend-config.yaml new file mode 100644 index 00000000..fd5e0a69 --- /dev/null +++ b/magicleaps/helm-pkg/magicleaps/templates/backend/magicleaps-backend-config.yaml @@ -0,0 +1,22 @@ + +apiVersion: v1 +kind: Secret +metadata: + name: magicleaps-backend-config + namespace: {{ .Release.Namespace }} +type: Opaque +data: + TZ: {{ .Values.backend.configs.tz | b64enc | quote }} + MONGODB_HOST: {{ .Values.backend.configs.mongodbHost | b64enc | quote }} + MONGODB_PORT: {{ .Values.backend.configs.mongodbPort | b64enc | quote }} + MONGODB_NAME: {{ .Values.backend.configs.mongodbName | b64enc | quote }} + EMAIL_USER: {{ .Values.backend.configs.emailUser | b64enc | quote }} + EMAIL_PASSWORD: {{ .Values.backend.configs.emailPassword | b64enc | quote }} + SUPER_ADMIN: {{ .Values.backend.configs.superAdmin | b64enc | quote }} + TWILIO_ACCOUNT_SID: {{ .Values.backend.configs.twilioAccountSid | b64enc | quote }} + TWILIO_AUTH_TOKEN: {{ .Values.backend.configs.twilioAuthToken | b64enc | quote }} + EVELUATION_TASK_FOLDER_BASE: {{ .Values.backend.configs.eveluationTaskFolderBase | b64enc | quote }} + LOG_DIR: {{ .Values.backend.configs.logDir | b64enc | quote }} + APP_LOG_FILE: {{ .Values.backend.configs.appLogFile | b64enc | quote }} + APP_LOG_LEVEL: {{ .Values.backend.configs.appLogLevel | b64enc | quote }} + \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/templates/backend/service.yaml b/magicleaps/helm-pkg/magicleaps/templates/backend/service.yaml new file mode 100644 index 00000000..04fe0507 --- /dev/null +++ b/magicleaps/helm-pkg/magicleaps/templates/backend/service.yaml @@ -0,0 +1,26 @@ +{{ $namespace := .Release.Namespace }} +{{ $appVersion := .Chart.AppVersion | quote }} +{{ $releaseService := .Release.Service }} +{{ $releaseName := .Release.Name }} +{{- range $service := .Values.backend.services }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ $service.name }} + namespace: {{ $namespace }} + labels: + app.kubernetes.io/version: {{ $appVersion }} + app.kubernetes.io/name: {{ $service.name | quote }} + app.kubernetes.io/managed-by: {{ $releaseService }} + app.kubernetes.io/instance: {{ $releaseName }} +spec: + ports: + - port: {{ $service.port }} + targetPort: {{ $service.targetPort }} + selector: + app.kubernetes.io/version: {{ $appVersion }} + app.kubernetes.io/name: "backend" + app.kubernetes.io/managed-by: {{ $releaseService }} + app.kubernetes.io/instance: {{ $releaseName }} +{{- end }} \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/templates/deployments/backend.yaml b/magicleaps/helm-pkg/magicleaps/templates/deployments/backend.yaml deleted file mode 100644 index a18ae676..00000000 --- a/magicleaps/helm-pkg/magicleaps/templates/deployments/backend.yaml +++ /dev/null @@ -1,87 +0,0 @@ -{{- if .Values.backend.enabled -}} -apiVersion: {{ template "magicleaps.deployment.apiVersion" . }} -kind: Deployment -metadata: - labels: - {{- include "magicleaps.backend.labels" . | nindent 4 }} - name: {{ .Values.backend.name }} -{{ include "magicleaps.namespace" . | indent 2 }} -spec: - selector: - matchLabels: - {{- include "magicleaps.backend.labels" . | nindent 6 }} - replicas: {{ .Values.backend.replicaCount }} - template: - metadata: - labels: - {{- include "magicleaps.backend.labels" . | nindent 8 }} - spec: - {{- if .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml .Values.imagePullSecrets | nindent 8 }} - {{- end }} - containers: - - name: {{ .Values.backend.name }} - image: "{{ .Values.backend.image.repository }}/{{ .Values.backend.image.name }}{{ if .Values.backend.image.tag }}:{{ .Values.backend.image.tag }}{{ end }}" - imagePullPolicy: {{ .Values.backend.image.imagePullPolicy }} - ports: - - containerPort: {{ .Values.backend.port }} - {{- if .Values.backend.extraEnv }} - env: - {{- toYaml .Values.backend.extraEnv | nindent 12 }} - {{- end }} - livenessProbe: - {{- toYaml .Values.backend.livenessProbe | nindent 12 }} - readinessProbe: - {{- toYaml .Values.backend.readinessProbe | nindent 12 }} - {{- if .Values.backend.resources }} - resources: - {{- toYaml .Values.backend.resources | nindent 12 }} - {{- end }} - env: - - name: MONGO_DB - valueFrom: - secretKeyRef: - name: backend-secrets - key: MONGO_DB - - name: MONGO_HOST - valueFrom: - secretKeyRef: - name: backend-secrets - key: MONGO_HOST - - name: MONGO_PORT - valueFrom: - secretKeyRef: - name: backend-secrets - key: MONGO_PORT - - name: EMAIL_USER - valueFrom: - secretKeyRef: - name: backend-secrets - key: EMAIL_USER - - name: EMAIL_PASSWORD - valueFrom: - secretKeyRef: - name: backend-secrets - key: EMAIL_PASSWORD - - name: SUPER_ADMIN - valueFrom: - secretKeyRef: - name: backend-secrets - key: SUPER_ADMIN - - name: TWILIO_ACCOUNT_SID - valueFrom: - secretKeyRef: - name: backend-secrets - key: TWILIO_ACCOUNT_SID - - name: TWILIO_AUTH_TOKEN - valueFrom: - secretKeyRef: - name: backend-secrets - key: TWILIO_AUTH_TOKEN - - name: LOG_LEVEL - valueFrom: - secretKeyRef: - name: backend-secrets - key: LOG_LEVEL -{{- end -}} \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/templates/deployments/frontend.yaml b/magicleaps/helm-pkg/magicleaps/templates/deployments/frontend.yaml deleted file mode 100644 index 8700ece5..00000000 --- a/magicleaps/helm-pkg/magicleaps/templates/deployments/frontend.yaml +++ /dev/null @@ -1,41 +0,0 @@ -{{- if .Values.frontend.enabled }} -apiVersion: {{ template "magicleaps.deployment.apiVersion" . }} -kind: Deployment -metadata: - labels: - {{- include "magicleaps.frontend.labels" . | nindent 4 }} - name: {{ .Values.frontend.name }} -{{ include "magicleaps.namespace" . | indent 2 }} -spec: - selector: - matchLabels: - {{- include "magicleaps.frontend.labels" . | nindent 6 }} - replicas: {{ .Values.frontend.replicaCount }} - template: - metadata: - labels: - {{- include "magicleaps.frontend.labels" . | nindent 8 }} - spec: - {{- if .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml .Values.imagePullSecrets | nindent 8 }} - {{- end }} - containers: - - name: {{ .Values.frontend.name }} - image: "{{ .Values.frontend.image.repository }}/{{ .Values.frontend.image.name }}{{ if .Values.frontend.image.tag }}:{{ .Values.frontend.image.tag }}{{ end }}" - imagePullPolicy: {{ .Values.frontend.image.imagePullPolicy }} - ports: - - containerPort: {{ .Values.frontend.port }} - {{- if .Values.frontend.extraEnv }} - env: - {{- toYaml .Values.frontend.extraEnv | nindent 12 }} - {{- end }} - livenessProbe: - {{- toYaml .Values.frontend.livenessProbe | nindent 12 }} - readinessProbe: - {{- toYaml .Values.frontend.readinessProbe | nindent 12 }} - {{- if .Values.frontend.resources }} - resources: - {{- toYaml .Values.frontend.resources | nindent 12 }} - {{- end }} -{{- end }} diff --git a/magicleaps/helm-pkg/magicleaps/templates/frontend/certificate.yaml b/magicleaps/helm-pkg/magicleaps/templates/frontend/certificate.yaml new file mode 100644 index 00000000..8faf528d --- /dev/null +++ b/magicleaps/helm-pkg/magicleaps/templates/frontend/certificate.yaml @@ -0,0 +1,27 @@ +{{ $namespace := .Release.Namespace }} +{{ $appVersion := .Chart.AppVersion | quote }} +{{ $releaseCertificate := .Release.Certificate }} +{{ $releaseName := .Release.Name }} +{{- range $ingress := .Values.frontend.ingresses }} +{{- if not $ingress.tls.exists }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ $ingress.name }} + namespace: {{ $namespace }} + labels: + app.kubernetes.io/version: {{ $appVersion }} + app.kubernetes.io/name: {{ $ingress.name | quote }} + app.kubernetes.io/managed-by: {{ $releaseCertificate }} + app.kubernetes.io/instance: {{ $releaseName }} +spec: + commonName: {{ $ingress.host }} + dnsNames: + - {{ $ingress.host }} + issuerRef: + name: {{ $ingress.tls.issuerRef.name }} + kind: {{ $ingress.tls.issuerRef.kind }} + secretName: {{ $ingress.tls.name }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/templates/frontend/deployment.yaml b/magicleaps/helm-pkg/magicleaps/templates/frontend/deployment.yaml new file mode 100644 index 00000000..bf09ec19 --- /dev/null +++ b/magicleaps/helm-pkg/magicleaps/templates/frontend/deployment.yaml @@ -0,0 +1,98 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/name: "frontend" + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + name: "frontend" + namespace: {{ .Release.Namespace | quote }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: "frontend" + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + replicas: {{ .Values.frontend.replicas }} + template: + metadata: + labels: + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/name: "frontend" + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + containers: + - name: "frontend" + image: "{{ coalesce .Values.frontend.image.registry .Values.global.registry "docker.io"}}/{{ coalesce .Values.frontend.image.repository .Values.global.repository }}/{{ .Values.frontend.image.name }}:{{ .Values.frontend.image.tag | default "latest" }}" + imagePullPolicy: {{ .Values.frontend.image.imagePullPolicy | default "IfNotPresent" }} + ports: + {{- range $port := .Values.frontend.ports }} + - containerPort: {{ $port.containerPort }} + name: {{ $port.name }} + protocol: {{ $port.protocol }} + {{- end }} + {{- if .Values.frontend.resources }} + resources: + {{- toYaml .Values.frontend.resources | nindent 12 }} + {{- end }} + {{- if .Values.frontend.probes }} + {{- if and (.Values.frontend.probes.liveness) (eq .Values.frontend.probes.liveness.type "httpGet") }} + livenessProbe: + httpGet: + path: {{ .Values.frontend.probes.liveness.config.path }} + port: {{ .Values.frontend.probes.liveness.config.port }} + {{- if .Values.frontend.probes.liveness.config.initialDelaySeconds }} + initialDelaySeconds: {{ .Values.frontend.probes.liveness.config.initialDelaySeconds }} + {{- end }} + {{- if .Values.frontend.probes.liveness.config.periodSeconds }} + periodSeconds: {{ .Values.frontend.probes.liveness.config.periodSeconds }} + {{- end }} + {{- if .Values.frontend.probes.liveness.config.timeoutSeconds }} + timeoutSeconds: {{ .Values.frontend.probes.liveness.config.timeoutSeconds }} + {{- end }} + {{- if .Values.frontend.probes.liveness.config.successThreshold }} + successThreshold: {{ .Values.frontend.probes.liveness.config.successThreshold }} + {{- end }} + {{- if .Values.frontend.probes.liveness.config.failureThreshold }} + failureThreshold: {{ .Values.frontend.probes.liveness.config.failureThreshold }} + {{- end }} + {{- if .Values.frontend.probes.liveness.config.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.frontend.probes.liveness.config.terminationGracePeriodSeconds }} + {{- end }} + {{- end }} + {{- if and (.Values.frontend.probes.readiness) (eq .Values.frontend.probes.readiness.type "httpGet") }} + readinessProbe: + httpGet: + path: {{ .Values.frontend.probes.readiness.config.path }} + port: {{ .Values.frontend.probes.readiness.config.port }} + {{- if .Values.frontend.probes.readiness.config.initialDelaySeconds }} + initialDelaySeconds: {{ .Values.frontend.probes.readiness.config.initialDelaySeconds }} + {{- end }} + {{- if .Values.frontend.probes.readiness.config.periodSeconds }} + periodSeconds: {{ .Values.frontend.probes.readiness.config.periodSeconds }} + {{- end }} + {{- if .Values.frontend.probes.readiness.config.timeoutSeconds }} + timeoutSeconds: {{ .Values.frontend.probes.readiness.config.timeoutSeconds }} + {{- end }} + {{- if .Values.frontend.probes.readiness.config.successThreshold }} + successThreshold: {{ .Values.frontend.probes.readiness.config.successThreshold }} + {{- end }} + {{- if .Values.frontend.probes.readiness.config.failureThreshold }} + failureThreshold: {{ .Values.frontend.probes.readiness.config.failureThreshold }} + {{- end }} + {{- if .Values.frontend.probes.readiness.config.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.frontend.probes.readiness.config.terminationGracePeriodSeconds }} + {{- end }} + {{- end }} + {{- end}} + env: + {{- range $key, $value := .Values.frontend.configs }} + - name: {{ $key | snakecase | upper }} + valueFrom: + secretKeyRef: + name: magicleaps-frontend-config + key: {{ $key | snakecase | upper }} + {{- end }} \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/templates/frontend/ingress.yaml b/magicleaps/helm-pkg/magicleaps/templates/frontend/ingress.yaml new file mode 100644 index 00000000..33b52993 --- /dev/null +++ b/magicleaps/helm-pkg/magicleaps/templates/frontend/ingress.yaml @@ -0,0 +1,38 @@ +{{ $namespace := .Release.Namespace }} +{{ $appVersion := .Chart.AppVersion | quote }} +{{ $releaseIngress := .Release.Ingress }} +{{ $releaseName := .Release.Name }} +{{- range $ingress := .Values.frontend.ingresses }} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ $ingress.name }} + namespace: {{ $namespace }} + labels: + app.kubernetes.io/version: {{ $appVersion }} + app.kubernetes.io/name: {{ $ingress.name | quote }} + app.kubernetes.io/managed-by: {{ $releaseIngress }} + app.kubernetes.io/instance: {{ $releaseName }} +spec: +{{- if $ingress.class }} + ingressClassName: {{ $ingress.class }} +{{- end }} +{{- if $ingress.tls }} + tls: + - hosts: + - {{ $ingress.host }} +{{- if $ingress.tls.exists }} + secretName: {{ $ingress.tls.secretRef.name }} +{{- else }} + secretName: {{ $ingress.tls.name }} +{{- end }} +{{- end }} + rules: + - host: {{ $ingress.host }} + http: + paths: +{{- range $path := $ingress.rules }} +{{ toYaml $path | indent 10 }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/templates/frontend/magicleaps-frontend-config.yaml b/magicleaps/helm-pkg/magicleaps/templates/frontend/magicleaps-frontend-config.yaml new file mode 100644 index 00000000..84683c2d --- /dev/null +++ b/magicleaps/helm-pkg/magicleaps/templates/frontend/magicleaps-frontend-config.yaml @@ -0,0 +1,10 @@ + +apiVersion: v1 +kind: Secret +metadata: + name: magicleaps-frontend-config + namespace: {{ .Release.Namespace }} +type: Opaque +data: + TZ: {{ .Values.frontend.configs.tz | b64enc | quote }} + \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/templates/frontend/service.yaml b/magicleaps/helm-pkg/magicleaps/templates/frontend/service.yaml new file mode 100644 index 00000000..ed21b00a --- /dev/null +++ b/magicleaps/helm-pkg/magicleaps/templates/frontend/service.yaml @@ -0,0 +1,26 @@ +{{ $namespace := .Release.Namespace }} +{{ $appVersion := .Chart.AppVersion | quote }} +{{ $releaseService := .Release.Service }} +{{ $releaseName := .Release.Name }} +{{- range $service := .Values.frontend.services }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ $service.name }} + namespace: {{ $namespace }} + labels: + app.kubernetes.io/version: {{ $appVersion }} + app.kubernetes.io/name: {{ $service.name | quote }} + app.kubernetes.io/managed-by: {{ $releaseService }} + app.kubernetes.io/instance: {{ $releaseName }} +spec: + ports: + - port: {{ $service.port }} + targetPort: {{ $service.targetPort }} + selector: + app.kubernetes.io/version: {{ $appVersion }} + app.kubernetes.io/name: "frontend" + app.kubernetes.io/managed-by: {{ $releaseService }} + app.kubernetes.io/instance: {{ $releaseName }} +{{- end }} \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/templates/ingresses/backend.yaml b/magicleaps/helm-pkg/magicleaps/templates/ingresses/backend.yaml deleted file mode 100644 index 39c84bb7..00000000 --- a/magicleaps/helm-pkg/magicleaps/templates/ingresses/backend.yaml +++ /dev/null @@ -1,24 +0,0 @@ -{{- if and .Values.backend.enabled .Values.backend.ingress.enabled -}} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ .Values.backend.name }}-ingress - annotations: - kubernetes.io/ingress.class: "nginx" - {{- if .Values.backend.ingress.annotations }} - {{ .Values.backend.ingress.annotations | toYaml | nindent 4 }} - {{- end }} -{{ include "magicleaps.namespace" . | indent 2 }} -spec: - rules: - - host: {{ .Values.backend.ingress.host }} - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: {{ .Values.backend.name }}-svc - port: - number: {{ .Values.backend.service.port }} -{{- end -}} \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/templates/ingresses/frontend.yaml b/magicleaps/helm-pkg/magicleaps/templates/ingresses/frontend.yaml deleted file mode 100644 index 7fa27ea5..00000000 --- a/magicleaps/helm-pkg/magicleaps/templates/ingresses/frontend.yaml +++ /dev/null @@ -1,24 +0,0 @@ -{{- if .Values.frontend.enabled -}} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ .Values.frontend.name }}-ingress - annotations: - kubernetes.io/ingress.class: "nginx" - {{- if .Values.frontend.ingress.annotations }} - {{ .Values.frontend.ingress.annotations | toYaml | nindent 4 }} - {{- end }} -{{ include "magicleaps.namespace" . | indent 2 }} -spec: - rules: - - host: {{ .Values.frontend.ingress.host }} - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: {{ .Values.frontend.name }}-svc - port: - number: {{ .Values.frontend.service.port }} -{{- end -}} \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/templates/secrets/backend.yaml b/magicleaps/helm-pkg/magicleaps/templates/secrets/backend.yaml deleted file mode 100644 index 5f527d45..00000000 --- a/magicleaps/helm-pkg/magicleaps/templates/secrets/backend.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: backend-secrets - namespace: magicleaps-alpha -type: Opaque -data: - MONGO_DB: {{ .Values.backend.config.mongo.db | b64enc | quote }} - MONGO_HOST: {{ .Values.backend.config.mongo.host | b64enc | quote }} - MONGO_PORT: {{ .Values.backend.config.mongo.port | toString | b64enc | quote }} - EMAIL_USER: {{ .Values.backend.config.email.user | b64enc | quote }} - EMAIL_PASSWORD: {{ .Values.backend.config.email.password | b64enc | quote }} - SUPER_ADMIN: {{ .Values.backend.config.superAdmin | b64enc | quote }} - TWILIO_ACCOUNT_SID: {{ .Values.backend.config.twilio.accountSid | b64enc | quote }} - TWILIO_AUTH_TOKEN: {{ .Values.backend.config.twilio.authToken | b64enc | quote }} - LOG_LEVEL: {{ .Values.backend.config.log.level | b64enc | quote }} \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/templates/services/backend.yaml b/magicleaps/helm-pkg/magicleaps/templates/services/backend.yaml deleted file mode 100644 index feab012b..00000000 --- a/magicleaps/helm-pkg/magicleaps/templates/services/backend.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if .Values.backend.enabled -}} -apiVersion: v1 -kind: Service -metadata: - labels: - {{- include "magicleaps.backend.labels" . | nindent 4 }} - name: {{ .Values.backend.name }}-svc -{{ include "magicleaps.namespace" . | indent 2 }} -spec: - ports: - - port: {{ .Values.backend.service.port }} - targetPort: 8081 - selector: - {{- include "magicleaps.backend.selectorLabels" . | nindent 4 }} - sessionAffinity: {{ .Values.backend.service.sessionAffinity }} - type: {{ .Values.backend.service.type }} -{{- end -}} \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/templates/services/frontend.yaml b/magicleaps/helm-pkg/magicleaps/templates/services/frontend.yaml deleted file mode 100644 index 87c3177a..00000000 --- a/magicleaps/helm-pkg/magicleaps/templates/services/frontend.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if .Values.frontend.enabled -}} -apiVersion: v1 -kind: Service -metadata: - labels: - {{- include "magicleaps.frontend.labels" . | nindent 4 }} - name: {{ .Values.frontend.name }}-svc -{{ include "magicleaps.namespace" . | indent 2 }} -spec: - ports: - - port: {{ .Values.frontend.service.port }} - targetPort: 80 - selector: - {{- include "magicleaps.frontend.selectorLabels" . | nindent 4 }} - sessionAffinity: {{ .Values.frontend.service.sessionAffinity }} - type: {{ .Values.frontend.service.type }} -{{- end -}} \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/values.alpha.yaml b/magicleaps/helm-pkg/magicleaps/values.alpha.yaml index b827a614..ab5e034a 100644 --- a/magicleaps/helm-pkg/magicleaps/values.alpha.yaml +++ b/magicleaps/helm-pkg/magicleaps/values.alpha.yaml @@ -1,76 +1,110 @@ -imagePullSecrets: -- name: docker-secret -backend: - enabled: true - name: magicleaps-backend - image: - repository: docker.io/zhenyus - name: magicleaps - imagePullPolicy: IfNotPresent - tag: backend-snapshot-ce69a02-linux-amd64 - extraEnv: {} - port: 8081 - ingress: - enabled: false - annotations: {} - host: '' - replicaCount: 1 - service: - type: ClusterIP - port: 8081 - sessionAffinity: None - resources: {} - livenessProbe: - enabled: true - httpGet: - path: /api/_/probe/liveness - port: 8081 - readinessProbe: - enabled: true - httpGet: - path: /api/_/probe/readiness - port: 8081 - config: - mongo: - db: magicleaps_alpha - host: mongo-mongodb.magicleaps-alpha.svc.cluster.local - port: 27017 - email: - user: your@freeleaps.com - password: your-password - superAdmin: your@email.com - twilio: - accountSid: '' - authToken: '' - log: - level: INFO -frontend: - enabled: true - name: magicleaps-frontend - image: - repository: docker.io/zhenyus - name: magicleaps - imagePullPolicy: IfNotPresent - tag: frontend-snapshot-ce69a02-linux-amd64 - extraEnv: {} - port: 80 - ingress: - annotations: {} - host: magicleaps-alpha.wearelsp.com + +global: + registry: docker.io + repository: sunzhenyucn nodeSelector: {} - affinity: {} - replicaCount: 1 - service: - type: ClusterIP - port: 80 - sessionAffinity: None - livenessProbe: - enabled: true - httpGet: - path: / - port: 80 - readinessProbe: - enabled: true - httpGet: - path: / +frontend: + replicas: 1 + image: + registry: + repository: sunzhenyucn + name: magicleaps-frontend + tag: 1.0.0 + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 8080 + protocol: TCP + resources: + requests: + cpu: "50m" + memory: "128Mi" + limits: + cpu: "100m" + memory: "256Mi" + probes: + liveness: + type: httpGet + config: + path: / + port: 8080 + readiness: + type: httpGet + config: + path: / + port: 8080 + services: + - name: magicleaps-frontend-service + type: ClusterIP port: 80 + targetPort: 8080 + ingresses: + - name: magicleaps-frontend-ingress + host: alpha.magicleaps.mathmast.com + class: nginx + rules: + - path: /* + pathType: ImplementationSpecific + backend: + service: + name: magicleaps-frontend-service + port: + number: 80 + tls: + exists: false + issuerRef: + name: mathmast-dot-com + kind: ClusterIssuer + name: magicleaps-alpha-frontend-ingress-tls + configs: + tz: "America/Settle" +backend: + replicas: 1 + image: + registry: + repository: sunzhenyucn + name: magicleaps-backend + tag: 1.0.0 + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 8081 + protocol: TCP + resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + cpu: "200m" + memory: "512Mi" + probes: + liveness: + type: httpGet + config: + path: /api/_/probe/liveness + port: 8081 + readiness: + type: httpGet + config: + path: /api/_/probe/readiness + port: 8081 + services: + - name: magicleaps-backend-service + type: ClusterIP + port: 8081 + targetPort: 8081 + ingresses: + configs: + tz: "America/Settle" + mongodbHost: "mongodb.magicleaps-alpha.svc.cluster.local" + mongodbPort: "27017" + mongodbName: "interview" + emailUser: "your@freeleaps.com" + emailPassword: "your-password" + superAdmin: "your@email.com" + twilioAccountSid: "" + twilioAuthToken: "" + eveluationTaskFolderBase: "temp/interview/eveluation_task/" + logDir: "logs" + appLogFile: "app.log" + appLogLevel: "INFO" \ No newline at end of file diff --git a/magicleaps/helm-pkg/magicleaps/values.yaml b/magicleaps/helm-pkg/magicleaps/values.yaml index 664c8391..10040819 100644 --- a/magicleaps/helm-pkg/magicleaps/values.yaml +++ b/magicleaps/helm-pkg/magicleaps/values.yaml @@ -1,74 +1,110 @@ -imagePullSecrets: - - name: docker-secret -backend: - enabled: true - name: magicleaps-backend - image: - repository: docker.io/magicleaps - name: magicleaps - imagePullPolicy: IfNotPresent - tag: "backend-snapshot-5e9dea2-linux-amd64" - extraEnv: {} - port: 8081 - ingress: - enabled: false - annotations: {} - host: '' - replicaCount: 1 - service: - type: ClusterIP - port: 8081 - sessionAffinity: None - resources: {} - livenessProbe: - httpGet: - path: /api/_/probe/liveness - port: 8081 - readinessProbe: - httpGet: - path: /api/_/probe/readiness - port: 8081 - config: - mongo: - db: magicleaps_alpha - host: '' - port: 27017 - email: - user: '' - password: '' - superAdmin: '' - twilio: - accountSid: '' - authToken: '' - log: - level: 'INFO' - -frontend: - enabled: true - name: magicleaps-frontend - image: - repository: docker.io/magicleaps - name: magicleaps - imagePullPolicy: IfNotPresent - tag: "frontend-snapshot-5e9dea2-linux-amd64" - extraEnv: {} - port: 80 - ingress: - annotations: {} - host: '' +global: + registry: docker.io + repository: sunzhenyucn nodeSelector: {} - affinity: {} - replicaCount: 1 - service: - type: ClusterIP - port: 80 - sessionAffinity: None - livenessProbe: - httpGet: - path: / +frontend: + replicas: 1 + image: + registry: + repository: sunzhenyucn + name: magicleaps-frontend + tag: 1.0.0 + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 8080 + protocol: TCP + resources: + requests: + cpu: "50m" + memory: "128Mi" + limits: + cpu: "100m" + memory: "256Mi" + probes: + liveness: + type: httpGet + config: + path: / + port: 8080 + readiness: + type: httpGet + config: + path: / + port: 8080 + services: + - name: magicleaps-frontend-service + type: ClusterIP port: 80 - readinessProbe: - httpGet: - path: / - port: 80 \ No newline at end of file + targetPort: 8080 + ingresses: + - name: magicleaps-frontend-ingress + host: alpha.magicleaps.mathmast.com + class: nginx + rules: + - path: /* + pathType: ImplementationSpecific + backend: + service: + name: magicleaps-frontend-service + port: + number: 80 + tls: + exists: false + issuerRef: + name: mathmast-dot-com + kind: ClusterIssuer + name: magicleaps-alpha-frontend-ingress-tls + configs: + tz: "America/Settle" +backend: + replicas: 1 + image: + registry: + repository: sunzhenyucn + name: magicleaps-backend + tag: 1.0.0 + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 8081 + protocol: TCP + resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + cpu: "200m" + memory: "512Mi" + probes: + liveness: + type: httpGet + config: + path: /api/_/probe/liveness + port: 8081 + readiness: + type: httpGet + config: + path: /api/_/probe/readiness + port: 8081 + services: + - name: magicleaps-backend-service + type: ClusterIP + port: 8081 + targetPort: 8081 + ingresses: + configs: + tz: "America/Settle" + mongodbHost: "localhost" + mongodbPort: "27017" + mongodbName: "interview" + emailUser: "your@freeleaps.com" + emailPassword: "your-password" + superAdmin: "your@email.com" + twilioAccountSid: "" + twilioAuthToken: "" + eveluationTaskFolderBase: "temp/interview/eveluation_task/" + logDir: "logs" + appLogFile: "app.log" + appLogLevel: "INFO" \ No newline at end of file diff --git a/operators/freeleaps-gitops-initializer/api/v1alpha1/projectinitialize_types.go b/operators/freeleaps-gitops-initializer/api/v1alpha1/projectinitialize_types.go index 6a2d3041..a89d1549 100644 --- a/operators/freeleaps-gitops-initializer/api/v1alpha1/projectinitialize_types.go +++ b/operators/freeleaps-gitops-initializer/api/v1alpha1/projectinitialize_types.go @@ -102,6 +102,8 @@ type RepositorySpec struct { Name string `json:"name,omitempty"` // Type defines the type of the Git repository Type RepositoryType `json:"type,omitempty"` + // Branch defines the branch of the Git repository + Branch string `json:"branch,omitempty"` // HookRegister defines the Git repository hook registration HookRegister RepositoryHookRegisterSpec `json:"hookRegister,omitempty"` } diff --git a/operators/freeleaps-gitops-initializer/cmd/main.go b/operators/freeleaps-gitops-initializer/cmd/main.go index 1c0a879e..da51e8f7 100644 --- a/operators/freeleaps-gitops-initializer/cmd/main.go +++ b/operators/freeleaps-gitops-initializer/cmd/main.go @@ -17,6 +17,7 @@ limitations under the License. package main import ( + "context" "crypto/tls" "flag" "os" @@ -38,6 +39,7 @@ import ( gitopsv1alpha1 "freeleaps.com/gitops/initializer/api/v1alpha1" "freeleaps.com/gitops/initializer/internal/controller" + "freeleaps.com/gitops/initializer/internal/repo" // +kubebuilder:scaffold:imports ) @@ -145,10 +147,48 @@ func main() { os.Exit(1) } + // read configurations from the environment + gitopsRepoName := os.Getenv("FREELEAPS_GITOPS_REPO_NAME") + gitopsProjectName := os.Getenv("FREELEAPS_GITOPS_PROJECT_NAME") + gitopsBranchName := os.Getenv("FREELEAPS_GITOPS_BRANCH_NAME") + gitopsRepoPAT := os.Getenv("FREELEAPS_GITOPS_REPO_PAT") + gitopsOrganizationUrl := os.Getenv("FREELEAPS_GITOPS_ORGANIZATION_URL") + + if gitopsRepoName == "" || gitopsProjectName == "" || gitopsBranchName == "" || gitopsRepoPAT == "" || gitopsOrganizationUrl == "" { + setupLog.Error(nil, "missing environment variables") + os.Exit(1) + } + + // create repo manager + repoMgr, ok := repo.GetPlugin("azure-devops") + if !ok { + setupLog.Error(nil, "repo plugin not found") + os.Exit(1) + } + + // create plugin config + pluginConfig := repo.NewPluginConfig() + pluginConfig.Set("pat", gitopsRepoPAT) + pluginConfig.Set("organizationUrl", gitopsOrganizationUrl) + + // initialize repo manager + err = repoMgr.Initialize(context.Background(), + repo.WithProject(gitopsProjectName), + repo.WithName(gitopsRepoName), + repo.WithBranch(gitopsBranchName), + repo.WithAuthor("freeleaps-gitops-bot", "gitops@mathmast.com"), + repo.WithPluginConfig(pluginConfig), + ) + if err != nil { + setupLog.Error(err, "failed to initialize repo manager") + os.Exit(1) + } + if err = (&controller.ProjectInitializeReconciler{ - Log: ctrl.Log.WithName("controllers").WithName("ProjectInitialize"), - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), + Log: ctrl.Log.WithName("controllers").WithName("ProjectInitialize"), + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + GitOpsRepoManager: repoMgr, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "ProjectInitialize") os.Exit(1) diff --git a/operators/freeleaps-gitops-initializer/config/samples/gitops_v1alpha1_projectinitialize.yaml b/operators/freeleaps-gitops-initializer/config/samples/gitops_v1alpha1_projectinitialize.yaml index 2332c7a3..bd597ff3 100644 --- a/operators/freeleaps-gitops-initializer/config/samples/gitops_v1alpha1_projectinitialize.yaml +++ b/operators/freeleaps-gitops-initializer/config/samples/gitops_v1alpha1_projectinitialize.yaml @@ -12,7 +12,6 @@ spec: name: magicleaps-alpha project: magicleaps namespace: magicleaps-alpha - branch: develop syncPolicy: automated: true prune: true @@ -21,6 +20,7 @@ spec: plugins: azure-devops project: magicleaps name: magicleaps + branch: develop pluginConfig: organizationUrl: https://dev.azure.com/freeleaps pat: 3E9J1v0si6HRvyc1RSRgT791W9ZvMi4kBmrznfcIXB8mq6Trj9VkJQQJ99BBACAAAAArj0WRAAASAZDO32n4 diff --git a/operators/freeleaps-gitops-initializer/internal/controller/projectinitialize_controller.go b/operators/freeleaps-gitops-initializer/internal/controller/projectinitialize_controller.go index 7ecf2d9c..5b1454a9 100644 --- a/operators/freeleaps-gitops-initializer/internal/controller/projectinitialize_controller.go +++ b/operators/freeleaps-gitops-initializer/internal/controller/projectinitialize_controller.go @@ -31,14 +31,16 @@ import ( gitopsv1alpha1 "freeleaps.com/gitops/initializer/api/v1alpha1" "freeleaps.com/gitops/initializer/internal/helm" "freeleaps.com/gitops/initializer/internal/metrics" + "freeleaps.com/gitops/initializer/internal/repo" utilerrors "k8s.io/apimachinery/pkg/util/errors" ) // ProjectInitializeReconciler reconciles a ProjectInitialize object type ProjectInitializeReconciler struct { client.Client - Scheme *runtime.Scheme - Log logr.Logger + Scheme *runtime.Scheme + Log logr.Logger + GitOpsRepoManager repo.RepoManager } // +kubebuilder:rbac:groups=gitops.freeleaps.com,resources=projectinitializes,verbs=get;list;watch;create;update;patch;delete @@ -107,6 +109,8 @@ func (r *ProjectInitializeReconciler) Reconcile(ctx context.Context, req ctrl.Re } } + // reconcile Jenkinsfile for the ProjectInitialize instance + return ctrl.Result{}, nil } @@ -139,6 +143,31 @@ func (r *ProjectInitializeReconciler) reconcileHelmPackage(ctx context.Context, return err } + requests := make([]repo.ChangeRequest, 0) + + // commit generated files to gitops repo + err = generator.Walk(func(f *helm.HelmGeneratedFile) error { + if blob, err := f.ReadAll(); err != nil { + return err + } else { + req := repo.ChangeRequest{ + Path: fmt.Sprintf("%s/helm-pkg/%s", cr.ObjectMeta.GetName(), f.QualifiedPath), + Content: blob, + Operation: repo.OpCreate, + } + requests = append(requests, req) + } + return nil + }) + if err != nil { + return err + } + + // apply changes to gitops repo + if err := r.GitOpsRepoManager.ApplyChanges(ctx, requests, "chore(freeleaps-gitios-initializer): commit generated helm package"); err != nil { + return err + } + return nil } diff --git a/operators/freeleaps-gitops-initializer/internal/helm/generator.go b/operators/freeleaps-gitops-initializer/internal/helm/generator.go index 9a982c7c..a3ca9299 100644 --- a/operators/freeleaps-gitops-initializer/internal/helm/generator.go +++ b/operators/freeleaps-gitops-initializer/internal/helm/generator.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "os" + "path/filepath" "text/template" "freeleaps.com/gitops/initializer/api/v1alpha1" @@ -18,6 +19,7 @@ type HelmGenerator struct { io.Closer Instance *v1alpha1.ProjectInitialize workingDir string + generated bool } const leftDelim = "[[" @@ -205,9 +207,36 @@ func (hg *HelmGenerator) Generate() error { return err } } + hg.generated = true return nil } +type HelmGeneratedFile struct { + QualifiedPath string +} + +func (hgf *HelmGeneratedFile) ReadAll() ([]byte, error) { + return os.ReadFile(hgf.QualifiedPath) +} + +type HelmGeneratedFileCallback func(f *HelmGeneratedFile) error + +func (hg *HelmGenerator) Walk(cb HelmGeneratedFileCallback) error { + if !hg.generated { + return errors.New("helm package not generated") + } + + return filepath.Walk(hg.workingDir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() { + return cb(&HelmGeneratedFile{QualifiedPath: path}) + } + return nil + }) +} + func (hg *HelmGenerator) Close() error { if hg.workingDir != "" { return os.RemoveAll(hg.workingDir) diff --git a/operators/freeleaps-gitops-initializer/internal/helm/generator_test.go b/operators/freeleaps-gitops-initializer/internal/helm/generator_test.go new file mode 100644 index 00000000..9439bbf8 --- /dev/null +++ b/operators/freeleaps-gitops-initializer/internal/helm/generator_test.go @@ -0,0 +1,261 @@ +package helm + +import ( + "testing" + + "freeleaps.com/gitops/initializer/api/v1alpha1" + cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" + corev1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +var pathType = networkingv1.PathTypeImplementationSpecific + +var testCase = v1alpha1.ProjectInitialize{ + ObjectMeta: metav1.ObjectMeta{ + Name: "magicleaps-alpha", + }, + Spec: v1alpha1.ProjectInitializeSpec{ + Repository: &v1alpha1.RepositorySpec{ + Plugin: "azure-devops", + PluginConfig: map[string]string{ + "pat": "3E9J1v0si6HRvyc1RSRgT791W9ZvMi4kBmrznfcIXB8mq6Trj9VkJQQJ99BBACAAAAArj0WRAAASAZDO32n4", + "organizationUrl": "https://dev.azure.com/freeleaps", + }, + RegisterToArgo: true, + Project: "magicleaps", + Name: "magicleaps", + Type: v1alpha1.Monorepo, + Branch: "develop", + }, + Helm: &v1alpha1.HelmSpec{ + Generate: true, + Metadata: v1alpha1.HelmMetadataSpec{ + Name: "magicleaps", + Description: "A Helm Chart of magicleaps, powered by Freeleaps.", + }, + Global: v1alpha1.HelmGlobalValuesSpec{ + Registry: "docker.io", + Repository: "sunzhenyucn", + }, + Components: []v1alpha1.HelmComponentSpec{ + { + Name: "frontend", + Ports: []corev1.ContainerPort{ + { + Name: "http", + ContainerPort: 8080, + Protocol: corev1.ProtocolTCP, + }, + }, + Replicas: 1, + Resources: v1alpha1.HelmComponentResourceRequirementsSpec{ + Limits: v1alpha1.HelmComponentResourceSettingSpec{ + CPU: "100m", + Memory: "256Mi", + }, + Requests: v1alpha1.HelmComponentResourceSettingSpec{ + CPU: "50m", + Memory: "128Mi", + }, + }, + Image: v1alpha1.HelmComponentImageSpec{ + Repository: "sunzhenyucn", + Name: "magicleaps-frontend", + Tag: "1.0.0", + ImagePullPolicy: corev1.PullIfNotPresent, + }, + Probes: v1alpha1.HelmComponentProbesSpec{ + Liveness: v1alpha1.HelmComponentProbeSpec{ + Type: v1alpha1.HTTPGet, + Config: v1alpha1.HelmComponentProbeConfigSpec{ + Path: "/", + Port: 8080, + }, + }, + Readiness: v1alpha1.HelmComponentProbeSpec{ + Type: v1alpha1.HTTPGet, + Config: v1alpha1.HelmComponentProbeConfigSpec{ + Path: "/", + Port: 8080, + }, + }, + }, + Services: []v1alpha1.HelmComponentServiceSpec{ + { + Name: "magicleaps-frontend-service", + Type: corev1.ServiceTypeClusterIP, + Port: 80, + TargetPort: 8080, + }, + }, + Ingresses: []v1alpha1.HelmComponentIngressSpec{ + { + Name: "magicleaps-frontend-ingress", + Class: "nginx", + Host: "alpha.magicleaps.mathmast.com", + Rules: []networkingv1.HTTPIngressPath{ + { + Path: "/*", + PathType: &pathType, + Backend: networkingv1.IngressBackend{ + Service: &networkingv1.IngressServiceBackend{ + Name: "magicleaps-frontend-service", + Port: networkingv1.ServiceBackendPort{ + Number: 80, + }, + }, + }, + }, + }, + TLS: v1alpha1.HelmComponentIngressTLSSpec{ + Exists: false, + Name: "magicleaps-alpha-frontend-ingress-tls", + IssuerRef: &cmmeta.ObjectReference{ + Name: "mathmast-dot-com", + Kind: "ClusterIssuer", + Group: "cert-manager.io", + }, + }, + }, + }, + Configs: []v1alpha1.HelmComponentConfigSpec{ + { + Name: "magicleaps-frontend-config", + Type: v1alpha1.EnvironmentSecret, + Data: []corev1.EnvVar{ + { + Name: "TZ", + Value: "America/Settle", + }, + }, + }, + }, + }, + + { + Name: "backend", + Ports: []corev1.ContainerPort{ + { + Name: "http", + ContainerPort: 8081, + Protocol: corev1.ProtocolTCP, + }, + }, + Replicas: 1, + Resources: v1alpha1.HelmComponentResourceRequirementsSpec{ + Limits: v1alpha1.HelmComponentResourceSettingSpec{ + CPU: "200m", + Memory: "512Mi", + }, + Requests: v1alpha1.HelmComponentResourceSettingSpec{ + CPU: "100m", + Memory: "256Mi", + }, + }, + Image: v1alpha1.HelmComponentImageSpec{ + Repository: "sunzhenyucn", + Name: "magicleaps-backend", + Tag: "1.0.0", + ImagePullPolicy: corev1.PullIfNotPresent, + }, + Probes: v1alpha1.HelmComponentProbesSpec{ + Liveness: v1alpha1.HelmComponentProbeSpec{ + Type: v1alpha1.HTTPGet, + Config: v1alpha1.HelmComponentProbeConfigSpec{ + Path: "/api/_/probe/liveness", + Port: 8081, + }, + }, + Readiness: v1alpha1.HelmComponentProbeSpec{ + Type: v1alpha1.HTTPGet, + Config: v1alpha1.HelmComponentProbeConfigSpec{ + Path: "/api/_/probe/readiness", + Port: 8081, + }, + }, + }, + Services: []v1alpha1.HelmComponentServiceSpec{ + { + Name: "magicleaps-backend-service", + Type: corev1.ServiceTypeClusterIP, + Port: 8081, + TargetPort: 8081, + }, + }, + Ingresses: []v1alpha1.HelmComponentIngressSpec{}, + Configs: []v1alpha1.HelmComponentConfigSpec{ + { + Name: "magicleaps-backend-config", + Type: v1alpha1.EnvironmentSecret, + Data: []corev1.EnvVar{ + { + Name: "TZ", + Value: "America/Settle", + }, + { + Name: "MONGODB_HOST", + Value: "localhost", + }, + { + Name: "MONGODB_PORT", + Value: "27017", + }, + { + Name: "MONGODB_NAME", + Value: "interview", + }, + { + Name: "EMAIL_USER", + Value: "your@freeleaps.com", + }, + { + Name: "EMAIL_PASSWORD", + Value: "your-password", + }, + { + Name: "SUPER_ADMIN", + Value: "your@email.com", + }, + { + Name: "TWILIO_ACCOUNT_SID", + Value: "", + }, + { + Name: "TWILIO_AUTH_TOKEN", + Value: "", + }, + { + Name: "EVELUATION_TASK_FOLDER_BASE", + Value: "temp/interview/eveluation_task/", + }, + { + Name: "LOG_DIR", + Value: "logs", + }, + { + Name: "APP_LOG_FILE", + Value: "app.log", + }, + { + Name: "APP_LOG_LEVEL", + Value: "INFO", + }, + }, + }, + }, + }, + }, + }, + }, +} + +func TestGenerate(t *testing.T) { + gen := &HelmGenerator{ + Instance: &testCase, + } + if err := gen.Generate(); err != nil { + t.Error(err) + } +} diff --git a/operators/freeleaps-gitops-initializer/internal/helm/metadata-values.yaml b/operators/freeleaps-gitops-initializer/internal/helm/metadata-values.yaml deleted file mode 100644 index de530a71..00000000 --- a/operators/freeleaps-gitops-initializer/internal/helm/metadata-values.yaml +++ /dev/null @@ -1,109 +0,0 @@ -global: - registry: docker.io - repository: test - nodeSelector: - beta.kubernetes.io/os: linux -frontend: - replicas: 1 - image: - registry: docker.io - repository: test - name: frontend - tag: latest - imagePullPolicy: IfNotPresent - resources: - requests: - cpu: "100m" - memory: "128Mi" - limits: - cpu: "100m" - memory: "128Mi" - probes: - liveness: - type: httpGet - config: - path: /healthz - port: 8080 - readiness: - type: httpGet - config: - path: /readyz - port: 8080 - services: - - name: frontend - type: ClusterIP - port: 8080 - targetPort: 8080 - ingresses: - - name: frontend - host: test.com - class: nginx - rules: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: frontend - port: - number: 8080 - tls: - exists: false - issuerRef: - name: test-issuer - kind: ClusterIssuer - name: test-cert - configs: - testEnvVar: "test" - mongoDb: "mongodb" -backend: - replicas: 1 - image: - registry: docker.io - repository: test - name: backend - tag: latest - imagePullPolicy: IfNotPresent - resources: - requests: - cpu: "100m" - memory: "128Mi" - limits: - cpu: "100m" - memory: "128Mi" - probes: - liveness: - type: httpGet - config: - path: /healthz - port: 8081 - readiness: - type: httpGet - config: - path: /readyz - port: 8081 - services: - - name: backend - type: ClusterIP - port: 8081 - targetPort: 8081 - ingresses: - - name: backend - host: test.com - class: nginx - rules: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: backend - port: - number: 8080 - tls: - exists: false - issuerRef: - name: test-issuer - kind: ClusterIssuer - name: test-cert - configs: - testEnvVar1: "test" - mongoDb1: "mongodb" diff --git a/operators/freeleaps-gitops-initializer/internal/jenkins/generator.go b/operators/freeleaps-gitops-initializer/internal/jenkins/generator.go new file mode 100644 index 00000000..6cde1600 --- /dev/null +++ b/operators/freeleaps-gitops-initializer/internal/jenkins/generator.go @@ -0,0 +1,96 @@ +package jenkins + +import ( + "embed" + "fmt" + "html/template" + "io" + "os" + + "freeleaps.com/gitops/initializer/api/v1alpha1" +) + +//go:embed templates/* +var embeddedTemplates embed.FS + +type JenkinsfileGenerator struct { + io.Closer + Instance *v1alpha1.ProjectInitialize + workingDir string + generated bool +} + +const leftDelim = "[[" +const rightDelim = "]]" + +func (jg *JenkinsfileGenerator) prepareWorkingDir() error { + path, err := os.MkdirTemp("", fmt.Sprintf("jenkinsfile-gen-%s-*", jg.Instance.Name)) + if err != nil { + return fmt.Errorf("failed to create jenkinsfile generator temp dir: %w", err) + } + jg.workingDir = path + return nil +} + +func (jg *JenkinsfileGenerator) readTemplate(name string) (*template.Template, error) { + tpl := template.New(name) + templateBytes, err := embeddedTemplates.ReadFile(name) + if err != nil { + return nil, fmt.Errorf("failed to read template %s: %w", name, err) + } + tpl, err = tpl. + Delims(leftDelim, rightDelim). + Parse(string(templateBytes)) + if err != nil { + return nil, fmt.Errorf("failed to parse template %s: %w", name, err) + } + return tpl, nil +} + +func (jg *JenkinsfileGenerator) Generate() error { + if jg.Instance == nil { + return fmt.Errorf("instance is nil") + } + + if err := jg.prepareWorkingDir(); err != nil { + return err + } + + tpl, err := jg.readTemplate("templates/Jenkinsfile.tpl") + if err != nil { + return err + } + + jenkinsfileFd, err := os.Create(jg.workingDir + "/Jenkinsfile") + if err != nil { + return fmt.Errorf("failed to create Jenkinsfile: %w", err) + } + defer jenkinsfileFd.Close() + + if err := tpl.Execute(jenkinsfileFd, jg.Instance.Spec); err != nil { + return fmt.Errorf("failed to render Jenkinsfile with template: %w", err) + } + jg.generated = true + + return nil +} + +func (jg *JenkinsfileGenerator) Close() error { + if jg.workingDir != "" { + return os.RemoveAll(jg.workingDir) + } + return nil +} + +func (jg *JenkinsfileGenerator) ReadGeneratedJenkinsfile() ([]byte, error) { + if !jg.generated { + return nil, fmt.Errorf("jenkinsfile not generated") + } + + jenkinsfileBytes, err := os.ReadFile(jg.workingDir + "/Jenkinsfile") + if err != nil { + return nil, fmt.Errorf("failed to read generated Jenkinsfile: %w", err) + } + + return jenkinsfileBytes, nil +} diff --git a/operators/freeleaps-gitops-initializer/internal/jenkins/templates/Jenkinsfile.tpl b/operators/freeleaps-gitops-initializer/internal/jenkins/templates/Jenkinsfile.tpl new file mode 100644 index 00000000..0da2ecdb --- /dev/null +++ b/operators/freeleaps-gitops-initializer/internal/jenkins/templates/Jenkinsfile.tpl @@ -0,0 +1,28 @@ +library 'first-class-pipeline' + +executeFreeleapsPipeline { + serviceName = [[ .ServiceName | quote ]] + environmentSlug = [[ .EnvironmentSlug | quote ]] + serviceGitBranch = [[ .Spec.Repository.Branch | quote ]] + serviceGitRepo = [[ .GitRepoURL | quote ]] + serviceGitRepoType = [[ .Spec.Repository.Type | quote ]] + serviceGitCredentialsId = [[ .JenkinsGitCredentialsId | quote ]] + executeMode = [[ .Spec.ContinuousIntegrationSpec.ExecuteMode | quote ]] + commitMessageLintEnabled = [[ .Spec.ContinuousIntegrationSpec.CommitMessageLintEnabled ]] + components = [ +[[- range $component := .Spec.ContinuousIntegrationSpec.Components ]] + [ + name: [[ $component.Name | quote ]], + root: [[ $component.Root | quote ]], + language: [[ $component.Language | quote ]], + dependenciesManager: [[ $component.DependenciesManager | quote ]], +[[- if and (eq $component.DependenciesManager "npm") ($component.NPMPackageJsonFile) ]] + npmPackageJsonFile: [[ $component.NPMPackageJsonFile | quote ]], +[[- end ]] +[[- if $component.BuildCacheEnabled ]] + buildCacheEnabled: [[ $component.BuildCacheEnabled ]], +[[- end ]] + ] +[[- end ]] + ] +} \ No newline at end of file diff --git a/operators/freeleaps-gitops-initializer/internal/repo/plugin.go b/operators/freeleaps-gitops-initializer/internal/repo/plugin.go index 2a92959d..3dc09738 100644 --- a/operators/freeleaps-gitops-initializer/internal/repo/plugin.go +++ b/operators/freeleaps-gitops-initializer/internal/repo/plugin.go @@ -7,9 +7,11 @@ import ( var ( pluginsMu sync.RWMutex - plugins = make(map[string]RepoManager) + plugins = make(map[string]PluginCreateFunc) ) +type PluginCreateFunc func() RepoManager + type PluginConfig interface { Get(key string) (any, error) Set(key string, value any) @@ -37,25 +39,25 @@ func NewPluginConfig() PluginConfig { } } -func RegisterPlugin(name string, plugin RepoManager) { +func RegisterPlugin(name string, fun PluginCreateFunc) { pluginsMu.Lock() defer pluginsMu.Unlock() - if plugin == nil { - panic("plugin cannot be nil") + if fun == nil { + panic("plugin create func cannot be nil") } if old, exists := plugins[name]; exists { fmt.Printf("WARNING: plugin '%s' already registered (%T), overwriting\n", name, old) } - plugins[name] = plugin + plugins[name] = fun } func GetPlugin(name string) (RepoManager, bool) { pluginsMu.RLock() defer pluginsMu.RUnlock() - plugin, exists := plugins[name] - return plugin, exists + fun, exists := plugins[name] + return fun(), exists } diff --git a/operators/freeleaps-gitops-initializer/internal/repo/plugins/azure/azure.go b/operators/freeleaps-gitops-initializer/internal/repo/plugins/azure/azure.go index 7b34ef7b..b2c4ca68 100644 --- a/operators/freeleaps-gitops-initializer/internal/repo/plugins/azure/azure.go +++ b/operators/freeleaps-gitops-initializer/internal/repo/plugins/azure/azure.go @@ -19,7 +19,9 @@ type AzureDevOpsRepoManager struct { var _ repo.RepoManager = &AzureDevOpsRepoManager{} func init() { - repo.RegisterPlugin("azure-devops", &AzureDevOpsRepoManager{}) + repo.RegisterPlugin("azure-devops", func() repo.RepoManager { + return &AzureDevOpsRepoManager{} + }) } // Initialize implements repo.RepoManager.