diff --git a/.github/actions/install-trustify/action.yml b/.github/actions/install-trustify/action.yml
index c07718f..9f6a320 100644
--- a/.github/actions/install-trustify/action.yml
+++ b/.github/actions/install-trustify/action.yml
@@ -14,6 +14,10 @@ inputs:
description: "JSON encoded Trustify Custom Resource (CR) string"
required: false
default: ""
+ app-name:
+ description: "Name of the Trustify instance (should match CR metadata if passed)"
+ required: false
+ default: "myapp"
runs:
using: "composite"
steps:
@@ -33,12 +37,13 @@ runs:
echo "operator-sdk is already installed...yay"
exit 0
fi
- curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.35.0/operator-sdk_linux_amd64
+ curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.37.0/operator-sdk_linux_amd64
sudo install -o root -g root -m 0755 operator-sdk_linux_amd64 /usr/local/bin/operator-sdk
- name: Install Trustify
env:
OPERATOR_BUNDLE_IMAGE: ${{ inputs.operator-bundle-image }}
NAMESPACE: ${{ inputs.namespace }}
+ APP_NAME: ${{ inputs.app-name }}
TRUSTIFY_CR: ${{ inputs.trustify-cr }}
run: |
make install-trustify
diff --git a/.github/workflows/image-build.yaml b/.github/workflows/image-build.yaml
index a28c5ad..b281191 100644
--- a/.github/workflows/image-build.yaml
+++ b/.github/workflows/image-build.yaml
@@ -31,7 +31,7 @@ jobs:
registry: "ghcr.io"
image_name: "${{ github.repository_owner }}/trustify-operator"
containerfile: "./Dockerfile"
- architectures: '[ "amd64" ]'
+ architectures: '[ "amd64", "arm64" ]'
secrets:
registry_username: ${{ github.actor }}
registry_password: ${{ secrets.GITHUB_TOKEN }}
@@ -45,7 +45,7 @@ jobs:
registry: "ghcr.io"
image_name: "${{ github.repository_owner }}/trustify-operator-bundle"
containerfile: "./bundle.Dockerfile"
- architectures: '[ "amd64" ]'
+ architectures: '[ "amd64", "arm64" ]'
extra-args: '--build-arg QUARKUS_OPTS="-Dquarkus.container-image.image=ghcr.io/${{ github.repository_owner }}/trustify-operator:${{ needs.prepare.outputs.tag }}"'
secrets:
registry_username: ${{ github.actor }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 83e9237..d03fffe 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -15,6 +15,10 @@ on:
description: "The Trustify container image"
default: "ghcr.io/trustification/trustd:latest"
required: true
+ image-db:
+ description: "The Database container image"
+ default: "quay.io/sclorg/postgresql-15-c9s:latest"
+ required: true
jobs:
prepare:
@@ -26,9 +30,25 @@ jobs:
java-version: 21
distribution: temurin
cache: maven
+ - name: Install YQ
+ run: |
+ wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq
+ chmod +x /usr/bin/yq
+ - name: Prepare application.yaml
+ run: |
+ yq e -P -i '.related.image.server=strenv(IMAGE_SERVER)' src/main/resources/application.yaml
+ yq e -P -i '.related.image.db=strenv(IMAGE_DB)' src/main/resources/application.yaml
+ env:
+ IMAGE_SERVER: ${{ github.event.inputs.image-server }}
+ IMAGE_DB: ${{ github.event.inputs.image-db }}
+ - name: Prepare Chart.yaml
+ run: |
+ NEW_VERSION=$NEW_VERSION yq e -i '.version=strenv(NEW_VERSION)' helm/Chart.yaml
+ NEW_VERSION=$NEW_VERSION yq e -i '.appVersion=strenv(NEW_VERSION)' helm/Chart.yaml
+ env:
+ NEW_VERSION: ${{ github.event.inputs.version }}
- name: Set release version ${{ github.event.inputs.version }}
run: |
- sed -i "/related\.image\.server=/ s/=.*/=ghcr\.io\/trustification\/trustd:${{ github.event.inputs.image-server }}/" src/main/resources/application.properties
mvn -B versions:set versions:commit -DnewVersion=$NEW_VERSION
env:
NEW_VERSION: ${{ github.event.inputs.version }}
@@ -36,7 +56,7 @@ jobs:
uses: trustification/release-tools/.github/actions/commit@main
with:
commit_message: "🏁 Releasing version ${{ github.event.inputs.version }}"
- branch: main
+ branch: ${{github.ref_name}}
release:
needs: [ prepare ]
@@ -67,16 +87,30 @@ jobs:
with:
name: jreleaser-log
path: 'jreleaser-log.tgz'
+ - name: Install YQ
+ run: |
+ wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq
+ chmod +x /usr/bin/yq
+ - name: Restore application.yaml
+ run: |
+ yq e -P -i '.related.image.server="${RELATED_IMAGE_SERVER:ghcr.io/trustification/trustd:latest}"' src/main/resources/application.yaml
+ yq e -P -i '.related.image.db="${RELATED_IMAGE_DB:quay.io/sclorg/postgresql-15-c9s:latest}"' src/main/resources/application.yaml
+ - name: Restore Chart.yaml
+ run: |
+ NEXT_VERSION=$NEXT_VERSION yq e -i '.version=strenv(NEXT_VERSION)' helm/Chart.yaml
+ yq e -i '.appVersion="latest"' helm/Chart.yaml
+ env:
+ NEXT_VERSION: ${{ github.event.inputs.next }}
- name: Set version ${{ github.event.inputs.next }}
run: |
- mvn -B versions:set versions:commit -DnewVersion=$NEW_VERSION
+ mvn -B versions:set versions:commit -DnewVersion=$NEXT_VERSION
env:
- NEW_VERSION: ${{ github.event.inputs.next }}
+ NEXT_VERSION: ${{ github.event.inputs.next }}
- name: Commit and Push
uses: trustification/release-tools/.github/actions/commit@main
with:
commit_message: "⬆️ Next version ${{ github.event.inputs.next }}"
- branch: main
+ branch: ${{github.ref_name}}
publish-bundle:
needs: [ release ]
diff --git a/README.md b/README.md
index e991de7..27ae240 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,31 @@
+# Quick Start - Helm Chart
+
+If you want to give a quick try of the operator without the whole glory of OLM you can deploy our Operator using Helm.
+
+- Start minikube:
+
+```shell
+minikube start --addons=ingress,dashboard
+```
+
+- Install the Helm Chart:
+
+```shell
+helm install myhelm helm/
+```
+
+- Create an instance of Trustify:
+
+```shell
+cat << EOF | kubectl apply -f -
+apiVersion: "org.trustify/v1alpha1"
+kind: "Trustify"
+metadata:
+ name: myapp
+spec: { }
+EOF
+```
+
# Local development
## Minikube
diff --git a/bundle.Dockerfile b/bundle.Dockerfile
index 705bfaf..302982c 100644
--- a/bundle.Dockerfile
+++ b/bundle.Dockerfile
@@ -15,15 +15,23 @@ RUN ./mvnw package -DskipTests ${QUARKUS_OPTS} -Dquarkus.operator-sdk.bundle.cha
FROM registry.access.redhat.com/ubi9/ubi:latest AS bundle
COPY scripts /scripts
COPY --from=build /code/target/bundle/trustify-operator/ /code/target/bundle/trustify-operator/
-RUN dnf install curl zip unzip --allowerasing -y && \
- curl -s "https://get.sdkman.io?rcupdate=false" | bash && \
- source "$HOME/.sdkman/bin/sdkman-init.sh" && \
- sdk install java && \
- sdk install groovy && \
- groovy scripts/enrichCSV.groovy /code/target/bundle/trustify-operator/manifests/trustify-operator.clusterserviceversion.yaml
-RUN curl --output /usr/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 && \
+RUN dnf install wget --allowerasing -y && \
+ wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq && \
chmod +x /usr/bin/yq && \
- yq e -P -i '.annotations."com.redhat.openshift.versions"="v4.10"'
+ # annotations.yaml \
+ ANNOTATIONS_FILE=/code/target/bundle/trustify-operator/metadata/annotations.yaml && \
+ yq e -P -i '.annotations."com.redhat.openshift.versions"="v4.10"' ${ANNOTATIONS_FILE} && \
+ # clusterserviceversion.yaml \
+ CSV_FILE=/code/target/bundle/trustify-operator/manifests/trustify-operator.clusterserviceversion.yaml && \
+ yq e -P -i '.metadata.annotations.support = "https://github.com/trustification/trustify-operator/issues"' ${CSV_FILE} && \
+ yq e -P -i '.metadata.annotations.description = "An Operator for installing and managing Trustify"' ${CSV_FILE} && \
+ NOW_DATE=$(date --iso-8601=seconds) yq e -P -i '.metadata.annotations.createdAt = strenv(NOW_DATE)' ${CSV_FILE} && \
+ yq e -P -i '.metadata.annotations.containerImage = .spec.install.spec.deployments[0].spec.template.spec.containers[0].image' ${CSV_FILE} && \
+ yq e -P -i '.spec.customresourcedefinitions.owned[0].description = "Represents a Trustify instance"' ${CSV_FILE} && \
+ yq e -P -i '.spec.customresourcedefinitions.owned[0].displayName = "Trustify"' ${CSV_FILE} && \
+ yq e -P -i '.spec.install.spec.clusterPermissions[0].rules[0].apiGroups = ["apiextensions.k8s.io", "config.openshift.io"]' ${CSV_FILE} && \
+ yq e -P -i '.spec.install.spec.clusterPermissions[0].rules[0].resources = ["customresourcedefinitions", "ingresses"]' ${CSV_FILE} && \
+ yq e -P -i '.spec.install.spec.clusterPermissions[0].rules[0].verbs = ["get", "list"]' ${CSV_FILE}
FROM scratch
ARG CHANNELS=alpha
diff --git a/hack/install-trustify.sh b/hack/install-trustify.sh
index 25c317f..44dc286 100755
--- a/hack/install-trustify.sh
+++ b/hack/install-trustify.sh
@@ -5,6 +5,7 @@ set -x
set -o pipefail
NAMESPACE="${NAMESPACE:-trustify}"
+APP_NAME="${APP_NAME:-myapp}"
OPERATOR_BUNDLE_IMAGE="${OPERATOR_BUNDLE_IMAGE:-ghcr.io/trustification/trustify-operator-bundle:latest}"
TRUSTIFY_CR="${TRUSTIFY_CR:-}"
TIMEOUT="${TIMEOUT:-15m}"
@@ -21,7 +22,15 @@ fi
run_bundle() {
kubectl auth can-i create namespace --all-namespaces
- kubectl create namespace ${NAMESPACE} || true
+
+ # delete the ns if it exists, effectively undeploying the current
+ # Trustify instance. This kinda defeats the purpose of operators,
+ # obviously, but I'm not familiar enough with the operator-sdk
+ # command to convince it to reinstall/upgrade the bundle -- run
+ # bundle-upgrade didn't work :(
+ kubectl delete namespace ${NAMESPACE} || true
+
+ kubectl create namespace ${NAMESPACE}
operator-sdk run bundle "${OPERATOR_BUNDLE_IMAGE}" --namespace "${NAMESPACE}" --timeout "${TIMEOUT}" || (kubectl get Subscription --namespace "${NAMESPACE}" -o yaml && exit 1)
# If on MacOS, need to install `brew install coreutils` to get `timeout`
@@ -47,40 +56,38 @@ install_trustify() {
kind: Trustify
apiVersion: org.trustify/v1alpha1
metadata:
- name: myapp
+ name: ${APP_NAME}
spec: {}
EOF
fi
# Want to see in github logs what we just created
- kubectl get --namespace "${NAMESPACE}" -o yaml trustifies.org.trustify/myapp
+ kubectl get --namespace "${NAMESPACE}" -o yaml trustifies.org.trustify/${APP_NAME}
# Wait for reconcile to finish
kubectl wait \
--namespace ${NAMESPACE} \
--for=condition=Successful \
--timeout=600s \
- trustifies.org.trustify/myapp \
+ trustifies.org.trustify/${APP_NAME} \
|| kubectl get \
--namespace ${NAMESPACE} \
-o yaml \
- trustifies.org.trustify/myapp # Print trustify debug when timed out
+ trustifies.org.trustify/${APP_NAME} # Print trustify debug when timed out
# Now wait for all the trustify deployments
kubectl wait \
--namespace ${NAMESPACE} \
- --selector="app.kubernetes.io/part-of=myapp" \
+ --selector="app.kubernetes.io/part-of=${APP_NAME}" \
--for=condition=Available \
--timeout=600s \
deployments.apps \
|| kubectl get \
--namespace ${NAMESPACE} \
- --selector="app.kubernetes.io/part-of=myapp" \
+ --selector="app.kubernetes.io/part-of=${APP_NAME}" \
--field-selector=status.phase!=Running \
-o yaml \
pods # Print not running trustify pods when timed out
-
- kubectl get deployments.apps -n "${NAMESPACE}" -o yaml
}
# Available versions of OLM here https://github.com/operator-framework/operator-lifecycle-manager/releases
diff --git a/helm/Chart.yaml b/helm/Chart.yaml
new file mode 100644
index 0000000..3cb5da1
--- /dev/null
+++ b/helm/Chart.yaml
@@ -0,0 +1,5 @@
+---
+name: "trustify-operator"
+version: "1.0.0-SNAPSHOT"
+apiVersion: "v2"
+appVersion: "latest"
diff --git a/helm/README.md b/helm/README.md
new file mode 100644
index 0000000..d48edfe
--- /dev/null
+++ b/helm/README.md
@@ -0,0 +1,10 @@
+## Configuration
+
+The following values are configurable:
+
+- `watchNamespaces` - namespaces to be watched, either:
+ - a list of comma-separated namespace names
+ - `JOSDK_ALL_NAMESPACES` to watch all namespaces
+ - `JOSDK_WATCH_CURRENT` to watch only the namespace in which the operator is deployed
+- `version` - the current version of the application.
+
diff --git a/helm/crds/trustifies.org.trustify-v1.yml b/helm/crds/trustifies.org.trustify-v1.yml
new file mode 100644
index 0000000..8c37639
--- /dev/null
+++ b/helm/crds/trustifies.org.trustify-v1.yml
@@ -0,0 +1,203 @@
+# Generated by Fabric8 CRDGenerator, manual edits might get overwritten!
+apiVersion: "apiextensions.k8s.io/v1"
+kind: "CustomResourceDefinition"
+metadata:
+ name: "trustifies.org.trustify"
+spec:
+ group: "org.trustify"
+ names:
+ kind: "Trustify"
+ plural: "trustifies"
+ singular: "trustify"
+ scope: "Namespaced"
+ versions:
+ - name: "v1alpha1"
+ schema:
+ openAPIV3Schema:
+ properties:
+ spec:
+ properties:
+ db:
+ description: "In this section you can find all properties related\
+ \ to connect to a database."
+ properties:
+ externalDatabase:
+ description: "Use external database."
+ type: "boolean"
+ host:
+ description: "The host of the database."
+ type: "string"
+ name:
+ description: "The database name."
+ type: "string"
+ passwordSecret:
+ description: "The reference to a secret holding the password of\
+ \ the database user."
+ properties:
+ key:
+ type: "string"
+ name:
+ type: "string"
+ optional:
+ type: "boolean"
+ type: "object"
+ port:
+ description: "The port of the database."
+ type: "string"
+ pvcSize:
+ description: "Size of the PVC to create. Valid only if externalDatabase=false"
+ type: "string"
+ resourceLimits:
+ description: "In this section you can configure resource limits\
+ \ settings. Valid only if externalDatabase=false"
+ properties:
+ cpuLimit:
+ description: "Limit CPU."
+ type: "string"
+ cpuRequest:
+ description: "Requested CPU."
+ type: "string"
+ memoryLimit:
+ description: "Limit Memory."
+ type: "string"
+ memoryRequest:
+ description: "Requested memory."
+ type: "string"
+ type: "object"
+ usernameSecret:
+ description: "The reference to a secret holding the username of\
+ \ the database user."
+ properties:
+ key:
+ type: "string"
+ name:
+ type: "string"
+ optional:
+ type: "boolean"
+ type: "object"
+ type: "object"
+ dbImage:
+ description: "Custom Trustify DB Server image to be used. For internal\
+ \ use only"
+ type: "string"
+ hostname:
+ description: "In this section you can configure hostname and related\
+ \ properties."
+ properties:
+ hostname:
+ description: "Hostname for the server."
+ type: "string"
+ type: "object"
+ http:
+ description: "In this section you can configure features related to\
+ \ HTTP and HTTPS"
+ properties:
+ tlsSecret:
+ description: "A secret containing the TLS configuration for HTTPS.\
+ \ Reference: https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets."
+ type: "string"
+ type: "object"
+ imagePullPolicy:
+ description: "Custom Image Pull Policy for images managed by the Operator"
+ type: "string"
+ imagePullSecrets:
+ description: "Secret(s) that might be used when pulling an image from\
+ \ a private container image registry or repository."
+ items:
+ properties:
+ name:
+ type: "string"
+ type: "object"
+ type: "array"
+ oidc:
+ description: "In this section you can configure Oidc settings."
+ properties:
+ enabled:
+ description: "Enable Oidc Auth."
+ type: "boolean"
+ serverClientId:
+ description: "Oidc client id for the Server."
+ type: "string"
+ serverUrl:
+ description: "Oidc server url."
+ type: "string"
+ uiClientId:
+ description: "Oidc client id for the UI."
+ type: "string"
+ type: "object"
+ serverImage:
+ description: "Custom Trustify Server image to be used. For internal\
+ \ use only"
+ type: "string"
+ serverResourceLimits:
+ description: "In this section you can configure resource limits settings\
+ \ for the Server."
+ properties:
+ cpuLimit:
+ description: "Limit CPU."
+ type: "string"
+ cpuRequest:
+ description: "Requested CPU."
+ type: "string"
+ memoryLimit:
+ description: "Limit Memory."
+ type: "string"
+ memoryRequest:
+ description: "Requested memory."
+ type: "string"
+ type: "object"
+ storage:
+ description: "In this section you can configure Storage settings."
+ properties:
+ compression:
+ description: "Storage compression."
+ enum:
+ - "NONE"
+ - "ZSTD"
+ type: "string"
+ filesystem:
+ properties:
+ pvcSize:
+ description: "Size of the PVC to create."
+ type: "string"
+ type: "object"
+ s3:
+ properties:
+ accessKey:
+ description: "Access key."
+ type: "string"
+ bucket:
+ description: "Bucket name."
+ type: "string"
+ region:
+ description: "Region name."
+ type: "string"
+ secretKey:
+ description: "Secret key."
+ type: "string"
+ type: "object"
+ type:
+ description: "Storage type."
+ enum:
+ - "FILESYSTEM"
+ - "S3"
+ type: "string"
+ type: "object"
+ type: "object"
+ status:
+ properties:
+ conditions:
+ items:
+ properties:
+ status:
+ type: "string"
+ type:
+ type: "string"
+ type: "object"
+ type: "array"
+ type: "object"
+ type: "object"
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/helm/templates/_helpers.tpl b/helm/templates/_helpers.tpl
new file mode 100644
index 0000000..be02936
--- /dev/null
+++ b/helm/templates/_helpers.tpl
@@ -0,0 +1,7 @@
+{{- define "app.tag" -}}
+{{- if eq .Chart.AppVersion "latest" }}
+{{- "latest" }}
+{{- else }}
+{{- printf "v%s" .Chart.AppVersion }}
+{{- end }}
+{{- end }}
diff --git a/helm/templates/additional-crd-role-binding.yaml b/helm/templates/additional-crd-role-binding.yaml
new file mode 100644
index 0000000..e69de29
diff --git a/helm/templates/deployment.yaml b/helm/templates/deployment.yaml
new file mode 100644
index 0000000..99556df
--- /dev/null
+++ b/helm/templates/deployment.yaml
@@ -0,0 +1,90 @@
+---
+apiVersion: "apps/v1"
+kind: "Deployment"
+metadata:
+ annotations:
+ app.quarkus.io/quarkus-version: "3.15.1"
+ app.quarkus.io/vcs-uri: "https://github.com/trustification/trustify-operator.git"
+ prometheus.io/scrape: "true"
+ prometheus.io/path: "/q/metrics"
+ prometheus.io/port: "8080"
+ prometheus.io/scheme: "http"
+ labels:
+ app.kubernetes.io/name: "trustify-operator"
+ app.kubernetes.io/managed-by: "quarkus"
+ name: "trustify-operator"
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: "trustify-operator"
+ template:
+ metadata:
+ annotations:
+ app.quarkus.io/quarkus-version: "3.15.1"
+ app.quarkus.io/vcs-uri: "https://github.com/trustification/trustify-operator.git"
+ prometheus.io/scrape: "true"
+ prometheus.io/path: "/q/metrics"
+ prometheus.io/port: "8080"
+ prometheus.io/scheme: "http"
+ labels:
+ app.kubernetes.io/managed-by: "quarkus"
+ app.kubernetes.io/name: "trustify-operator"
+ spec:
+ containers:
+ - env:
+ - name: "KUBERNETES_NAMESPACE"
+ valueFrom:
+ fieldRef:
+ fieldPath: "metadata.namespace"
+ - name: "RELATED_IMAGE_TRUSTIFY_SERVER"
+ value: "ghcr.io/trustification/trustd:latest"
+ - name: "RELATED_IMAGE_DB"
+ value: "quay.io/sclorg/postgresql-15-c9s:latest"
+ - name: "QUARKUS_OPERATOR_SDK_CONTROLLERS_TRUSTIFY_NAMESPACES"
+ value: {{ .Values.watchNamespaces }}
+ image: "ghcr.io/trustification/trustify-operator:{{ include "app.tag" . }}"
+ imagePullPolicy: "Always"
+ livenessProbe:
+ failureThreshold: 3
+ httpGet:
+ path: "/q/health/live"
+ port: 8080
+ scheme: "HTTP"
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 10
+ name: "trustify-operator"
+ ports:
+ - containerPort: 8080
+ name: "http"
+ protocol: "TCP"
+ readinessProbe:
+ failureThreshold: 3
+ httpGet:
+ path: "/q/health/ready"
+ port: 8080
+ scheme: "HTTP"
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 10
+ resources:
+ limits:
+ cpu: "250m"
+ memory: "256Mi"
+ requests:
+ cpu: "50m"
+ memory: "64Mi"
+ startupProbe:
+ failureThreshold: 3
+ httpGet:
+ path: "/q/health/started"
+ port: 8080
+ scheme: "HTTP"
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ successThreshold: 1
+ timeoutSeconds: 10
+ serviceAccountName: "trustify-operator"
diff --git a/helm/templates/generic-crd-cluster-role-binding.yaml b/helm/templates/generic-crd-cluster-role-binding.yaml
new file mode 100644
index 0000000..25f17ed
--- /dev/null
+++ b/helm/templates/generic-crd-cluster-role-binding.yaml
@@ -0,0 +1,16 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: {{ .Chart.Name }}-crd-validating-role-binding
+ labels:
+ app.kubernetes.io/name: {{ .Chart.Name }}
+ app.kubernetes.io/version: {{ .Chart.AppVersion }}
+ app.kubernetes.io/managed-by: quarkus
+roleRef:
+ kind: ClusterRole
+ apiGroup: rbac.authorization.k8s.io
+ name: {{ .Chart.Name }}-crd-validating-cluster-role
+subjects:
+ - kind: ServiceAccount
+ name: {{ .Chart.Name }}
+ namespace: {{ .Release.Namespace }}
diff --git a/helm/templates/generic-crd-cluster-role.yaml b/helm/templates/generic-crd-cluster-role.yaml
new file mode 100644
index 0000000..d7d6b0e
--- /dev/null
+++ b/helm/templates/generic-crd-cluster-role.yaml
@@ -0,0 +1,16 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: {{ .Chart.Name }}-crd-validating-cluster-role
+ labels:
+ app.kubernetes.io/name: {{ .Chart.Name }}
+ app.kubernetes.io/version: {{ .Chart.AppVersion }}
+ app.kubernetes.io/managed-by: quarkus
+rules:
+ - apiGroups:
+ - apiextensions.k8s.io
+ resources:
+ - customresourcedefinitions
+ verbs:
+ - get
+ - list
diff --git a/helm/templates/service.yaml b/helm/templates/service.yaml
new file mode 100644
index 0000000..efedaa9
--- /dev/null
+++ b/helm/templates/service.yaml
@@ -0,0 +1,18 @@
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ app.kubernetes.io/name: {{ .Chart.Name }}
+ app.kubernetes.io/version: {{ .Chart.AppVersion }}
+ app.kubernetes.io/managed-by: quarkus
+ name: {{ .Chart.Name }}
+spec:
+ ports:
+ - name: http
+ port: 80
+ protocol: TCP
+ targetPort: 8080
+ selector:
+ app.kubernetes.io/name: {{ .Chart.Name }}
+ app.kubernetes.io/version: {{ .Chart.AppVersion }}
+ type: ClusterIP
diff --git a/helm/templates/serviceaccount.yaml b/helm/templates/serviceaccount.yaml
new file mode 100644
index 0000000..d9181f0
--- /dev/null
+++ b/helm/templates/serviceaccount.yaml
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ labels:
+ app.kubernetes.io/managed-by: quarkus
+ app.kubernetes.io/name: {{ .Chart.Name }}
+ app.kubernetes.io/version: {{ .Chart.AppVersion }}
+ name: {{ .Chart.Name }}
diff --git a/helm/templates/trustify-crd-cluster-role.yaml b/helm/templates/trustify-crd-cluster-role.yaml
new file mode 100644
index 0000000..fb89f79
--- /dev/null
+++ b/helm/templates/trustify-crd-cluster-role.yaml
@@ -0,0 +1,80 @@
+---
+apiVersion: "rbac.authorization.k8s.io/v1"
+kind: "ClusterRole"
+metadata:
+ name: "trustify-cluster-role"
+rules:
+- apiGroups:
+ - "org.trustify"
+ resources:
+ - "trustifies"
+ - "trustifies/status"
+ - "trustifies/finalizers"
+ verbs:
+ - "get"
+ - "list"
+ - "watch"
+ - "patch"
+ - "update"
+ - "create"
+ - "delete"
+- apiGroups:
+ - ""
+ resources:
+ - "persistentvolumeclaims"
+ verbs:
+ - "create"
+ - "delete"
+ - "get"
+ - "list"
+ - "patch"
+ - "update"
+ - "watch"
+- apiGroups:
+ - "apps"
+ resources:
+ - "deployments"
+ verbs:
+ - "create"
+ - "delete"
+ - "get"
+ - "list"
+ - "patch"
+ - "update"
+ - "watch"
+- apiGroups:
+ - ""
+ resources:
+ - "secrets"
+ verbs:
+ - "create"
+ - "delete"
+ - "get"
+ - "list"
+ - "patch"
+ - "update"
+ - "watch"
+- apiGroups:
+ - ""
+ resources:
+ - "services"
+ verbs:
+ - "create"
+ - "delete"
+ - "get"
+ - "list"
+ - "patch"
+ - "update"
+ - "watch"
+- apiGroups:
+ - "networking.k8s.io"
+ resources:
+ - "ingresses"
+ verbs:
+ - "create"
+ - "delete"
+ - "get"
+ - "list"
+ - "patch"
+ - "update"
+ - "watch"
diff --git a/helm/templates/trustify-crd-role-binding.yaml b/helm/templates/trustify-crd-role-binding.yaml
new file mode 100644
index 0000000..16f71b2
--- /dev/null
+++ b/helm/templates/trustify-crd-role-binding.yaml
@@ -0,0 +1,57 @@
+{{ if eq $.Values.watchNamespaces "JOSDK_WATCH_CURRENT" }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: trustify-role-binding
+ namespace: {{ $.Release.Namespace }}
+ labels:
+ app.kubernetes.io/name: {{ .Chart.Name }}
+ app.kubernetes.io/version: {{ .Chart.AppVersion }}
+ app.kubernetes.io/managed-by: quarkus
+roleRef:
+ kind: ClusterRole
+ apiGroup: rbac.authorization.k8s.io
+ name: trustify-cluster-role
+subjects:
+ - kind: ServiceAccount
+ name: {{ $.Chart.Name }}
+ namespace: {{ $.Release.Namespace }}
+{{ else if eq $.Values.watchNamespaces "JOSDK_ALL_NAMESPACES" }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: trustify-role-binding
+ labels:
+ app.kubernetes.io/name: {{ .Chart.Name }}
+ app.kubernetes.io/version: {{ .Chart.AppVersion }}
+ app.kubernetes.io/managed-by: quarkus
+roleRef:
+ kind: ClusterRole
+ apiGroup: rbac.authorization.k8s.io
+ name: trustify-cluster-role
+subjects:
+ - kind: ServiceAccount
+ name: {{ $.Chart.Name }}
+ namespace: {{ $.Release.Namespace }}
+{{ else }}
+{{ range $anamespace := ( split "," $.Values.watchNamespaces ) }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: trustify-role-binding
+ namespace: {{ $anamespace }}
+ labels:
+ app.kubernetes.io/name: {{ .Chart.Name }}
+ app.kubernetes.io/version: {{ .Chart.AppVersion }}
+ app.kubernetes.io/managed-by: quarkus
+roleRef:
+ kind: ClusterRole
+ apiGroup: rbac.authorization.k8s.io
+ name: trustify-cluster-role
+subjects:
+ - kind: ServiceAccount
+ name: {{ $.Chart.Name }}
+ namespace: {{ $.Release.Namespace }}
+---
+{{- end }}
+{{- end }}
diff --git a/helm/values.schema.json b/helm/values.schema.json
new file mode 100644
index 0000000..d7b8b83
--- /dev/null
+++ b/helm/values.schema.json
@@ -0,0 +1,10 @@
+{
+ "$schema": "https://json-schema.org/draft-07/schema#",
+ "title": "Values",
+ "type": "object",
+ "properties": {
+ "watchNamespaces": {
+ "type": "string"
+ }
+ }
+}
\ No newline at end of file
diff --git a/helm/values.yaml b/helm/values.yaml
new file mode 100644
index 0000000..7096e08
--- /dev/null
+++ b/helm/values.yaml
@@ -0,0 +1,2 @@
+---
+watchNamespaces: "JOSDK_ALL_NAMESPACES"
diff --git a/pom.xml b/pom.xml
index b6918a3..fcf71a1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,7 +17,7 @@
true
3.2.5
- 6.8.2
+ 6.8.4
@@ -45,12 +45,16 @@
io.quarkus
- quarkus-resteasy-reactive
+ quarkus-rest
io.quarkus
quarkus-smallrye-health
+
+ io.quarkus
+ quarkus-config-yaml
+
io.quarkus
@@ -86,20 +90,20 @@
com.fasterxml.jackson.datatype
jackson-datatype-jsr310
- 2.17.2
+ 2.17.3
test
org.testcontainers
k3s
- 1.19.7
+ 1.20.3
test
org.awaitility
awaitility
- 4.2.1
+ 4.2.2
test
diff --git a/scripts/enrichCSV.groovy b/scripts/enrichCSV.groovy
deleted file mode 100644
index 7707ba3..0000000
--- a/scripts/enrichCSV.groovy
+++ /dev/null
@@ -1,32 +0,0 @@
-@Grab('org.yaml:snakeyaml:1.33')
-import org.yaml.snakeyaml.*
-import groovy.yaml.*
-import java.util.Map
-import java.time.LocalDate
-
-def file = new File(this.args[0])
-
-def fileReader = new FileReader(file)
-def yaml = new Yaml().load(fileReader)
-
-yaml.metadata.annotations.support = "https://github.com/trustification/trustify-operator/issues"
-yaml.metadata.annotations.description = "An Operator for installing and managing Trustify"
-yaml.metadata.annotations.createdAt = LocalDate.now().toString()
-yaml.metadata.annotations.containerImage = yaml.spec.install.spec.deployments[0].spec.template.spec.containers[0].image
-
-yaml.spec.customresourcedefinitions.owned[0].description = "Represents a Trustify instance"
-yaml.spec.customresourcedefinitions.owned[0].displayName = "Trustify"
-
-// Adding cluster permissions to be able to fetch host domain
-yaml.spec.install.spec.clusterPermissions.rules[0][1] = [:]
-yaml.spec.install.spec.clusterPermissions.rules[0][1].apiGroups = ['config.openshift.io']
-yaml.spec.install.spec.clusterPermissions.rules[0][1].resources = ['ingresses']
-yaml.spec.install.spec.clusterPermissions.rules[0][1].verbs = ['get', 'list']
-
-DumperOptions options = new DumperOptions();
-options.indent = 2
-options.defaultFlowStyle = DumperOptions.FlowStyle.BLOCK
-options.defaultScalarStyle = DumperOptions.ScalarStyle.PLAIN
-options.prettyFlow = true
-
-new Yaml(options).dump(yaml, new FileWriter(file))
diff --git a/scripts/examples/storage-filesystem.yaml b/scripts/examples/storage-filesystem.yaml
new file mode 100644
index 0000000..29a1e6f
--- /dev/null
+++ b/scripts/examples/storage-filesystem.yaml
@@ -0,0 +1,9 @@
+apiVersion: "org.trustify/v1alpha1"
+kind: "Trustify"
+metadata:
+ name: myapp
+spec:
+ storage:
+ type: FILESYSTEM
+ filesystem:
+ pvcSize: 5Gi
diff --git a/scripts/examples/storage-s3.yaml b/scripts/examples/storage-s3.yaml
new file mode 100644
index 0000000..60429f5
--- /dev/null
+++ b/scripts/examples/storage-s3.yaml
@@ -0,0 +1,12 @@
+apiVersion: "org.trustify/v1alpha1"
+kind: "Trustify"
+metadata:
+ name: myapp
+spec:
+ storage:
+ type: S3
+ s3:
+ region: myregion
+ bucket: mybucket
+ secretKey: mysecretkey
+ accessKey: myaccesskey
diff --git a/src/main/java/org/trustify/operator/Constants.java b/src/main/java/org/trustify/operator/Constants.java
index 6a971a6..b868b5b 100644
--- a/src/main/java/org/trustify/operator/Constants.java
+++ b/src/main/java/org/trustify/operator/Constants.java
@@ -44,11 +44,12 @@ public class Constants {
public static final String OIDC_DB_DEPLOYMENT_SUFFIX = "-" + OIDC_DB_NAME + "-deployment";
public static final String OIDC_DB_SERVICE_SUFFIX = "-" + OIDC_DB_NAME + "-service";
+ public static final String SERVER_PVC_SUFFIX = "-" + TRUSTI_SERVER_NAME + "-pvc";
public static final String SERVER_DEPLOYMENT_SUFFIX = "-" + TRUSTI_SERVER_NAME + "-deployment";
public static final String SERVER_SERVICE_SUFFIX = "-" + TRUSTI_SERVER_NAME + "-service";
- public static final String INGRESS_SUFFIX = "-" + TRUSTI_SERVER_NAME + "-ingress";
+ public static final String INGRESS_SUFFIX = "-" + TRUSTI_NAME + "-ingress";
//
public static final String DB_SECRET_USERNAME = "username";
@@ -56,7 +57,7 @@ public class Constants {
public static final String DB_NAME = "database";
public static final Integer DB_PORT= 5432;
- public static final String POSTGRESQL_PVC_SIZE = "10G";
+ public static final String DEFAULT_PVC_SIZE = "10G";
public static final String CERTIFICATES_FOLDER = "/mnt/certificates";
public static final String WORKSPACES_FOLDER = "/mnt/workspace";
diff --git a/src/main/java/org/trustify/operator/cdrs/v2alpha1/TrustifySpec.java b/src/main/java/org/trustify/operator/cdrs/v2alpha1/TrustifySpec.java
index a4cbb6c..770fb86 100644
--- a/src/main/java/org/trustify/operator/cdrs/v2alpha1/TrustifySpec.java
+++ b/src/main/java/org/trustify/operator/cdrs/v2alpha1/TrustifySpec.java
@@ -36,6 +36,10 @@ public record TrustifySpec(
@JsonPropertyDescription("In this section you can configure Oidc settings.")
OidcSpec oidcSpec,
+ @JsonProperty("storage")
+ @JsonPropertyDescription("In this section you can configure Storage settings.")
+ StorageSpec storageSpec,
+
@JsonProperty("serverResourceLimits")
@JsonPropertyDescription("In this section you can configure resource limits settings for the Server.")
ResourcesLimitSpec serverResourceLimitSpec
@@ -51,6 +55,7 @@ public TrustifySpec() {
null,
null,
null,
+ null,
null
);
}
@@ -96,11 +101,13 @@ public record HttpSpec(
public record OidcSpec(
@JsonPropertyDescription("Enable Oidc Auth.")
- String enabled,
+ boolean enabled,
@JsonPropertyDescription("Oidc server url.")
String serverUrl,
- @JsonPropertyDescription("Oidc client id.")
- String clientId,
+ @JsonPropertyDescription("Oidc client id for the UI.")
+ String uiClientId,
+ @JsonPropertyDescription("Oidc client id for the Server.")
+ String serverClientId,
@JsonProperty("db")
@JsonPropertyDescription("In this section you can find all properties related to connect to a database.")
@@ -108,6 +115,64 @@ public record OidcSpec(
) {
}
+ public enum StorageStrategyType {
+ FILESYSTEM("fs"),
+ S3("s3");
+ private final String value;
+
+ StorageStrategyType(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+ }
+
+ public enum StorageCompressionType {
+ NONE("none"),
+ ZSTD("zstd");
+ private final String value;
+
+ StorageCompressionType(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+ }
+
+ public record StorageSpec(
+ @JsonPropertyDescription("Storage compression.")
+ StorageCompressionType compression,
+ @JsonPropertyDescription("Storage type.")
+ StorageStrategyType type,
+ @JsonProperty("filesystem")
+ FilesystemStorageSpec filesystemStorageSpec,
+ @JsonProperty("s3")
+ S3StorageSpec s3StorageSpec
+ ) {
+ }
+
+ public record FilesystemStorageSpec(
+ @JsonPropertyDescription("Size of the PVC to create.")
+ String pvcSize
+ ) {
+ }
+
+ public record S3StorageSpec(
+ @JsonPropertyDescription("Region name.")
+ String region,
+ @JsonPropertyDescription("Bucket name.")
+ String bucket,
+ @JsonPropertyDescription("Access key.")
+ String accessKey,
+ @JsonPropertyDescription("Secret key.")
+ String secretKey
+ ) {
+ }
+
public record ResourcesLimitSpec(
@JsonPropertyDescription("Requested CPU.")
String cpuRequest,
diff --git a/src/main/java/org/trustify/operator/cdrs/v2alpha1/db/DBDeploymentDiscriminator.java b/src/main/java/org/trustify/operator/cdrs/v2alpha1/db/DBDeploymentDiscriminator.java
index 9268fb3..8f78d84 100644
--- a/src/main/java/org/trustify/operator/cdrs/v2alpha1/db/DBDeploymentDiscriminator.java
+++ b/src/main/java/org/trustify/operator/cdrs/v2alpha1/db/DBDeploymentDiscriminator.java
@@ -6,6 +6,7 @@
import io.javaoperatorsdk.operator.processing.event.ResourceID;
import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
import org.trustify.operator.cdrs.v2alpha1.Trustify;
+import org.trustify.operator.controllers.TrustifyReconciler;
import java.util.Optional;
@@ -14,7 +15,7 @@ public class DBDeploymentDiscriminator implements ResourceDiscriminator distinguish(Class resource, Trustify cr, Context context) {
String deploymentName = DBDeployment.getDeploymentName(cr);
ResourceID resourceID = new ResourceID(deploymentName, cr.getMetadata().getNamespace());
- var informerEventSource = (InformerEventSource) context.eventSourceRetriever().getResourceEventSourceFor(Deployment.class, "db-deployment");
+ var informerEventSource = (InformerEventSource) context.eventSourceRetriever().getResourceEventSourceFor(Deployment.class, TrustifyReconciler.DEPLOYMENT_EVENT_SOURCE);
return informerEventSource.get(resourceID);
}
}
diff --git a/src/main/java/org/trustify/operator/cdrs/v2alpha1/db/DBPersistentVolumeClaim.java b/src/main/java/org/trustify/operator/cdrs/v2alpha1/db/DBPersistentVolumeClaim.java
index f1bcaa1..934aa2d 100644
--- a/src/main/java/org/trustify/operator/cdrs/v2alpha1/db/DBPersistentVolumeClaim.java
+++ b/src/main/java/org/trustify/operator/cdrs/v2alpha1/db/DBPersistentVolumeClaim.java
@@ -36,7 +36,7 @@ private PersistentVolumeClaim newPersistentVolumeClaim(Trustify cr, Context distinguish(Class resource, Trustify cr, Context context) {
String persistentVolumeClaimName = DBPersistentVolumeClaim.getPersistentVolumeClaimName(cr);
ResourceID resourceID = new ResourceID(persistentVolumeClaimName, cr.getMetadata().getNamespace());
- var informerEventSource = (InformerEventSource) context.eventSourceRetriever().getResourceEventSourceFor(PersistentVolumeClaim.class);
+ var informerEventSource = (InformerEventSource) context.eventSourceRetriever().getResourceEventSourceFor(PersistentVolumeClaim.class, TrustifyReconciler.PVC_EVENT_SOURCE);
return informerEventSource.get(resourceID);
}
}
diff --git a/src/main/java/org/trustify/operator/cdrs/v2alpha1/db/DBServiceDiscriminator.java b/src/main/java/org/trustify/operator/cdrs/v2alpha1/db/DBServiceDiscriminator.java
index 8eeff53..ec1048d 100644
--- a/src/main/java/org/trustify/operator/cdrs/v2alpha1/db/DBServiceDiscriminator.java
+++ b/src/main/java/org/trustify/operator/cdrs/v2alpha1/db/DBServiceDiscriminator.java
@@ -6,6 +6,7 @@
import io.javaoperatorsdk.operator.processing.event.ResourceID;
import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
import org.trustify.operator.cdrs.v2alpha1.Trustify;
+import org.trustify.operator.controllers.TrustifyReconciler;
import java.util.Optional;
@@ -14,7 +15,7 @@ public class DBServiceDiscriminator implements ResourceDiscriminator distinguish(Class resource, Trustify cr, Context context) {
String serviceName = DBService.getServiceName(cr);
ResourceID resourceID = new ResourceID(serviceName, cr.getMetadata().getNamespace());
- var informerEventSource = (InformerEventSource) context.eventSourceRetriever().getResourceEventSourceFor(Service.class, "db-service");
+ var informerEventSource = (InformerEventSource) context.eventSourceRetriever().getResourceEventSourceFor(Service.class, TrustifyReconciler.SERVICE_EVENT_SOURCE);
return informerEventSource.get(resourceID);
}
}
diff --git a/src/main/java/org/trustify/operator/cdrs/v2alpha1/server/ServerDeployment.java b/src/main/java/org/trustify/operator/cdrs/v2alpha1/server/ServerDeployment.java
index df02aba..085d9eb 100644
--- a/src/main/java/org/trustify/operator/cdrs/v2alpha1/server/ServerDeployment.java
+++ b/src/main/java/org/trustify/operator/cdrs/v2alpha1/server/ServerDeployment.java
@@ -130,6 +130,18 @@ private DeploymentSpec getDeploymentSpec(Trustify cr, Context context,
.withTerminationGracePeriodSeconds(70L)
.withImagePullSecrets(cr.getSpec().imagePullSecrets())
// .withServiceAccountName(Constants.TRUSTI_NAME)
+ .withInitContainers(new ContainerBuilder()
+ .withName("migrate")
+ .withImage(image)
+ .withImagePullPolicy(imagePullPolicy)
+ .withEnv(envVars)
+ .withCommand(
+ "/usr/local/bin/trustd",
+ "db",
+ "migrate"
+ )
+ .build()
+ )
.withContainers(new ContainerBuilder()
.withName(Constants.TRUSTI_SERVER_NAME)
.withImage(image)
@@ -138,7 +150,7 @@ private DeploymentSpec getDeploymentSpec(Trustify cr, Context context,
.withCommand(
"/usr/local/bin/trustd",
"api",
- "--devmode",
+ "--sample-data",
"--infrastructure-enabled",
"--infrastructure-bind=0.0.0.0:" + Constants.HTTP_INFRAESTRUCTURE_PORT
)
diff --git a/src/main/java/org/trustify/operator/cdrs/v2alpha1/server/ServerStoragePersistentVolumeClaim.java b/src/main/java/org/trustify/operator/cdrs/v2alpha1/server/ServerStoragePersistentVolumeClaim.java
index f6f5975..5cced6f 100644
--- a/src/main/java/org/trustify/operator/cdrs/v2alpha1/server/ServerStoragePersistentVolumeClaim.java
+++ b/src/main/java/org/trustify/operator/cdrs/v2alpha1/server/ServerStoragePersistentVolumeClaim.java
@@ -8,9 +8,11 @@
import jakarta.enterprise.context.ApplicationScoped;
import org.trustify.operator.Constants;
import org.trustify.operator.cdrs.v2alpha1.Trustify;
+import org.trustify.operator.cdrs.v2alpha1.TrustifySpec;
import org.trustify.operator.utils.CRDUtils;
import java.util.Map;
+import java.util.Optional;
@KubernetesDependent(labelSelector = ServerStoragePersistentVolumeClaim.LABEL_SELECTOR, resourceDiscriminator = ServerStoragePersistentVolumeClaimDiscriminator.class)
@ApplicationScoped
@@ -33,7 +35,10 @@ private PersistentVolumeClaim newPersistentVolumeClaim(Trustify cr, Context) context.managedDependentResourceContext()
.getMandatory(Constants.CONTEXT_LABELS_KEY, Map.class);
- String pvcStorageSize = "10Gi";
+ String pvcStorageSize = Optional.ofNullable(cr.getSpec().storageSpec())
+ .flatMap(storageSpec -> Optional.ofNullable(storageSpec.filesystemStorageSpec()))
+ .map(TrustifySpec.FilesystemStorageSpec::pvcSize)
+ .orElse(Constants.DEFAULT_PVC_SIZE);
return new PersistentVolumeClaimBuilder()
.withNewMetadata()
@@ -65,7 +70,7 @@ public Result match(PersistentVolumeClaim actual, Trustif
}
public static String getPersistentVolumeClaimName(Trustify cr) {
- return cr.getMetadata().getName() + Constants.DB_PVC_SUFFIX;
+ return cr.getMetadata().getName() + Constants.SERVER_PVC_SUFFIX;
}
}
diff --git a/src/main/java/org/trustify/operator/cdrs/v2alpha1/server/ServerStoragePersistentVolumeClaimActivationCondition.java b/src/main/java/org/trustify/operator/cdrs/v2alpha1/server/ServerStoragePersistentVolumeClaimActivationCondition.java
new file mode 100644
index 0000000..d079722
--- /dev/null
+++ b/src/main/java/org/trustify/operator/cdrs/v2alpha1/server/ServerStoragePersistentVolumeClaimActivationCondition.java
@@ -0,0 +1,24 @@
+package org.trustify.operator.cdrs.v2alpha1.server;
+
+import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
+import jakarta.enterprise.context.ApplicationScoped;
+import org.trustify.operator.cdrs.v2alpha1.Trustify;
+import org.trustify.operator.cdrs.v2alpha1.TrustifySpec;
+
+import java.util.Objects;
+import java.util.Optional;
+
+@ApplicationScoped
+public class ServerStoragePersistentVolumeClaimActivationCondition implements Condition {
+
+ @Override
+ public boolean isMet(DependentResource resource, Trustify cr, Context context) {
+ return Optional.ofNullable(cr.getSpec().storageSpec())
+ .map(storageSpec -> Objects.isNull(storageSpec.type()) || Objects.equals(TrustifySpec.StorageStrategyType.FILESYSTEM, storageSpec.type()))
+ .orElse(true);
+ }
+
+}
diff --git a/src/main/java/org/trustify/operator/cdrs/v2alpha1/server/ServerStoragePersistentVolumeClaimDiscriminator.java b/src/main/java/org/trustify/operator/cdrs/v2alpha1/server/ServerStoragePersistentVolumeClaimDiscriminator.java
index d10225f..a277503 100644
--- a/src/main/java/org/trustify/operator/cdrs/v2alpha1/server/ServerStoragePersistentVolumeClaimDiscriminator.java
+++ b/src/main/java/org/trustify/operator/cdrs/v2alpha1/server/ServerStoragePersistentVolumeClaimDiscriminator.java
@@ -6,6 +6,7 @@
import io.javaoperatorsdk.operator.processing.event.ResourceID;
import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
import org.trustify.operator.cdrs.v2alpha1.Trustify;
+import org.trustify.operator.controllers.TrustifyReconciler;
import java.util.Optional;
@@ -14,7 +15,7 @@ public class ServerStoragePersistentVolumeClaimDiscriminator implements Resource
public Optional distinguish(Class resource, Trustify cr, Context context) {
String persistentVolumeClaimName = ServerStoragePersistentVolumeClaim.getPersistentVolumeClaimName(cr);
ResourceID resourceID = new ResourceID(persistentVolumeClaimName, cr.getMetadata().getNamespace());
- var informerEventSource = (InformerEventSource) context.eventSourceRetriever().getResourceEventSourceFor(PersistentVolumeClaim.class);
+ var informerEventSource = (InformerEventSource) context.eventSourceRetriever().getResourceEventSourceFor(PersistentVolumeClaim.class, TrustifyReconciler.PVC_EVENT_SOURCE);
return informerEventSource.get(resourceID);
}
}
diff --git a/src/main/java/org/trustify/operator/controllers/TrustifyDistConfigurator.java b/src/main/java/org/trustify/operator/controllers/TrustifyDistConfigurator.java
index 2e86267..ee14ea8 100644
--- a/src/main/java/org/trustify/operator/controllers/TrustifyDistConfigurator.java
+++ b/src/main/java/org/trustify/operator/controllers/TrustifyDistConfigurator.java
@@ -122,33 +122,79 @@ private void configureDatabase() {
}
private void configureStorage() {
- List envVars = optionMapper(cr.getSpec())
- .mapOption("TRUSTD_STORAGE_FS_PATH", spec -> "/opt/trustify/storage")
- .getEnvVars();
+ List envVars = new ArrayList<>();
- var volume = new VolumeBuilder()
- .withName("trustify-pvol")
- .withPersistentVolumeClaim(new PersistentVolumeClaimVolumeSourceBuilder()
- .withClaimName(ServerStoragePersistentVolumeClaim.getPersistentVolumeClaimName(cr))
- .build()
- )
- .build();
+ TrustifySpec.StorageSpec storageSpec = Optional.ofNullable(cr.getSpec().storageSpec())
+ .orElse(new TrustifySpec.StorageSpec(null, null, null, null));
- var volumeMount = new VolumeMountBuilder()
- .withName(volume.getName())
- .withMountPath("/opt/trustify")
- .build();
+ // Storage type
+ TrustifySpec.StorageStrategyType storageStrategyType = Objects.nonNull(storageSpec.type()) ? storageSpec.type() : TrustifySpec.StorageStrategyType.FILESYSTEM;
+ envVars.add(new EnvVarBuilder()
+ .withName("TRUSTD_STORAGE_STRATEGY")
+ .withValue(storageStrategyType.getValue())
+ .build()
+ );
- allVolumes.add(volume);
- allVolumeMounts.add(volumeMount);
+ // Other config
+ envVars.addAll(optionMapper(storageSpec)
+ .mapOption("TRUSTD_STORAGE_COMPRESSION", spec -> Objects.nonNull(spec.compression()) ? spec.compression().getValue() : null)
+ .getEnvVars()
+ );
+
+ switch (storageStrategyType) {
+ case FILESYSTEM -> {
+ envVars.add(new EnvVarBuilder()
+ .withName("TRUSTD_STORAGE_FS_PATH")
+ .withValue("/opt/trustify/storage")
+ .build()
+ );
+
+ var volume = new VolumeBuilder()
+ .withName("trustify-pvol")
+ .withPersistentVolumeClaim(new PersistentVolumeClaimVolumeSourceBuilder()
+ .withClaimName(ServerStoragePersistentVolumeClaim.getPersistentVolumeClaimName(cr))
+ .build()
+ )
+ .build();
+
+ var volumeMount = new VolumeMountBuilder()
+ .withName(volume.getName())
+ .withMountPath("/opt/trustify")
+ .build();
+
+ allVolumes.add(volume);
+ allVolumeMounts.add(volumeMount);
+ }
+ case S3 -> {
+ envVars.addAll(optionMapper(storageSpec.s3StorageSpec())
+ .mapOption("TRUSTD_S3_BUCKET", TrustifySpec.S3StorageSpec::bucket)
+ .mapOption("TRUSTD_S3_REGION", TrustifySpec.S3StorageSpec::region)
+ .mapOption("TRUSTD_S3_ACCESS_KEY", TrustifySpec.S3StorageSpec::accessKey)
+ .mapOption("TRUSTD_S3_SECRET_KEY", TrustifySpec.S3StorageSpec::secretKey)
+ .getEnvVars()
+ );
+ }
+ }
allEnvVars.addAll(envVars);
}
private void configureOidc() {
- List envVars = optionMapper(cr.getSpec())
- .mapOption("AUTH_DISABLED", spec -> true)
- .getEnvVars();
+ List envVars = Optional.ofNullable(cr.getSpec().oidcSpec())
+ .map(oidcSpec -> optionMapper(oidcSpec)
+ .mapOption("AUTH_DISABLED", spec -> !spec.enabled())
+ .mapOption("AUTHENTICATOR_OIDC_ISSUER_URL", TrustifySpec.OidcSpec::serverUrl)
+ .mapOption("AUTHENTICATOR_OIDC_CLIENT_IDS", TrustifySpec.OidcSpec::serverClientId)
+ .mapOption("UI_ISSUER_URL", TrustifySpec.OidcSpec::serverUrl)
+ .mapOption("UI_CLIENT_ID", TrustifySpec.OidcSpec::uiClientId)
+ .getEnvVars()
+ )
+ .orElseGet(() -> List.of(new EnvVarBuilder()
+ .withName("AUTH_DISABLED")
+ .withValue(Boolean.TRUE.toString())
+ .build())
+ );
+
allEnvVars.addAll(envVars);
}
diff --git a/src/main/java/org/trustify/operator/controllers/TrustifyReconciler.java b/src/main/java/org/trustify/operator/controllers/TrustifyReconciler.java
index bf38b08..fe0a036 100644
--- a/src/main/java/org/trustify/operator/controllers/TrustifyReconciler.java
+++ b/src/main/java/org/trustify/operator/controllers/TrustifyReconciler.java
@@ -12,10 +12,9 @@
import org.trustify.operator.cdrs.v2alpha1.Trustify;
import org.trustify.operator.cdrs.v2alpha1.TrustifyStatusCondition;
import org.trustify.operator.cdrs.v2alpha1.db.*;
-import org.trustify.operator.cdrs.v2alpha1.keycloak.*;
-import org.trustify.operator.cdrs.v2alpha1.server.ServerDeployment;
-import org.trustify.operator.cdrs.v2alpha1.server.ServerIngress;
-import org.trustify.operator.cdrs.v2alpha1.server.ServerService;
+import org.trustify.operator.cdrs.v2alpha1.keycloak.KeycloakDBPersistentVolumeClaim;
+import org.trustify.operator.cdrs.v2alpha1.keycloak.KeycloakDBPersistentVolumeClaimActivationCondition;
+import org.trustify.operator.cdrs.v2alpha1.server.*;
import java.time.Duration;
import java.util.Map;
@@ -33,78 +32,76 @@
activationCondition = KeycloakDBPersistentVolumeClaimActivationCondition.class,
useEventSourceWithName = TrustifyReconciler.PVC_EVENT_SOURCE
),
-// @Dependent(
-// name = "oidc-db-secret",
-// type = KeycloakDBSecret.class,
-// activationCondition = KeycloakDBSecretActivationCondition.class
-// ),
-// @Dependent(
-// name = "oidc-db-deployment",
-// type = KeycloakDBDeployment.class,
-// dependsOn = {"db-pvc", "db-secret"},
-// readyPostcondition = KeycloakDBDeployment.class,
-// activationCondition = KeycloakDBDeploymentActivationCondition.class
-// ),
-// @Dependent(
-// name = "oidc-db-service",
-// type = KeycloakDBService.class,
-// dependsOn = {"oidc-db-deployment"},
-// activationCondition = KeycloakDBServiceActivationCondition.class
-// ),
-
- // Trustify
+ @Dependent(
+ name = "oidc-db-secret",
+ type = KeycloakDBSecret.class,
+ activationCondition = KeycloakDBSecretActivationCondition.class
+ ),
+ @Dependent(
+ name = "oidc-db-deployment",
+ type = KeycloakDBDeployment.class,
+ dependsOn = {"db-pvc", "db-secret"},
+ readyPostcondition = KeycloakDBDeployment.class,
+ activationCondition = KeycloakDBDeploymentActivationCondition.class
+ ),
+ @Dependent(
+ name = "oidc-db-service",
+ type = KeycloakDBService.class,
+ dependsOn = {"oidc-db-deployment"},
+ activationCondition = KeycloakDBServiceActivationCondition.class
+ ),
+
@Dependent(
name = "db-pvc",
type = DBPersistentVolumeClaim.class,
- activationCondition = DBPersistentVolumeClaimActivationCondition.class,
- useEventSourceWithName = TrustifyReconciler.PVC_EVENT_SOURCE
+ activationCondition = DBPersistentVolumeClaimActivationCondition.class
),
-// @Dependent(
-// name = "db-secret",
-// type = DBSecret.class,
-// activationCondition = DBSecretActivationCondition.class
-// ),
-// @Dependent(
-// name = "db-deployment",
-// type = DBDeployment.class,
-// dependsOn = {"db-pvc", "db-secret"},
-// readyPostcondition = DBDeployment.class,
-// activationCondition = DBDeploymentActivationCondition.class
-// ),
-// @Dependent(
-// name = "db-service",
-// type = DBService.class,
-// dependsOn = {"db-deployment"},
-// activationCondition = DBServiceActivationCondition.class
-// ),
-//
-// @Dependent(
-// name = "server-deployment",
-// type = ServerDeployment.class,
-//// dependsOn = {"db-service"},
-// readyPostcondition = ServerDeployment.class,
-// useEventSourceWithName = "server-deployment"
-// ),
-// @Dependent(
-// name = "server-service",
-// type = ServerService.class,
-// dependsOn = {"server-deployment"},
-// useEventSourceWithName = "server-service"
-// ),
-//
-// @Dependent(
-// name = "ingress",
-// type = ServerIngress.class,
-// dependsOn = {"server-service"},
-// readyPostcondition = ServerIngress.class
-// )
+ @Dependent(
+ name = "db-secret",
+ type = DBSecret.class,
+ activationCondition = DBSecretActivationCondition.class
+ ),
+ @Dependent(
+ name = "db-deployment",
+ type = DBDeployment.class,
+ dependsOn = {"db-pvc", "db-secret"},
+ readyPostcondition = DBDeployment.class,
+ activationCondition = DBDeploymentActivationCondition.class
+ ),
+ @Dependent(
+ name = "db-service",
+ type = DBService.class,
+ dependsOn = {"db-deployment"},
+ activationCondition = DBServiceActivationCondition.class
+ ),
+
+ @Dependent(
+ name = "server-deployment",
+ type = ServerDeployment.class,
+// dependsOn = {"db-service"},
+ readyPostcondition = ServerDeployment.class,
+ useEventSourceWithName = "server-deployment"
+ ),
+ @Dependent(
+ name = "server-service",
+ type = ServerService.class,
+ dependsOn = {"server-deployment"},
+ useEventSourceWithName = "server-service"
+ ),
+
+ @Dependent(
+ name = "ingress",
+ type = ServerIngress.class,
+ dependsOn = {"server-service"},
+ readyPostcondition = ServerIngress.class
+ )
}
)
public class TrustifyReconciler implements Reconciler, ContextInitializer, EventSourceInitializer {
private static final Logger logger = Logger.getLogger(TrustifyReconciler.class);
- public static final String PVC_EVENT_SOURCE = "pvcSource";
+ public static final String PVC_EVENT_SOURCE = "pcvSource";
public static final String DEPLOYMENT_EVENT_SOURCE = "deploymentSource";
public static final String SERVICE_EVENT_SOURCE = "serviceSource";
@@ -152,16 +149,16 @@ public UpdateControl reconcile(Trustify cr, Context context) {
@Override
public Map prepareEventSources(EventSourceContext context) {
- var pvcInformerConfiguration = InformerConfiguration.from(PersistentVolumeClaim.class, context).build();
+ var pcvInformerConfiguration = InformerConfiguration.from(PersistentVolumeClaim.class, context).build();
var deploymentInformerConfiguration = InformerConfiguration.from(Deployment.class, context).build();
var serviceInformerConfiguration = InformerConfiguration.from(Service.class, context).build();
- var pvcInformerEventSource = new InformerEventSource<>(pvcInformerConfiguration, context);
+ var pcvInformerEventSource = new InformerEventSource<>(pcvInformerConfiguration, context);
var deploymentInformerEventSource = new InformerEventSource<>(deploymentInformerConfiguration, context);
var serviceInformerEventSource = new InformerEventSource<>(serviceInformerConfiguration, context);
return Map.of(
- PVC_EVENT_SOURCE, pvcInformerEventSource,
+ PVC_EVENT_SOURCE, pcvInformerEventSource,
DEPLOYMENT_EVENT_SOURCE, deploymentInformerEventSource,
SERVICE_EVENT_SOURCE, serviceInformerEventSource
);
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
deleted file mode 100644
index ee358db..0000000
--- a/src/main/resources/application.properties
+++ /dev/null
@@ -1,35 +0,0 @@
-quarkus.container-image.registry=ghcr.io
-quarkus.container-image.tag=v${quarkus.application.version}
-
-# set to true to automatically apply CRDs to the cluster when they get regenerated
-quarkus.operator-sdk.crd.apply=true
-
-# Operator config
-related.image.server=${RELATED_IMAGE_SERVER:ghcr.io/trustification/trustd:latest}
-related.image.db=${RELATED_IMAGE_DB:quay.io/sclorg/postgresql-15-c9s:latest}
-related.image.pull-policy=Always
-
-# https://quarkus.io/guides/deploying-to-kubernetes#environment-variables-from-keyvalue-pairs
-quarkus.kubernetes.env.vars.related-image-trustify-server=${related.image.server}
-quarkus.kubernetes.env.vars.related-image-db=${related.image.db}
-quarkus.kubernetes.env.vars.related-image-importer=${related.image.importer}
-quarkus.openshift.env.vars.related-image-trustify-server=${related.image.server}
-quarkus.openshift.env.vars.related-image-db=${related.image.db}
-quarkus.openshift.env.vars.related-image-importer=${related.image.importer}
-
-quarkus.kubernetes.resources.requests.memory=64Mi
-quarkus.kubernetes.resources.requests.cpu=50m
-quarkus.kubernetes.resources.limits.memory=256Mi
-quarkus.kubernetes.resources.limits.cpu=250m
-
-quarkus.kubernetes.rbac.roles.trustify.policy-rules.0.api-groups=
-quarkus.kubernetes.rbac.roles.trustify.policy-rules.0.resources=*
-quarkus.kubernetes.rbac.roles.trustify.policy-rules.0.verbs=*
-
-quarkus.kubernetes.rbac.roles.trustify.policy-rules.1.api-groups=security.openshift.io
-quarkus.kubernetes.rbac.roles.trustify.policy-rules.1.resources=securitycontextconstraints
-quarkus.kubernetes.rbac.roles.trustify.policy-rules.1.verbs=use
-quarkus.kubernetes.rbac.roles.trustify.policy-rules.1.resource-names=anyuid
-
-# Increase test hang time since the operator takes time to initiate all deployments
-quarkus.test.hang-detection-timeout=30M
\ No newline at end of file
diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml
new file mode 100644
index 0000000..77f33ec
--- /dev/null
+++ b/src/main/resources/application.yaml
@@ -0,0 +1,50 @@
+# Operator config
+related:
+ image:
+ server: ${RELATED_IMAGE_SERVER:ghcr.io/trustification/trustd:latest}
+ db: ${RELATED_IMAGE_DB:quay.io/sclorg/postgresql-15-c9s:latest}
+ pull-policy: Always
+# Quarkus config
+quarkus:
+ container-image:
+ registry: ghcr.io
+ tag: v${quarkus.application.version}
+ # Increase test hang time since the operator takes time to initiate all deployments
+ test:
+ hang-detection-timeout: 30M
+ operator-sdk:
+ crd:
+ # set to true to automatically apply CRDs to the cluster when they get regenerated
+ apply: true
+ namespaces: JOSDK_WATCH_CURRENT
+ generate-with-watched-namespaces: JOSDK_WATCH_CURRENT
+ helm:
+ enabled: true
+ # https://quarkus.io/guides/deploying-to-kubernetes#environment-variables-from-keyvalue-pairs
+ kubernetes:
+ idempotent: "true"
+ prometheus:
+ generate-service-monitor: "false"
+ env:
+ vars:
+ related-image-trustify-server: ${related.image.server}
+ related-image-db: ${related.image.db}
+ related-image-importer: ${related.image.importer}
+ resources:
+ requests:
+ memory: 64Mi
+ cpu: 50m
+ limits:
+ memory: 256Mi
+ cpu: 250m
+ rbac:
+ roles:
+ trustify:
+ policy-rules:
+ - api-groups:
+ resources: '*'
+ verbs: '*'
+ - api-groups: security.openshift.io
+ resources: securitycontextconstraints
+ verbs: use
+ resource-names: anyuid
diff --git a/src/test/java/org/trustify/operator/controllers/TrustifyReconcilerTest.java b/src/test/java/org/trustify/operator/controllers/TrustifyReconcilerTest.java
index c6ba426..11cd94d 100644
--- a/src/test/java/org/trustify/operator/controllers/TrustifyReconcilerTest.java
+++ b/src/test/java/org/trustify/operator/controllers/TrustifyReconcilerTest.java
@@ -12,12 +12,12 @@
import org.hamcrest.Matchers;
import org.junit.jupiter.api.*;
import org.trustify.operator.Constants;
-import org.trustify.operator.cdrs.v2alpha1.*;
+import org.trustify.operator.cdrs.v2alpha1.Trustify;
+import org.trustify.operator.cdrs.v2alpha1.db.DBDeployment;
+import org.trustify.operator.cdrs.v2alpha1.db.DBService;
import org.trustify.operator.cdrs.v2alpha1.server.ServerDeployment;
import org.trustify.operator.cdrs.v2alpha1.server.ServerIngress;
import org.trustify.operator.cdrs.v2alpha1.server.ServerService;
-import org.trustify.operator.cdrs.v2alpha1.db.DBDeployment;
-import org.trustify.operator.cdrs.v2alpha1.db.DBService;
import org.trustify.operator.controllers.setup.K3sResource;
import java.util.List;