From eebf5c58e0f5a68b03d9613949455d278e94d5da357e454f1b29c35a6cffa192 Mon Sep 17 00:00:00 2001 From: raven <7156279+RavenX8@users.noreply.github.com> Date: Mon, 17 Mar 2025 23:59:33 -0400 Subject: [PATCH] - add: helm chart - add: python script for building and pushing the containers --- charts/osirose-new/.helmignore | 23 ++++ charts/osirose-new/Chart.yaml | 24 ++++ charts/osirose-new/templates/_helpers.tpl | 62 +++++++++ charts/osirose-new/templates/configmap.yaml | 14 ++ charts/osirose-new/templates/deployment.yaml | 33 +++++ charts/osirose-new/templates/hpa.yaml | 33 +++++ charts/osirose-new/templates/ingress.yaml | 25 ++++ charts/osirose-new/templates/service.yaml | 20 +++ .../templates/tests/test-connection.yaml | 20 +++ charts/osirose-new/values.yaml | 127 ++++++++++++++++++ scripts/build_and_push.py | 72 ++++++++++ 11 files changed, 453 insertions(+) create mode 100644 charts/osirose-new/.helmignore create mode 100644 charts/osirose-new/Chart.yaml create mode 100644 charts/osirose-new/templates/_helpers.tpl create mode 100644 charts/osirose-new/templates/configmap.yaml create mode 100644 charts/osirose-new/templates/deployment.yaml create mode 100644 charts/osirose-new/templates/hpa.yaml create mode 100644 charts/osirose-new/templates/ingress.yaml create mode 100644 charts/osirose-new/templates/service.yaml create mode 100644 charts/osirose-new/templates/tests/test-connection.yaml create mode 100644 charts/osirose-new/values.yaml create mode 100644 scripts/build_and_push.py diff --git a/charts/osirose-new/.helmignore b/charts/osirose-new/.helmignore new file mode 100644 index 0000000..1b9a9cc --- /dev/null +++ b/charts/osirose-new/.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/charts/osirose-new/Chart.yaml b/charts/osirose-new/Chart.yaml new file mode 100644 index 0000000..ad5bcc6 --- /dev/null +++ b/charts/osirose-new/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: osirose-new +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: "0.1.0" diff --git a/charts/osirose-new/templates/_helpers.tpl b/charts/osirose-new/templates/_helpers.tpl new file mode 100644 index 0000000..cdb19e2 --- /dev/null +++ b/charts/osirose-new/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "osirose-new.name" -}} +{{- default .Chart.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 "osirose-new.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 "osirose-new.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "osirose-new.labels" -}} +helm.sh/chart: {{ include "osirose-new.chart" . }} +{{ include "osirose-new.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "osirose-new.selectorLabels" -}} +app.kubernetes.io/name: {{ include "osirose-new.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "osirose-new.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "osirose-new.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/charts/osirose-new/templates/configmap.yaml b/charts/osirose-new/templates/configmap.yaml new file mode 100644 index 0000000..93920d0 --- /dev/null +++ b/charts/osirose-new/templates/configmap.yaml @@ -0,0 +1,14 @@ +{{- range .Values.services }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .name }}-env +data: +{{- range $key, $value := $.Values.global.env }} + {{ $key }}: "{{ $value }}" +{{- end }} +{{- range $key, $value := .env }} + {{ $key }}: "{{ $value }}" +{{- end }} +--- +{{- end }} diff --git a/charts/osirose-new/templates/deployment.yaml b/charts/osirose-new/templates/deployment.yaml new file mode 100644 index 0000000..14005c8 --- /dev/null +++ b/charts/osirose-new/templates/deployment.yaml @@ -0,0 +1,33 @@ +{{- range .Values.services }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .name }} + labels: + app: {{ .name }} +spec: + replicas: {{ .replicas }} + selector: + matchLabels: + app: {{ .name }} + template: + metadata: + labels: + app: {{ .name }} + spec: + containers: + - name: {{ .name }} + image: "{{ $.Values.repository }}/{{ .image }}" + ports: + - containerPort: {{ .port }} + envFrom: + - configMapRef: + name: {{ .name }}-env + volumeMounts: + - name: service-ids + mountPath: /services + volumes: + - name: service-ids + emptyDir: {} +--- +{{- end }} diff --git a/charts/osirose-new/templates/hpa.yaml b/charts/osirose-new/templates/hpa.yaml new file mode 100644 index 0000000..492594a --- /dev/null +++ b/charts/osirose-new/templates/hpa.yaml @@ -0,0 +1,33 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "osirose-new.fullname" . }} + labels: + {{- include "osirose-new.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "osirose-new.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +--- +{{- end }} diff --git a/charts/osirose-new/templates/ingress.yaml b/charts/osirose-new/templates/ingress.yaml new file mode 100644 index 0000000..f00b698 --- /dev/null +++ b/charts/osirose-new/templates/ingress.yaml @@ -0,0 +1,25 @@ +{{- range .Values.services }} +{{- if .ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .name }}-ingress + labels: + app: {{ .name }} + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + rules: + - host: {{ .ingress.hostname }} + http: + paths: + - path: {{ .ingress.path }} + pathType: Prefix + backend: + service: + name: {{ .name }} + port: + number: {{ .port }} +--- +{{- end }} +{{- end }} diff --git a/charts/osirose-new/templates/service.yaml b/charts/osirose-new/templates/service.yaml new file mode 100644 index 0000000..15d8cd7 --- /dev/null +++ b/charts/osirose-new/templates/service.yaml @@ -0,0 +1,20 @@ +{{- range .Values.services }} +{{- if .tcp.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ .name }} + labels: + app: {{ .name }} +spec: + type: {{ .tcp.type | default "ClusterIP" }} + ports: + - name: {{ .tcp.portName | default "tcp" }} + port: {{ .tcp.port }} + targetPort: {{ .tcp.targetPort | default .tcp.port }} + protocol: {{ .tcp.protocol | default "TCP" }} + selector: + app: {{ .name }} +{{- end }} +--- +{{- end }} diff --git a/charts/osirose-new/templates/tests/test-connection.yaml b/charts/osirose-new/templates/tests/test-connection.yaml new file mode 100644 index 0000000..d3b5e3d --- /dev/null +++ b/charts/osirose-new/templates/tests/test-connection.yaml @@ -0,0 +1,20 @@ +{{- if .Values.tests.enabled }} +{{- range .Values.tests.services }} +apiVersion: v1 +kind: Pod +metadata: + name: {{ .name }}-test + annotations: + "helm.sh/hook": test + "helm.sh/hook-delete-policy": before-hook-creation + labels: + app: {{ .name }} +spec: + containers: + - name: {{ .name }}-test + image: {{ .image }} + command: {{ .testCommand }} + restartPolicy: Never +--- +{{- end }} +{{- end }} diff --git a/charts/osirose-new/values.yaml b/charts/osirose-new/values.yaml new file mode 100644 index 0000000..234df09 --- /dev/null +++ b/charts/osirose-new/values.yaml @@ -0,0 +1,127 @@ + +repository: gitea.azgstudio.com/raven + +autoscaling: + enabled: false + +global: + env: + LOG_LEVEL: "info" + APP_ENV: "dev" + DATABASE_URL: "postgres://postgres:5432/osirose" + +services: + - name: api-service + replicas: 1 + image: api-service:latest + port: 8080 + env: + SERVICE_NAME: "api-service" + tcp: + enabled: true + portName: api-service + port: 8080 + targetPort: 8080 + protocol: TCP + ingress: + enabled: true + hostname: game-api.azgstudio.com + path: "/" + port: 8080 + + - name: auth-service + replicas: 1 + image: auth-service:latest + port: 50051 + env: + SERVICE_NAME: "auth-service" + tcp: + enabled: true + portName: auth-service + port: 50051 + targetPort: 50051 + protocol: TCP + ingress: + enabled: false + + - name: character-service + replicas: 1 + image: character-service:latest + port: 50053 + env: + SERVICE_NAME: "character-service" + tcp: + enabled: true + portName: character-service + port: 50053 + targetPort: 50053 + protocol: TCP + ingress: + enabled: false + + - name: database-service + replicas: 1 + image: database-service:latest + port: 50052 + env: + SERVICE_NAME: "database-service" + tcp: + enabled: true + portName: database-service + port: 50052 + targetPort: 50052 + protocol: TCP + ingress: + enabled: false + + - name: packet-service + replicas: 1 + image: packet-service:latest + port: 29000 + env: + SERVICE_NAME: "packet-service" + tcp: + enabled: true + portName: game-packet-service + port: 29000 + targetPort: 29000 + protocol: TCP + ingress: + enabled: false + + - name: session-service + replicas: 1 + image: session-service:latest + port: 50055 + env: + SERVICE_NAME: "session-service" + tcp: + enabled: true + portName: session-service + port: 50055 + targetPort: 50055 + protocol: TCP + ingress: + enabled: false + + - name: world-service + replicas: 1 + image: world-service:latest + port: 50054 + env: + SERVICE_NAME: "world-service" + tcp: + enabled: true + portName: world-service + port: 50054 + targetPort: 50054 + protocol: TCP + ingress: + enabled: false + +tests: + enabled: true + services: + - name: api-service + testCommand: ["curl", "-f", "http://api-service:8080/health"] + image: curlimages/curl:latest diff --git a/scripts/build_and_push.py b/scripts/build_and_push.py new file mode 100644 index 0000000..2873801 --- /dev/null +++ b/scripts/build_and_push.py @@ -0,0 +1,72 @@ +import subprocess +import os + +# Define your images, tags, and Dockerfile paths +images = ["api-service", "auth-service", "character-service", "database-service", "packet-service", "session-service", "world-service"] +dockerfile_paths = [ + "../api-service/Dockerfile", + "../auth-service/Dockerfile", + "../character-service/Dockerfile", + "../database-service/Dockerfile", + "../packet-service/Dockerfile", + "../session-service/Dockerfile", + "../world-service/Dockerfile", +] + +common_tag = "latest" +version_tag = "v0.1.0" +image_tag_prefix = "gitea.azgstudio.com/raven/" +build_context = "../" + +def run_command(command): + """Run a shell command and handle errors.""" + try: + subprocess.run(command, check=True) + except subprocess.CalledProcessError as e: + print(f"Error: Command '{' '.join(command)}' failed with exit code {e.returncode}") + exit(1) + + +def build_images(images, dockerfile_paths, common_tag, version_tag, image_tag_prefix, build_context): + """Build all Docker images.""" + for image, dockerfile_path in zip(images, dockerfile_paths): + # Add the prefix to the image name + full_image_name = f"{image_tag_prefix}{image}" + + # Build the image with both tags + print(f"Building {full_image_name}:{version_tag} and {full_image_name}:{common_tag} using Dockerfile at {dockerfile_path}...") + run_command([ + "docker", "build", + "-t", f"{full_image_name}:{version_tag}", + "-t", f"{full_image_name}:{common_tag}", + "-f", dockerfile_path, + build_context + ]) + + +def push_images(images, common_tag, version_tag, image_tag_prefix): + """Push all Docker images.""" + for image in images: + # Add the prefix to the image name + full_image_name = f"{image_tag_prefix}{image}" + + # Push both tags + print(f"Pushing {full_image_name}:{version_tag}...") + run_command(["docker", "push", f"{full_image_name}:{version_tag}"]) + + print(f"Pushing {full_image_name}:{common_tag}...") + run_command(["docker", "push", f"{full_image_name}:{common_tag}"]) + + +if __name__ == "__main__": + script_dir = os.path.dirname(os.path.abspath(__file__)) + os.chdir(script_dir) + + # Build all images first + print("Starting the build phase...") + build_images(images, dockerfile_paths, common_tag, version_tag, image_tag_prefix, build_context) + + # Push all images after builds are complete + print("Starting the push phase...") + push_images(images, common_tag, version_tag, image_tag_prefix) +