diff --git a/build.gradle.kts b/build.gradle.kts index 8974f2a..e6da829 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -30,6 +30,47 @@ nexusPublishing { } } +/** + * Sanitizes a Helm release name to ensure it adheres to Helm's naming conventions. + * + * Helm release names must: + * - Be no longer than 53 characters. + * - Contain only lowercase letters (`a-z`), digits (`0-9`), and hyphens (`-`). + * - Start with a letter. + * - End with a letter or digit. + * + * @param name The original release name to be sanitized. + * @return A sanitized release name that conforms to Helm's naming conventions. + */ +fun sanitizeHelmReleaseName(name: String?): String? { + if (name == null) { + return null + } + + var sanitized = name.toLowerCase().replace(Regex("[^a-z0-9-]"), "-") + + if (!sanitized.first().isLetter()) { + sanitized = "a$sanitized" + } + + if (!sanitized.last().isLetterOrDigit()) { + sanitized = sanitized.dropLastWhile { !it.isLetterOrDigit() } + if (sanitized.isEmpty()) { + sanitized = "default-release" + } + } + + if (sanitized.length > 53) { + sanitized = sanitized.take(53) + } + + if (!sanitized.last().isLetterOrDigit()) { + sanitized = sanitized.dropLastWhile { !it.isLetterOrDigit() } + } + + return sanitized +} + subprojects { apply(plugin = "java") apply(plugin = "idea") @@ -82,6 +123,17 @@ subprojects { set("dockerRegistry", it.getOrDefault("DOCKER_REGISTRY", project.properties["docker.registry"])) set("octopusGithubDockerRegistry", it.getOrDefault("OCTOPUS_GITHUB_DOCKER_REGISTRY", project.properties["octopus.github.docker.registry"])) set("bitbucketLicense", it.getOrDefault("BITBUCKET_LICENSE", project.properties["bitbucket.license"])) + + val platform = it.getOrDefault("PLATFORM", project.properties["platform"]) + set("platform", platform) + val helmRelease = sanitizeHelmReleaseName(it.getOrDefault("HELM_RELEASE", project.properties["helmRelease"]) as String?) + set("helmRelease", helmRelease) + val helmNamespace = it.getOrDefault("HELM_NAMESPACE", project.properties["helmNamespace"]) + set("helmNamespace", helmNamespace) + val clusterDomain = it.getOrDefault("CLUSTER_DOMAIN", project.properties["clusterDomain"]) + set( "clusterDomain", clusterDomain) + set("localDomain", it.getOrDefault("LOCAL_DOMAIN", project.properties["localDomain"])) + set("bitbucketHost", "$helmRelease-bitbucket-route-$helmNamespace.$clusterDomain") } } diff --git a/deploy/README.md b/deploy/README.md new file mode 100644 index 0000000..038b16c --- /dev/null +++ b/deploy/README.md @@ -0,0 +1,77 @@ +### Required enveraments + +- Helm +- OC (Openshift Client) + +### OC login + +```shell +oc login --token= --server= +``` + +### To show deployments + +To view templates generated by Helm with the Bitbucket profile: + +```shell +helm template chart --set bitbucket.license= --set vcsFacade.image.version= +``` + +To install the application in the namespace: + +```shell +helm upgrade --wait --install chart --namespace --set bitbucket.license= --set vcs-facade.image.tag= --set clusterDomain= --set localDomain= --set dockerRegistry= --set platform=okd +``` + +To uninstall the application: + +```shell +helm uninstall --namespace +``` + +#### Parameters + +- helm_release - Helm release name(This release is a specific deployment of that chart with a unique configuration, and it includes all the Kubernetes resources specified in the chart templates, such as deployments, services, and config maps. Helm releases allow you to manage, upgrade, and roll back your applications easily) +- project - Project namespace +- bitbucket.license - license token for BitBucket server +- dockerRegistry - Docker registry with images. +- cluster_domain - Cluster domain(the root domain used for all internal addresses within the cluster. It ensures predictable DNS names for inter-service communication.) +- local_host - Local host(typically refers to the default local domain suffix used for internal network addresses) + +### To run from gradle + +```shell +./gradlew deployHelm -Pdocker.registry= -Pplatform=okd -PhelmRelease= -PhelmNamespace= -PlocalDomain= -PclusterDomain= -Ptest.profile=bitbucket -Pversion= -Pbitbucket.license= +``` + +```shell +./gradlw uninstallHelm -PhelmRelease= -PhelmNamespace= +``` + +### Create a project in OKD + +1. To create a new project, you need to click the **Create Project** button in the dropdown menu, as shown in the image below. + +![img1.png](img/img1.png) + +2. Next, you need to create a **ServiceAccount** for access to the project. To do this, click the **Create ServiceAccount** button as shown in the image below. + +![img2.png](img/img2.png) + +3. In the ServiceAccount parameters, you need to specify a unique arbitrary name and the project name, as shown below. + +```yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: + namespace: +``` + +4. The created ServiceAccount will automatically create two sections in the Secrets section. One of them should have the type service-account-token, as shown in the picture. By entering this section, you will find a permanent token in the token field, which can be used to access OKD. + +![img3.png](img/img3.png) + +5. To assign roles, in the Project Access section, you need to add new access. In the Name field, specify the name of the ServiceAccount, and in the Role field, specify the role that will be assigned to this ServiceAccount. + +![img4.png](img/img4.png) diff --git a/deploy/build.gradle.kts b/deploy/build.gradle.kts new file mode 100644 index 0000000..3191c80 --- /dev/null +++ b/deploy/build.gradle.kts @@ -0,0 +1,67 @@ +val testProfile: String? = project.ext["testProfile"] as String? +val platform: String? = project.ext["platform"] as String? +val helmNamespace: String? = project.ext["helmNamespace"] as String? +val helmRelease: String? = project.ext["helmRelease"] as String? +val clusterDomain: String? = project.ext["clusterDomain"] as String? +val localDomain: String? = project.ext["localDomain"] as String? +var bitbucketHost: String? = project.ext["bitbucketHost"] as String? +val dockerRegistry: String? = project.ext["dockerRegistry"] as String? + +tasks.register("uninstallHelm") { + doLast { + if (helmRelease == null) { + throw GradleException("Helm release name is not set") + } + if (helmNamespace == null) { + throw GradleException("Helm namespace is not set") + } + val result = exec { + commandLine("helm", "uninstall", helmRelease, "--namespace", helmNamespace) + } + if (result.exitValue != 0) { + throw GradleException("Helm uninstall failed with exit code ${result.exitValue}") + } + } +} + +println("Profile: " + testProfile) +println("Platform: " + if (platform == "okd") "OKD" else "DOCKER-COMPOSE") + +tasks.register("deployHelm") { + + if (helmRelease == null) { + throw GradleException("Helm release name is not set") + } + if (helmNamespace == null) { + throw GradleException("Helm namespace is not set") + } + if (clusterDomain == null) { + throw GradleException("Cluster domain is not set") + } + if (localDomain == null) { + throw GradleException("Local domain is not set") + } + + println("Release: $helmRelease") + + val bitbucketLicense: String by project + + commandLine("helm", "upgrade", "--wait" + , "--install", helmRelease, "chart" + , "--namespace", helmNamespace + , "--set", "bitbucket.license=$bitbucketLicense" + , "--set", "vcs-facade.image.tag=${project.version}" + , "--set", "bitbucket.host=${bitbucketHost}" + , "--set", "clusterDomain=${clusterDomain}" + , "--set", "localDomain=${localDomain}" + , "--set", "dockerRegistry=$dockerRegistry" + , "--set", "platform=openshift" + ) + doLast { + val execResult = executionResult.get() + if (execResult.exitValue != 0) { + val errorOutput = standardOutput.toString() + throw GradleException("Helm deploy failed with exit code ${execResult.exitValue} and the following error:\\n$errorOutput") + } + } +} \ No newline at end of file diff --git a/deploy/chart/.helmignore b/deploy/chart/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/deploy/chart/.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/deploy/chart/Chart.yaml b/deploy/chart/Chart.yaml new file mode 100644 index 0000000..7d0701d --- /dev/null +++ b/deploy/chart/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: vcs-facade +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.0.1" diff --git a/deploy/chart/files/application-bitbucket.yml b/deploy/chart/files/application-bitbucket.yml new file mode 100644 index 0000000..eb3a03c --- /dev/null +++ b/deploy/chart/files/application-bitbucket.yml @@ -0,0 +1,17 @@ +vcs-facade: + vcs: + bitbucket: + host: http://{{ .Values.bitbucket.host | default "bitbucket:7990" }} + username: admin + password: admin + health-check: + repo: ssh://git@bitbucket:7990/test-data/vcs-facade-healthcheck.git + root-commit: 9320183f5d5f5868fdb82b36e3abd6f9d1424114 + last-release: 321d4908aef10bafa1488f9b053270acc29f3d78 + expected-commits: 9320183f5d5f5868fdb82b36e3abd6f9d1424114,00cc61dd4c3eca64d12e6beceff1a40a436962f5 + gitea: + enabled: false + gitlab: + enabled: false + opensearch: + enabled: false diff --git a/deploy/chart/files/application-ft.yml b/deploy/chart/files/application-ft.yml new file mode 100644 index 0000000..b10eef6 --- /dev/null +++ b/deploy/chart/files/application-ft.yml @@ -0,0 +1,4 @@ +vcs-facade: + job: + fast-work-timout-secs: 0 + retry-interval-secs: 1 diff --git a/deploy/chart/files/bootstrap-ft.yml b/deploy/chart/files/bootstrap-ft.yml new file mode 100644 index 0000000..b17d963 --- /dev/null +++ b/deploy/chart/files/bootstrap-ft.yml @@ -0,0 +1,4 @@ +spring: + cloud: + config: + enabled: false diff --git a/deploy/chart/templates/_helpers.tpl b/deploy/chart/templates/_helpers.tpl new file mode 100644 index 0000000..5b9e94b --- /dev/null +++ b/deploy/chart/templates/_helpers.tpl @@ -0,0 +1,147 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "chart-test.name" -}} +{{- default .Chart.Name .Values.vcsFacade.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 "chart-test.fullname" -}} +{{- if .Values.vcsFacade.fullnameOverride }} +{{- .Values.vcsFacade.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.vcsFacade.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 "chart-test.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "chart-test.labels" -}} +helm.sh/chart: {{ include "chart-test.chart" . }} +{{ include "chart-test.selectorLabels" . }} +{{- if .Values.vcsFacade.image.version }} +app/version: {{ .Values.vcsFacade.image.version | quote }} +{{- end }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "chart-test.selectorLabels" -}} +app.kubernetes.io/name: {{ include "chart-test.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{- define "bitbucket-db.selectorLabels" -}} +app.kubernetes.io/name: {{ include "bitbucketDb.fullname" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "chart-test.serviceAccountName" -}} +{{- if .Values.vcsFacade.serviceAccount.create }} +{{- default (include "chart-test.fullname" .) .Values.vcsFacade.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.vcsFacade.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create a test-component 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 "test-component.fullname" -}} +{{- if .Values.vcsFacade.fullnameOverride }} +{{- .Values.vcsFacade.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.vcsFacade.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "test-component-%s" .Release.Name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create a components-registry 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 "components-registry.fullname" -}} +{{- if .Values.componentsRegisty.fullnameOverride }} +{{- .Values.componentsRegisty.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.componentsRegisty.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "components-registy-%s" .Release.Name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + + +{{/* +Components-registry labels +*/}} +{{- define "components-registry.labels" -}} +helm.sh/chart: {{ include "chart-test.chart" . }} +{{ include "chart-test.selectorLabels" . }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{- define "gitea.fullname" -}} +{{- if .Values.gitea.fullnameOverride }} +{{- .Values.gitea.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.gitea.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "gitea-%s" .Release.Name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{- define "bitbucket.fullname" -}} +{{- if .Values.bitbucket.fullnameOverride }} +{{- printf "%s-%s" .Release.Name .Values.bitbucket.fullnameOverride }} +{{- end }} +{{- end }} + +{{- define "bitbucketDb.fullname" -}} +{{- if .Values.bitbucketDb.fullnameOverride }} +{{- printf "%s-%s" .Release.Name .Values.bitbucketDb.fullnameOverride }} +{{- end }} +{{- end }} + +{{- define "vcsFacade.fullname" -}} +{{- if .Values.vcsFacade.fullnameOverride }} +{{- printf "%s-%s" .Release.Name .Values.vcsFacade.fullnameOverride }} +{{- end }} +{{- end }} diff --git a/deploy/chart/templates/bitbucket-db/deployment.yaml b/deploy/chart/templates/bitbucket-db/deployment.yaml new file mode 100644 index 0000000..a2d76fc --- /dev/null +++ b/deploy/chart/templates/bitbucket-db/deployment.yaml @@ -0,0 +1,58 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "bitbucketDb.fullname" . }} + namespace: {{ .Release.Namespace | quote }} +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: {{ include "bitbucketDb.fullname" . }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "bitbucketDb.fullname" . }} + spec: + containers: + - name: {{ include "bitbucketDb.fullname" . }} + securityContext: {} + image: {{ .Values.dockerRegistry }}/postgres:{{ .Values.bitbucketDb.image.version }} + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 5432 + {{- if eq .Values.platform "podman" }} + hostPort: 5432 + {{- end }} + protocol: TCP + env: + {{- range $key, $value := .Values.bitbucketDb.environment }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} + volumeMounts: + - name: {{ .Release.Namespace }}-bitbucket-db-storage + mountPath: /var/lib/postgresql/ + livenessProbe: + exec: + command: + - /bin/sh + - -c + - exec pg_isready -U {{ .Values.bitbucket.environment.JDBC_USER }} + initialDelaySeconds: 90 + resources: {} + volumes: + - name: {{ .Release.Namespace }}-bitbucket-db-storage + persistentVolumeClaim: + claimName: {{ .Release.Namespace }}-bitbucket-db-storage +--- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ .Release.Namespace }}-bitbucket-db-storage +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi \ No newline at end of file diff --git a/deploy/chart/templates/bitbucket-db/service.yaml b/deploy/chart/templates/bitbucket-db/service.yaml new file mode 100644 index 0000000..ae6f80c --- /dev/null +++ b/deploy/chart/templates/bitbucket-db/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "bitbucketDb.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "chart-test.labels" . | nindent 4 }} +spec: + type: {{ .Values.bitbucketDb.service.type }} + ports: + - port: {{ .Values.bitbucketDb.service.port }} + targetPort: {{ .Values.bitbucketDb.service.targetPort }} + protocol: TCP + name: http + selector: + app.kubernetes.io/name: {{ include "bitbucketDb.fullname" . }} diff --git a/deploy/chart/templates/bitbucket/deployment.yaml b/deploy/chart/templates/bitbucket/deployment.yaml new file mode 100644 index 0000000..9660e9e --- /dev/null +++ b/deploy/chart/templates/bitbucket/deployment.yaml @@ -0,0 +1,98 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "bitbucket.fullname" . }} + namespace: {{ .Release.Namespace | quote }} +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: {{ include "bitbucket.fullname" . }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "bitbucket.fullname" . }} + spec: + containers: + - name: vcs-facade-ft-bitbucket + securityContext: {} + image: {{ .Values.dockerRegistry }}/atlassian/bitbucket-server:{{ .Values.bitbucket.image.version }} + imagePullPolicy: IfNotPresent + ports: + - name: ssh + containerPort: 7999 + {{- if eq .Values.platform "podman" }} + hostPort: 7999 + {{- end }} + protocol: TCP + - name: http + containerPort: 7990 + {{- if eq .Values.platform "podman" }} + hostPort: 7990 + {{- end }} + protocol: TCP + env: + {{- range $key, $value := .Values.bitbucket.environment }} + {{- if contains $key "SETUP_LICENSE" }} + - name: {{ $key }} + valueFrom: + secretKeyRef: + name: {{ $value }} + key: token + {{- else }} + - name: {{ $key }} + value: "{{ tpl $value $ }}" + {{- end }} + {{- end }} + livenessProbe: + exec: + command: + - sh + - -c + - | + if curl -s http://localhost:7990/status | grep -q '"state":"RUNNING"'; then + exit 0 + else + exit 1 + fi + initialDelaySeconds: 120 + readinessProbe: + exec: + command: + - sh + - -c + - | + if curl -s http://localhost:7990/status | grep -q '"state":"RUNNING"'; then + exit 0 + else + exit 1 + fi + initialDelaySeconds: 30 + periodSeconds: 15 + timeoutSeconds: 5 + failureThreshold: 5 + resources: {} + volumeMounts: + - name: {{ .Release.Namespace }}-bitbucket-volume + mountPath: /var/atlassian/application-data/bitbucket + volumes: + - name: {{ .Release.Namespace }}-bitbucket-volume + {{- if eq .Values.platform "podman" }} + hostPath: + path: {{ .Values.bitbucket.path }} + type: Directory + {{ else }} + persistentVolumeClaim: + claimName: {{ .Release.Namespace }}-bitbucket-volume + {{- end }} +--- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ .Release.Namespace }}-bitbucket-volume +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi \ No newline at end of file diff --git a/deploy/chart/templates/bitbucket/route.yaml b/deploy/chart/templates/bitbucket/route.yaml new file mode 100644 index 0000000..e337ed4 --- /dev/null +++ b/deploy/chart/templates/bitbucket/route.yaml @@ -0,0 +1,10 @@ +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: {{ template "bitbucket.fullname" . }}-route +spec: + port: + targetPort: 7990 + to: + kind: Service + name: {{ template "bitbucket.fullname" . }} \ No newline at end of file diff --git a/deploy/chart/templates/bitbucket/secret.yaml b/deploy/chart/templates/bitbucket/secret.yaml new file mode 100644 index 0000000..9681410 --- /dev/null +++ b/deploy/chart/templates/bitbucket/secret.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +metadata: + name: bitbucket-license-secret +type: Opaque +data: + token: {{ .Values.bitbucket.license | b64enc | quote }} \ No newline at end of file diff --git a/deploy/chart/templates/bitbucket/service.yaml b/deploy/chart/templates/bitbucket/service.yaml new file mode 100644 index 0000000..c745e93 --- /dev/null +++ b/deploy/chart/templates/bitbucket/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "bitbucket.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "chart-test.labels" . | nindent 4 }} +spec: + type: {{ .Values.bitbucket.service.type }} + ports: + - port: {{ .Values.bitbucket.service.ssh.port }} + targetPort: {{ .Values.bitbucket.service.ssh.targetPort }} + protocol: TCP + name: ssh + - port: {{ .Values.bitbucket.service.http.port }} + targetPort: {{ .Values.bitbucket.service.http.targetPort }} + protocol: TCP + name: http + selector: + app.kubernetes.io/name: {{ include "bitbucket.fullname" . }} diff --git a/deploy/chart/templates/vcs-facade/configmap.yaml b/deploy/chart/templates/vcs-facade/configmap.yaml new file mode 100644 index 0000000..927c437 --- /dev/null +++ b/deploy/chart/templates/vcs-facade/configmap.yaml @@ -0,0 +1,14 @@ +{{- if eq .Values.platform "openshift" }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "vcsFacade.fullname" . }}-conf + namespace: {{ .Release.Namespace | quote }} +data: + bootstrap-ft.yml: | +{{ tpl (.Files.Get "files/bootstrap-ft.yml") . | indent 4 }} + application-bitbucket.yml: | +{{ tpl (.Files.Get "files/application-bitbucket.yml") . | indent 4 }} + application-ft.yml: | +{{ tpl (.Files.Get "files/application-ft.yml") . | indent 4 }} +{{- end }} diff --git a/deploy/chart/templates/vcs-facade/deployment.yaml b/deploy/chart/templates/vcs-facade/deployment.yaml new file mode 100644 index 0000000..ed4c853 --- /dev/null +++ b/deploy/chart/templates/vcs-facade/deployment.yaml @@ -0,0 +1,73 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "vcsFacade.fullname" . }} + namespace: {{ .Release.Namespace | quote }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "chart-test.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.vcsFacade.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "chart-test.selectorLabels" . | nindent 8 }} + spec: + containers: + - name: {{ include "vcsFacade.fullname" . }} + securityContext: {} + image: {{ .Values.dockerRegistry }}/octopusden/vcs-facade:{{ .Values.vcsFacade.image.version }} + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 8080 + {{- if eq .Values.platform "podman" }} + hostPort: 8080 + {{- end }} + protocol: TCP + env: + {{- range $key, $value := .Values.vcsFacade.environment }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} + resources: {} + volumeMounts: +{{- if eq .Values.platform "podman" }} + - name: {{ .Release.Namespace }}-application-bitbucket-config + mountPath: /app/config/application-bitbucket.yml + readOnly: true + - name: {{ .Release.Namespace }}-application-ft-config + mountPath: /app/config/application-ft.yml + readOnly: true + - name: {{ .Release.Namespace }}-bootstrap-ft-config + mountPath: /app/config/bootstrap-ft.yml + readOnly: true +{{ else }} + - name: {{ .Release.Namespace }}-application-config + mountPath: /app/config + readOnly: true +{{- end }} + volumes: +{{- if eq .Values.platform "podman" }} + - hostPath: + path: {{ .Values.vcsFacade.configFile.applicationBitbucket.path }} + type: File + name: {{ .Release.Namespace }}-application-bitbucket-config + - hostPath: + path: {{ .Values.vcsFacade.configFile.applicationFt.path }} + type: File + name: {{ .Release.Namespace }}-application-ft-config + - hostPath: + path: {{ .Values.vcsFacade.configFile.bootstrapFt.path }} + type: File + name: {{ .Release.Namespace }}-bootstrap-ft-config +{{ else }} + - name: {{ .Release.Namespace }}-application-config + configMap: + name: {{ include "vcsFacade.fullname" . }}-conf + defaultMode: 420 +{{- end }} diff --git a/deploy/chart/templates/vcs-facade/route.yaml b/deploy/chart/templates/vcs-facade/route.yaml new file mode 100644 index 0000000..2506b5e --- /dev/null +++ b/deploy/chart/templates/vcs-facade/route.yaml @@ -0,0 +1,10 @@ +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: {{ template "vcsFacade.fullname" . }}-route +spec: + port: + targetPort: 8080 + to: + kind: Service + name: {{ template "vcsFacade.fullname" . }} \ No newline at end of file diff --git a/deploy/chart/templates/vcs-facade/service.yaml b/deploy/chart/templates/vcs-facade/service.yaml new file mode 100644 index 0000000..31e4539 --- /dev/null +++ b/deploy/chart/templates/vcs-facade/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "vcsFacade.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "chart-test.labels" . | nindent 4 }} +spec: + type: {{ .Values.vcsFacade.service.type }} + ports: + - port: {{ .Values.vcsFacade.service.port }} + targetPort: {{ .Values.vcsFacade.service.targetPort }} + protocol: TCP + name: http + selector: + app.kubernetes.io/name: vcs-facade diff --git a/deploy/chart/values.yaml b/deploy/chart/values.yaml new file mode 100644 index 0000000..2469da2 --- /dev/null +++ b/deploy/chart/values.yaml @@ -0,0 +1,77 @@ +# Default values for chart-test. +# This is a YAML-formatted file. + +platform: openshift +profile: gitea + +clusterDomain: +localDomain: svc.cluster.local + +dockerRegistry: docker.io/library + +gitea: + fullnameOverride: vcs-facade-ft-gitea + image: + version: 1.21.10 + +bitbucket: + host: bitbucket:7990 + fullnameOverride: bitbucket + license: + image: + version: 8.14.0-jdk11 + environment: + SETUP_DISPLAYNAME: Bitbucket + SETUP_BASEURL: http://localhost:7990 + SETUP_LICENSE: bitbucket-license-secret + SETUP_SYSADMIN_USERNAME: admin + SETUP_SYSADMIN_PASSWORD: admin + SETUP_SYSADMIN_DISPLAYNAME: Dev Instance Admin + SETUP_SYSADMIN_EMAILADDRESS: admin@domain.corp + JDBC_DRIVER: org.postgresql.Driver + JDBC_USER: bitbucket + JDBC_PASSWORD: bitbucket + JDBC_URL: "jdbc:postgresql://{{ .Release.Name }}-{{ .Values.bitbucketDb.fullnameOverride }}.{{ .Release.Namespace }}.{{ .Values.localDomain }}:5432/bitbucket" + service: + ssh: + type: ClusterIP + port: 7999 + targetPort: 7999 + http: + type: ClusterIP + port: 7990 + targetPort: 7990 + path: /Users/ozonophore/Projects/octopus-vcs-facade/ft/deploy/bitbucket + +bitbucketDb: + fullnameOverride: bitbucket-db + image: + version: 13-alpine + environment: + POSTGRES_USER: bitbucket + POSTGRES_PASSWORD: bitbucket + POSTGRES_DB: bitbucket + service: + type: ClusterIP + port: 5432 + targetPort: 5432 + +vcsFacade: + fullnameOverride: vcs-facade + image: + version: 3.0.5 + environment: + SPRING_CONFIG_ADDITIONAL_LOCATION: /app/config/ + SPRING_PROFILES_ACTIVE: ft,bitbucket + service: + type: ClusterIP + port: 8080 + targetPort: 8080 + configFile: + applicationBitbucket: + path: /Users/ozonophore/Projects/octopus-vcs-facade/ft/deploy/chart/files/application-bitbucket.yml + applicationFt: + path: /Users/ozonophore/Projects/octopus-vcs-facade/ft/deploy/chart/files/application-ft.yml + bootstrapFt: + path: /Users/ozonophore/Projects/octopus-vcs-facade/ft/deploy/chart/files/bootstrap-ft.yml + diff --git a/deploy/img/img1.png b/deploy/img/img1.png new file mode 100644 index 0000000..189ea56 Binary files /dev/null and b/deploy/img/img1.png differ diff --git a/deploy/img/img2.png b/deploy/img/img2.png new file mode 100644 index 0000000..93d1d80 Binary files /dev/null and b/deploy/img/img2.png differ diff --git a/deploy/img/img3.png b/deploy/img/img3.png new file mode 100644 index 0000000..103eedf Binary files /dev/null and b/deploy/img/img3.png differ diff --git a/deploy/img/img4.png b/deploy/img/img4.png new file mode 100644 index 0000000..abc0201 Binary files /dev/null and b/deploy/img/img4.png differ diff --git a/ft/src/ft/kotlin/org/octopusden/octopus/vcsfacade/BaseVcsFacadeFunctionalTest.kt b/ft/src/ft/kotlin/org/octopusden/octopus/vcsfacade/BaseVcsFacadeFunctionalTest.kt index c6b1c72..894d455 100644 --- a/ft/src/ft/kotlin/org/octopusden/octopus/vcsfacade/BaseVcsFacadeFunctionalTest.kt +++ b/ft/src/ft/kotlin/org/octopusden/octopus/vcsfacade/BaseVcsFacadeFunctionalTest.kt @@ -2,7 +2,6 @@ package org.octopusden.octopus.vcsfacade import java.util.Date import org.octopusden.octopus.infrastructure.common.test.TestClient -import org.octopusden.octopus.vcsfacade.TestService.Companion.VCS_FACADE_API_URL import org.octopusden.octopus.vcsfacade.client.common.dto.CreatePullRequest import org.octopusden.octopus.vcsfacade.client.common.dto.SearchIssuesInRangesRequest import org.octopusden.octopus.vcsfacade.client.impl.ClassicVcsFacadeClient @@ -59,7 +58,7 @@ abstract class BaseVcsFacadeFunctionalTest( companion object { private val client = ClassicVcsFacadeClient(object : VcsFacadeClientParametersProvider { - override fun getApiUrl() = VCS_FACADE_API_URL + override fun getApiUrl() = Configuration.model.vcsFacadeUrl override fun getTimeRetryInMillis() = 180000 }) } diff --git a/ft/src/ft/kotlin/org/octopusden/octopus/vcsfacade/VcsFacadeFunctionalTestBitbucket.kt b/ft/src/ft/kotlin/org/octopusden/octopus/vcsfacade/VcsFacadeFunctionalTestBitbucket.kt index f2613d3..c64ac13 100644 --- a/ft/src/ft/kotlin/org/octopusden/octopus/vcsfacade/VcsFacadeFunctionalTestBitbucket.kt +++ b/ft/src/ft/kotlin/org/octopusden/octopus/vcsfacade/VcsFacadeFunctionalTestBitbucket.kt @@ -3,8 +3,13 @@ package org.octopusden.octopus.vcsfacade import org.junit.jupiter.api.condition.EnabledIfSystemProperty import org.octopusden.octopus.infastructure.bitbucket.test.BitbucketTestClient -@EnabledIfSystemProperty(named = "test.profile", matches = "bitbucket") +@EnabledIfSystemProperty(named = TEST_PROFILE, matches = BITBUCKET) class VcsFacadeFunctionalTestBitbucket : BaseVcsFacadeFunctionalTest( - TestService.Bitbucket(BITBUCKET_HOST, BITBUCKET_EXTERNAL_HOST), - BitbucketTestClient("http://$BITBUCKET_HOST", BITBUCKET_USER, BITBUCKET_PASSWORD, BITBUCKET_EXTERNAL_HOST) + TestService.Bitbucket(Configuration.model.bitbucket.host, Configuration.model.bitbucket.externalHost), + BitbucketTestClient( + Configuration.model.bitbucket.url, + Configuration.model.bitbucket.user, + Configuration.model.bitbucket.password, + Configuration.model.bitbucket.externalHost + ) ) diff --git a/ft/src/ft/kotlin/org/octopusden/octopus/vcsfacade/VcsFacadeFunctionalTestGitea.kt b/ft/src/ft/kotlin/org/octopusden/octopus/vcsfacade/VcsFacadeFunctionalTestGitea.kt index d7cfe81..07a8c66 100644 --- a/ft/src/ft/kotlin/org/octopusden/octopus/vcsfacade/VcsFacadeFunctionalTestGitea.kt +++ b/ft/src/ft/kotlin/org/octopusden/octopus/vcsfacade/VcsFacadeFunctionalTestGitea.kt @@ -10,19 +10,27 @@ import org.octopusden.octopus.infrastructure.common.test.dto.NewChangeSet import org.octopusden.octopus.infrastructure.gitea.test.GiteaTestClient import org.octopusden.octopus.vcsfacade.client.common.dto.CreatePullRequest -@EnabledIfSystemProperty(named = "test.profile", matches = "gitea") +@EnabledIfSystemProperty(named = TEST_PROFILE, matches = GITEA) class VcsFacadeFunctionalTestGitea : BaseVcsFacadeFunctionalTest( - TestService.Gitea(GITEA_HOST, GITEA_EXTERNAL_HOST, true), - GiteaTestClient("http://$GITEA_HOST", GITEA_USER, GITEA_PASSWORD, GITEA_EXTERNAL_HOST) + TestService.Gitea( + Configuration.model.gitea.host, + Configuration.model.gitea.externalHost, + true), + GiteaTestClient( + Configuration.model.gitea.url, + Configuration.model.gitea.user, + Configuration.model.gitea.password, + Configuration.model.gitea.externalHost + ) ) { @BeforeAll fun beforeAllVcsFacadeFunctionalTestGitea() { - val url = URI("http://$GITEA_HOST/api/v1/repos/$GROUP/$REPOSITORY_2/hooks").toURL() + val url = URI("http://${Configuration.model.gitea.host}/api/v1/repos/$GROUP/$REPOSITORY_2/hooks").toURL() with(url.openConnection() as HttpURLConnection) { setRequestMethod("POST") setRequestProperty( "Authorization", - "Basic " + Base64.getEncoder().encodeToString("$GITEA_USER:$GITEA_PASSWORD".toByteArray()) + "Basic " + Base64.getEncoder().encodeToString("${Configuration.model.gitea.user}:${Configuration.model.gitea.password}".toByteArray()) ) setRequestProperty("Content-Type", "application/json") setRequestProperty("Accept", "application/json") diff --git a/ft/src/ft/kotlin/org/octopusden/octopus/vcsfacade/VcsFacadeFunctionalTestGitlab.kt b/ft/src/ft/kotlin/org/octopusden/octopus/vcsfacade/VcsFacadeFunctionalTestGitlab.kt index f461f38..99fe2f6 100644 --- a/ft/src/ft/kotlin/org/octopusden/octopus/vcsfacade/VcsFacadeFunctionalTestGitlab.kt +++ b/ft/src/ft/kotlin/org/octopusden/octopus/vcsfacade/VcsFacadeFunctionalTestGitlab.kt @@ -3,8 +3,16 @@ package org.octopusden.octopus.vcsfacade import org.junit.jupiter.api.condition.EnabledIfSystemProperty import org.octopusden.octopus.infrastructure.gitlab.test.GitlabTestClient -@EnabledIfSystemProperty(named = "test.profile", matches = "gitlab") +@EnabledIfSystemProperty(named = TEST_PROFILE, matches = GITLAB) class VcsFacadeFunctionalTestGitlab : BaseVcsFacadeFunctionalTest( - TestService.Gitlab(GITLAB_HOST, GITLAB_EXTERNAL_HOST), - GitlabTestClient("http://$GITLAB_HOST", GITLAB_USER, GITLAB_PASSWORD, GITLAB_EXTERNAL_HOST) + TestService.Gitlab( + Configuration.model.gitlab.host, + Configuration.model.gitlab.externalHost + ), + GitlabTestClient( + Configuration.model.gitlab.url, + Configuration.model.gitlab.user, + Configuration.model.gitlab.password, + Configuration.model.gitlab.externalHost + ) ) diff --git a/server/src/test/kotlin/org/octopusden/octopus/vcsfacade/vcs/VcsFacadeUnitTestBitbucket.kt b/server/src/test/kotlin/org/octopusden/octopus/vcsfacade/vcs/VcsFacadeUnitTestBitbucket.kt index d011feb..54d2d84 100644 --- a/server/src/test/kotlin/org/octopusden/octopus/vcsfacade/vcs/VcsFacadeUnitTestBitbucket.kt +++ b/server/src/test/kotlin/org/octopusden/octopus/vcsfacade/vcs/VcsFacadeUnitTestBitbucket.kt @@ -1,12 +1,18 @@ package org.octopusden.octopus.vcsfacade.vcs import org.octopusden.octopus.infastructure.bitbucket.test.BitbucketTestClient +import org.octopusden.octopus.vcsfacade.BITBUCKET +import org.octopusden.octopus.vcsfacade.Configuration import org.octopusden.octopus.vcsfacade.TestService import org.springframework.test.context.junit.jupiter.EnabledIf -@EnabledIf("#{environment.getActiveProfiles().$[#this == 'bitbucket'] == 'bitbucket'}", loadContext = true) +@EnabledIf("#{environment.getActiveProfiles().$[#this == '$BITBUCKET'] == '$BITBUCKET'}", loadContext = true) class VcsFacadeUnitTestBitbucket : BaseVcsFacadeUnitTest( - TestService.Bitbucket(BITBUCKET_HOST), - BitbucketTestClient("http://$BITBUCKET_HOST", BITBUCKET_USER, BITBUCKET_PASSWORD) + TestService.Bitbucket(Configuration.model.bitbucket.host), + BitbucketTestClient( + Configuration.model.bitbucket.url, + Configuration.model.bitbucket.user, + Configuration.model.bitbucket.password + ) ) diff --git a/server/src/test/kotlin/org/octopusden/octopus/vcsfacade/vcs/VcsFacadeUnitTestGitea.kt b/server/src/test/kotlin/org/octopusden/octopus/vcsfacade/vcs/VcsFacadeUnitTestGitea.kt index 81ee581..4d9696d 100644 --- a/server/src/test/kotlin/org/octopusden/octopus/vcsfacade/vcs/VcsFacadeUnitTestGitea.kt +++ b/server/src/test/kotlin/org/octopusden/octopus/vcsfacade/vcs/VcsFacadeUnitTestGitea.kt @@ -2,13 +2,19 @@ package org.octopusden.octopus.vcsfacade.vcs import org.junit.jupiter.api.BeforeAll import org.octopusden.octopus.infrastructure.gitea.test.GiteaTestClient +import org.octopusden.octopus.vcsfacade.Configuration +import org.octopusden.octopus.vcsfacade.GITEA import org.octopusden.octopus.vcsfacade.TestService import org.springframework.test.context.junit.jupiter.EnabledIf -@EnabledIf("#{environment.getActiveProfiles().$[#this == 'gitea'] == 'gitea'}", loadContext = true) +@EnabledIf("#{environment.getActiveProfiles().$[#this == '$GITEA'] == '$GITEA'}", loadContext = true) class VcsFacadeUnitTestGitea : BaseVcsFacadeUnitTest( - TestService.Gitea(GITEA_HOST), - GiteaTestClient("http://$GITEA_HOST", GITEA_USER, GITEA_PASSWORD) + TestService.Gitea(Configuration.model.gitea.host), + GiteaTestClient( + Configuration.model.gitea.url, + Configuration.model.gitea.user, + Configuration.model.gitea.password + ) ) { @BeforeAll fun beforeAllVcsFacadeUnitTestGitea() { diff --git a/server/src/test/kotlin/org/octopusden/octopus/vcsfacade/vcs/VcsFacadeUnitTestGitlab.kt b/server/src/test/kotlin/org/octopusden/octopus/vcsfacade/vcs/VcsFacadeUnitTestGitlab.kt index 0c771cc..3973476 100644 --- a/server/src/test/kotlin/org/octopusden/octopus/vcsfacade/vcs/VcsFacadeUnitTestGitlab.kt +++ b/server/src/test/kotlin/org/octopusden/octopus/vcsfacade/vcs/VcsFacadeUnitTestGitlab.kt @@ -1,11 +1,17 @@ package org.octopusden.octopus.vcsfacade.vcs import org.octopusden.octopus.infrastructure.gitlab.test.GitlabTestClient +import org.octopusden.octopus.vcsfacade.Configuration +import org.octopusden.octopus.vcsfacade.GITLAB import org.octopusden.octopus.vcsfacade.TestService import org.springframework.test.context.junit.jupiter.EnabledIf -@EnabledIf("#{environment.getActiveProfiles().$[#this == 'gitlab'] == 'gitlab'}", loadContext = true) +@EnabledIf("#{environment.getActiveProfiles().$[#this == '$GITLAB'] == '$GITLAB'}", loadContext = true) class VcsFacadeUnitTestGitlab : BaseVcsFacadeUnitTest( - TestService.Gitlab(GITLAB_HOST), - GitlabTestClient("http://$GITLAB_HOST", GITLAB_USER, GITLAB_PASSWORD) + TestService.Gitlab(Configuration.model.gitlab.host), + GitlabTestClient( + Configuration.model.gitlab.url, + Configuration.model.gitlab.user, + Configuration.model.gitlab.password + ) ) diff --git a/server/src/test/resources/test-properties.yaml b/server/src/test/resources/test-properties.yaml new file mode 100644 index 0000000..9c04cce --- /dev/null +++ b/server/src/test/resources/test-properties.yaml @@ -0,0 +1,22 @@ +bitbucket: + host: "localhost:7990" + externalHost: "bitbucket:7990" + user: "admin" + password: "admin" + url: "http://localhost:7990" + +gitlab: + host: "localhost:8990" + externalHost: "gitlab:8990" + user: "root" + password: "VomkaEa6PD1OIgY7dQVbPUuO8wi9RMCaZw/i9yPXcI0=" + url: "http://localhost:8990" + +gitea: + host: "localhost:3000" + externalHost: "gitea:3000" + user: "test-admin" + password: "test-admin" + url: "http://localhost:3000" + +vcsFacadeUrl: "http://localhost:8080" diff --git a/settings.gradle.kts b/settings.gradle.kts index 6e6a585..0d215a8 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -23,3 +23,4 @@ include(":test-common") include(":server") findProject(":server")?.name = "vcs-facade" include(":ft") +include(":deploy") diff --git a/test-common/build.gradle.kts b/test-common/build.gradle.kts index 6090b26..7d53716 100644 --- a/test-common/build.gradle.kts +++ b/test-common/build.gradle.kts @@ -3,6 +3,7 @@ dependencies { implementation("org.junit.jupiter:junit-jupiter-engine") implementation("org.junit.jupiter:junit-jupiter-params") implementation("com.fasterxml.jackson.core:jackson-databind") + implementation("org.yaml:snakeyaml:1.29") api("org.octopusden.octopus.octopus-external-systems-clients:bitbucket-test-client:${project.properties["external-systems-client.version"]}") api("org.octopusden.octopus.octopus-external-systems-clients:gitea-test-client:${project.properties["external-systems-client.version"]}") api("org.octopusden.octopus.octopus-external-systems-clients:gitlab-test-client:${project.properties["external-systems-client.version"]}") diff --git a/test-common/src/main/kotlin/org/octopusden/octopus/vcsfacade/BaseVcsFacadeTest.kt b/test-common/src/main/kotlin/org/octopusden/octopus/vcsfacade/BaseVcsFacadeTest.kt index e6e8f01..c28b733 100644 --- a/test-common/src/main/kotlin/org/octopusden/octopus/vcsfacade/BaseVcsFacadeTest.kt +++ b/test-common/src/main/kotlin/org/octopusden/octopus/vcsfacade/BaseVcsFacadeTest.kt @@ -521,21 +521,6 @@ abstract class BaseVcsFacadeTest( companion object { - const val BITBUCKET_HOST = "localhost:7990" - const val BITBUCKET_USER = "admin" - const val BITBUCKET_PASSWORD = "admin" - const val BITBUCKET_EXTERNAL_HOST = "bitbucket:7990" - - const val GITEA_HOST = "localhost:3000" - const val GITEA_USER = "test-admin" - const val GITEA_PASSWORD = "test-admin" - const val GITEA_EXTERNAL_HOST = "gitea:3000" - - const val GITLAB_HOST = "localhost:8990" - const val GITLAB_USER = "root" - const val GITLAB_PASSWORD = "VomkaEa6PD1OIgY7dQVbPUuO8wi9RMCaZw/i9yPXcI0=" - const val GITLAB_EXTERNAL_HOST = "gitlab:8990" - const val GROUP = "test" const val REPOSITORY = "repository" const val REPOSITORY_2 = "repository-2" diff --git a/test-common/src/main/kotlin/org/octopusden/octopus/vcsfacade/Configuration.kt b/test-common/src/main/kotlin/org/octopusden/octopus/vcsfacade/Configuration.kt new file mode 100644 index 0000000..c40fad5 --- /dev/null +++ b/test-common/src/main/kotlin/org/octopusden/octopus/vcsfacade/Configuration.kt @@ -0,0 +1,88 @@ +package org.octopusden.octopus.vcsfacade + +import org.yaml.snakeyaml.Yaml + +private const val PROPERTY_FILE = "test-properties.yaml" +const val TEST_PROFILE = "test.profile" +const val GITLAB = "gitlab" +const val GITEA = "gitea" +const val BITBUCKET = "bitbucket" + +/** + * Configuration object that reads the test-properties.yaml file and provides access to its properties. + */ +object Configuration { + + val model: ConfigModel by lazy { + val yaml = Yaml() + val inputStream = ConfigModel::class.java.getClassLoader().getResourceAsStream(PROPERTY_FILE) + requireNotNull(inputStream) { "$PROPERTY_FILE not found" } + overrideWithPropVariables(yaml.loadAs(inputStream, ConfigModel::class.java)) + } + + private fun overrideWithPropVariables(configModel: ConfigModel): ConfigModel { + configModel.bitbucket.host = System.getProperty("bitbucketHost", configModel.bitbucket.host) + configModel.bitbucket.externalHost = System.getProperty("bitbucketExternalHost", configModel.bitbucket.externalHost) + configModel.bitbucket.url = System.getProperty("bitbucketUrl", configModel.bitbucket.url) + configModel.gitea.host = System.getProperty("giteaHost", configModel.gitea.host) + configModel.gitea.externalHost = System.getProperty("giteaExternalHost", configModel.gitea.externalHost) + configModel.gitea.url = System.getProperty("giteaUrl", configModel.gitea.url) + configModel.gitlab.host = System.getProperty("gitlabHost", configModel.gitlab.host) + configModel.gitlab.externalHost = System.getProperty("gitlabExternalHost", configModel.gitlab.externalHost) + configModel.gitlab.url = System.getProperty("gitlabUrl", configModel.gitlab.url) + configModel.vcsFacadeUrl = System.getProperty("vcsFacadeUrl", configModel.vcsFacadeUrl) + return configModel + } +} + +/** + * Configuration model representing the structure of the test-properties.yaml file. + */ +data class ConfigModel( + var bitbucket: VcsModel = VcsModel( + "admin", + "admin", + "localhost:7990", + "bitbucket:7990", + "http://localhost:7990"), + var gitlab: VcsModel = VcsModel( + "root", + "VomkaEa6PD1OIgY7dQVbPUuO8wi9RMCaZw/i9yPXcI0=", + "localhost:3000", + "gitlab:8990", + "http://localhost:8990" + ), + var gitea: VcsModel = VcsModel( + "test-admin", + "test-admin", + "localhost:8990", + "gitea:3000", + "http://localhost:3000"), + + var vcsFacadeUrl: String = "http://localhost:8080", + var project: String = "test-project", + var repository: String = "test-repository", + var repository2: String = "test-repository-2", + var mainBranch: String = "master", + var featureBranch: String = "feature/FEATURE-1", + var messageInit: String = "initial commit", + var message1: String = "TEST-1 First commit", + var message2: String = "TEST-1 Second commit", + var message3: String = "TEST-2 Third commit", + var featureMessage: String = "FEATURE-1 First commit", + var tag1: String = "commit-1-tag", + var tag2: String = "commit-2-tag", + var tag3: String = "commit-3-tag", + var defaultId: String = "0123456789abcde", +) + +/** + * Configuration model representing the structure of the VCS properties. + */ +data class VcsModel( + var user: String = "", + var password: String = "", + var host: String = "", + var externalHost: String = "", + var url: String = "", +) \ No newline at end of file diff --git a/test-common/src/main/kotlin/org/octopusden/octopus/vcsfacade/TestService.kt b/test-common/src/main/kotlin/org/octopusden/octopus/vcsfacade/TestService.kt index c5dfd69..3044e03 100644 --- a/test-common/src/main/kotlin/org/octopusden/octopus/vcsfacade/TestService.kt +++ b/test-common/src/main/kotlin/org/octopusden/octopus/vcsfacade/TestService.kt @@ -104,7 +104,7 @@ sealed class TestService( class Bitbucket( host: String, externalHost: String? = null ) : TestService(host, externalHost) { - override val type = "bitbucket" + override val type = BITBUCKET override fun sshUrl(group: String, repository: String) = "ssh://git@$effectiveHost/$group/$repository.git" @@ -113,14 +113,14 @@ sealed class TestService( class Gitea( host: String, externalHost: String? = null, private val useColon: Boolean = false ) : TestService(host, externalHost) { - override val type = "gitea" + override val type = GITEA override fun sshUrl(group: String, repository: String) = "ssh://git@$effectiveHost${if (useColon) ":" else "/"}$group/$repository.git" fun scan(group: String, repository: String) { val query = "sshUrl=${URLEncoder.encode(sshUrl(group, repository), StandardCharsets.UTF_8)}" - val url = URI("$VCS_FACADE_API_URL/rest/api/1/indexer/gitea/scan?$query").toURL() + val url = URI("${Configuration.model.vcsFacadeUrl}/rest/api/1/indexer/gitea/scan?$query").toURL() with(url.openConnection() as HttpURLConnection) { setRequestMethod("POST") if (getResponseCode() / 100 != 2) { @@ -134,14 +134,13 @@ sealed class TestService( class Gitlab( host: String, externalHost: String? = null ) : TestService(host, externalHost) { - override val type = "gitlab" + override val type = GITLAB override fun sshUrl(group: String, repository: String) = "ssh://git@$effectiveHost:$group/$repository.git" } companion object { - const val VCS_FACADE_API_URL = "http://localhost:8080" //TODO: use some custom port? private val OBJECT_MAPPER = ObjectMapper().registerKotlinModule() diff --git a/test-common/src/main/resources/test-properties.yaml b/test-common/src/main/resources/test-properties.yaml new file mode 100644 index 0000000..9c04cce --- /dev/null +++ b/test-common/src/main/resources/test-properties.yaml @@ -0,0 +1,22 @@ +bitbucket: + host: "localhost:7990" + externalHost: "bitbucket:7990" + user: "admin" + password: "admin" + url: "http://localhost:7990" + +gitlab: + host: "localhost:8990" + externalHost: "gitlab:8990" + user: "root" + password: "VomkaEa6PD1OIgY7dQVbPUuO8wi9RMCaZw/i9yPXcI0=" + url: "http://localhost:8990" + +gitea: + host: "localhost:3000" + externalHost: "gitea:3000" + user: "test-admin" + password: "test-admin" + url: "http://localhost:3000" + +vcsFacadeUrl: "http://localhost:8080"