From 2b32dfb95b3334e1550948d4d3f64c9af0040fa4 Mon Sep 17 00:00:00 2001 From: Elie CHARRA Date: Wed, 21 Feb 2024 11:24:22 +0100 Subject: [PATCH] Initial commit --- .github/workflows/build.yml | 29 ++++++++++++++ app/Dockerfile | 11 ++++++ app/go.mod | 3 ++ app/main.go | 32 +++++++++++++++ infra/app/deployment.yaml | 30 +++++++++++++++ infra/app/service.yaml | 10 +++++ infra/app/spacelift.yaml | 37 ++++++++++++++++++ infra/helm/.helmignore | 23 +++++++++++ infra/helm/Chart.yaml | 24 ++++++++++++ infra/helm/templates/_helpers.tpl | 47 +++++++++++++++++++++++ infra/helm/templates/deployment.yaml | 31 +++++++++++++++ infra/helm/templates/service.yaml | 15 ++++++++ infra/helm/templates/spacelift/run.yaml | 6 +++ infra/helm/templates/spacelift/stack.yaml | 9 +++++ infra/helm/values.yaml | 37 ++++++++++++++++++ infra/tf/.terraform.lock.hcl | 36 +++++++++++++++++ infra/tf/main.tf | 3 ++ infra/tf/provider.tf | 3 ++ infra/tf/s3.tf | 10 +++++ 19 files changed, 396 insertions(+) create mode 100644 .github/workflows/build.yml create mode 100644 app/Dockerfile create mode 100644 app/go.mod create mode 100644 app/main.go create mode 100644 infra/app/deployment.yaml create mode 100644 infra/app/service.yaml create mode 100644 infra/app/spacelift.yaml create mode 100644 infra/helm/.helmignore create mode 100644 infra/helm/Chart.yaml create mode 100644 infra/helm/templates/_helpers.tpl create mode 100644 infra/helm/templates/deployment.yaml create mode 100644 infra/helm/templates/service.yaml create mode 100644 infra/helm/templates/spacelift/run.yaml create mode 100644 infra/helm/templates/spacelift/stack.yaml create mode 100644 infra/helm/values.yaml create mode 100644 infra/tf/.terraform.lock.hcl create mode 100644 infra/tf/main.tf create mode 100644 infra/tf/provider.tf create mode 100644 infra/tf/s3.tf diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..5dfc216 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,29 @@ +name: Build docker image +on: + push: + branches: + - main +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: ./app + platforms: linux/amd64,linux/arm64 + push: true + tags: | + ghcr.io/spacelift-io/spacelift-operator-demo:latest + ghcr.io/spacelift-io/spacelift-operator-demo:${{ github.sha }} diff --git a/app/Dockerfile b/app/Dockerfile new file mode 100644 index 0000000..3ce8635 --- /dev/null +++ b/app/Dockerfile @@ -0,0 +1,11 @@ +FROM golang:1.21.7 as builder +WORKDIR /build +COPY . . +RUN GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o demo . + +FROM scratch +COPY --from=builder /build/demo /bin/demo +ENTRYPOINT ["/bin/demo"] + + + diff --git a/app/go.mod b/app/go.mod new file mode 100644 index 0000000..7ffef20 --- /dev/null +++ b/app/go.mod @@ -0,0 +1,3 @@ +module github.com/spacelift-io/spacelift-operator-demo + +go 1.21.7 diff --git a/app/main.go b/app/main.go new file mode 100644 index 0000000..5bca7d0 --- /dev/null +++ b/app/main.go @@ -0,0 +1,32 @@ +package main + +import ( + "errors" + "fmt" + "log" + "net/http" + "os" +) + +func main() { + listenAddr := ":8888" + http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) { + log.Println(request.Method, request.URL.String()) + if request.URL.Path != "/" { + writer.WriteHeader(http.StatusNotFound) + return + } + secrets := os.Environ() + body := "" + for i := 0; i < len(secrets); i++ { + body += fmt.Sprintf("%s\n", secrets[i]) + } + _, _ = writer.Write([]byte(body)) + }) + log.Printf("Listening on %s\n", listenAddr) + if err := http.ListenAndServe(listenAddr, nil); err != nil { + if !errors.Is(err, http.ErrServerClosed) { + log.Fatal(err) + } + } +} diff --git a/infra/app/deployment.yaml b/infra/app/deployment.yaml new file mode 100644 index 0000000..f5dffaf --- /dev/null +++ b/infra/app/deployment.yaml @@ -0,0 +1,30 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: demo +spec: + replicas: 1 + revisionHistoryLimit: 3 + selector: + matchLabels: + app: demo + template: + metadata: + labels: + app: demo + spec: + containers: + - image: ghcr.io/spacelift-io/spacelift-operator-demo:latest + imagePullPolicy: Always + name: demo + ports: + - containerPort: 80 + name: demo-port + volumeMounts: + - name: secrets + mountPath: /secrets + readOnly: true + volumes: + - name: secrets + secret: + secretName: stack-output-spacelift-operator-demo diff --git a/infra/app/service.yaml b/infra/app/service.yaml new file mode 100644 index 0000000..e2c4c22 --- /dev/null +++ b/infra/app/service.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: demo +spec: + ports: + - port: 80 + targetPort: demo-port + selector: + app: demo diff --git a/infra/app/spacelift.yaml b/infra/app/spacelift.yaml new file mode 100644 index 0000000..8f82f1b --- /dev/null +++ b/infra/app/spacelift.yaml @@ -0,0 +1,37 @@ +apiVersion: app.spacelift.io/v1beta1 +kind: Stack +metadata: + name: demo-stack + annotations: + argocd.argoproj.io/sync-wave: "-2" +spec: + name: spacelift-operator-demo + commitSHA: 37ecb7856840b8336b6b9e163472ef844c8d9800 + settings: + administrative: false + space: spacelift-operator-01HR9KQ590MFT6H6ETFJ657KR6 + namespace: spacelift-io + repository: spacelift-operator-demo + projectRoot: infra/tf + branch: main + managesStateFile: true + awsIntegration: + id: 01HRQ4YMJQTP5R6K8Q9N1NB3XM + read: true + write: true + vendorConfig: + terraform: + version: 1.6.2 + workflowTool: OPEN_TOFU + labels: + - argo +--- +apiVersion: app.spacelift.io/v1beta1 +kind: Run +metadata: + name: spacelift-operator-demo + annotations: + argocd.argoproj.io/hook: Sync + argocd.argoproj.io/sync-wave: "-1" +spec: + stackName: demo-stack diff --git a/infra/helm/.helmignore b/infra/helm/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/infra/helm/.helmignore @@ -0,0 +1,23 @@ +# 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/infra/helm/Chart.yaml b/infra/helm/Chart.yaml new file mode 100644 index 0000000..f422eea --- /dev/null +++ b/infra/helm/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: operator-demo +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.0.0" diff --git a/infra/helm/templates/_helpers.tpl b/infra/helm/templates/_helpers.tpl new file mode 100644 index 0000000..a6b2985 --- /dev/null +++ b/infra/helm/templates/_helpers.tpl @@ -0,0 +1,47 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "operator-demo.name" -}} +{{- default .Chart.Name | 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 "operator-demo.fullname" -}} +{{- $name := default .Chart.Name }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "operator-demo.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "operator-demo.labels" -}} +helm.sh/chart: {{ include "operator-demo.chart" . }} +{{ include "operator-demo.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "operator-demo.selectorLabels" -}} +app.kubernetes.io/name: {{ include "operator-demo.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/infra/helm/templates/deployment.yaml b/infra/helm/templates/deployment.yaml new file mode 100644 index 0000000..2f3de8b --- /dev/null +++ b/infra/helm/templates/deployment.yaml @@ -0,0 +1,31 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "operator-demo.fullname" . }} + labels: + {{- include "operator-demo.labels" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "operator-demo.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "operator-demo.labels" . | nindent 8 }} + spec: + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + envFrom: + - secretRef: + name: stack-output-spacelift-operator-demo diff --git a/infra/helm/templates/service.yaml b/infra/helm/templates/service.yaml new file mode 100644 index 0000000..047bf56 --- /dev/null +++ b/infra/helm/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "operator-demo.fullname" . }} + labels: + {{- include "operator-demo.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "operator-demo.selectorLabels" . | nindent 4 }} diff --git a/infra/helm/templates/spacelift/run.yaml b/infra/helm/templates/spacelift/run.yaml new file mode 100644 index 0000000..fa5df0a --- /dev/null +++ b/infra/helm/templates/spacelift/run.yaml @@ -0,0 +1,6 @@ +apiVersion: app.spacelift.io/v1beta1 +kind: Run +metadata: + name: run-{{ .Values.image.tag }} +spec: + stackName: {{ .Values.spacelift.stack.name }} diff --git a/infra/helm/templates/spacelift/stack.yaml b/infra/helm/templates/spacelift/stack.yaml new file mode 100644 index 0000000..2fbc920 --- /dev/null +++ b/infra/helm/templates/spacelift/stack.yaml @@ -0,0 +1,9 @@ +apiVersion: app.spacelift.io/v1beta1 +kind: Stack +metadata: + name: {{ .Values.spacelift.stack.name }} +spec: + name: {{ .Values.spacelift.stack.name }} + commitSHA: {{ .Values.image.tag }} + settings: + {{- toYaml .Values.spacelift.stack.settings | nindent 4 }} diff --git a/infra/helm/values.yaml b/infra/helm/values.yaml new file mode 100644 index 0000000..e6b9ae3 --- /dev/null +++ b/infra/helm/values.yaml @@ -0,0 +1,37 @@ +replicaCount: 1 +image: + repository: ghcr.io/spacelift-io/spacelift-operator-demo + pullPolicy: IfNotPresent + tag: "" +service: + type: ClusterIP + port: 80 +livenessProbe: + httpGet: + path: / + port: http +readinessProbe: + httpGet: + path: / + port: http +spacelift: + stack: + name: spacelift-operator-demo + settings: + administrative: false + space: spacelift-operator-01HR9KQ590MFT6H6ETFJ657KR6 + namespace: spacelift-io + repository: spacelift-operator-demo + projectRoot: infra/tf + branch: main + managesStateFile: true + awsIntegration: + id: 01HRQ4YMJQTP5R6K8Q9N1NB3XM + read: true + write: true + vendorConfig: + terraform: + version: 1.6.2 + workflowTool: OPEN_TOFU + labels: + - argo diff --git a/infra/tf/.terraform.lock.hcl b/infra/tf/.terraform.lock.hcl new file mode 100644 index 0000000..57b15de --- /dev/null +++ b/infra/tf/.terraform.lock.hcl @@ -0,0 +1,36 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/hashicorp/aws" { + version = "5.40.0" + hashes = [ + "h1:Z5VaTP8jwXG60IfHLaUIT2T+W0XvKrPWpZyxVmUUdsw=", + "zh:1689604abc131df74ef66839273474ee69a79256655de726242819a19c8d9f40", + "zh:1777da5659cd5a85d078674a7a80239f37397912036cb98e695ef5097d5ff53c", + "zh:216a63569d03e8fd1785dce59ceab182c84cf60dec6080e52e4d8e4e8be10cf3", + "zh:29ef1afbc819c5f52818f76ec1232f424a1502294774e32405c6c5e81e189331", + "zh:4bd44590ff060fac4b776c276f914a0d2225e78ec8a1cf83ea4236b0b29c7cbb", + "zh:75cceb4d9fa1736bd3969c7df2d477272f2187ff2f321fb2240a76e99b0e1f30", + "zh:c8938042376000ee904abddb8756533f2f4d861313cd4b99833df860ff0ed5f7", + "zh:eafe59e7fd68fb8d814a81c6139bd9463874e85f252ffefc9eb696c2e4828de6", + "zh:eef0ed78b52050afdd07563fcb2a0a49c9651edaf45f5810be71d60b141bb13c", + "zh:ff169ae274cd3cde075a9d3bfc2c6555d6ab40d6f9ced73ef14d31ef4ee58779", + ] +} + +provider "registry.opentofu.org/hashicorp/random" { + version = "3.6.0" + hashes = [ + "h1:6QMZ6JACl+V2t8daN5GTlw22EtG7nhc3BbkbJDw2a5M=", + "zh:486a1c921eab5c51a480f2eb0ad85173f207c9b7bb215f3893e58bc38d3b7c75", + "zh:6901b3afa4607d1e31934ba91ed2625215ada42b3518c3a9adeeac7a5f656dc3", + "zh:7e93752c9de710e417191353ad1a41b5a60432ab7ef4f8b556bf248297ec5e23", + "zh:c795d3d319e8ee7be972746b935963b7e772a6a14080261a35c03915c1f9ccb2", + "zh:cd4f8bcaf332828d1736c73874549c25e427737f136173c7b61e2df3db50e5d9", + "zh:e0103eb2e280989c3d9ffda5d6b413e8f583be21bc1d5754c6e9ca87ecc1c44a", + "zh:f4fbec2510322d5b7ad584a92436b5dbd0f2e897a3ec538932af59e245a4c8e4", + "zh:f5418842afd4aa7676e2456e425e8f573cb2b9bffd29bd7de09d91845644ab24", + "zh:f572a26f93d00ec42461ce478678366e570fa4497e2273f9d47f24cdfc4b42b4", + "zh:ff1f07c561a3f7f219b6fee1647a559933b5dd6181753e164c3978fd47a11685", + ] +} diff --git a/infra/tf/main.tf b/infra/tf/main.tf new file mode 100644 index 0000000..fb236b6 --- /dev/null +++ b/infra/tf/main.tf @@ -0,0 +1,3 @@ +output "BUCKET_URL" { + value = "https://${aws_s3_bucket.bucket.bucket_regional_domain_name}" +} diff --git a/infra/tf/provider.tf b/infra/tf/provider.tf new file mode 100644 index 0000000..e62fc36 --- /dev/null +++ b/infra/tf/provider.tf @@ -0,0 +1,3 @@ +provider "aws" { + region = "eu-west-1" +} diff --git a/infra/tf/s3.tf b/infra/tf/s3.tf new file mode 100644 index 0000000..ddfc3e4 --- /dev/null +++ b/infra/tf/s3.tf @@ -0,0 +1,10 @@ +resource "random_string" "random" { + length = 6 + special = false + numeric = false + upper = false +} + +resource "aws_s3_bucket" "bucket" { + bucket = "bucket-${random_string.random.result}" +}