├── .gitignore ├── .project ├── .s2i └── environment ├── .settings └── org.eclipse.m2e.core.prefs ├── README.md ├── gitops ├── argocd │ └── quarkus-simple-app.yaml └── tekton │ ├── infra │ ├── maven-artifact-cache-pvc.yaml │ ├── maven-settings-cm.yaml │ ├── sa.yaml │ └── secret.yaml │ ├── pipeline.sh │ ├── pipelines │ ├── stage-release.yaml │ └── tekton-pipeline.yaml │ └── tasks │ ├── bash-task.yaml │ ├── create-release.yaml │ ├── extract-digest-from-kustomize-task.yaml │ ├── extract-digest-task.yaml │ ├── git-update-deployment.yaml │ ├── kustomize-task.yaml │ └── maven-task.yaml ├── helm ├── Chart.yaml ├── templates │ ├── NOTES.txt │ ├── config-map.yaml │ ├── deployment.yaml │ ├── post-install-hook.yaml │ ├── route.yaml │ └── service.yaml └── values.yaml ├── kubernetes-files ├── deployment.yaml ├── route.yaml ├── service.yaml └── template.yaml ├── kustomize ├── base │ ├── deployment.yaml │ ├── kustomization.yaml │ ├── route.yaml │ └── service.yaml └── overlays │ ├── dev │ ├── deployment.yaml │ ├── kustomization.yaml │ └── route.yaml │ └── stage │ ├── deployment.yaml │ ├── kustomization.yaml │ └── route.yaml ├── kustomize_ext ├── base │ ├── config-map.yaml │ ├── deployment.yaml │ ├── kustomization.yaml │ ├── route.yaml │ └── service.yaml └── overlays │ ├── dev │ └── kustomization.yaml │ ├── prod │ └── kustomization.yaml │ └── stage │ ├── apply-health-checks.yaml │ ├── change-env-value.yaml │ └── kustomization.yaml ├── mvnw.cmd ├── operator ├── .gitignore ├── Dockerfile ├── Makefile ├── PROJECT ├── bundle.Dockerfile ├── bundle │ ├── manifests │ │ ├── charts.wanja.org_quarkussimples.yaml │ │ ├── simple-quarkus-operator-controller-manager-metrics-service_v1_service.yaml │ │ ├── simple-quarkus-operator-controller-manager_v1_serviceaccount.yaml │ │ ├── simple-quarkus-operator-manager-config_v1_configmap.yaml │ │ ├── simple-quarkus-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml │ │ └── simple-quarkus-operator.clusterserviceversion.yaml │ ├── metadata │ │ └── annotations.yaml │ └── tests │ │ └── scorecard │ │ └── config.yaml ├── config │ ├── crd │ │ ├── bases │ │ │ └── charts.wanja.org_quarkussimples.yaml │ │ └── kustomization.yaml │ ├── default │ │ ├── kustomization.yaml │ │ ├── manager_auth_proxy_patch.yaml │ │ └── manager_config_patch.yaml │ ├── manager │ │ ├── controller_manager_config.yaml │ │ ├── kustomization.yaml │ │ └── manager.yaml │ ├── manifests │ │ ├── bases │ │ │ └── simple-quarkus-operator.clusterserviceversion.yaml │ │ └── kustomization.yaml │ ├── prometheus │ │ ├── kustomization.yaml │ │ └── monitor.yaml │ ├── rbac │ │ ├── auth_proxy_client_clusterrole.yaml │ │ ├── auth_proxy_role.yaml │ │ ├── auth_proxy_role_binding.yaml │ │ ├── auth_proxy_service.yaml │ │ ├── kustomization.yaml │ │ ├── leader_election_role.yaml │ │ ├── leader_election_role_binding.yaml │ │ ├── quarkussimple_editor_role.yaml │ │ ├── quarkussimple_viewer_role.yaml │ │ ├── role.yaml │ │ ├── role_binding.yaml │ │ └── service_account.yaml │ ├── samples │ │ ├── charts_v1alpha1_quarkussimple.yaml │ │ └── kustomization.yaml │ └── scorecard │ │ ├── bases │ │ └── config.yaml │ │ ├── kustomization.yaml │ │ └── patches │ │ ├── basic.config.yaml │ │ └── olm.config.yaml ├── helm-charts │ └── quarkus-simple │ │ ├── Chart.yaml │ │ ├── templates │ │ ├── NOTES.txt │ │ ├── config-map.yaml │ │ ├── deployment.yaml │ │ ├── post-install-hook.yaml │ │ ├── route.yaml │ │ └── service.yaml │ │ └── values.yaml └── watches.yaml ├── pom.xml ├── src ├── main │ ├── docker │ │ └── Dockerfile.jvm │ ├── java │ │ └── org │ │ │ └── wanja │ │ │ └── quarkus │ │ │ ├── GreetingResource.java │ │ │ ├── HttpHandler.java │ │ │ ├── NameFakerResource.java │ │ │ ├── RkiDataGrabberResource.java │ │ │ ├── RkiDataGrabberService.java │ │ │ ├── RkiQuteReaderResource.java │ │ │ ├── RkiReaderResource.java │ │ │ ├── RkiReportResource.java │ │ │ └── model │ │ │ ├── Attributes.java │ │ │ ├── Bl.java │ │ │ ├── Converter.java │ │ │ ├── Feature.java │ │ │ ├── Field.java │ │ │ ├── LastUpdate.java │ │ │ ├── RkiModel.java │ │ │ ├── SQLType.java │ │ │ ├── SpatialReference.java │ │ │ ├── Type.java │ │ │ └── UniqueIDField.java │ └── resources │ │ ├── META-INF │ │ └── resources │ │ │ └── index.html │ │ ├── application.properties │ │ └── templates │ │ ├── rkiQuteReader.txt │ │ └── rkiReport.html └── test │ └── java │ └── org │ └── wanja │ └── quarkus │ ├── GreetingResourceTest.java │ └── NativeGreetingResourceIT.java └── tektondev ├── infra ├── maven-artifact-cache-pvc.yaml └── maven-settings-cm.yaml ├── pipeline.sh ├── pipelines ├── tekton-pipeline-test.yaml └── tekton-pipeline.yaml └── tasks ├── bash-task.yaml ├── kustomize-task.yaml └── maven-task.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # MacOS .DS_Store files 23 | *.DS_Store 24 | 25 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 26 | hs_err_pid* 27 | 28 | # local build 29 | target/* 30 | .settings/* 31 | .vscode/* 32 | .classpath 33 | .factorypath 34 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | quarkus-simple 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | 25 | 1618816297807 26 | 27 | 30 28 | 29 | org.eclipse.core.resources.regexFilterMatcher 30 | node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /.s2i/environment: -------------------------------------------------------------------------------- 1 | ARTIFACT_COPY_ARGS=-p -r quarkus-app/* quarkus-app/quarkus-run.jar 2 | 3 | -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # simple-quarkus project 2 | This is a simple demo application written in Java with [Quarkus](https://quarkus.io) to demonstrate how to work in a Kubernetes environment. 3 | 4 | ## Intention 5 | This is the example, I am using in my article series **Automated Application Packaging and Distribution with OpenShift** which you could read here: 6 | 7 | - [Chapter one](https://www.opensourcerers.org/2021/04/26/automated-application-packaging-and-distribution-with-openshift-part-12/) talks about container images and explains all the basic files and gives you a guide through OpenShift Templates and Kustomize as a base technology for application packaging 8 | - [Chapter two](https://www.opensourcerers.org/2021/05/24/automated-application-packaging-and-distribution-with-openshift-part-23/) provides an overview of the various packaging formats, namely Helm Charts and Kubernetes Operators, and explains how they differ from each other and how to create them 9 | - [Chapter three](https://www.opensourcerers.org/2021/07/26/automated-application-packaging-and-distribution-with-openshift-tekton-pipelines-part-34-2/) gives you a detailed view of Tekton / OpenShift Pipelines and helps you to quickly start your CI/CD process 10 | - [And finally chapter four](https://www.opensourcerers.org/2021/09/06/automated-application-packaging-and-distribution-with-openshift-gitops-and-argocd-part-44) provides a detailed overview of GitOps and how to use it with OpenShift. 11 | 12 | ## Prerequisites 13 | You simply need an OpenShift 4.7 or 4.8 instance. For example CodeReady Containers, which you can download and use from here for free: 14 | 15 | https://cloud.redhat.com/openshift/create/local 16 | 17 | ## Chapters corresponding with folders in this repository 18 | This repository contains all the files necessary to follow the blog posts. It is derived into several folders. 19 | 20 | ### Chapter One - Basic Development 21 | If you’re reading chapter one, you can find the corresponding files in those folders: 22 | 23 | - `kubernetes-files`: What are the necessary files to (re-) deploy your app into Kubernetes? You can also find the OpenShift Template file in here. 24 | - `kustomize`: All necessary files to (re-) deploy your app into Kubernetes based on Kustomize 25 | - `kustomize_ext`: A more sophisticated example with patches etc 26 | 27 | 28 | ### Chapter Two - Helm Charts and Kubernetes Operators 29 | If you’re reading chapter two, you can find all the corresponding files in those folders: 30 | 31 | - `helm`: How to create a Helm Chart for this quarkus application 32 | - `operator`: How to create a Kubernetes Operator for this quarkus application 33 | 34 | ### Chapter Three: Tekton / OpenShift Pipelines 35 | You can find all necessary files to follow chapter three in the folder `tektondev`. 36 | 37 | To prepare your OpenShift cluster, you have to install the Operator `OpenShift Pipelines`. And then you can install everything by executing the script: 38 | 39 | ```bash 40 | $> ./tektondev/pipeline.sh init 41 | ``` 42 | 43 | To execute the pipeline, simply start: 44 | 45 | ```bash 46 | $> ./tektondev/pipeline.sh start -u -p 47 | ``` 48 | 49 | 50 | ### Chapter Four: GitOps and ArgoCD 51 | You can find all necessary files to follow chapter four in the folder `gitops`. To prepare your OpenShift cluster, you need to install two Operators: 52 | - OpenShift Pipelines 53 | - OpenShift GitOps 54 | 55 | Then you can install the pipelines by executing the following script: 56 | 57 | ```bash 58 | $> ./gitops/tekton/pipeline.sh init -u -p 59 | ``` 60 | 61 | To start the development pipeline, execute 62 | ```bash 63 | $> ./gitops/tekton/pipeline.sh start -u -p 64 | ``` 65 | 66 | To start the staging pipeline, execute 67 | ```bash 68 | $> ./gitops/tekton/pipeline.sh stage 69 | ``` 70 | 71 | After you’ve followed the corresponding section „Creating a stage release pipeline“. 72 | 73 | -------------------------------------------------------------------------------- /gitops/argocd/quarkus-simple-app.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: quarkus-simple 5 | namespace: openshift-gitops 6 | spec: 7 | destination: 8 | namespace: art-gitops 9 | server: https://kubernetes.default.svc 10 | project: default 11 | source: 12 | path: config/overlays/dev 13 | repoURL: https://github.com/wpernath/quarkus-simple-config.git 14 | targetRevision: HEAD 15 | syncPolicy: 16 | automated: 17 | selfHeal: true 18 | -------------------------------------------------------------------------------- /gitops/tekton/infra/maven-artifact-cache-pvc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: maven-repo-pvc 5 | spec: 6 | resources: 7 | requests: 8 | storage: 10Gi 9 | volumeMode: Filesystem 10 | accessModes: 11 | - ReadWriteOnce 12 | - ReadWriteMany 13 | persistentVolumeReclaimPolicy: Retain 14 | --- 15 | apiVersion: v1 16 | kind: PersistentVolumeClaim 17 | metadata: 18 | name: builder-pvc 19 | spec: 20 | resources: 21 | requests: 22 | storage: 10Gi 23 | volumeMode: Filesystem 24 | accessModes: 25 | - ReadWriteOnce 26 | - ReadWriteMany 27 | persistentVolumeReclaimPolicy: Retain 28 | -------------------------------------------------------------------------------- /gitops/tekton/infra/maven-settings-cm.yaml: -------------------------------------------------------------------------------- 1 | kind: ConfigMap 2 | apiVersion: v1 3 | metadata: 4 | name: maven-settings 5 | data: 6 | settings.xml: | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | all 18 | http://nexus.ci.svc:8081/repository/maven-public 19 | * 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /gitops/tekton/infra/sa.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: pipeline-bot 5 | secrets: 6 | - name: git-user-pass 7 | - name: quay-push-secret 8 | --- 9 | apiVersion: rbac.authorization.k8s.io/v1 10 | kind: RoleBinding 11 | metadata: 12 | name: piplinebot-rolebinding1 13 | roleRef: 14 | apiGroup: rbac.authorization.k8s.io 15 | kind: ClusterRole 16 | name: pipelines-scc-clusterrole 17 | subjects: 18 | - kind: ServiceAccount 19 | name: pipeline-bot 20 | --- 21 | apiVersion: rbac.authorization.k8s.io/v1 22 | kind: RoleBinding 23 | metadata: 24 | name: piplinebot-rolebinding2 25 | roleRef: 26 | apiGroup: rbac.authorization.k8s.io 27 | kind: ClusterRole 28 | name: edit 29 | subjects: 30 | - kind: ServiceAccount 31 | name: pipeline-bot 32 | -------------------------------------------------------------------------------- /gitops/tekton/infra/secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: git-user-pass 5 | annotations: 6 | tekton.dev/git-0: https://github.com # Described below 7 | type: kubernetes.io/basic-auth 8 | stringData: 9 | username: 10 | password: 11 | --- 12 | apiVersion: v1 13 | kind: Secret 14 | metadata: 15 | annotations: 16 | tekton.dev/docker-0: https://quay.io 17 | name: quay-push-secret 18 | type: kubernetes.io/basic-auth 19 | stringData: 20 | username: 21 | password: 22 | 23 | -------------------------------------------------------------------------------- /gitops/tekton/pipeline.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This starts the pipeline new-pipeline with a given 3 | 4 | set -e -u -o pipefail 5 | declare -r SCRIPT_DIR=$(cd -P $(dirname $0) && pwd) 6 | declare COMMAND="help" 7 | 8 | GIT_URL=https://github.com/wpernath/quarkus-simple.git 9 | GIT_REVISION=main 10 | PIPELINE=gitops-dev-pipeline 11 | CONTEXT_DIR=the-source 12 | IMAGE_NAME=quay.io/wpernath/quarkus-simple-wow 13 | IMAGE_USER=wpernath 14 | IMAGE_PASSWORD= 15 | TARGET_NAMESPACE=quarkus-dev 16 | 17 | valid_command() { 18 | local fn=$1; shift 19 | [[ $(type -t "$fn") == "function" ]] 20 | } 21 | 22 | info() { 23 | printf "\n# INFO: $@\n" 24 | } 25 | 26 | err() { 27 | printf "\n# ERROR: $1\n" 28 | exit 1 29 | } 30 | 31 | command.help() { 32 | cat <<-EOF 33 | Starts a new pipeline in current kubernetes context 34 | 35 | Usage: 36 | pipeline.sh [command] [options] 37 | 38 | Examples: 39 | pipeline.sh init -u wpernath -p # installs and creates all tasks, pvc and secrets 40 | pipeline.sh start -u wpernath -p -t art-tekton 41 | pipeline.sh stage -r 1.2.3 42 | pipeline.sh logs 43 | 44 | COMMANDS: 45 | init creates ConfigMap, Tasks and Pipelines into current context 46 | it also creates a secret with -u/-p user/pwd for GitHub.com access 47 | start starts the given pipeline 48 | stage starts the stage pipeline and creates a release in quay.io and github 49 | logs shows logs of the last pipeline run 50 | help Help about this command 51 | 52 | OPTIONS: 53 | -u, --registry-user User to store the image into quay.io ($IMAGE_USER) 54 | -p, --registry-password Password to store the image into quay.io ($IMAGE_PASSWORD) 55 | -c, --context-dir Which context-dir to user ($CONTEXT_DIR) 56 | -t, --target-namespace Which target namespace to start the app ($TARGET_NAMESPACE) 57 | -g, --git-repo Which quarkus repository to clone ($GIT_URL) 58 | -r, --git-revision Which git revision to use ($GIT_REVISION) 59 | 60 | EOF 61 | } 62 | 63 | command.test() { 64 | cat > /tmp/tr.yaml <<-EOF 65 | apiVersion: tekton.dev/v1beta1 66 | kind: TaskRun 67 | metadata: 68 | name: git-test-run-$(date "+%Y%m%d-%H%M%S") 69 | spec: 70 | params: 71 | - name: kustomize-dir 72 | value: config/overlays/dev 73 | workspaces: 74 | - name: source 75 | persistentVolumeClaim: 76 | claimName: builder-pvc 77 | serviceAccountName: pipeline-bot 78 | taskRef: 79 | name: extract-kustomize-digest 80 | EOF 81 | 82 | oc apply -f /tmp/tr.yaml 83 | } 84 | 85 | 86 | 87 | while (( "$#" )); do 88 | case "$1" in 89 | start|logs|init|test|stage) 90 | COMMAND=$1 91 | shift 92 | ;; 93 | -c|--context-dir) 94 | CONTEXT_DIR=$2 95 | shift 2 96 | ;; 97 | -t|--target-namespace) 98 | TARGET_NAMESPACE=$2 99 | shift 2 100 | ;; 101 | -u|--registry-user) 102 | IMAGE_USER=$2 103 | shift 2 104 | ;; 105 | -p|--registry-password) 106 | IMAGE_PASSWORD=$2 107 | shift 2 108 | ;; 109 | -g|--git-repo) 110 | GIT_URL=$2 111 | shift 2 112 | ;; 113 | -r|--git-revision) 114 | GIT_REVISION=$2 115 | shift 2 116 | ;; 117 | -l|--pipeline) 118 | PIPELINE=$2 119 | shift 2 120 | ;; 121 | --) 122 | shift 123 | break 124 | ;; 125 | -*|--*) 126 | command.help 127 | err "Error: Unsupported flag $1" 128 | ;; 129 | *) 130 | break 131 | esac 132 | done 133 | 134 | 135 | command.init() { 136 | # This script imports the necessary files into the current project 137 | 138 | oc apply -f infra/maven-settings-cm.yaml 139 | oc apply -f infra/maven-artifact-cache-pvc.yaml 140 | oc apply -f infra/sa.yaml 141 | 142 | oc apply -f tasks/kustomize-task.yaml 143 | oc apply -f tasks/extract-digest-task.yaml 144 | oc apply -f tasks/extract-digest-from-kustomize-task.yaml 145 | oc apply -f tasks/create-release.yaml 146 | 147 | oc apply -f tasks/maven-task.yaml 148 | oc apply -f tasks/git-update-deployment.yaml 149 | oc apply -f tasks/bash-task.yaml 150 | 151 | oc apply -f pipelines/tekton-pipeline.yaml 152 | oc apply -f pipelines/stage-release.yaml 153 | 154 | cat > /tmp/tekton-git-secret.yaml <<-EOF 155 | apiVersion: v1 156 | kind: Secret 157 | metadata: 158 | name: git-user-pass 159 | annotations: 160 | tekton.dev/git-0: https://github.com # Described below 161 | type: kubernetes.io/basic-auth 162 | stringData: 163 | username: $IMAGE_USER 164 | password: $IMAGE_PASSWORD 165 | EOF 166 | 167 | oc apply -f /tmp/tekton-git-secret.yaml 168 | } 169 | 170 | 171 | command.logs() { 172 | tkn pr logs -f -L 173 | } 174 | 175 | command.start() { 176 | cat > /tmp/pipelinerun.yaml <<-EOF 177 | apiVersion: tekton.dev/v1beta1 178 | kind: PipelineRun 179 | metadata: 180 | name: $PIPELINE-run-$(date "+%Y%m%d-%H%M%S") 181 | spec: 182 | params: 183 | - name: git-url 184 | value: '$GIT_URL' 185 | - name: git-revision 186 | value: $GIT_REVISION 187 | - name: context-dir 188 | value: $CONTEXT_DIR 189 | - name: image-name 190 | value: $IMAGE_NAME 191 | - name: image-username 192 | value: $IMAGE_USER 193 | - name: image-password 194 | value: $IMAGE_PASSWORD 195 | - name: target-namespace 196 | value: $TARGET_NAMESPACE 197 | workspaces: 198 | - name: shared-workspace 199 | persistentVolumeClaim: 200 | claimName: builder-pvc 201 | - configMap: 202 | name: maven-settings 203 | name: maven-settings 204 | pipelineRef: 205 | name: $PIPELINE 206 | serviceAccountName: pipeline-bot 207 | EOF 208 | 209 | oc apply -f /tmp/pipelinerun.yaml 210 | } 211 | 212 | 213 | command.stage() { 214 | cat > /tmp/pipelinerun.yaml <<-EOF 215 | apiVersion: tekton.dev/v1beta1 216 | kind: PipelineRun 217 | metadata: 218 | name: gitops-stage-release-run-$(date "+%Y%m%d-%H%M%S") 219 | spec: 220 | params: 221 | - name: release-name 222 | value: $GIT_REVISION 223 | workspaces: 224 | - name: shared-workspace 225 | persistentVolumeClaim: 226 | claimName: builder-pvc 227 | - configMap: 228 | name: maven-settings 229 | name: maven-settings 230 | pipelineRef: 231 | name: gitops-stage-release 232 | serviceAccountName: pipeline-bot 233 | EOF 234 | 235 | oc apply -f /tmp/pipelinerun.yaml 236 | } 237 | 238 | main() { 239 | local fn="command.$COMMAND" 240 | valid_command "$fn" || { 241 | command.help 242 | err "invalid command '$COMMAND'" 243 | } 244 | 245 | cd $SCRIPT_DIR 246 | $fn 247 | return $? 248 | } 249 | 250 | main 251 | -------------------------------------------------------------------------------- /gitops/tekton/pipelines/stage-release.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Pipeline 3 | metadata: 4 | name: gitops-stage-release 5 | spec: 6 | params: 7 | - name: git-url 8 | type: string 9 | description: the url of the config repo to clone 10 | default: 'https://github.com/wpernath/quarkus-simple-config.git' 11 | - name: git-revision 12 | type: string 13 | description: the revision of the config repo to clone 14 | default: main 15 | - name: context-dir 16 | type: string 17 | description: the target in the PVC to clone the git repo to 18 | default: the-config 19 | - name: target-image 20 | type: string 21 | description: The target image name of the config (without tag/digest) 22 | default: quay.io/wpernath/quarkus-simple-wow 23 | 24 | - name: kustomize-dev 25 | type: string 26 | description: Kustomize target dev 27 | default: config/overlays/dev 28 | - name: kustomize-stage 29 | type: string 30 | description: kustomize target stage 31 | default: config/overlays/stage 32 | - name: release-name 33 | type: string 34 | description: Release name will be used as image tag in quay.io and feature branch in Git 35 | tasks: 36 | - name: git-clone 37 | params: 38 | - name: url 39 | value: $(params.git-url) 40 | - name: deleteExisting 41 | value: 'true' 42 | - name: verbose 43 | value: 'true' 44 | - name: revision 45 | value: $(params.git-revision) 46 | - name: subdirectory 47 | value: $(params.context-dir) 48 | taskRef: 49 | kind: ClusterTask 50 | name: git-clone 51 | workspaces: 52 | - name: output 53 | workspace: shared-workspace 54 | - name: git-branch 55 | params: 56 | - name: BASE_IMAGE 57 | value: >- 58 | docker.io/alpine/git:v2.26.2@sha256:23618034b0be9205d9cc0846eb711b12ba4c9b468efdd8a59aac1d7b1a23363f 59 | - name: GIT_SCRIPT 60 | value: cd $(params.context-dir) && git checkout -b release-$(params.release-name) 61 | runAfter: 62 | - git-clone 63 | taskRef: 64 | kind: ClusterTask 65 | name: git-cli 66 | when: 67 | - input: $(params.release-name) 68 | operator: notin 69 | values: 70 | - "" 71 | workspaces: 72 | - name: source 73 | workspace: shared-workspace 74 | - name: input 75 | workspace: shared-workspace 76 | - name: extract-digest 77 | params: 78 | - name: kustomize-dir 79 | value: $(params.context-dir)/$(params.kustomize-dev) 80 | runAfter: 81 | - git-branch 82 | taskRef: 83 | kind: Task 84 | name: extract-kustomize-digest 85 | workspaces: 86 | - name: source 87 | workspace: shared-workspace 88 | 89 | - name: tag-image 90 | params: 91 | - name: srcImageURL 92 | value: >- 93 | docker://$(params.target-image)@$(tasks.extract-digest.results.DIGEST) 94 | - name: destImageURL 95 | value: >- 96 | docker://$(params.target-image):$(params.release-name) 97 | - name: srcTLSverify 98 | value: 'false' 99 | - name: destTLSverify 100 | value: 'false' 101 | runAfter: 102 | - extract-digest 103 | taskRef: 104 | kind: ClusterTask 105 | name: skopeo-copy 106 | workspaces: 107 | - name: images-url 108 | workspace: shared-workspace 109 | 110 | - name: update-release 111 | params: 112 | - name: context-dir 113 | value: $(params.context-dir) 114 | - name: kustomize-dir 115 | value: $(params.kustomize-stage) 116 | - name: release-name 117 | value: "$(params.release-name)" 118 | - name: old-image 119 | value: quay.io/wpernath/simple-quarkus:latest 120 | - name: new-image 121 | value: "$(params.target-image)" 122 | - name: digest 123 | value: "$(tasks.extract-digest.results.DIGEST)" 124 | runAfter: 125 | - tag-image 126 | taskRef: 127 | kind: Task 128 | name: create-release 129 | workspaces: 130 | - name: workspace 131 | workspace: shared-workspace 132 | 133 | workspaces: 134 | - name: shared-workspace 135 | optional: false 136 | -------------------------------------------------------------------------------- /gitops/tekton/pipelines/tekton-pipeline.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Pipeline 3 | metadata: 4 | name: gitops-dev-pipeline 5 | spec: 6 | params: 7 | - default: 'https://github.com/wpernath/quarkus-simple.git' 8 | description: Source to the GIT 9 | name: git-url 10 | type: string 11 | - default: main 12 | description: revision to be used 13 | name: git-revision 14 | type: string 15 | - name: config-git-url 16 | type: string 17 | description: URL of the Git config repository 18 | default: 'https://github.com/wpernath/quarkus-simple-config.git' 19 | - name: config-dir 20 | type: string 21 | description: Configuration directory within the config-git-url with the files 22 | default: 'config/overlays/dev' 23 | - name: context-dir 24 | default: "the-source" 25 | type: string 26 | description: Where to checkout the source relative to the workspace 27 | - name: image-name 28 | type: string 29 | description: the name of the target image including registry 30 | default: quay.io/wpernath/quarkus-simple-wow 31 | - name: image-username 32 | type: string 33 | description: the username you use to access the registry 34 | - name: image-password 35 | type: string 36 | description: The password you use to access the registry 37 | tasks: 38 | - name: git-clone 39 | params: 40 | - name: url 41 | value: $(params.git-url) 42 | - name: deleteExisting 43 | value: 'true' 44 | - name: verbose 45 | value: 'true' 46 | - name: revision 47 | value: $(params.git-revision) 48 | - name: subdirectory 49 | value: $(params.context-dir) 50 | taskRef: 51 | kind: ClusterTask 52 | name: git-clone 53 | workspaces: 54 | - name: output 55 | workspace: shared-workspace 56 | - name: package 57 | params: 58 | - name: GOALS 59 | value: 60 | - package 61 | - '-DskipTests' 62 | - name: CONTEXT_DIR 63 | value: $(params.context-dir) 64 | runAfter: 65 | - git-clone 66 | taskRef: 67 | kind: Task 68 | name: maven-caching 69 | workspaces: 70 | - name: source 71 | workspace: shared-workspace 72 | - name: maven-settings 73 | workspace: maven-settings 74 | - name: build-and-push-image 75 | params: 76 | - name: GOALS 77 | value: 78 | - package 79 | - '-DskipTests' 80 | - '-Dquarkus.container-image.build=true' 81 | - '-Dquarkus.container-image.push=true' 82 | - '-Dquarkus.container-image.builder=jib' 83 | - '-Dquarkus.container-image.image=$(params.image-name)' 84 | - '-Dquarkus.container-image.username=$(params.image-username)' 85 | - '-Dquarkus.container-image.password=$(params.image-password)' 86 | - name: CONTEXT_DIR 87 | value: $(params.context-dir) 88 | runAfter: 89 | - package 90 | taskRef: 91 | kind: Task 92 | name: maven-caching 93 | workspaces: 94 | - name: source 95 | workspace: shared-workspace 96 | - name: maven-settings 97 | workspace: maven-settings 98 | - name: extract-digest 99 | params: 100 | - name: image-digest-path 101 | value: $(params.context-dir)/target 102 | runAfter: 103 | - build-and-push-image 104 | taskRef: 105 | kind: Task 106 | name: extract-quarkus-digest 107 | workspaces: 108 | - name: source 109 | workspace: shared-workspace 110 | - name: git-update-deployment 111 | params: 112 | - name: GIT_REPOSITORY 113 | value: $(params.config-git-url) 114 | - name: CURRENT_IMAGE 115 | value: quay.io/wpernath/simple-quarkus:latest 116 | - name: NEW_IMAGE 117 | value: $(params.image-name) 118 | - name: NEW_DIGEST 119 | value: $(tasks.extract-digest.results.DIGEST) 120 | - name: KUSTOMIZATION_PATH 121 | value: $(params.config-dir) 122 | runAfter: 123 | - extract-digest 124 | taskRef: 125 | kind: Task 126 | name: git-update-deployment 127 | workspaces: 128 | - name: workspace 129 | workspace: shared-workspace 130 | workspaces: 131 | - name: shared-workspace 132 | optional: false 133 | - name: maven-settings 134 | optional: false 135 | -------------------------------------------------------------------------------- /gitops/tekton/tasks/bash-task.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: bash 5 | labels: 6 | app.kubernetes.io/version: "0.4" 7 | annotations: 8 | tekton.dev/pipelines.minVersion: "0.12.1" 9 | tekton.dev/tags: build-tool 10 | spec: 11 | description: >- 12 | This task can be used to execute kustomze build scripts and to apply the changes via oc apply -f 13 | params: 14 | - name: script 15 | description: Where should kustomize look for kustomization in source? 16 | default: ls -al 17 | steps: 18 | - name: script 19 | image: quay.io/wpernath/kustomize-ubi:latest 20 | script: | 21 | echo 22 | ls -al /tekton/creds 23 | 24 | echo 25 | ls -al ~/.docker/config.json 26 | cat ~/.docker/config.json 27 | 28 | echo 29 | #ls -al ~/.ssh 30 | ls -al ~/.gitconfig 31 | echo 32 | cat ~/.gitconfig 33 | echo 34 | echo 35 | cat ~/.git-credentials 36 | 37 | git clone 38 | $(params.script) 39 | ls -al ~/.ssh 40 | 41 | 42 | -------------------------------------------------------------------------------- /gitops/tekton/tasks/create-release.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | annotations: 5 | tekton.dev/pipelines.minVersion: 0.12.1 6 | tekton.dev/tags: git 7 | name: create-release 8 | labels: 9 | app.kubernetes.io/version: '0.2' 10 | operator.tekton.dev/provider-type: community 11 | spec: 12 | description: This Task can be used to update image digest in a Git repo using kustomize. It requires a secret with credentials for accessing the git repo. 13 | params: 14 | - name: release-name 15 | description: The tag of the release. There is a branch with release-$(release-name) available 16 | - name: old-image 17 | - name: new-image 18 | - name: digest 19 | - name: kustomize-dir 20 | - name: context-dir 21 | 22 | workspaces: 23 | - description: The workspace consisting of maven project. 24 | name: workspace 25 | 26 | results: 27 | - name: commit 28 | description: The commit SHA 29 | 30 | steps: 31 | - name: update-digest 32 | image: quay.io/wpernath/kustomize-ubi:latest 33 | workingDir: $(workspaces.workspace.path)/$(params.context-dir)/$(params.kustomize-dir) 34 | script: | 35 | kustomize edit set image $(params.old-image)=$(params.new-image):$(params.release-name)@$(params.digest) 36 | 37 | echo "##########################" 38 | echo "### kustomization.yaml ###" 39 | echo "##########################" 40 | cat kustomization.yaml 41 | 42 | - name: git-commit 43 | image: docker.io/alpine/git:v2.26.2 44 | workingDir: $(workspaces.workspace.path)/$(params.context-dir) 45 | script: | 46 | git config user.email "wpernath@redhat.com" 47 | git config user.name "My Tekton Bot" 48 | 49 | git status 50 | git add $(params.kustomize-dir)/kustomization.yaml 51 | git commit -m "[ci] Branch for $(params.release-name) release" 52 | 53 | git push --set-upstream origin release-$(params.release-name) 54 | 55 | RESULT_SHA="$(git rev-parse HEAD | tr -d '\n')" 56 | EXIT_CODE="$?" 57 | if [ "$EXIT_CODE" != 0 ] 58 | then 59 | exit $EXIT_CODE 60 | fi 61 | # Make sure we don't add a trailing newline to the result! 62 | echo -n "$RESULT_SHA" > $(results.commit.path) -------------------------------------------------------------------------------- /gitops/tekton/tasks/extract-digest-from-kustomize-task.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: extract-kustomize-digest 5 | labels: 6 | app.kubernetes.io/version: "0.1" 7 | annotations: 8 | tekton.dev/pipelines.minVersion: "0.12.1" 9 | tekton.dev/tags: build-tool 10 | 11 | spec: 12 | params: 13 | - name: kustomize-dir 14 | description: Where to extract the DIGEST from. 15 | 16 | results: 17 | - name: DIGEST 18 | description: The image digest of the last quarkus maven build with JIB image creation 19 | 20 | workspaces: 21 | - name: source 22 | description: The workspace holding the cloned and compiled quarkus source. 23 | 24 | description: >- 25 | This task can be used to extract any Image DIGEST from a Kustomization.yaml file. 26 | 27 | steps: 28 | - name: extract-digest 29 | image: quay.io/wpernath/kustomize-ubi:latest 30 | script: | 31 | # yq eval '.images[0].digest' $(workspaces.source.path)/$(params.kustomize-dir)/kustomization.yaml 32 | 33 | DIGEST=$(yq eval '.images[0].digest' $(workspaces.source.path)/$(params.kustomize-dir)/kustomization.yaml) 34 | echo " DIGEST: $DIGEST" 35 | echo 36 | echo -n $DIGEST > $(results.DIGEST.path) 37 | 38 | 39 | -------------------------------------------------------------------------------- /gitops/tekton/tasks/extract-digest-task.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: extract-quarkus-digest 5 | labels: 6 | app.kubernetes.io/version: "0.1" 7 | annotations: 8 | tekton.dev/pipelines.minVersion: "0.12.1" 9 | tekton.dev/tags: build-tool 10 | 11 | spec: 12 | params: 13 | - name: image-digest-path 14 | default: target 15 | results: 16 | - name: DIGEST 17 | description: The image digest of the last quarkus maven build with JIB image creation 18 | 19 | workspaces: 20 | - name: source 21 | description: The workspace holding the cloned and compiled quarkus source. 22 | 23 | description: >- 24 | This task can be used to extract the image digest of a quarkus maven build. Whenever you're using JIB to create the app image, 25 | quarkus will produce a target/jib-image.digest file. The content of this file will be put into DIGEST result 26 | steps: 27 | - name: extract-digest 28 | image: quay.io/wpernath/kustomize-ubi:latest 29 | script: | 30 | DIGEST=$(cat $(workspaces.source.path)/$(params.image-digest-path)/jib-image.digest) 31 | echo " DIGEST: $DIGEST" 32 | echo 33 | echo -n $DIGEST > $(results.DIGEST.path) 34 | 35 | 36 | -------------------------------------------------------------------------------- /gitops/tekton/tasks/git-update-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | annotations: 5 | tekton.dev/pipelines.minVersion: 0.12.1 6 | tekton.dev/tags: git 7 | name: git-update-deployment 8 | labels: 9 | app.kubernetes.io/version: '0.2' 10 | operator.tekton.dev/provider-type: community 11 | spec: 12 | description: This Task can be used to update image digest in a Git repo using kustomize. It requires a secret with credentials for accessing the git repo. 13 | params: 14 | - name: GIT_REPOSITORY 15 | type: string 16 | - name: CURRENT_IMAGE 17 | type: string 18 | - name: NEW_IMAGE 19 | type: string 20 | - name: NEW_DIGEST 21 | type: string 22 | - name: KUSTOMIZATION_PATH 23 | type: string 24 | 25 | workspaces: 26 | - description: The workspace consisting of maven project. 27 | name: workspace 28 | 29 | results: 30 | - name: commit 31 | description: The commit SHA 32 | 33 | steps: 34 | 35 | - name: git-clone 36 | image: docker.io/alpine/git:v2.26.2 37 | workingDir: $(workspaces.workspace.path) 38 | script: | 39 | rm -rf git-update-digest-workdir 40 | git clone $(params.GIT_REPOSITORY) git-update-digest-workdir 41 | 42 | - name: update-digest 43 | image: quay.io/wpernath/kustomize-ubi:latest 44 | workingDir: $(workspaces.workspace.path) 45 | script: | 46 | cd git-update-digest-workdir/$(params.KUSTOMIZATION_PATH) 47 | kustomize edit set image $(params.CURRENT_IMAGE)=$(params.NEW_IMAGE)@$(params.NEW_DIGEST) 48 | 49 | echo "##########################" 50 | echo "### kustomization.yaml ###" 51 | echo "##########################" 52 | cat kustomization.yaml 53 | 54 | - name: git-commit 55 | image: docker.io/alpine/git:v2.26.2 56 | workingDir: $(workspaces.workspace.path) 57 | script: | 58 | cd git-update-digest-workdir 59 | 60 | git config user.email "wpernath@redhat.com" 61 | git config user.name "My Tekton Bot" 62 | 63 | git status 64 | git add $(params.KUSTOMIZATION_PATH)/kustomization.yaml 65 | git commit -m "[ci] Image digest updated" 66 | 67 | git push 68 | 69 | RESULT_SHA="$(git rev-parse HEAD | tr -d '\n')" 70 | EXIT_CODE="$?" 71 | if [ "$EXIT_CODE" != 0 ] 72 | then 73 | exit $EXIT_CODE 74 | fi 75 | # Make sure we don't add a trailing newline to the result! 76 | echo -n "$RESULT_SHA" > $(results.commit.path) -------------------------------------------------------------------------------- /gitops/tekton/tasks/kustomize-task.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: kustomize 5 | labels: 6 | app.kubernetes.io/version: "0.4" 7 | annotations: 8 | tekton.dev/pipelines.minVersion: "0.12.1" 9 | tekton.dev/tags: build-tool 10 | spec: 11 | description: >- 12 | This task can be used to execute kustomze build scripts and to apply the changes via oc apply -f 13 | workspaces: 14 | - name: source 15 | description: The workspace holding the cloned and compiled quarkus source. 16 | params: 17 | - name: kustomize-dir 18 | description: Where should kustomize look for kustomization in source? 19 | - name: target-namespace 20 | description: Where to apply the kustomization to 21 | - name: image-name 22 | description: Which image to use. Kustomize is taking care of it 23 | - name: image-digest-path 24 | description: The path of the jib-image.digest file generated by quarkus package 25 | steps: 26 | - name: build 27 | image: quay.io/wpernath/kustomize-ubi:latest 28 | workingDir: $(workspaces.source.path)/$(params.kustomize-dir) 29 | script: | 30 | DIGEST=$(cat $(workspaces.source.path)/$(params.image-digest-path)/jib-image.digest) 31 | echo "Calculated DIGEST: $DIGEST" 32 | echo 33 | 34 | kustomize edit set image quay.io/wpernath/simple-quarkus:latest=$(params.image-name)@$DIGEST 35 | 36 | kustomize build . 37 | kustomize build . > ./kustomized.yaml 38 | 39 | - name: apply 40 | image: 'image-registry.openshift-image-registry.svc:5000/openshift/cli:latest' 41 | workingDir: $(workspaces.source.path)/$(params.kustomize-dir) 42 | script: | 43 | oc apply -f ./kustomized.yaml -n $(params.target-namespace) 44 | 45 | -------------------------------------------------------------------------------- /gitops/tekton/tasks/maven-task.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: maven-caching 5 | labels: 6 | app.kubernetes.io/version: "0.4" 7 | annotations: 8 | tekton.dev/pipelines.minVersion: "0.12.1" 9 | tekton.dev/tags: build-tool 10 | spec: 11 | description: >- 12 | This Task can be used to run a Maven build. The only difference to 13 | the original one from github.com/tektoncd/catalog is that it uses an 14 | optional local maven repo path to cache all the dependencies. And it requires a 15 | a maven-settings workspace. 16 | workspaces: 17 | - name: source 18 | description: The workspace consisting of maven project. 19 | optional: false 20 | - name: maven-settings 21 | description: >- 22 | The workspace consisting of the custom maven settings 23 | provided by the user. 24 | optional: false 25 | params: 26 | - name: GOALS 27 | description: maven goals to run 28 | type: array 29 | default: 30 | - "package" 31 | - name: CONTEXT_DIR 32 | type: string 33 | description: >- 34 | The context directory within the repository for sources on 35 | which we want to execute maven goals. 36 | default: "." 37 | steps: 38 | - name: mvn-goals 39 | image: gcr.io/cloud-builders/mvn@sha256:57523fc43394d6d9d2414ee8d1c85ed7a13460cbb268c3cd16d28cfb3859e641 40 | workingDir: $(workspaces.source.path)/$(params.CONTEXT_DIR) 41 | command: ["/usr/bin/mvn"] 42 | args: 43 | - -B 44 | - -s 45 | - $(workspaces.maven-settings.path)/settings.xml 46 | - -Dmaven.repo.local=$(workspaces.source.path)/MAVEN_MIRROR 47 | - "$(params.GOALS)" -------------------------------------------------------------------------------- /helm/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: quarkus-simple 3 | description: A helm chart for the basic app described on https://www.opensourcerers.org/2021/04/26/automated-application-packaging-and-distribution-with-openshift-part-12/ 4 | home: https://github.com/wpernath/quarkus-simple 5 | type: application 6 | version: 0.0.10 7 | appVersion: "1.2.0" 8 | sources: 9 | - https://github.com/wpernath/quarkus-simple 10 | - https://www.opensourcerers.org/2021/04/26/automated-application-packaging-and-distribution-with-openshift-part-12/ 11 | - https://www.opensourcerers.org/2021/04/26/automated-application-packaging-and-distribution-with-openshift-part-22/ 12 | maintainers: 13 | - name: Wanja Pernath 14 | email: wpernath@redhat.com 15 | -------------------------------------------------------------------------------- /helm/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 2 | # simple-quarkus 3 | 4 | This is the helm chart for the project. 5 | 6 | ## build and install the helm chart 7 | ```bash 8 | $ helm package helm -u 9 | $ helm install 10 | $ helm upgrade 11 | ``` 12 | 13 | 14 | ## To learn more about the release, try: 15 | 16 | ```bash 17 | $ helm status quarkus-simple 18 | $ helm get all quarkus-simple 19 | ``` 20 | 21 | ## New Version contains something more 22 | -------------------------------------------------------------------------------- /helm/templates/config-map.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: app-config 5 | data: 6 | APP_GREETING: |- 7 | {{ .Values.config.greeting | default "Yeah, it's openshift time" }} 8 | -------------------------------------------------------------------------------- /helm/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: simple 5 | spec: 6 | replicas: {{ .Values.deployment.replicas | default 1 }} 7 | selector: 8 | matchLabels: 9 | app: simple 10 | strategy: 11 | rollingUpdate: 12 | maxSurge: 25% 13 | maxUnavailable: 25% 14 | type: RollingUpdate 15 | template: 16 | metadata: 17 | labels: 18 | app: simple 19 | spec: 20 | containers: 21 | - name: simple 22 | image: "{{ .Values.deployment.image }}:{{ .Values.deployment.version }}" 23 | imagePullPolicy: Always 24 | {{- if .Values.deployment.includeHealthChecks }} 25 | readinessProbe: 26 | httpGet: 27 | path: /q/health/ready 28 | port: 8080 29 | scheme: HTTP 30 | timeoutSeconds: 1 31 | periodSeconds: 10 32 | successThreshold: 1 33 | failureThreshold: 3 34 | livenessProbe: 35 | httpGet: 36 | path: /q/health/live 37 | port: 8080 38 | scheme: HTTP 39 | timeoutSeconds: 2 40 | periodSeconds: 10 41 | successThreshold: 1 42 | failureThreshold: 3 43 | {{- end }} 44 | ports: 45 | - containerPort: 8080 46 | protocol: TCP 47 | envFrom: 48 | - configMapRef: 49 | name: app-config 50 | -------------------------------------------------------------------------------- /helm/templates/post-install-hook.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: "{{ .Release.Name }}" 5 | labels: 6 | app.kubernetes.io/managed-by: {{ .Release.Service | quote }} 7 | app.kubernetes.io/instance: {{ .Chart.Name | quote }} 8 | app.kubernetes.io/version: {{ .Chart.AppVersion }} 9 | "helm.sh/chart": "{{ .Chart.Name }}-{{ .Chart.Version }}" 10 | annotations: 11 | # This is what defines this resource as a hook. Without this line, the 12 | # job is considered part of the release. 13 | "helm.sh/hook": post-install,post-upgrade 14 | "helm.sh/hook-weight": "-5" 15 | "helm.sh/hook-delete-policy": before-hook-creation 16 | spec: 17 | template: 18 | metadata: 19 | name: {{ .Chart.Name }} 20 | labels: 21 | "helm.sh/chart": "{{ .Chart.Name }}-{{ .Chart.Version }}" 22 | spec: 23 | restartPolicy: Never 24 | containers: 25 | - name: post-install-job 26 | image: "registry.access.redhat.com/ubi8/ubi-minimal:latest" 27 | command: 28 | - /bin/sh 29 | - -c 30 | - | 31 | echo "WELCOME TO '{{ .Chart.Name }}-{{ .Chart.Version }}' " 32 | echo "-------------------------------------------------" 33 | echo "Here we could now do initialization work." 34 | echo "Like filling our DB with some data or what's so ever" 35 | echo "..." 36 | 37 | sleep 10 38 | 39 | 40 | -------------------------------------------------------------------------------- /helm/templates/route.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: route.openshift.io/v1 2 | kind: Route 3 | metadata: 4 | name: simple 5 | spec: 6 | host: {{ .Values.route.host | default "paul.apps-crc.testing" }} 7 | port: 8 | targetPort: 8080-tcp 9 | to: 10 | kind: Service 11 | name: simple 12 | weight: 100 13 | wildcardPolicy: None 14 | -------------------------------------------------------------------------------- /helm/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: simple 6 | name: simple 7 | spec: 8 | ports: 9 | - name: 8080-tcp 10 | port: 8080 11 | protocol: TCP 12 | selector: 13 | app: simple 14 | -------------------------------------------------------------------------------- /helm/values.yaml: -------------------------------------------------------------------------------- 1 | deployment: 2 | image: quay.io/wpernath/simple-quarkus 3 | version: 1.2.0 4 | replicas: 1 5 | includeHealthChecks: true 6 | 7 | route: 8 | host: simple-article-helm.apps-crc.testing 9 | 10 | config: 11 | greeting: 'We are on a newer version now!' 12 | 13 | -------------------------------------------------------------------------------- /kubernetes-files/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: simple 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: simple 10 | strategy: 11 | rollingUpdate: 12 | maxSurge: 25% 13 | maxUnavailable: 25% 14 | type: RollingUpdate 15 | template: 16 | metadata: 17 | labels: 18 | app: simple 19 | spec: 20 | containers: 21 | - image: image-registry.openshift-image-registry.svc:5000/wpernath-article/simple:latest 22 | imagePullPolicy: Always 23 | name: simple 24 | ports: 25 | - containerPort: 8080 26 | protocol: TCP 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /kubernetes-files/route.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: route.openshift.io/v1 2 | kind: Route 3 | metadata: 4 | name: simple 5 | spec: 6 | host: simple-wpernath-article-test.apps.beta.rhepds.com 7 | port: 8 | targetPort: 8080-tcp 9 | to: 10 | kind: Service 11 | name: simple 12 | weight: 100 13 | wildcardPolicy: None 14 | -------------------------------------------------------------------------------- /kubernetes-files/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: simple 6 | name: simple 7 | spec: 8 | ports: 9 | - name: 8080-tcp 10 | port: 8080 11 | protocol: TCP 12 | selector: 13 | app: simple 14 | -------------------------------------------------------------------------------- /kubernetes-files/template.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: template.openshift.io/v1 2 | kind: Template 3 | name: app-template 4 | metadata: 5 | name: app-template 6 | annotation: 7 | tags: java 8 | iconClass: icon-rh-openjdk 9 | openshift.io/display-name: The APPLICATION template 10 | description: This Template creates the APPLICATION 11 | objects: 12 | - apiVersion: v1 13 | kind: Service 14 | metadata: 15 | labels: 16 | app: ${APPLICATION_NAME} 17 | name: ${APPLICATION_NAME} 18 | spec: 19 | ports: 20 | - name: 8080-tcp 21 | port: 8080 22 | protocol: TCP 23 | selector: 24 | app: ${APPLICATION_NAME} 25 | - apiVersion: apps/v1 26 | kind: Deployment 27 | metadata: 28 | name: ${APPLICATION_NAME} 29 | spec: 30 | replicas: 1 31 | selector: 32 | matchLabels: 33 | app: ${APPLICATION_NAME} 34 | strategy: 35 | rollingUpdate: 36 | maxSurge: 25% 37 | maxUnavailable: 25% 38 | type: RollingUpdate 39 | template: 40 | metadata: 41 | labels: 42 | app: ${APPLICATION_NAME} 43 | spec: 44 | containers: 45 | - image: ${IMAGE_NAME}:${IMAGE_TAG} 46 | imagePullPolicy: Always 47 | name: ${APPLICATION_NAME} 48 | ports: 49 | - containerPort: 8080 50 | protocol: TCP 51 | - apiVersion: route.openshift.io/v1 52 | kind: Route 53 | metadata: 54 | name: ${APPLICATION_NAME} 55 | spec: 56 | host: ${HOST_NAME} 57 | port: 58 | targetPort: 8080-tcp 59 | to: 60 | kind: Service 61 | name: ${APPLICATION_NAME} 62 | weight: 100 63 | wildcardPolicy: None 64 | parameters: 65 | - name: APPLICATION_NAME 66 | description: The name of the application you'd like to create 67 | displayName: Application Name 68 | required: true 69 | value: simple 70 | - name: IMAGE_NAME 71 | description: The name and path of the image 72 | displayName: Image Name 73 | required: true 74 | value: quay.io/wpernath/simple-quarkus 75 | - name: IMAGE_TAG 76 | displayName: Image Tag 77 | description: The tag of the image 78 | required: true 79 | value: latest 80 | - name: HOST_NAME 81 | description: Name of the Route host name 82 | displayName: Host Name 83 | required: true 84 | value: simple-article.apps.example.com 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /kustomize/base/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: simple 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: simple 10 | strategy: 11 | rollingUpdate: 12 | maxSurge: 25% 13 | maxUnavailable: 25% 14 | type: RollingUpdate 15 | template: 16 | metadata: 17 | labels: 18 | app: simple 19 | spec: 20 | containers: 21 | - name: simple 22 | image: quay.io/wpernath/simple-quarkus:latest 23 | imagePullPolicy: Always 24 | ports: 25 | - containerPort: 8080 26 | protocol: TCP 27 | env: 28 | - name: APP_GREETING 29 | value: 'Hey, this is the DEVELOPMENT environment of the App' 30 | 31 | -------------------------------------------------------------------------------- /kustomize/base/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | commonLabels: 5 | # application-name: simple 6 | org: wanja.org 7 | 8 | resources: 9 | - deployment.yaml 10 | - service.yaml 11 | - route.yaml 12 | -------------------------------------------------------------------------------- /kustomize/base/route.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: route.openshift.io/v1 2 | kind: Route 3 | metadata: 4 | name: simple 5 | spec: 6 | host: quarkus.apps-crc.testing 7 | port: 8 | targetPort: 8080-tcp 9 | to: 10 | kind: Service 11 | name: simple 12 | weight: 100 13 | wildcardPolicy: None 14 | -------------------------------------------------------------------------------- /kustomize/base/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: simple 6 | name: simple 7 | spec: 8 | ports: 9 | - name: 8080-tcp 10 | port: 8080 11 | protocol: TCP 12 | selector: 13 | app: simple 14 | -------------------------------------------------------------------------------- /kustomize/overlays/dev/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: simple 5 | spec: 6 | replicas: 1 7 | template: 8 | spec: 9 | containers: 10 | - image: quay.io/wpernath/simple-quarkus:latest 11 | imagePullPolicy: Always 12 | name: simple 13 | ports: 14 | - containerPort: 8080 15 | protocol: TCP 16 | env: 17 | - name: APP_GREETING 18 | value: 'Hey, this is the DEVELOPMENT environment of the App' 19 | -------------------------------------------------------------------------------- /kustomize/overlays/dev/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namePrefix: dev- 2 | commonLabels: 3 | variant: development 4 | #commonAnnotations: 5 | # note: We are on dev now 6 | bases: 7 | - ../../base 8 | patchesStrategicMerge: 9 | - deployment.yaml 10 | - route.yaml -------------------------------------------------------------------------------- /kustomize/overlays/dev/route.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: route.openshift.io/v1 2 | kind: Route 3 | metadata: 4 | name: simple 5 | spec: 6 | host: simple-article-kustomize.apps-crc.testing 7 | port: 8 | targetPort: 8080-tcp 9 | to: 10 | kind: Service 11 | name: dev-simple 12 | weight: 100 13 | wildcardPolicy: None 14 | 15 | -------------------------------------------------------------------------------- /kustomize/overlays/stage/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: simple 5 | spec: 6 | replicas: 2 7 | template: 8 | spec: 9 | containers: 10 | - image: quay.io/wpernath/simple-quarkus:stage 11 | imagePullPolicy: Always 12 | name: simple 13 | ports: 14 | - containerPort: 8080 15 | protocol: TCP 16 | env: 17 | - name: APP_GREETING 18 | value: 'Hey, this is the STAGING environment of the App' -------------------------------------------------------------------------------- /kustomize/overlays/stage/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namePrefix: staging- 2 | commonLabels: 3 | variant: staging 4 | #commonAnnotations: 5 | # note: We are on staging now 6 | bases: 7 | - ../../base 8 | patchesStrategicMerge: 9 | - deployment.yaml 10 | - route.yaml -------------------------------------------------------------------------------- /kustomize/overlays/stage/route.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: route.openshift.io/v1 2 | kind: Route 3 | metadata: 4 | name: simple 5 | spec: 6 | host: staging-simple-article-kustomize.apps-crc.testing 7 | to: 8 | kind: Service 9 | name: staging-simple -------------------------------------------------------------------------------- /kustomize_ext/base/config-map.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: app-config 5 | data: 6 | APP_GREETING: 'This needs to be changed per stage!' 7 | -------------------------------------------------------------------------------- /kustomize_ext/base/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: simple 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: simple 10 | strategy: 11 | rollingUpdate: 12 | maxSurge: 25% 13 | maxUnavailable: 25% 14 | type: RollingUpdate 15 | template: 16 | metadata: 17 | labels: 18 | app: simple 19 | spec: 20 | containers: 21 | - name: simple 22 | image: quay.io/wpernath/simple-quarkus:latest 23 | imagePullPolicy: Always 24 | ports: 25 | - containerPort: 8080 26 | protocol: TCP 27 | envFrom: 28 | - configMapRef: 29 | name: app-config 30 | 31 | 32 | -------------------------------------------------------------------------------- /kustomize_ext/base/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | commonLabels: 5 | application-name: simple-quarkus 6 | org: wanja.org 7 | 8 | resources: 9 | - config-map.yaml 10 | - deployment.yaml 11 | - service.yaml 12 | - route.yaml 13 | 14 | -------------------------------------------------------------------------------- /kustomize_ext/base/route.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: route.openshift.io/v1 2 | kind: Route 3 | metadata: 4 | name: simple 5 | spec: 6 | port: 7 | targetPort: 8080-tcp 8 | to: 9 | kind: Service 10 | name: simple 11 | weight: 100 12 | wildcardPolicy: None 13 | -------------------------------------------------------------------------------- /kustomize_ext/base/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: simple 6 | name: simple 7 | spec: 8 | ports: 9 | - name: 8080-tcp 10 | port: 8080 11 | protocol: TCP 12 | selector: 13 | app: simple 14 | -------------------------------------------------------------------------------- /kustomize_ext/overlays/dev/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namePrefix: dev- 2 | commonLabels: 3 | variant: development 4 | 5 | 6 | # replace the image tag of the container with latest 7 | images: 8 | - name: quay.io/wpernath/simple-quarkus 9 | newTag: latest 10 | 11 | # apply a patch to replace the Host of the Route 12 | #- patch: |- 13 | # - op: replace 14 | # path: /spec/host 15 | # value: art-test.apps-crc.testing 16 | # target: 17 | # kind: Route 18 | # this patch needs to be done, because kustomize does not change 19 | # the route target service name 20 | patches: 21 | - patch: |- 22 | - op: replace 23 | path: /spec/to/name 24 | value: dev-simple 25 | target: 26 | kind: Route 27 | apiVersion: kustomize.config.k8s.io/v1beta1 28 | kind: Kustomization 29 | resources: 30 | - ../../base 31 | -------------------------------------------------------------------------------- /kustomize_ext/overlays/prod/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namePrefix: prod- 2 | commonLabels: 3 | variant: production 4 | 5 | bases: 6 | - ../../base 7 | 8 | # replace the image tag of the container with latest 9 | images: 10 | - name: quay.io/wpernath/simple-quarkus 11 | newTag: prod 12 | 13 | # apply a patch to replace the Host of the Route 14 | patches: 15 | - patch: |- 16 | - op: replace 17 | path: /spec/host 18 | value: article-kustomize-prod.apps.beta.rhepds.com 19 | target: 20 | kind: Route 21 | 22 | -------------------------------------------------------------------------------- /kustomize_ext/overlays/stage/apply-health-checks.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: simple 5 | spec: 6 | template: 7 | spec: 8 | containers: 9 | - name: simple 10 | readinessProbe: 11 | httpGet: 12 | path: /q/health/ready 13 | port: 8080 14 | scheme: HTTP 15 | timeoutSeconds: 1 16 | periodSeconds: 10 17 | successThreshold: 1 18 | failureThreshold: 3 19 | livenessProbe: 20 | httpGet: 21 | path: /q/health/live 22 | port: 8080 23 | scheme: HTTP 24 | timeoutSeconds: 2 25 | periodSeconds: 10 26 | successThreshold: 1 27 | failureThreshold: 3 28 | -------------------------------------------------------------------------------- /kustomize_ext/overlays/stage/change-env-value.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: app-config 5 | data: 6 | APP_GREETING: 'We are on the STAGING environment' 7 | -------------------------------------------------------------------------------- /kustomize_ext/overlays/stage/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namePrefix: stage- 2 | commonLabels: 3 | variant: stage 4 | 5 | bases: 6 | - ../../base 7 | 8 | # in stage we have 2 replicas 9 | replicas: 10 | - name: simple 11 | count: 2 12 | 13 | # replace the image tag of the container with stage 14 | images: 15 | - name: quay.io/wpernath/simple-quarkus 16 | newTag: 1.2.0 17 | 18 | # apply some patches 19 | patches: 20 | # apply health checks to deployment 21 | - path: apply-health-checks.yaml 22 | target: 23 | version: v1 24 | kind: Deployment 25 | name: simple 26 | 27 | # change the host name of the generated route 28 | - patch: |- 29 | - op: replace 30 | path: /spec/host 31 | value: simple-stage-art-stage.apps-crc.testing 32 | target: 33 | kind: Route 34 | 35 | # this patch needs to be done, because kustomize does not change 36 | # the route target service name 37 | - patch: |- 38 | - op: replace 39 | path: /spec/to/name 40 | value: stage-simple 41 | target: 42 | kind: Route 43 | 44 | # change env parameter in config-map 45 | # we could also simply generate the config-map from a source 46 | # or we could use one of the patches above for this 47 | patchesStrategicMerge: 48 | - change-env-value.yaml 49 | 50 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 124 | 125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 162 | if ERRORLEVEL 1 goto error 163 | goto end 164 | 165 | :error 166 | set ERROR_CODE=1 167 | 168 | :end 169 | @endlocal & set ERROR_CODE=%ERROR_CODE% 170 | 171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 175 | :skipRcPost 176 | 177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 179 | 180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 181 | 182 | exit /B %ERROR_CODE% 183 | -------------------------------------------------------------------------------- /operator/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | 10 | # editor and IDE paraphernalia 11 | .idea 12 | *.swp 13 | *.swo 14 | *~ 15 | -------------------------------------------------------------------------------- /operator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the manager binary 2 | #FROM quay.io/operator-framework/helm-operator:v1.7.2 3 | FROM registry.redhat.io/openshift4/ose-helm-operator:v4.7 4 | 5 | ENV HOME=/opt/helm 6 | COPY watches.yaml ${HOME}/watches.yaml 7 | COPY helm-charts ${HOME}/helm-charts 8 | WORKDIR ${HOME} 9 | -------------------------------------------------------------------------------- /operator/Makefile: -------------------------------------------------------------------------------- 1 | # VERSION defines the project version for the bundle. 2 | # Update this value when you upgrade the version of your project. 3 | # To re-generate a bundle for another specific version without changing the standard setup, you can: 4 | # - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) 5 | # - use environment variables to overwrite this value (e.g export VERSION=0.0.2) 6 | VERSION ?= 0.0.4 7 | 8 | # CHANNELS define the bundle channels used in the bundle. 9 | # Add a new line here if you would like to change its default config. (E.g CHANNELS = "preview,fast,stable") 10 | # To re-generate a bundle for other specific channels without changing the standard setup, you can: 11 | # - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=preview,fast,stable) 12 | # - use environment variables to overwrite this value (e.g export CHANNELS="preview,fast,stable") 13 | ifneq ($(origin CHANNELS), undefined) 14 | BUNDLE_CHANNELS := --channels=$(CHANNELS) 15 | endif 16 | 17 | # DEFAULT_CHANNEL defines the default channel used in the bundle. 18 | # Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable") 19 | # To re-generate a bundle for any other default channel without changing the default setup, you can: 20 | # - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable) 21 | # - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable") 22 | ifneq ($(origin DEFAULT_CHANNEL), undefined) 23 | BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) 24 | endif 25 | BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) 26 | 27 | # IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images. 28 | # This variable is used to construct full image tags for bundle and catalog images. 29 | # 30 | # For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both 31 | # wanja.org/simple-quarkus-operator-bundle:$VERSION and wanja.org/simple-quarkus-operator-catalog:$VERSION. 32 | IMAGE_TAG_BASE ?= quay.io/wpernath/simple-quarkus-operator 33 | 34 | # BUNDLE_IMG defines the image:tag used for the bundle. 35 | # You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) 36 | BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION) 37 | 38 | # Image URL to use all building/pushing image targets 39 | IMG ?= $(IMAGE_TAG_BASE):$(VERSION) 40 | 41 | all: docker-build 42 | 43 | ##@ General 44 | 45 | # The help target prints out all targets with their descriptions organized 46 | # beneath their categories. The categories are represented by '##@' and the 47 | # target descriptions by '##'. The awk commands is responsible for reading the 48 | # entire set of makefiles included in this invocation, looking for lines of the 49 | # file as xyz: ## something, and then pretty-format the target and help. Then, 50 | # if there's a line with ##@ something, that gets pretty-printed as a category. 51 | # More info on the usage of ANSI control characters for terminal formatting: 52 | # https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters 53 | # More info on the awk command: 54 | # http://linuxcommand.org/lc3_adv_awk.php 55 | 56 | help: ## Display this help. 57 | @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) 58 | 59 | ##@ Build 60 | 61 | run: helm-operator ## Run against the configured Kubernetes cluster in ~/.kube/config 62 | $(HELM_OPERATOR) run 63 | 64 | docker-build: ## Build docker image with the manager. 65 | docker build -t ${IMG} . 66 | 67 | docker-push: ## Push docker image with the manager. 68 | docker push ${IMG} 69 | 70 | ##@ Deployment 71 | 72 | install: kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. 73 | $(KUSTOMIZE) build config/crd | kubectl apply -f - 74 | 75 | uninstall: kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. 76 | $(KUSTOMIZE) build config/crd | kubectl delete -f - 77 | 78 | deploy: kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config. 79 | cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} 80 | $(KUSTOMIZE) build config/default | kubectl apply -f - 81 | 82 | undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. 83 | $(KUSTOMIZE) build config/default | kubectl delete -f - 84 | 85 | OS := $(shell uname -s | tr '[:upper:]' '[:lower:]') 86 | ARCH := $(shell uname -m | sed 's/x86_64/amd64/') 87 | 88 | .PHONY: kustomize 89 | KUSTOMIZE = $(shell pwd)/bin/kustomize 90 | kustomize: ## Download kustomize locally if necessary. 91 | ifeq (,$(wildcard $(KUSTOMIZE))) 92 | ifeq (,$(shell which kustomize 2>/dev/null)) 93 | @{ \ 94 | set -e ;\ 95 | mkdir -p $(dir $(KUSTOMIZE)) ;\ 96 | curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.5.4/kustomize_v3.5.4_$(OS)_$(ARCH).tar.gz | \ 97 | tar xzf - -C bin/ ;\ 98 | } 99 | else 100 | KUSTOMIZE = $(shell which kustomize) 101 | endif 102 | endif 103 | 104 | .PHONY: helm-operator 105 | HELM_OPERATOR = $(shell pwd)/bin/helm-operator 106 | helm-operator: ## Download helm-operator locally if necessary, preferring the $(pwd)/bin path over global if both exist. 107 | ifeq (,$(wildcard $(HELM_OPERATOR))) 108 | ifeq (,$(shell which helm-operator 2>/dev/null)) 109 | @{ \ 110 | set -e ;\ 111 | mkdir -p $(dir $(HELM_OPERATOR)) ;\ 112 | curl -sSLo $(HELM_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/v1.7.2/helm-operator_$(OS)_$(ARCH) ;\ 113 | chmod +x $(HELM_OPERATOR) ;\ 114 | } 115 | else 116 | HELM_OPERATOR = $(shell which helm-operator) 117 | endif 118 | endif 119 | 120 | .PHONY: bundle 121 | bundle: kustomize ## Generate bundle manifests and metadata, then validate generated files. 122 | operator-sdk generate kustomize manifests -q 123 | cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) 124 | $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) 125 | operator-sdk bundle validate ./bundle 126 | 127 | .PHONY: bundle-build 128 | bundle-build: ## Build the bundle image. 129 | docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . 130 | 131 | .PHONY: bundle-push 132 | bundle-push: ## Push the bundle image. 133 | $(MAKE) docker-push IMG=$(BUNDLE_IMG) 134 | 135 | .PHONY: opm 136 | OPM = ./bin/opm 137 | opm: ## Download opm locally if necessary. 138 | ifeq (,$(wildcard $(OPM))) 139 | ifeq (,$(shell which opm 2>/dev/null)) 140 | @{ \ 141 | set -e ;\ 142 | mkdir -p $(dir $(OPM)) ;\ 143 | curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.15.1/$(OS)-$(ARCH)-opm ;\ 144 | chmod +x $(OPM) ;\ 145 | } 146 | else 147 | OPM = $(shell which opm) 148 | endif 149 | endif 150 | 151 | # A comma-separated list of bundle images (e.g. make catalog-build BUNDLE_IMGS=example.com/operator-bundle:v0.1.0,example.com/operator-bundle:v0.2.0). 152 | # These images MUST exist in a registry and be pull-able. 153 | BUNDLE_IMGS ?= $(BUNDLE_IMG) 154 | 155 | # The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0). 156 | CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION) 157 | 158 | # Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMGS to that image. 159 | ifneq ($(origin CATALOG_BASE_IMG), undefined) 160 | FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG) 161 | endif 162 | 163 | # Build a catalog image by adding bundle images to an empty catalog using the operator package manager tool, 'opm'. 164 | # This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see: 165 | # https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator 166 | .PHONY: catalog-build 167 | catalog-build: opm ## Build a catalog image. 168 | $(OPM) index add --container-tool docker --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT) 169 | 170 | # Push the catalog image. 171 | .PHONY: catalog-push 172 | catalog-push: ## Push a catalog image. 173 | $(MAKE) docker-push IMG=$(CATALOG_IMG) 174 | -------------------------------------------------------------------------------- /operator/PROJECT: -------------------------------------------------------------------------------- 1 | domain: wanja.org 2 | layout: 3 | - helm.sdk.operatorframework.io/v1 4 | plugins: 5 | manifests.sdk.operatorframework.io/v2: {} 6 | scorecard.sdk.operatorframework.io/v2: {} 7 | projectName: simple-quarkus-operator 8 | resources: 9 | - api: 10 | crdVersion: v1 11 | namespaced: true 12 | domain: wanja.org 13 | group: charts 14 | kind: QuarkusSimple 15 | version: v1alpha1 16 | version: "3" 17 | -------------------------------------------------------------------------------- /operator/bundle.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | 3 | # Core bundle labels. 4 | LABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1 5 | LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/ 6 | LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/ 7 | LABEL operators.operatorframework.io.bundle.package.v1=simple-quarkus-operator 8 | LABEL operators.operatorframework.io.bundle.channels.v1=alpha 9 | LABEL operators.operatorframework.io.metrics.builder=operator-sdk-v1.7.2 10 | LABEL operators.operatorframework.io.metrics.mediatype.v1=metrics+v1 11 | LABEL operators.operatorframework.io.metrics.project_layout=helm.sdk.operatorframework.io/v1 12 | 13 | # Labels for testing. 14 | LABEL operators.operatorframework.io.test.mediatype.v1=scorecard+v1 15 | LABEL operators.operatorframework.io.test.config.v1=tests/scorecard/ 16 | 17 | # Copy files to locations specified by labels. 18 | COPY bundle/manifests /manifests/ 19 | COPY bundle/metadata /metadata/ 20 | COPY bundle/tests/scorecard /tests/scorecard/ 21 | -------------------------------------------------------------------------------- /operator/bundle/manifests/charts.wanja.org_quarkussimples.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | creationTimestamp: null 5 | name: quarkussimples.charts.wanja.org 6 | spec: 7 | group: charts.wanja.org 8 | names: 9 | kind: QuarkusSimple 10 | listKind: QuarkusSimpleList 11 | plural: quarkussimples 12 | singular: quarkussimple 13 | scope: Namespaced 14 | versions: 15 | - name: v1alpha1 16 | schema: 17 | openAPIV3Schema: 18 | description: QuarkusSimple is the Schema for the quarkussimples API 19 | properties: 20 | apiVersion: 21 | description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 22 | type: string 23 | kind: 24 | description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 25 | type: string 26 | metadata: 27 | type: object 28 | spec: 29 | description: Spec defines the desired state of QuarkusSimple 30 | type: object 31 | x-kubernetes-preserve-unknown-fields: true 32 | status: 33 | description: Status defines the observed state of QuarkusSimple 34 | type: object 35 | x-kubernetes-preserve-unknown-fields: true 36 | type: object 37 | served: true 38 | storage: true 39 | subresources: 40 | status: {} 41 | status: 42 | acceptedNames: 43 | kind: "" 44 | plural: "" 45 | conditions: null 46 | storedVersions: null 47 | -------------------------------------------------------------------------------- /operator/bundle/manifests/simple-quarkus-operator-controller-manager-metrics-service_v1_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | creationTimestamp: null 5 | labels: 6 | control-plane: controller-manager 7 | name: simple-quarkus-operator-controller-manager-metrics-service 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | targetPort: https 13 | selector: 14 | control-plane: controller-manager 15 | status: 16 | loadBalancer: {} 17 | -------------------------------------------------------------------------------- /operator/bundle/manifests/simple-quarkus-operator-controller-manager_v1_serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | creationTimestamp: null 5 | name: simple-quarkus-operator-controller-manager 6 | -------------------------------------------------------------------------------- /operator/bundle/manifests/simple-quarkus-operator-manager-config_v1_configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | data: 3 | controller_manager_config.yaml: | 4 | apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 5 | kind: ControllerManagerConfig 6 | health: 7 | healthProbeBindAddress: :8081 8 | metrics: 9 | bindAddress: 127.0.0.1:8080 10 | 11 | leaderElection: 12 | leaderElect: true 13 | resourceName: 811c9dc5.wanja.org 14 | kind: ConfigMap 15 | metadata: 16 | name: simple-quarkus-operator-manager-config 17 | -------------------------------------------------------------------------------- /operator/bundle/manifests/simple-quarkus-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | creationTimestamp: null 5 | name: simple-quarkus-operator-metrics-reader 6 | rules: 7 | - nonResourceURLs: 8 | - /metrics 9 | verbs: 10 | - get 11 | -------------------------------------------------------------------------------- /operator/bundle/manifests/simple-quarkus-operator.clusterserviceversion.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1alpha1 2 | kind: ClusterServiceVersion 3 | metadata: 4 | annotations: 5 | alm-examples: |- 6 | [ 7 | { 8 | "apiVersion": "charts.wanja.org/v1alpha1", 9 | "kind": "QuarkusSimple", 10 | "metadata": { 11 | "name": "quarkussimple-sample" 12 | }, 13 | "spec": { 14 | "config": { 15 | "greeting": "This needs to be changed per stage!" 16 | }, 17 | "deployment": { 18 | "image": "quay.io/wpernath/simple-quarkus", 19 | "includeHealthChecks": true, 20 | "replicas": 1, 21 | "version": "1.2.0" 22 | }, 23 | "route": { 24 | "host": "article-operator.apps-crc.testing" 25 | } 26 | } 27 | } 28 | ] 29 | capabilities: Basic Install 30 | operators.operatorframework.io/builder: operator-sdk-v1.7.2 31 | operators.operatorframework.io/project_layout: helm.sdk.operatorframework.io/v1 32 | name: simple-quarkus-operator.v0.0.4 33 | namespace: placeholder 34 | spec: 35 | apiservicedefinitions: {} 36 | customresourcedefinitions: 37 | owned: 38 | - kind: QuarkusSimple 39 | name: quarkussimples.charts.wanja.org 40 | version: v1alpha1 41 | description: This is a simple quarkus operator created for the article mentioned on https://github.com/wpernath/quarkus-simple 42 | displayName: Simple Quarkus Operator 43 | icon: 44 | - base64data: "" 45 | mediatype: "" 46 | install: 47 | spec: 48 | clusterPermissions: 49 | - rules: 50 | - apiGroups: 51 | - "" 52 | resources: 53 | - namespaces 54 | verbs: 55 | - get 56 | - apiGroups: 57 | - "" 58 | resources: 59 | - secrets 60 | verbs: 61 | - '*' 62 | - apiGroups: 63 | - "" 64 | resources: 65 | - events 66 | verbs: 67 | - create 68 | - apiGroups: 69 | - charts.wanja.org 70 | resources: 71 | - quarkussimples 72 | - quarkussimples/status 73 | - quarkussimples/finalizers 74 | verbs: 75 | - create 76 | - delete 77 | - get 78 | - list 79 | - patch 80 | - update 81 | - watch 82 | - apiGroups: 83 | - "" 84 | resources: 85 | - configmaps 86 | - services 87 | verbs: 88 | - '*' 89 | - apiGroups: 90 | - apps 91 | resources: 92 | - deployments 93 | verbs: 94 | - '*' 95 | - apiGroups: 96 | - route.openshift.io 97 | resources: 98 | - routes 99 | verbs: 100 | - '*' 101 | - apiGroups: 102 | - authentication.k8s.io 103 | resources: 104 | - tokenreviews 105 | verbs: 106 | - create 107 | - apiGroups: 108 | - authorization.k8s.io 109 | resources: 110 | - subjectaccessreviews 111 | verbs: 112 | - create 113 | serviceAccountName: simple-quarkus-operator-controller-manager 114 | deployments: 115 | - name: simple-quarkus-operator-controller-manager 116 | spec: 117 | replicas: 1 118 | selector: 119 | matchLabels: 120 | control-plane: controller-manager 121 | strategy: {} 122 | template: 123 | metadata: 124 | labels: 125 | control-plane: controller-manager 126 | spec: 127 | containers: 128 | - args: 129 | - --secure-listen-address=0.0.0.0:8443 130 | - --upstream=http://127.0.0.1:8080/ 131 | - --logtostderr=true 132 | - --v=10 133 | image: registry.redhat.io/openshift4/ose-kube-rbac-proxy:v4.7 134 | name: kube-rbac-proxy 135 | ports: 136 | - containerPort: 8443 137 | name: https 138 | resources: {} 139 | - args: 140 | - --health-probe-bind-address=:8081 141 | - --metrics-bind-address=127.0.0.1:8080 142 | - --leader-elect 143 | - --leader-election-id=simple-quarkus-operator 144 | image: quay.io/wpernath/simple-quarkus-operator:0.0.4 145 | livenessProbe: 146 | httpGet: 147 | path: /healthz 148 | port: 8081 149 | initialDelaySeconds: 15 150 | periodSeconds: 20 151 | name: manager 152 | readinessProbe: 153 | httpGet: 154 | path: /readyz 155 | port: 8081 156 | initialDelaySeconds: 5 157 | periodSeconds: 10 158 | resources: 159 | limits: 160 | cpu: 100m 161 | memory: 90Mi 162 | requests: 163 | cpu: 100m 164 | memory: 60Mi 165 | securityContext: 166 | allowPrivilegeEscalation: false 167 | securityContext: 168 | runAsNonRoot: true 169 | serviceAccountName: simple-quarkus-operator-controller-manager 170 | terminationGracePeriodSeconds: 10 171 | permissions: 172 | - rules: 173 | - apiGroups: 174 | - "" 175 | resources: 176 | - configmaps 177 | verbs: 178 | - get 179 | - list 180 | - watch 181 | - create 182 | - update 183 | - patch 184 | - delete 185 | - apiGroups: 186 | - coordination.k8s.io 187 | resources: 188 | - leases 189 | verbs: 190 | - get 191 | - list 192 | - watch 193 | - create 194 | - update 195 | - patch 196 | - delete 197 | - apiGroups: 198 | - "" 199 | resources: 200 | - events 201 | verbs: 202 | - create 203 | - patch 204 | serviceAccountName: simple-quarkus-operator-controller-manager 205 | strategy: deployment 206 | installModes: 207 | - supported: false 208 | type: OwnNamespace 209 | - supported: false 210 | type: SingleNamespace 211 | - supported: false 212 | type: MultiNamespace 213 | - supported: true 214 | type: AllNamespaces 215 | keywords: 216 | - simple 217 | - quarkus 218 | - helm 219 | - operator 220 | links: 221 | - name: Simple Quarkus Operator 222 | url: https://simple-quarkus-operator.domain 223 | maintainers: 224 | - email: wpernath@redhat.com 225 | name: Wanja Pernath 226 | maturity: alpha 227 | provider: 228 | name: Wanja Pernath 229 | url: https://github.com/wpernath/quarkus-simple 230 | version: 0.0.4 231 | -------------------------------------------------------------------------------- /operator/bundle/metadata/annotations.yaml: -------------------------------------------------------------------------------- 1 | annotations: 2 | # Core bundle annotations. 3 | operators.operatorframework.io.bundle.mediatype.v1: registry+v1 4 | operators.operatorframework.io.bundle.manifests.v1: manifests/ 5 | operators.operatorframework.io.bundle.metadata.v1: metadata/ 6 | operators.operatorframework.io.bundle.package.v1: simple-quarkus-operator 7 | operators.operatorframework.io.bundle.channels.v1: alpha 8 | operators.operatorframework.io.metrics.builder: operator-sdk-v1.7.2 9 | operators.operatorframework.io.metrics.mediatype.v1: metrics+v1 10 | operators.operatorframework.io.metrics.project_layout: helm.sdk.operatorframework.io/v1 11 | 12 | # Annotations for testing. 13 | operators.operatorframework.io.test.mediatype.v1: scorecard+v1 14 | operators.operatorframework.io.test.config.v1: tests/scorecard/ 15 | -------------------------------------------------------------------------------- /operator/bundle/tests/scorecard/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: scorecard.operatorframework.io/v1alpha3 2 | kind: Configuration 3 | metadata: 4 | name: config 5 | stages: 6 | - parallel: true 7 | tests: 8 | - entrypoint: 9 | - scorecard-test 10 | - basic-check-spec 11 | image: quay.io/operator-framework/scorecard-test:v1.7.2 12 | labels: 13 | suite: basic 14 | test: basic-check-spec-test 15 | - entrypoint: 16 | - scorecard-test 17 | - olm-bundle-validation 18 | image: quay.io/operator-framework/scorecard-test:v1.7.2 19 | labels: 20 | suite: olm 21 | test: olm-bundle-validation-test 22 | - entrypoint: 23 | - scorecard-test 24 | - olm-crds-have-validation 25 | image: quay.io/operator-framework/scorecard-test:v1.7.2 26 | labels: 27 | suite: olm 28 | test: olm-crds-have-validation-test 29 | - entrypoint: 30 | - scorecard-test 31 | - olm-crds-have-resources 32 | image: quay.io/operator-framework/scorecard-test:v1.7.2 33 | labels: 34 | suite: olm 35 | test: olm-crds-have-resources-test 36 | - entrypoint: 37 | - scorecard-test 38 | - olm-spec-descriptors 39 | image: quay.io/operator-framework/scorecard-test:v1.7.2 40 | labels: 41 | suite: olm 42 | test: olm-spec-descriptors-test 43 | - entrypoint: 44 | - scorecard-test 45 | - olm-status-descriptors 46 | image: quay.io/operator-framework/scorecard-test:v1.7.2 47 | labels: 48 | suite: olm 49 | test: olm-status-descriptors-test 50 | -------------------------------------------------------------------------------- /operator/config/crd/bases/charts.wanja.org_quarkussimples.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: quarkussimples.charts.wanja.org 6 | spec: 7 | group: charts.wanja.org 8 | names: 9 | kind: QuarkusSimple 10 | listKind: QuarkusSimpleList 11 | plural: quarkussimples 12 | singular: quarkussimple 13 | scope: Namespaced 14 | versions: 15 | - name: v1alpha1 16 | schema: 17 | openAPIV3Schema: 18 | description: QuarkusSimple is the Schema for the quarkussimples API 19 | properties: 20 | apiVersion: 21 | description: 'APIVersion defines the versioned schema of this representation 22 | of an object. Servers should convert recognized schemas to the latest 23 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 24 | type: string 25 | kind: 26 | description: 'Kind is a string value representing the REST resource this 27 | object represents. Servers may infer this from the endpoint the client 28 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 29 | type: string 30 | metadata: 31 | type: object 32 | spec: 33 | description: Spec defines the desired state of QuarkusSimple 34 | type: object 35 | x-kubernetes-preserve-unknown-fields: true 36 | status: 37 | description: Status defines the observed state of QuarkusSimple 38 | type: object 39 | x-kubernetes-preserve-unknown-fields: true 40 | type: object 41 | served: true 42 | storage: true 43 | subresources: 44 | status: {} 45 | -------------------------------------------------------------------------------- /operator/config/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # This kustomization.yaml is not intended to be run by itself, 2 | # since it depends on service name and namespace that are out of this kustomize package. 3 | # It should be run by config/default 4 | resources: 5 | - bases/charts.wanja.org_quarkussimples.yaml 6 | #+kubebuilder:scaffold:crdkustomizeresource 7 | -------------------------------------------------------------------------------- /operator/config/default/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: simple-quarkus-operator-system 3 | 4 | # Value of this field is prepended to the 5 | # names of all resources, e.g. a deployment named 6 | # "wordpress" becomes "alices-wordpress". 7 | # Note that it should also match with the prefix (text before '-') of the namespace 8 | # field above. 9 | namePrefix: simple-quarkus-operator- 10 | 11 | # Labels to add to all resources and selectors. 12 | #commonLabels: 13 | # someName: someValue 14 | 15 | bases: 16 | - ../crd 17 | - ../rbac 18 | - ../manager 19 | # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. 20 | #- ../prometheus 21 | 22 | patchesStrategicMerge: 23 | # Protect the /metrics endpoint by putting it behind auth. 24 | # If you want your controller-manager to expose the /metrics 25 | # endpoint w/o any authn/z, please comment the following line. 26 | - manager_auth_proxy_patch.yaml 27 | 28 | # Mount the controller config file for loading manager configurations 29 | # through a ComponentConfig type 30 | #- manager_config_patch.yaml 31 | -------------------------------------------------------------------------------- /operator/config/default/manager_auth_proxy_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch inject a sidecar container which is a HTTP proxy for the 2 | # controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | name: controller-manager 7 | namespace: system 8 | spec: 9 | template: 10 | spec: 11 | containers: 12 | - name: kube-rbac-proxy 13 | #image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0 14 | image: registry.redhat.io/openshift4/ose-kube-rbac-proxy:v4.7 15 | args: 16 | - "--secure-listen-address=0.0.0.0:8443" 17 | - "--upstream=http://127.0.0.1:8080/" 18 | - "--logtostderr=true" 19 | - "--v=10" 20 | ports: 21 | - containerPort: 8443 22 | name: https 23 | - name: manager 24 | args: 25 | - "--health-probe-bind-address=:8081" 26 | - "--metrics-bind-address=127.0.0.1:8080" 27 | - "--leader-elect" 28 | - "--leader-election-id=simple-quarkus-operator" 29 | -------------------------------------------------------------------------------- /operator/config/default/manager_config_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | args: 12 | - "--config=controller_manager_config.yaml" 13 | volumeMounts: 14 | - name: manager-config 15 | mountPath: /controller_manager_config.yaml 16 | subPath: controller_manager_config.yaml 17 | volumes: 18 | - name: manager-config 19 | configMap: 20 | name: manager-config 21 | -------------------------------------------------------------------------------- /operator/config/manager/controller_manager_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 2 | kind: ControllerManagerConfig 3 | health: 4 | healthProbeBindAddress: :8081 5 | metrics: 6 | bindAddress: 127.0.0.1:8080 7 | 8 | leaderElection: 9 | leaderElect: true 10 | resourceName: 811c9dc5.wanja.org 11 | -------------------------------------------------------------------------------- /operator/config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manager.yaml 3 | 4 | generatorOptions: 5 | disableNameSuffixHash: true 6 | 7 | configMapGenerator: 8 | - files: 9 | - controller_manager_config.yaml 10 | name: manager-config 11 | apiVersion: kustomize.config.k8s.io/v1beta1 12 | kind: Kustomization 13 | images: 14 | - name: controller 15 | newName: quay.io/wpernath/simple-quarkus-operator 16 | newTag: 0.0.4 17 | -------------------------------------------------------------------------------- /operator/config/manager/manager.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: system 7 | --- 8 | apiVersion: apps/v1 9 | kind: Deployment 10 | metadata: 11 | name: controller-manager 12 | namespace: system 13 | labels: 14 | control-plane: controller-manager 15 | spec: 16 | selector: 17 | matchLabels: 18 | control-plane: controller-manager 19 | replicas: 1 20 | template: 21 | metadata: 22 | labels: 23 | control-plane: controller-manager 24 | spec: 25 | securityContext: 26 | runAsNonRoot: true 27 | containers: 28 | - args: 29 | - --leader-elect 30 | - --leader-election-id=simple-quarkus-operator 31 | image: controller:latest 32 | name: manager 33 | securityContext: 34 | allowPrivilegeEscalation: false 35 | livenessProbe: 36 | httpGet: 37 | path: /healthz 38 | port: 8081 39 | initialDelaySeconds: 15 40 | periodSeconds: 20 41 | readinessProbe: 42 | httpGet: 43 | path: /readyz 44 | port: 8081 45 | initialDelaySeconds: 5 46 | periodSeconds: 10 47 | resources: 48 | limits: 49 | cpu: 100m 50 | memory: 90Mi 51 | requests: 52 | cpu: 100m 53 | memory: 60Mi 54 | serviceAccountName: controller-manager 55 | terminationGracePeriodSeconds: 10 56 | -------------------------------------------------------------------------------- /operator/config/manifests/bases/simple-quarkus-operator.clusterserviceversion.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1alpha1 2 | kind: ClusterServiceVersion 3 | metadata: 4 | annotations: 5 | alm-examples: '[]' 6 | capabilities: Basic Install 7 | name: simple-quarkus-operator.v0.0.0 8 | namespace: placeholder 9 | spec: 10 | apiservicedefinitions: {} 11 | customresourcedefinitions: {} 12 | description: This is a simple quarkus operator created for the article mentioned on https://github.com/wpernath/quarkus-simple 13 | displayName: Simple Quarkus Operator 14 | icon: 15 | - base64data: "" 16 | mediatype: "" 17 | install: 18 | spec: 19 | deployments: null 20 | strategy: "" 21 | installModes: 22 | - supported: false 23 | type: OwnNamespace 24 | - supported: false 25 | type: SingleNamespace 26 | - supported: false 27 | type: MultiNamespace 28 | - supported: true 29 | type: AllNamespaces 30 | keywords: 31 | - simple 32 | - quarkus 33 | - helm 34 | - operator 35 | links: 36 | - name: Simple Quarkus Operator 37 | url: https://simple-quarkus-operator.domain 38 | maintainers: 39 | - email: wpernath@redhat.com 40 | name: Wanja Pernath 41 | maturity: alpha 42 | provider: 43 | name: Wanja Pernath 44 | url: https://github.com/wpernath/quarkus-simple 45 | version: 0.0.0 46 | -------------------------------------------------------------------------------- /operator/config/manifests/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # These resources constitute the fully configured set of manifests 2 | # used to generate the 'manifests/' directory in a bundle. 3 | resources: 4 | - bases/simple-quarkus-operator.clusterserviceversion.yaml 5 | - ../default 6 | - ../samples 7 | - ../scorecard 8 | -------------------------------------------------------------------------------- /operator/config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /operator/config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | 2 | # Prometheus Monitor Service (Metrics) 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | control-plane: controller-manager 8 | name: controller-manager-metrics-monitor 9 | namespace: system 10 | spec: 11 | endpoints: 12 | - path: /metrics 13 | port: https 14 | scheme: https 15 | bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 16 | tlsConfig: 17 | insecureSkipVerify: true 18 | selector: 19 | matchLabels: 20 | control-plane: controller-manager 21 | -------------------------------------------------------------------------------- /operator/config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: 7 | - "/metrics" 8 | verbs: 9 | - get 10 | -------------------------------------------------------------------------------- /operator/config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: 7 | - authentication.k8s.io 8 | resources: 9 | - tokenreviews 10 | verbs: 11 | - create 12 | - apiGroups: 13 | - authorization.k8s.io 14 | resources: 15 | - subjectaccessreviews 16 | verbs: 17 | - create 18 | -------------------------------------------------------------------------------- /operator/config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /operator/config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: controller-manager-metrics-service 7 | namespace: system 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | targetPort: https 13 | selector: 14 | control-plane: controller-manager 15 | -------------------------------------------------------------------------------- /operator/config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | # All RBAC will be applied under this service account in 3 | # the deployment namespace. You may comment out this resource 4 | # if your manager will use a service account that exists at 5 | # runtime. Be sure to update RoleBinding and ClusterRoleBinding 6 | # subjects if changing service account names. 7 | - service_account.yaml 8 | - role.yaml 9 | - role_binding.yaml 10 | - leader_election_role.yaml 11 | - leader_election_role_binding.yaml 12 | # Comment the following 4 lines if you want to disable 13 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 14 | # which protects your /metrics endpoint. 15 | - auth_proxy_service.yaml 16 | - auth_proxy_role.yaml 17 | - auth_proxy_role_binding.yaml 18 | - auth_proxy_client_clusterrole.yaml 19 | -------------------------------------------------------------------------------- /operator/config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - configmaps 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - create 16 | - update 17 | - patch 18 | - delete 19 | - apiGroups: 20 | - coordination.k8s.io 21 | resources: 22 | - leases 23 | verbs: 24 | - get 25 | - list 26 | - watch 27 | - create 28 | - update 29 | - patch 30 | - delete 31 | - apiGroups: 32 | - "" 33 | resources: 34 | - events 35 | verbs: 36 | - create 37 | - patch 38 | -------------------------------------------------------------------------------- /operator/config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /operator/config/rbac/quarkussimple_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit quarkussimples. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: quarkussimple-editor-role 6 | rules: 7 | - apiGroups: 8 | - charts.wanja.org 9 | resources: 10 | - quarkussimples 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - charts.wanja.org 21 | resources: 22 | - quarkussimples/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /operator/config/rbac/quarkussimple_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view quarkussimples. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: quarkussimple-viewer-role 6 | rules: 7 | - apiGroups: 8 | - charts.wanja.org 9 | resources: 10 | - quarkussimples 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - charts.wanja.org 17 | resources: 18 | - quarkussimples/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /operator/config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: manager-role 5 | rules: 6 | ## 7 | ## Base operator rules 8 | ## 9 | # We need to get namespaces so the operator can read namespaces to ensure they exist 10 | - apiGroups: 11 | - "" 12 | resources: 13 | - namespaces 14 | verbs: 15 | - get 16 | # We need to manage Helm release secrets 17 | - apiGroups: 18 | - "" 19 | resources: 20 | - secrets 21 | verbs: 22 | - "*" 23 | # We need to create events on CRs about things happening during reconciliation 24 | - apiGroups: 25 | - "" 26 | resources: 27 | - events 28 | verbs: 29 | - create 30 | 31 | ## 32 | ## Rules for charts.wanja.org/v1alpha1, Kind: QuarkusSimple 33 | ## 34 | - apiGroups: 35 | - charts.wanja.org 36 | resources: 37 | - quarkussimples 38 | - quarkussimples/status 39 | - quarkussimples/finalizers 40 | verbs: 41 | - create 42 | - delete 43 | - get 44 | - list 45 | - patch 46 | - update 47 | - watch 48 | - verbs: 49 | - "*" 50 | apiGroups: 51 | - "" 52 | resources: 53 | - "configmaps" 54 | - "services" 55 | - verbs: 56 | - "*" 57 | apiGroups: 58 | - "apps" 59 | resources: 60 | - "deployments" 61 | - verbs: 62 | - "*" 63 | apiGroups: 64 | - "route.openshift.io" 65 | resources: 66 | - "routes" 67 | 68 | #+kubebuilder:scaffold:rules 69 | -------------------------------------------------------------------------------- /operator/config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: manager-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /operator/config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | -------------------------------------------------------------------------------- /operator/config/samples/charts_v1alpha1_quarkussimple.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: charts.wanja.org/v1alpha1 2 | kind: QuarkusSimple 3 | metadata: 4 | name: quarkussimple-sample 5 | spec: 6 | # Default values copied from /helm-charts/quarkus-simple/values.yaml 7 | config: 8 | greeting: This needs to be changed per stage! 9 | deployment: 10 | image: quay.io/wpernath/simple-quarkus 11 | includeHealthChecks: true 12 | replicas: 1 13 | version: "1.2.0" 14 | route: 15 | host: article-operator.apps-crc.testing 16 | 17 | 18 | -------------------------------------------------------------------------------- /operator/config/samples/kustomization.yaml: -------------------------------------------------------------------------------- 1 | ## Append samples you want in your CSV to this file as resources ## 2 | resources: 3 | - charts_v1alpha1_quarkussimple.yaml 4 | #+kubebuilder:scaffold:manifestskustomizesamples 5 | -------------------------------------------------------------------------------- /operator/config/scorecard/bases/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: scorecard.operatorframework.io/v1alpha3 2 | kind: Configuration 3 | metadata: 4 | name: config 5 | stages: 6 | - parallel: true 7 | tests: [] 8 | -------------------------------------------------------------------------------- /operator/config/scorecard/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - bases/config.yaml 3 | patchesJson6902: 4 | - path: patches/basic.config.yaml 5 | target: 6 | group: scorecard.operatorframework.io 7 | version: v1alpha3 8 | kind: Configuration 9 | name: config 10 | - path: patches/olm.config.yaml 11 | target: 12 | group: scorecard.operatorframework.io 13 | version: v1alpha3 14 | kind: Configuration 15 | name: config 16 | #+kubebuilder:scaffold:patchesJson6902 17 | -------------------------------------------------------------------------------- /operator/config/scorecard/patches/basic.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - basic-check-spec 7 | image: quay.io/operator-framework/scorecard-test:v1.7.2 8 | labels: 9 | suite: basic 10 | test: basic-check-spec-test 11 | -------------------------------------------------------------------------------- /operator/config/scorecard/patches/olm.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - olm-bundle-validation 7 | image: quay.io/operator-framework/scorecard-test:v1.7.2 8 | labels: 9 | suite: olm 10 | test: olm-bundle-validation-test 11 | - op: add 12 | path: /stages/0/tests/- 13 | value: 14 | entrypoint: 15 | - scorecard-test 16 | - olm-crds-have-validation 17 | image: quay.io/operator-framework/scorecard-test:v1.7.2 18 | labels: 19 | suite: olm 20 | test: olm-crds-have-validation-test 21 | - op: add 22 | path: /stages/0/tests/- 23 | value: 24 | entrypoint: 25 | - scorecard-test 26 | - olm-crds-have-resources 27 | image: quay.io/operator-framework/scorecard-test:v1.7.2 28 | labels: 29 | suite: olm 30 | test: olm-crds-have-resources-test 31 | - op: add 32 | path: /stages/0/tests/- 33 | value: 34 | entrypoint: 35 | - scorecard-test 36 | - olm-spec-descriptors 37 | image: quay.io/operator-framework/scorecard-test:v1.7.2 38 | labels: 39 | suite: olm 40 | test: olm-spec-descriptors-test 41 | - op: add 42 | path: /stages/0/tests/- 43 | value: 44 | entrypoint: 45 | - scorecard-test 46 | - olm-status-descriptors 47 | image: quay.io/operator-framework/scorecard-test:v1.7.2 48 | labels: 49 | suite: olm 50 | test: olm-status-descriptors-test 51 | -------------------------------------------------------------------------------- /operator/helm-charts/quarkus-simple/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | appVersion: 1.2.0 3 | description: A helm chart for the basic app described on https://www.opensourcerers.org/2021/04/26/automated-application-packaging-and-distribution-with-openshift-part-12/ 4 | home: https://github.com/wpernath/quarkus-simple 5 | maintainers: 6 | - email: wpernath@redhat.com 7 | name: Wanja Pernath 8 | name: quarkus-simple 9 | sources: 10 | - https://github.com/wpernath/quarkus-simple 11 | - https://www.opensourcerers.org/2021/04/26/automated-application-packaging-and-distribution-with-openshift-part-12/ 12 | - https://www.opensourcerers.org/2021/04/26/automated-application-packaging-and-distribution-with-openshift-part-22/ 13 | type: application 14 | version: 0.0.8 15 | -------------------------------------------------------------------------------- /operator/helm-charts/quarkus-simple/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 2 | # simple-quarkus 3 | 4 | This is the helm chart for the project. 5 | 6 | ## build and install the helm chart 7 | ```bash 8 | $ helm package helm -u 9 | $ helm install 10 | $ helm upgrade 11 | ``` 12 | 13 | 14 | ## To learn more about the release, try: 15 | 16 | ```bash 17 | $ helm status quarkus-simple 18 | $ helm get all quarkus-simple 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /operator/helm-charts/quarkus-simple/templates/config-map.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: app-config 5 | data: 6 | APP_GREETING: |- 7 | {{ .Values.config.greeting | default "Yeah, it's openshift time" }} 8 | -------------------------------------------------------------------------------- /operator/helm-charts/quarkus-simple/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: simple-quarkus-deployment 5 | spec: 6 | replicas: {{ .Values.deployment.replicas | default 1 }} 7 | selector: 8 | matchLabels: 9 | app: simple 10 | strategy: 11 | rollingUpdate: 12 | maxSurge: 25% 13 | maxUnavailable: 25% 14 | type: RollingUpdate 15 | template: 16 | metadata: 17 | labels: 18 | app: simple 19 | spec: 20 | containers: 21 | - name: simple 22 | image: "{{ .Values.deployment.image }}:{{ .Values.deployment.version }}" 23 | imagePullPolicy: Always 24 | {{- if .Values.deployment.includeHealthChecks }} 25 | readinessProbe: 26 | httpGet: 27 | path: /q/health/ready 28 | port: 8080 29 | scheme: HTTP 30 | timeoutSeconds: 1 31 | periodSeconds: 10 32 | successThreshold: 1 33 | failureThreshold: 3 34 | livenessProbe: 35 | httpGet: 36 | path: /q/health/live 37 | port: 8080 38 | scheme: HTTP 39 | timeoutSeconds: 2 40 | periodSeconds: 10 41 | successThreshold: 1 42 | failureThreshold: 3 43 | {{- end }} 44 | ports: 45 | - containerPort: 8080 46 | protocol: TCP 47 | envFrom: 48 | - configMapRef: 49 | name: app-config 50 | -------------------------------------------------------------------------------- /operator/helm-charts/quarkus-simple/templates/post-install-hook.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: "{{ .Release.Name }}" 5 | labels: 6 | app.kubernetes.io/managed-by: {{ .Release.Service | quote }} 7 | app.kubernetes.io/instance: {{ .Chart.Name | quote }} 8 | app.kubernetes.io/version: {{ .Chart.AppVersion }} 9 | "helm.sh/chart": "{{ .Chart.Name }}-{{ .Chart.Version }}" 10 | annotations: 11 | # This is what defines this resource as a hook. Without this line, the 12 | # job is considered part of the release. 13 | "helm.sh/hook": post-install,post-upgrade 14 | "helm.sh/hook-weight": "-5" 15 | "helm.sh/hook-delete-policy": before-hook-creation 16 | spec: 17 | template: 18 | metadata: 19 | name: {{ .Chart.Name }} 20 | labels: 21 | "helm.sh/chart": "{{ .Chart.Name }}-{{ .Chart.Version }}" 22 | spec: 23 | restartPolicy: Never 24 | containers: 25 | - name: post-install-job 26 | image: "registry.access.redhat.com/ubi8/ubi-minimal:latest" 27 | command: 28 | - /bin/sh 29 | - -c 30 | - | 31 | echo "WELCOME TO '{{ .Chart.Name }}-{{ .Chart.Version }}' " 32 | echo "-------------------------------------------------" 33 | echo "Here we could now do initialization work." 34 | echo "Like filling our DB with some data or what's so ever" 35 | echo "..." 36 | 37 | sleep 10 38 | 39 | 40 | -------------------------------------------------------------------------------- /operator/helm-charts/quarkus-simple/templates/route.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: route.openshift.io/v1 2 | kind: Route 3 | metadata: 4 | name: simple-quarkus-route 5 | spec: 6 | host: {{ .Values.route.host | default "paul.apps-crc.testing" }} 7 | port: 8 | targetPort: 8080-tcp 9 | to: 10 | kind: Service 11 | name: simple-quarkus 12 | weight: 100 13 | wildcardPolicy: None 14 | -------------------------------------------------------------------------------- /operator/helm-charts/quarkus-simple/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: simple 6 | name: simple-quarkus 7 | spec: 8 | ports: 9 | - name: 8080-tcp 10 | port: 8080 11 | protocol: TCP 12 | selector: 13 | app: simple 14 | -------------------------------------------------------------------------------- /operator/helm-charts/quarkus-simple/values.yaml: -------------------------------------------------------------------------------- 1 | deployment: 2 | image: quay.io/wpernath/simple-quarkus 3 | version: 1.2.0 4 | replicas: 1 5 | includeHealthChecks: true 6 | 7 | route: 8 | host: simple-article-helm.apps-crc.testing 9 | 10 | config: 11 | greeting: 'This needs to be changed per stage!' 12 | 13 | -------------------------------------------------------------------------------- /operator/watches.yaml: -------------------------------------------------------------------------------- 1 | # Use the 'create api' subcommand to add watches to this file. 2 | - group: charts.wanja.org 3 | version: v1alpha1 4 | kind: QuarkusSimple 5 | chart: helm-charts/quarkus-simple 6 | #+kubebuilder:scaffold:watch 7 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | org.wanja.quarkus 6 | simple-quarkus 7 | 1.0.1 8 | 9 | 3.8.1 10 | true 11 | 11 12 | 11 13 | UTF-8 14 | UTF-8 15 | 2.6.3.Final 16 | quarkus-universe-bom 17 | io.quarkus 18 | 2.6.3.Final 19 | 3.0.0-M5 20 | 21 | 22 | 23 | 24 | ${quarkus.platform.group-id} 25 | ${quarkus.platform.artifact-id} 26 | ${quarkus.platform.version} 27 | pom 28 | import 29 | 30 | 31 | 32 | 33 | 34 | com.github.javafaker 35 | javafaker 36 | 1.0.2 37 | 38 | 39 | io.quarkus 40 | quarkus-resteasy-qute 41 | 42 | 43 | io.quarkus 44 | quarkus-qute 45 | 46 | 47 | io.quarkus 48 | quarkus-resteasy-jsonb 49 | 50 | 51 | io.quarkus 52 | quarkus-resteasy 53 | 54 | 55 | io.quarkus 56 | quarkus-arc 57 | 58 | 59 | io.quarkus 60 | quarkus-junit5 61 | test 62 | 63 | 64 | io.rest-assured 65 | rest-assured 66 | test 67 | 68 | 69 | io.quarkus 70 | quarkus-smallrye-metrics 71 | 72 | 73 | io.quarkus 74 | quarkus-smallrye-health 75 | 76 | 77 | io.quarkus 78 | quarkus-smallrye-openapi 79 | 80 | 81 | io.quarkus 82 | quarkus-resteasy-jackson 83 | 84 | 85 | io.quarkus 86 | quarkus-rest-client-jackson 87 | 88 | 89 | io.quarkus 90 | quarkus-rest-client 91 | 92 | 93 | io.quarkus 94 | quarkus-container-image-jib 95 | 96 | 97 | 98 | 99 | 100 | io.quarkus 101 | quarkus-maven-plugin 102 | ${quarkus-plugin.version} 103 | true 104 | 105 | 106 | 107 | build 108 | generate-code 109 | generate-code-tests 110 | 111 | 112 | 113 | 114 | 115 | maven-compiler-plugin 116 | ${compiler-plugin.version} 117 | 118 | ${maven.compiler.parameters} 119 | 120 | 121 | 122 | maven-surefire-plugin 123 | ${surefire-plugin.version} 124 | 125 | 126 | org.jboss.logmanager.LogManager 127 | ${maven.home} 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | native 136 | 137 | 138 | native 139 | 140 | 141 | 142 | 143 | 144 | maven-failsafe-plugin 145 | ${surefire-plugin.version} 146 | 147 | 148 | 149 | integration-test 150 | verify 151 | 152 | 153 | 154 | ${project.build.directory}/${project.build.finalName}-runner 155 | org.jboss.logmanager.LogManager 156 | ${maven.home} 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | native 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /src/main/docker/Dockerfile.jvm: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode 3 | # 4 | # Before building the container image run: 5 | # 6 | # $> ./mvnw clean package -DskipTests 7 | # 8 | # Then, build the image with: 9 | # $> docker build -f src/main/docker/Dockerfile.jvm -t quay.io/wpernath/simple-quarkus . 10 | # 11 | # Push all image changes to quay.io 12 | # $> docker push quay.io/wpernath/simple-quarkus -a 13 | # 14 | # Create a stage image (and push changes with docker push) 15 | # $> docker tag quay.io/wpernath/simple-quarkus:latest quay.io/wpernath/simple-quarkus:stage 16 | # 17 | # Test run the container once 18 | # $> docker run -i -p 8080:8080 quay.io/wpernath/simple-quarkus:latest 19 | # 20 | # 21 | # 22 | ### 23 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4 24 | 25 | ARG JAVA_PACKAGE=java-11-openjdk-headless 26 | ARG RUN_JAVA_VERSION=1.3.8 27 | ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' 28 | # Install java and the run-java script 29 | # Also set up permissions for user `1001` 30 | RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ 31 | && microdnf update \ 32 | && microdnf clean all \ 33 | && mkdir /deployments \ 34 | && chown 1001 /deployments \ 35 | && chmod "g+rwX" /deployments \ 36 | && chown 1001:root /deployments \ 37 | && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ 38 | && chown 1001 /deployments/run-java.sh \ 39 | && chmod 540 /deployments/run-java.sh \ 40 | && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security 41 | 42 | # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. 43 | ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" 44 | # We make four distinct layers so if there are application changes the library layers can be re-used 45 | COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/ 46 | COPY --chown=1001 target/quarkus-app/*.jar /deployments/ 47 | COPY --chown=1001 target/quarkus-app/app/ /deployments/app/ 48 | COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/ 49 | 50 | EXPOSE 8080 51 | USER 1001 52 | 53 | ENTRYPOINT [ "/deployments/run-java.sh" ] 54 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/GreetingResource.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus; 2 | 3 | import javax.ws.rs.GET; 4 | import javax.ws.rs.Path; 5 | import javax.ws.rs.Produces; 6 | import javax.ws.rs.core.MediaType; 7 | 8 | import org.eclipse.microprofile.config.inject.ConfigProperty; 9 | 10 | @Path("/hello") 11 | public class GreetingResource { 12 | 13 | @ConfigProperty(name = "app.greeting", defaultValue = "Hello, Hi and welcome") 14 | String message; 15 | 16 | @GET 17 | @Produces(MediaType.TEXT_PLAIN) 18 | public String hello() { 19 | return message; 20 | } 21 | } -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/HttpHandler.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus; 2 | 3 | import java.io.IOException; 4 | import java.net.URI; 5 | import java.net.http.HttpClient; 6 | import java.net.http.HttpRequest; 7 | import java.net.http.HttpResponse; 8 | import java.util.concurrent.ExecutorService; 9 | import java.util.concurrent.Executors; 10 | 11 | import javax.enterprise.context.ApplicationScoped; 12 | import javax.ws.rs.core.MediaType; 13 | 14 | @ApplicationScoped 15 | public class HttpHandler { 16 | 17 | public static HttpHandler getInstance() { 18 | return new HttpHandler(); 19 | } 20 | 21 | 22 | private final ExecutorService service = Executors.newFixedThreadPool(5); 23 | private final HttpClient client = HttpClient.newBuilder().executor(service).version(HttpClient.Version.HTTP_2) 24 | .build(); 25 | 26 | public String readRkiModel(String where) throws IOException { 27 | try { 28 | HttpResponse body = client.send(HttpRequest.newBuilder().GET().uri(URI.create(where)).header("Accept", MediaType.APPLICATION_JSON).build(), HttpResponse.BodyHandlers.ofString()); 29 | return body.body().toString(); 30 | } 31 | catch (InterruptedException e) { 32 | // TODO Auto-generated catch block 33 | e.printStackTrace(); 34 | } 35 | return "404/Not FOund"; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/NameFakerResource.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus; 2 | 3 | import javax.ws.rs.Produces; 4 | import javax.ws.rs.GET; 5 | import javax.ws.rs.Path; 6 | import javax.ws.rs.core.MediaType; 7 | 8 | import com.github.javafaker.Faker; 9 | 10 | @Path("/faker") 11 | @Produces(MediaType.TEXT_PLAIN) 12 | public class NameFakerResource { 13 | 14 | @GET 15 | public String fake() { 16 | Faker f = new Faker(); 17 | return f.ancient().hero()+"-"+f.app().name(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/RkiDataGrabberResource.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus; 2 | 3 | import javax.inject.Inject; 4 | import javax.ws.rs.Consumes; 5 | import javax.ws.rs.GET; 6 | import javax.ws.rs.Path; 7 | import javax.ws.rs.Produces; 8 | import javax.ws.rs.core.MediaType; 9 | 10 | import org.eclipse.microprofile.rest.client.inject.RestClient; 11 | import org.wanja.quarkus.model.*; 12 | 13 | @Path("/rki") 14 | public class RkiDataGrabberResource { 15 | /* 16 | Reading JSON Data via 17 | https://services7.arcgis.com/mOBPykOjAyBO2ZKk/arcgis/rest/services/RKI_Landkreisdaten/FeatureServer/0/query?where=1%3D1&outFields=OBJECTID,death_rate,cases,deaths,cases_per_100k,cases_per_population,BL,BL_ID,county,last_update,cases7_per_100k,EWZ_BL,cases7_bl_per_100k,cases7_bl,death7_bl,cases7_lk,death7_lk,cases7_per_100k_txt&returnGeometry=false&outSR=4326&f=json 18 | */ 19 | 20 | @Inject 21 | @RestClient 22 | RkiDataGrabberService dataGrabber; 23 | 24 | @GET 25 | @Produces(MediaType.APPLICATION_JSON) 26 | @Consumes(MediaType.APPLICATION_JSON) 27 | public RkiModel fetch() { 28 | RkiModel paul = dataGrabber.fetchAll(); 29 | if( paul != null && paul.getFeatures() != null) { 30 | System.out.println("YAYYYYY!!!!!!!"); 31 | } 32 | return dataGrabber.fetchAll(); 33 | } 34 | 35 | 36 | } -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/RkiDataGrabberService.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus; 2 | 3 | 4 | import javax.ws.rs.Consumes; 5 | import javax.ws.rs.GET; 6 | import javax.ws.rs.Path; 7 | import javax.ws.rs.Produces; 8 | import javax.ws.rs.core.MediaType; 9 | 10 | import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; 11 | 12 | import org.wanja.quarkus.model.*; 13 | 14 | @RegisterRestClient(configKey = "rki-api") 15 | @Path("/") 16 | public interface RkiDataGrabberService { 17 | 18 | @GET 19 | @Produces(MediaType.APPLICATION_JSON) 20 | @Consumes(MediaType.APPLICATION_JSON) 21 | public RkiModel fetchAll(); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/RkiQuteReaderResource.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.inject.Inject; 6 | import javax.ws.rs.GET; 7 | import javax.ws.rs.Path; 8 | import javax.ws.rs.Produces; 9 | import javax.ws.rs.core.MediaType; 10 | 11 | import org.eclipse.microprofile.config.inject.ConfigProperty; 12 | import org.wanja.quarkus.model.*; 13 | 14 | import io.quarkus.qute.Template; 15 | import io.quarkus.qute.TemplateInstance; 16 | 17 | @Path("qute-report") 18 | public class RkiQuteReaderResource { 19 | 20 | @ConfigProperty(name = "rki-api/mp-rest/url") 21 | String baseURL; 22 | 23 | @Inject 24 | Template rkiQuteReader; 25 | 26 | @GET 27 | @Produces(MediaType.TEXT_PLAIN) 28 | public TemplateInstance list() throws IOException { 29 | RkiModel model = Converter.fromJsonString(HttpHandler.getInstance().readRkiModel(baseURL)); 30 | return rkiQuteReader.data("list", model.getFeatures()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/RkiReaderResource.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus; 2 | 3 | import java.io.IOException; 4 | import java.text.NumberFormat; 5 | import java.util.Iterator; 6 | 7 | import javax.ws.rs.GET; 8 | import javax.ws.rs.Path; 9 | import javax.ws.rs.Produces; 10 | import javax.ws.rs.core.MediaType; 11 | 12 | import org.eclipse.microprofile.config.inject.ConfigProperty; 13 | import org.wanja.quarkus.model.*; 14 | 15 | @Path("/reader") 16 | public class RkiReaderResource { 17 | 18 | @ConfigProperty(name = "rki-api/mp-rest/url") 19 | String baseURL; 20 | 21 | 22 | @GET 23 | @Produces(MediaType.TEXT_PLAIN) 24 | public String read() throws IOException { 25 | String body = HttpHandler.getInstance().readRkiModel(baseURL); 26 | RkiModel model = Converter.fromJsonString(body); 27 | 28 | if (model != null) { 29 | Iterator itr = model.getFeatures().iterator(); 30 | Feature f; 31 | StringBuffer sb = new StringBuffer(); 32 | NumberFormat intFormat = NumberFormat.getIntegerInstance(); 33 | NumberFormat dec = NumberFormat.getNumberInstance(); 34 | 35 | while(itr.hasNext() ){ 36 | f = itr.next(); 37 | Attributes attr = f.getAttributes(); 38 | sb.append(attr.getCounty()) 39 | .append(" (") 40 | .append(attr.getBl().toValue()) 41 | .append(")").append(" = (") 42 | .append(intFormat.format(attr.getCases())) 43 | .append(" / ") 44 | .append(intFormat.format(attr.getDeaths())) 45 | .append(" / ") 46 | .append(dec.format(attr.getCases7BlPer100K())) 47 | .append(" -- ").append(attr.getLastUpdate()) 48 | .append(")\n"); 49 | } 50 | 51 | return sb.toString(); 52 | } 53 | return "DOES NOT WORK; DAMN!"; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/RkiReportResource.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.inject.Inject; 6 | import javax.ws.rs.GET; 7 | import javax.ws.rs.Path; 8 | import javax.ws.rs.Produces; 9 | import javax.ws.rs.core.MediaType; 10 | 11 | import org.eclipse.microprofile.config.inject.ConfigProperty; 12 | import org.wanja.quarkus.model.*; 13 | 14 | import io.quarkus.qute.Template; 15 | import io.quarkus.qute.TemplateInstance; 16 | 17 | @Path("report") 18 | public class RkiReportResource { 19 | 20 | @ConfigProperty(name = "rki-api/mp-rest/url") 21 | String baseURL; 22 | 23 | @Inject 24 | Template rkiReport; 25 | 26 | @GET 27 | @Produces(MediaType.TEXT_HTML) 28 | public TemplateInstance list() throws IOException { 29 | RkiModel model = Converter.fromJsonString(HttpHandler.getInstance().readRkiModel(baseURL)); 30 | return rkiReport.data("list", model.getFeatures()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/model/Attributes.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus.model; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | 5 | public class Attributes { 6 | private long objectid; 7 | private double deathRate; 8 | private long cases; 9 | private long deaths; 10 | private double casesPer100K; 11 | private double casesPerPopulation; 12 | private Bl bl; 13 | private String blID; 14 | private String county; 15 | private String lastUpdate; 16 | private double cases7Per100K; 17 | private long ewzBl; 18 | private double cases7BlPer100K; 19 | private long cases7Bl; 20 | private long death7Bl; 21 | private long cases7Lk; 22 | private long death7Lk; 23 | private String cases7Per100KTxt; 24 | 25 | @JsonProperty("OBJECTID") 26 | public long getObjectid() { return objectid; } 27 | @JsonProperty("OBJECTID") 28 | public void setObjectid(long value) { this.objectid = value; } 29 | 30 | @JsonProperty("death_rate") 31 | public double getDeathRate() { return deathRate; } 32 | @JsonProperty("death_rate") 33 | public void setDeathRate(double value) { this.deathRate = value; } 34 | 35 | @JsonProperty("cases") 36 | public long getCases() { return cases; } 37 | @JsonProperty("cases") 38 | public void setCases(long value) { this.cases = value; } 39 | 40 | @JsonProperty("deaths") 41 | public long getDeaths() { return deaths; } 42 | @JsonProperty("deaths") 43 | public void setDeaths(long value) { this.deaths = value; } 44 | 45 | @JsonProperty("cases_per_100k") 46 | public double getCasesPer100K() { return casesPer100K; } 47 | @JsonProperty("cases_per_100k") 48 | public void setCasesPer100K(double value) { this.casesPer100K = value; } 49 | 50 | @JsonProperty("cases_per_population") 51 | public double getCasesPerPopulation() { return casesPerPopulation; } 52 | @JsonProperty("cases_per_population") 53 | public void setCasesPerPopulation(double value) { this.casesPerPopulation = value; } 54 | 55 | @JsonProperty("BL") 56 | public Bl getBl() { return bl; } 57 | @JsonProperty("BL") 58 | public void setBl(Bl value) { this.bl = value; } 59 | 60 | @JsonProperty("BL_ID") 61 | public String getBlID() { return blID; } 62 | @JsonProperty("BL_ID") 63 | public void setBlID(String value) { this.blID = value; } 64 | 65 | @JsonProperty("county") 66 | public String getCounty() { return county; } 67 | @JsonProperty("county") 68 | public void setCounty(String value) { this.county = value; } 69 | 70 | @JsonProperty("last_update") 71 | public String getLastUpdate() { return lastUpdate; } 72 | @JsonProperty("last_update") 73 | public void setLastUpdate(String value) { this.lastUpdate = value; } 74 | 75 | @JsonProperty("cases7_per_100k") 76 | public double getCases7Per100K() { return cases7Per100K; } 77 | @JsonProperty("cases7_per_100k") 78 | public void setCases7Per100K(double value) { this.cases7Per100K = value; } 79 | 80 | @JsonProperty("EWZ_BL") 81 | public long getEwzBl() { return ewzBl; } 82 | @JsonProperty("EWZ_BL") 83 | public void setEwzBl(long value) { this.ewzBl = value; } 84 | 85 | @JsonProperty("cases7_bl_per_100k") 86 | public double getCases7BlPer100K() { return cases7BlPer100K; } 87 | @JsonProperty("cases7_bl_per_100k") 88 | public void setCases7BlPer100K(double value) { this.cases7BlPer100K = value; } 89 | 90 | @JsonProperty("cases7_bl") 91 | public long getCases7Bl() { return cases7Bl; } 92 | @JsonProperty("cases7_bl") 93 | public void setCases7Bl(long value) { this.cases7Bl = value; } 94 | 95 | @JsonProperty("death7_bl") 96 | public long getDeath7Bl() { return death7Bl; } 97 | @JsonProperty("death7_bl") 98 | public void setDeath7Bl(long value) { this.death7Bl = value; } 99 | 100 | @JsonProperty("cases7_lk") 101 | public long getCases7Lk() { return cases7Lk; } 102 | @JsonProperty("cases7_lk") 103 | public void setCases7Lk(long value) { this.cases7Lk = value; } 104 | 105 | @JsonProperty("death7_lk") 106 | public long getDeath7Lk() { return death7Lk; } 107 | @JsonProperty("death7_lk") 108 | public void setDeath7Lk(long value) { this.death7Lk = value; } 109 | 110 | @JsonProperty("cases7_per_100k_txt") 111 | public String getCases7Per100KTxt() { return cases7Per100KTxt; } 112 | @JsonProperty("cases7_per_100k_txt") 113 | public void setCases7Per100KTxt(String value) { this.cases7Per100KTxt = value; } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/model/Bl.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus.model; 2 | 3 | import java.io.IOException; 4 | import com.fasterxml.jackson.annotation.*; 5 | 6 | public enum Bl { 7 | BADEN_WRTTEMBERG, BAYERN, BERLIN, BRANDENBURG, BREMEN, HAMBURG, HESSEN, MECKLENBURG_VORPOMMERN, NIEDERSACHSEN, NORDRHEIN_WESTFALEN, RHEINLAND_PFALZ, SAARLAND, SACHSEN, SACHSEN_ANHALT, SCHLESWIG_HOLSTEIN, THRINGEN; 8 | 9 | @JsonValue 10 | public String toValue() { 11 | switch (this) { 12 | case BADEN_WRTTEMBERG: return "Baden-Württemberg"; 13 | case BAYERN: return "Bayern"; 14 | case BERLIN: return "Berlin"; 15 | case BRANDENBURG: return "Brandenburg"; 16 | case BREMEN: return "Bremen"; 17 | case HAMBURG: return "Hamburg"; 18 | case HESSEN: return "Hessen"; 19 | case MECKLENBURG_VORPOMMERN: return "Mecklenburg-Vorpommern"; 20 | case NIEDERSACHSEN: return "Niedersachsen"; 21 | case NORDRHEIN_WESTFALEN: return "Nordrhein-Westfalen"; 22 | case RHEINLAND_PFALZ: return "Rheinland-Pfalz"; 23 | case SAARLAND: return "Saarland"; 24 | case SACHSEN: return "Sachsen"; 25 | case SACHSEN_ANHALT: return "Sachsen-Anhalt"; 26 | case SCHLESWIG_HOLSTEIN: return "Schleswig-Holstein"; 27 | case THRINGEN: return "Thüringen"; 28 | } 29 | return null; 30 | } 31 | 32 | @JsonCreator 33 | public static Bl forValue(String value) throws IOException { 34 | if (value.equals("Baden-Württemberg")) return BADEN_WRTTEMBERG; 35 | if (value.equals("Bayern")) return BAYERN; 36 | if (value.equals("Berlin")) return BERLIN; 37 | if (value.equals("Brandenburg")) return BRANDENBURG; 38 | if (value.equals("Bremen")) return BREMEN; 39 | if (value.equals("Hamburg")) return HAMBURG; 40 | if (value.equals("Hessen")) return HESSEN; 41 | if (value.equals("Mecklenburg-Vorpommern")) return MECKLENBURG_VORPOMMERN; 42 | if (value.equals("Niedersachsen")) return NIEDERSACHSEN; 43 | if (value.equals("Nordrhein-Westfalen")) return NORDRHEIN_WESTFALEN; 44 | if (value.equals("Rheinland-Pfalz")) return RHEINLAND_PFALZ; 45 | if (value.equals("Saarland")) return SAARLAND; 46 | if (value.equals("Sachsen")) return SACHSEN; 47 | if (value.equals("Sachsen-Anhalt")) return SACHSEN_ANHALT; 48 | if (value.equals("Schleswig-Holstein")) return SCHLESWIG_HOLSTEIN; 49 | if (value.equals("Thüringen")) return THRINGEN; 50 | throw new IOException("Cannot deserialize Bl"); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/model/Converter.java: -------------------------------------------------------------------------------- 1 | // To use this code, add the following Maven dependency to your project: 2 | // 3 | // 4 | // com.fasterxml.jackson.core : jackson-databind : 2.9.0 5 | // com.fasterxml.jackson.datatype : jackson-datatype-jsr310 : 2.9.0 6 | // 7 | // Import this package: 8 | // 9 | // import org.wanja.quarkus.Converter; 10 | // 11 | // Then you can deserialize a JSON string with 12 | // 13 | // RkiModel data = Converter.fromJsonString(jsonString); 14 | 15 | package org.wanja.quarkus.model; 16 | 17 | import java.io.IOException; 18 | import com.fasterxml.jackson.databind.*; 19 | import com.fasterxml.jackson.databind.module.SimpleModule; 20 | import com.fasterxml.jackson.core.JsonParser; 21 | import com.fasterxml.jackson.core.JsonProcessingException; 22 | import java.time.OffsetDateTime; 23 | import java.time.OffsetTime; 24 | import java.time.ZoneOffset; 25 | import java.time.ZonedDateTime; 26 | import java.time.format.DateTimeFormatter; 27 | import java.time.format.DateTimeFormatterBuilder; 28 | import java.time.temporal.ChronoField; 29 | 30 | public class Converter { 31 | // Date-time helpers 32 | 33 | private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder() 34 | .appendOptional(DateTimeFormatter.ISO_DATE_TIME) 35 | .appendOptional(DateTimeFormatter.ISO_OFFSET_DATE_TIME) 36 | .appendOptional(DateTimeFormatter.ISO_INSTANT) 37 | .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SX")) 38 | .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssX")) 39 | .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) 40 | .toFormatter() 41 | .withZone(ZoneOffset.UTC); 42 | 43 | public static OffsetDateTime parseDateTimeString(String str) { 44 | return ZonedDateTime.from(Converter.DATE_TIME_FORMATTER.parse(str)).toOffsetDateTime(); 45 | } 46 | 47 | private static final DateTimeFormatter TIME_FORMATTER = new DateTimeFormatterBuilder() 48 | .appendOptional(DateTimeFormatter.ISO_TIME) 49 | .appendOptional(DateTimeFormatter.ISO_OFFSET_TIME) 50 | .parseDefaulting(ChronoField.YEAR, 2020) 51 | .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1) 52 | .parseDefaulting(ChronoField.DAY_OF_MONTH, 1) 53 | .toFormatter() 54 | .withZone(ZoneOffset.UTC); 55 | 56 | public static OffsetTime parseTimeString(String str) { 57 | return ZonedDateTime.from(Converter.TIME_FORMATTER.parse(str)).toOffsetDateTime().toOffsetTime(); 58 | } 59 | // Serialize/deserialize helpers 60 | 61 | public static RkiModel fromJsonString(String json) throws IOException { 62 | return getObjectReader().readValue(json); 63 | } 64 | 65 | public static String toJsonString(RkiModel obj) throws JsonProcessingException { 66 | return getObjectWriter().writeValueAsString(obj); 67 | } 68 | 69 | private static ObjectReader reader; 70 | private static ObjectWriter writer; 71 | 72 | private static void instantiateMapper() { 73 | ObjectMapper mapper = new ObjectMapper(); 74 | mapper.findAndRegisterModules(); 75 | mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); 76 | SimpleModule module = new SimpleModule(); 77 | module.addDeserializer(OffsetDateTime.class, new JsonDeserializer() { 78 | @Override 79 | public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { 80 | String value = jsonParser.getText(); 81 | return Converter.parseDateTimeString(value); 82 | } 83 | }); 84 | mapper.registerModule(module); 85 | reader = mapper.readerFor(RkiModel.class); 86 | writer = mapper.writerFor(RkiModel.class); 87 | } 88 | 89 | private static ObjectReader getObjectReader() { 90 | if (reader == null) instantiateMapper(); 91 | return reader; 92 | } 93 | 94 | private static ObjectWriter getObjectWriter() { 95 | if (writer == null) instantiateMapper(); 96 | return writer; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/model/Feature.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus.model; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | 5 | public class Feature { 6 | private Attributes attributes; 7 | 8 | @JsonProperty("attributes") 9 | public Attributes getAttributes() { return attributes; } 10 | @JsonProperty("attributes") 11 | public void setAttributes(Attributes value) { this.attributes = value; } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/model/Field.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus.model; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | 5 | public class Field { 6 | private String name; 7 | private Type type; 8 | private String alias; 9 | private SQLType sqlType; 10 | private Object domain; 11 | private Object defaultValue; 12 | private Long length; 13 | 14 | @JsonProperty("name") 15 | public String getName() { return name; } 16 | @JsonProperty("name") 17 | public void setName(String value) { this.name = value; } 18 | 19 | @JsonProperty("type") 20 | public Type getType() { return type; } 21 | @JsonProperty("type") 22 | public void setType(Type value) { this.type = value; } 23 | 24 | @JsonProperty("alias") 25 | public String getAlias() { return alias; } 26 | @JsonProperty("alias") 27 | public void setAlias(String value) { this.alias = value; } 28 | 29 | @JsonProperty("sqlType") 30 | public SQLType getSQLType() { return sqlType; } 31 | @JsonProperty("sqlType") 32 | public void setSQLType(SQLType value) { this.sqlType = value; } 33 | 34 | @JsonProperty("domain") 35 | public Object getDomain() { return domain; } 36 | @JsonProperty("domain") 37 | public void setDomain(Object value) { this.domain = value; } 38 | 39 | @JsonProperty("defaultValue") 40 | public Object getDefaultValue() { return defaultValue; } 41 | @JsonProperty("defaultValue") 42 | public void setDefaultValue(Object value) { this.defaultValue = value; } 43 | 44 | @JsonProperty("length") 45 | public Long getLength() { return length; } 46 | @JsonProperty("length") 47 | public void setLength(Long value) { this.length = value; } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/model/LastUpdate.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus.model; 2 | import java.io.IOException; 3 | import com.fasterxml.jackson.annotation.*; 4 | 5 | public enum LastUpdate { 6 | THE_250420210000_UHR; 7 | 8 | @JsonValue 9 | public String toValue() { 10 | switch (this) { 11 | case THE_250420210000_UHR: return "25.04.2021, 00:00 Uhr"; 12 | } 13 | return null; 14 | } 15 | 16 | @JsonCreator 17 | public static LastUpdate forValue(String value) throws IOException { 18 | if (value.equals("25.04.2021, 00:00 Uhr")) return THE_250420210000_UHR; 19 | throw new IOException("Cannot deserialize LastUpdate"); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/model/RkiModel.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus.model; 2 | import com.fasterxml.jackson.annotation.*; 3 | import java.util.List; 4 | 5 | public class RkiModel { 6 | private String objectIDFieldName; 7 | private UniqueIDField uniqueIDField; 8 | private String globalIDFieldName; 9 | private String geometryType; 10 | private SpatialReference spatialReference; 11 | private List fields; 12 | private List features; 13 | 14 | @JsonProperty("objectIdFieldName") 15 | public String getObjectIDFieldName() { return objectIDFieldName; } 16 | @JsonProperty("objectIdFieldName") 17 | public void setObjectIDFieldName(String value) { this.objectIDFieldName = value; } 18 | 19 | @JsonProperty("uniqueIdField") 20 | public UniqueIDField getUniqueIDField() { return uniqueIDField; } 21 | @JsonProperty("uniqueIdField") 22 | public void setUniqueIDField(UniqueIDField value) { this.uniqueIDField = value; } 23 | 24 | @JsonProperty("globalIdFieldName") 25 | public String getGlobalIDFieldName() { return globalIDFieldName; } 26 | @JsonProperty("globalIdFieldName") 27 | public void setGlobalIDFieldName(String value) { this.globalIDFieldName = value; } 28 | 29 | @JsonProperty("geometryType") 30 | public String getGeometryType() { return geometryType; } 31 | @JsonProperty("geometryType") 32 | public void setGeometryType(String value) { this.geometryType = value; } 33 | 34 | @JsonProperty("spatialReference") 35 | public SpatialReference getSpatialReference() { return spatialReference; } 36 | @JsonProperty("spatialReference") 37 | public void setSpatialReference(SpatialReference value) { this.spatialReference = value; } 38 | 39 | @JsonProperty("fields") 40 | public List getFields() { return fields; } 41 | @JsonProperty("fields") 42 | public void setFields(List value) { this.fields = value; } 43 | 44 | @JsonProperty("features") 45 | public List getFeatures() { return features; } 46 | @JsonProperty("features") 47 | public void setFeatures(List value) { this.features = value; } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/model/SQLType.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus.model; 2 | 3 | import java.io.IOException; 4 | import com.fasterxml.jackson.annotation.*; 5 | 6 | public enum SQLType { 7 | SQL_TYPE_OTHER; 8 | 9 | @JsonValue 10 | public String toValue() { 11 | switch (this) { 12 | case SQL_TYPE_OTHER: return "sqlTypeOther"; 13 | } 14 | return null; 15 | } 16 | 17 | @JsonCreator 18 | public static SQLType forValue(String value) throws IOException { 19 | if (value.equals("sqlTypeOther")) return SQL_TYPE_OTHER; 20 | throw new IOException("Cannot deserialize SQLType"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/model/SpatialReference.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus.model; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | 5 | public class SpatialReference { 6 | private long wkid; 7 | private long latestWkid; 8 | 9 | @JsonProperty("wkid") 10 | public long getWkid() { return wkid; } 11 | @JsonProperty("wkid") 12 | public void setWkid(long value) { this.wkid = value; } 13 | 14 | @JsonProperty("latestWkid") 15 | public long getLatestWkid() { return latestWkid; } 16 | @JsonProperty("latestWkid") 17 | public void setLatestWkid(long value) { this.latestWkid = value; } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/model/Type.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus.model; 2 | 3 | import java.io.IOException; 4 | import com.fasterxml.jackson.annotation.*; 5 | 6 | public enum Type { 7 | ESRI_FIELD_TYPE_DOUBLE, ESRI_FIELD_TYPE_INTEGER, ESRI_FIELD_TYPE_OID, ESRI_FIELD_TYPE_STRING; 8 | 9 | @JsonValue 10 | public String toValue() { 11 | switch (this) { 12 | case ESRI_FIELD_TYPE_DOUBLE: return "esriFieldTypeDouble"; 13 | case ESRI_FIELD_TYPE_INTEGER: return "esriFieldTypeInteger"; 14 | case ESRI_FIELD_TYPE_OID: return "esriFieldTypeOID"; 15 | case ESRI_FIELD_TYPE_STRING: return "esriFieldTypeString"; 16 | } 17 | return null; 18 | } 19 | 20 | @JsonCreator 21 | public static Type forValue(String value) throws IOException { 22 | if (value.equals("esriFieldTypeDouble")) return ESRI_FIELD_TYPE_DOUBLE; 23 | if (value.equals("esriFieldTypeInteger")) return ESRI_FIELD_TYPE_INTEGER; 24 | if (value.equals("esriFieldTypeOID")) return ESRI_FIELD_TYPE_OID; 25 | if (value.equals("esriFieldTypeString")) return ESRI_FIELD_TYPE_STRING; 26 | throw new IOException("Cannot deserialize Type"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/wanja/quarkus/model/UniqueIDField.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus.model; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | 5 | public class UniqueIDField { 6 | private String name; 7 | private boolean isSystemMaintained; 8 | 9 | @JsonProperty("name") 10 | public String getName() { return name; } 11 | @JsonProperty("name") 12 | public void setName(String value) { this.name = value; } 13 | 14 | @JsonProperty("isSystemMaintained") 15 | public boolean getIsSystemMaintained() { return isSystemMaintained; } 16 | @JsonProperty("isSystemMaintained") 17 | public void setIsSystemMaintained(boolean value) { this.isSystemMaintained = value; } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | simple-quarkus - DEVELOPER 6 | 108 | 109 | 110 | 111 | 112 | Your new Kubernetes-Native application is ready! 113 | 114 | 115 | 116 | 117 | Congratulations, this is a very simple quarkus application 118 | 119 | This page is still under construction. 120 | 121 | 122 | 123 | Information 124 | 125 | This is a very simple demo application for the article series on OpenSourcerers 126 | Part #1: Templates & Kustomize 127 | Part #2: Helm Charts & Operators 128 | Part #3: Tekton Pipelines 129 | Part #4: Managing GitOps with ArgoCD and Tekton 130 | 131 | 132 | 133 | You can find the code on GitHub 134 | 135 | 136 | 137 | This application is using the smallrye health quarkus extensions 138 | for liveness and readyness probes. 139 | 140 | 141 | 142 | The docker images can be found on quay.io 143 | 144 | 145 | Services 146 | 147 | 148 | The following endpoints are available: 149 | 150 | /q/health/live Lifeness check via smallrye 151 | /q/health/ready Readyness check via smallrye 152 | /q/metrics Metrics via smallrye 153 | /hello The app 154 | /faker The fake name generator app 155 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | Application 165 | 166 | GroupId: org.wanja.quarkus 167 | ArtifactId: simple-quarkus 168 | Version: 1.0.1 169 | Quarkus Version: 2.6.3.Final 170 | 171 | 172 | 173 | 174 | 175 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # quarkus container image commands 2 | quarkus.container-image.build=false 3 | quarkus.container-image.push=false 4 | quarkus.container-image.builder=jib 5 | quarkus.container-image.registry=quay.io 6 | quarkus.container-image.image=quay.io/wpernath/simple-quarkus 7 | #quarkus.jib.base-jvm-image=registry.access.redhat.com/ubi8/ubi-minimal:8.4 8 | 9 | # rest easy client 10 | rki-api/mp-rest/url=https://services7.arcgis.com/mOBPykOjAyBO2ZKk/arcgis/rest/services/RKI_Landkreisdaten/FeatureServer/0/query?where=1%3D1&outFields=OBJECTID,death_rate,cases,deaths,cases_per_100k,cases_per_population,BL,BL_ID,county,last_update,cases7_per_100k,EWZ_BL,cases7_bl_per_100k,cases7_bl,death7_bl,cases7_lk,death7_lk,cases7_per_100k_txt&returnGeometry=false&outSR=4326&f=json 11 | rki-api/mp-rest/scope=javax.inject.Singleton 12 | rki-api/mp-rest/hostnameVerifier=io.quarkus.restclient.NoopHostnameVerifier 13 | quarkus.tls.trust-all=true 14 | 15 | # welcome greeting 16 | app.greeting=Hello and Welcome to the Article "Application Packaging and Distribution" 17 | -------------------------------------------------------------------------------- /src/main/resources/templates/rkiQuteReader.txt: -------------------------------------------------------------------------------- 1 | #Bundesland,Landkreis,Erkrankungen,Tote,Inzidenz 2 | #{#for feature in list} 3 | #{feature.attributes.bl.toValue},{feature.attributes.county},{feature.attributes.cases},{feature.attributes.deaths},{feature.attributes.cases7Per100KTxt} 4 | #{/for} 5 | 6 | # states 7 | {#for feature in list} 8 | insert into state(id, name) values ((nextval('hibernate_sequence'), '{feature.attributes.bl.toValue}'); 9 | {/for} 10 | 11 | # counties 12 | {#for feature in list} 13 | insert into county(id, name, state_name) values ((nextval('hibernate_sequence'), '{feature.attributes.county}', '{feature.attributes.bl.toValue}'); 14 | {/for} 15 | -------------------------------------------------------------------------------- /src/main/resources/templates/rkiReport.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | simple-quarkus - COVID-19 7 | 135 | 136 | 137 | 138 | 139 | 140 | COVID-19 data of Robert Koch Institut 141 | 142 | 143 | 144 | 145 | Germany, COVID-19 146 | 147 | 148 | 149 | Bundesland 150 | Landkreis 151 | Erkrankungen 152 | Tote 153 | Akt. Inzidenz 154 | 155 | 156 | {#for feature in list} 157 | 158 | {feature.attributes.bl.toValue} 159 | {feature.attributes.county} 160 | {feature.attributes.cases} 161 | {feature.attributes.deaths} 162 | {feature.attributes.cases7Per100KTxt} 163 | 164 | {/for} 165 | 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /src/test/java/org/wanja/quarkus/GreetingResourceTest.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus; 2 | 3 | import io.quarkus.test.junit.QuarkusTest; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import static io.restassured.RestAssured.given; 7 | import static org.hamcrest.CoreMatchers.is; 8 | 9 | @QuarkusTest 10 | public class GreetingResourceTest { 11 | 12 | @Test 13 | public void testHelloEndpoint() { 14 | given() 15 | .when().get("/hello-resteasy") 16 | .then() 17 | .statusCode(200) 18 | .body(is("Hello RESTEasy")); 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /src/test/java/org/wanja/quarkus/NativeGreetingResourceIT.java: -------------------------------------------------------------------------------- 1 | package org.wanja.quarkus; 2 | 3 | import io.quarkus.test.junit.NativeImageTest; 4 | 5 | @NativeImageTest 6 | public class NativeGreetingResourceIT extends GreetingResourceTest { 7 | 8 | // Execute the same tests but in native mode. 9 | } -------------------------------------------------------------------------------- /tektondev/infra/maven-artifact-cache-pvc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: maven-repo-pvc 5 | spec: 6 | resources: 7 | requests: 8 | storage: 10Gi 9 | volumeMode: Filesystem 10 | accessModes: 11 | - ReadWriteOnce 12 | - ReadWriteMany 13 | persistentVolumeReclaimPolicy: Retain 14 | --- 15 | apiVersion: v1 16 | kind: PersistentVolumeClaim 17 | metadata: 18 | name: builder-pvc 19 | spec: 20 | resources: 21 | requests: 22 | storage: 10Gi 23 | volumeMode: Filesystem 24 | accessModes: 25 | - ReadWriteOnce 26 | - ReadWriteMany 27 | persistentVolumeReclaimPolicy: Retain 28 | -------------------------------------------------------------------------------- /tektondev/infra/maven-settings-cm.yaml: -------------------------------------------------------------------------------- 1 | kind: ConfigMap 2 | apiVersion: v1 3 | metadata: 4 | name: maven-settings 5 | data: 6 | settings.xml: | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | all 18 | http://nexus.ci.svc:8081/repository/maven-public 19 | * 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /tektondev/pipeline.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This starts the pipeline new-pipeline with a given 3 | 4 | set -e -u -o pipefail 5 | declare -r SCRIPT_DIR=$(cd -P $(dirname $0) && pwd) 6 | declare COMMAND="help" 7 | 8 | GIT_URL=https://github.com/wpernath/quarkus-simple.git 9 | GIT_REVISION=main 10 | PIPELINE=new-pipeline 11 | CONTEXT_DIR=the-source 12 | IMAGE_NAME=quay.io/wpernath/quarkus-simple-wow 13 | IMAGE_USER=wpernath 14 | IMAGE_PASSWORD= 15 | TARGET_NAMESPACE=art-tekton 16 | 17 | valid_command() { 18 | local fn=$1; shift 19 | [[ $(type -t "$fn") == "function" ]] 20 | } 21 | 22 | info() { 23 | printf "\n# INFO: $@\n" 24 | } 25 | 26 | err() { 27 | printf "\n# ERROR: $1\n" 28 | exit 1 29 | } 30 | 31 | command.help() { 32 | cat <<-EOF 33 | Starts a new pipeline in current kubernetes context 34 | 35 | Usage: 36 | pipeline.sh [command] [options] 37 | 38 | Example: 39 | pipeline.sh start -u wpernath -p -t art-tekton 40 | pipeline.sh logs 41 | 42 | COMMANDS: 43 | init creates ConfigMap, Tasks and Pipelines into current context 44 | start starts the given pipeline 45 | logs shows logs of the last pipeline run 46 | help Help about this command 47 | 48 | OPTIONS: 49 | -u, --registry-user User to store the image into quay.io ($IMAGE_USER) 50 | -p, --registry-password Password to store the image into quay.io ($IMAGE_PASSWORD) 51 | -c, --context-dir Which context-dir to user ($CONTEXT_DIR) 52 | -t, --target-namespace Which target namespace to start the app ($TARGET_NAMESPACE) 53 | -g, --git-repo Which quarkus repository to clone ($GIT_URL) 54 | -r, --git-revision Which git revision to use ($GIT_REVISION) 55 | 56 | EOF 57 | } 58 | 59 | while (( "$#" )); do 60 | case "$1" in 61 | start|logs|init) 62 | COMMAND=$1 63 | shift 64 | ;; 65 | -c|--context-dir) 66 | CONTEXT_DIR=$2 67 | shift 2 68 | ;; 69 | -t|--target-namespace) 70 | TARGET_NAMESPACE=$2 71 | shift 2 72 | ;; 73 | -u|--registry-user) 74 | IMAGE_USER=$2 75 | shift 2 76 | ;; 77 | -p|--registry-password) 78 | IMAGE_PASSWORD=$2 79 | shift 2 80 | ;; 81 | -g|--git-repo) 82 | GIT_URL=$2 83 | shift 2 84 | ;; 85 | -r|--git-revision) 86 | GIT_REVISION=$2 87 | shift 2 88 | ;; 89 | -l|--pipeline) 90 | PIPELINE=$2 91 | shift 2 92 | ;; 93 | --) 94 | shift 95 | break 96 | ;; 97 | -*|--*) 98 | command.help 99 | err "Error: Unsupported flag $1" 100 | ;; 101 | *) 102 | break 103 | esac 104 | done 105 | 106 | 107 | command.init() { 108 | # This script imports the necessary files into the current project 109 | pwd 110 | oc apply -f infra/maven-settings-cm.yaml 111 | oc apply -f infra/maven-artifact-cache-pvc.yaml 112 | 113 | oc apply -f tasks/kustomize-task.yaml 114 | oc apply -f tasks/maven-task.yaml 115 | 116 | oc apply -f pipelines/tekton-pipeline.yaml 117 | } 118 | 119 | 120 | command.logs() { 121 | tkn pr logs -f -L 122 | } 123 | 124 | command.start() { 125 | cat > /tmp/pipelinerun.yaml <<-EOF 126 | apiVersion: tekton.dev/v1beta1 127 | kind: PipelineRun 128 | metadata: 129 | name: $PIPELINE-run-$(date "+%Y%m%d-%H%M%S") 130 | spec: 131 | params: 132 | - name: git-url 133 | value: '$GIT_URL' 134 | - name: git-revision 135 | value: $GIT_REVISION 136 | - name: context-dir 137 | value: $CONTEXT_DIR 138 | - name: image-name 139 | value: $IMAGE_NAME 140 | - name: image-username 141 | value: $IMAGE_USER 142 | - name: image-password 143 | value: $IMAGE_PASSWORD 144 | - name: target-namespace 145 | value: $TARGET_NAMESPACE 146 | workspaces: 147 | - name: shared-workspace 148 | persistentVolumeClaim: 149 | claimName: builder-pvc 150 | - configMap: 151 | name: maven-settings 152 | name: maven-settings 153 | pipelineRef: 154 | name: $PIPELINE 155 | serviceAccountName: pipeline 156 | EOF 157 | 158 | oc apply -f /tmp/pipelinerun.yaml 159 | } 160 | 161 | main() { 162 | local fn="command.$COMMAND" 163 | valid_command "$fn" || { 164 | command.help 165 | err "invalid command '$COMMAND'" 166 | } 167 | 168 | cd $SCRIPT_DIR 169 | $fn 170 | return $? 171 | } 172 | 173 | main 174 | -------------------------------------------------------------------------------- /tektondev/pipelines/tekton-pipeline-test.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Pipeline 3 | metadata: 4 | name: new-test-pipeline 5 | spec: 6 | params: 7 | - default: 'https://github.com/wpernath/quarkus-simple.git' 8 | description: Source to the GIT 9 | name: git-url 10 | type: string 11 | - default: main 12 | description: revision to be used 13 | name: git-revision 14 | type: string 15 | - name: image-name 16 | type: string 17 | description: the name of the target image including registry 18 | default: quay.io/wpernath/quarkus-simple-wow:latest 19 | - name: image-username 20 | type: string 21 | description: the username you use to access the registry 22 | - name: image-password 23 | type: string 24 | description: The password you use to access the registry 25 | - name: target-namespace 26 | description: The name of the namespace to apply the result to 27 | tasks: 28 | - name: git-clone 29 | params: 30 | - name: url 31 | value: $(params.git-url) 32 | - name: deleteExisting 33 | value: 'true' 34 | - name: verbose 35 | value: 'true' 36 | - name: revision 37 | value: $(params.git-revision) 38 | taskRef: 39 | kind: ClusterTask 40 | name: git-clone 41 | workspaces: 42 | - name: output 43 | workspace: shared-workspace 44 | - name: package 45 | params: 46 | - name: GOALS 47 | value: 48 | - package 49 | - '-DskipTests' 50 | - name: PROXY_PROTOCOL 51 | value: http 52 | - name: CONTEXT_DIR 53 | value: . 54 | runAfter: 55 | - git-clone 56 | taskRef: 57 | kind: Task 58 | name: maven-caching 59 | workspaces: 60 | - name: source 61 | workspace: shared-workspace 62 | - name: maven-repo 63 | workspace: maven-repo 64 | - name: maven-settings 65 | workspace: maven-settings 66 | - name: apply-kustomize 67 | params: 68 | - name: kustomize-dir 69 | value: kustomize_ext/overlays/dev 70 | - name: target-namespace 71 | value: $(params.target-namespace) 72 | - name: image-name 73 | value: $(params.image-name) 74 | taskRef: 75 | kind: Task 76 | name: kustomize 77 | runAfter: 78 | - package 79 | workspaces: 80 | - name: source 81 | workspace: shared-workspace 82 | workspaces: 83 | - name: shared-workspace 84 | optional: false 85 | - name: maven-settings 86 | optional: false 87 | - name: maven-repo 88 | optional: false 89 | -------------------------------------------------------------------------------- /tektondev/pipelines/tekton-pipeline.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Pipeline 3 | metadata: 4 | name: new-pipeline 5 | spec: 6 | params: 7 | - default: 'https://github.com/wpernath/quarkus-simple.git' 8 | description: Source to the GIT 9 | name: git-url 10 | type: string 11 | - default: main 12 | description: revision to be used 13 | name: git-revision 14 | type: string 15 | - name: context-dir 16 | default: "the-source" 17 | type: string 18 | description: Where to checkout the source relative to the workspace 19 | - name: image-name 20 | type: string 21 | description: the name of the target image including registry 22 | default: quay.io/wpernath/quarkus-simple-wow 23 | - name: image-username 24 | type: string 25 | description: the username you use to access the registry 26 | - name: image-password 27 | type: string 28 | description: The password you use to access the registry 29 | - name: target-namespace 30 | description: The name of the namespace to apply the result to 31 | tasks: 32 | - name: git-clone 33 | params: 34 | - name: url 35 | value: $(params.git-url) 36 | - name: deleteExisting 37 | value: 'true' 38 | - name: verbose 39 | value: 'true' 40 | - name: revision 41 | value: $(params.git-revision) 42 | - name: subdirectory 43 | value: $(params.context-dir) 44 | taskRef: 45 | kind: ClusterTask 46 | name: git-clone 47 | workspaces: 48 | - name: output 49 | workspace: shared-workspace 50 | - name: package 51 | params: 52 | - name: GOALS 53 | value: 54 | - package 55 | - '-DskipTests' 56 | - name: CONTEXT_DIR 57 | value: "$(params.context-dir)" 58 | runAfter: 59 | - git-clone 60 | taskRef: 61 | kind: Task 62 | name: maven-caching 63 | workspaces: 64 | - name: source 65 | workspace: shared-workspace 66 | - name: maven-settings 67 | workspace: maven-settings 68 | - name: build-and-push-image 69 | params: 70 | - name: GOALS 71 | value: 72 | - package 73 | - '-DskipTests' 74 | - '-Dquarkus.container-image.build=true' 75 | - '-Dquarkus.container-image.push=true' 76 | - '-Dquarkus.container-image.builder=jib' 77 | - '-Dquarkus.container-image.image=$(params.image-name)' 78 | - '-Dquarkus.container-image.username=$(params.image-username)' 79 | - '-Dquarkus.container-image.password=$(params.image-password)' 80 | - name: CONTEXT_DIR 81 | value: "$(params.context-dir)" 82 | runAfter: 83 | - package 84 | taskRef: 85 | kind: Task 86 | name: maven-caching 87 | workspaces: 88 | - name: source 89 | workspace: shared-workspace 90 | - name: maven-settings 91 | workspace: maven-settings 92 | - name: apply-kustomize 93 | params: 94 | - name: kustomize-dir 95 | value: $(params.context-dir)/kustomize_ext/overlays/dev 96 | - name: target-namespace 97 | value: $(params.target-namespace) 98 | - name: image-name 99 | value: $(params.image-name) 100 | - name: image-digest-path 101 | value: $(params.context-dir)/target 102 | taskRef: 103 | kind: Task 104 | name: kustomize 105 | runAfter: 106 | - build-and-push-image 107 | workspaces: 108 | - name: source 109 | workspace: shared-workspace 110 | workspaces: 111 | - name: shared-workspace 112 | optional: false 113 | - name: maven-settings 114 | optional: false 115 | -------------------------------------------------------------------------------- /tektondev/tasks/bash-task.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: bash 5 | labels: 6 | app.kubernetes.io/version: "0.4" 7 | annotations: 8 | tekton.dev/pipelines.minVersion: "0.12.1" 9 | tekton.dev/tags: build-tool 10 | spec: 11 | description: >- 12 | This task can be used to execute kustomze build scripts and to apply the changes via oc apply -f 13 | workspaces: 14 | - name: source 15 | description: The workspace holding the cloned and compiled quarkus source. 16 | params: 17 | - name: script 18 | description: Where should kustomize look for kustomization in source? 19 | steps: 20 | - name: script 21 | image: quay.io/wpernath/kustomize-ubi:latest 22 | workingDir: $(workspaces.source.path) 23 | script: | 24 | echo 25 | ls -al /tekton/creds 26 | 27 | echo 28 | ls -al ~/.docker/config.json 29 | cat ~/.docker/config.json 30 | 31 | echo 32 | #ls -al ~/.ssh 33 | #ls -al ~/.gitconfig 34 | #cat ~/.gitconfig 35 | 36 | $(params.script) 37 | ls -al ~/.ssh 38 | -------------------------------------------------------------------------------- /tektondev/tasks/kustomize-task.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: kustomize 5 | labels: 6 | app.kubernetes.io/version: "0.4" 7 | annotations: 8 | tekton.dev/pipelines.minVersion: "0.12.1" 9 | tekton.dev/tags: build-tool 10 | spec: 11 | description: >- 12 | This task can be used to execute kustomze build scripts and to apply the changes via oc apply -f 13 | workspaces: 14 | - name: source 15 | description: The workspace holding the cloned and compiled quarkus source. 16 | params: 17 | - name: kustomize-dir 18 | description: Where should kustomize look for kustomization in source? 19 | - name: target-namespace 20 | description: Where to apply the kustomization to 21 | - name: image-name 22 | description: Which image to use. Kustomize is taking care of it 23 | - name: image-digest-path 24 | description: The path of the jib-image.digest file generated by quarkus package 25 | steps: 26 | - name: build 27 | image: quay.io/wpernath/kustomize-ubi:latest 28 | workingDir: $(workspaces.source.path)/$(params.kustomize-dir) 29 | script: | 30 | DIGEST=$(cat $(workspaces.source.path)/$(params.image-digest-path)/jib-image.digest) 31 | echo "Calculated DIGEST: $DIGEST" 32 | echo 33 | 34 | kustomize edit set image quay.io/wpernath/simple-quarkus:latest=$(params.image-name)@$DIGEST 35 | 36 | kustomize build . 37 | kustomize build . > ./kustomized.yaml 38 | 39 | - name: apply 40 | image: 'image-registry.openshift-image-registry.svc:5000/openshift/cli:latest' 41 | workingDir: $(workspaces.source.path)/$(params.kustomize-dir) 42 | script: | 43 | oc apply -f ./kustomized.yaml -n $(params.target-namespace) 44 | 45 | -------------------------------------------------------------------------------- /tektondev/tasks/maven-task.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: tekton.dev/v1beta1 2 | kind: Task 3 | metadata: 4 | name: maven-caching 5 | labels: 6 | app.kubernetes.io/version: "0.4" 7 | annotations: 8 | tekton.dev/pipelines.minVersion: "0.12.1" 9 | tekton.dev/tags: build-tool 10 | spec: 11 | description: >- 12 | This Task can be used to run a Maven build. The only difference to 13 | the original one from github.com/tektoncd/catalog is that it uses an 14 | optional local maven repo path to cache all the dependencies. And it requires a 15 | a maven-settings workspace. 16 | workspaces: 17 | - name: source 18 | description: The workspace consisting of maven project. 19 | optional: false 20 | - name: maven-settings 21 | description: >- 22 | The workspace consisting of the custom maven settings 23 | provided by the user. 24 | optional: false 25 | params: 26 | - name: GOALS 27 | description: maven goals to run 28 | type: array 29 | default: 30 | - "package" 31 | - name: CONTEXT_DIR 32 | type: string 33 | description: >- 34 | The context directory within the repository for sources on 35 | which we want to execute maven goals. 36 | default: "." 37 | steps: 38 | - name: mvn-goals 39 | image: gcr.io/cloud-builders/mvn@sha256:57523fc43394d6d9d2414ee8d1c85ed7a13460cbb268c3cd16d28cfb3859e641 40 | workingDir: $(workspaces.source.path)/$(params.CONTEXT_DIR) 41 | command: ["/usr/bin/mvn"] 42 | args: 43 | - -B 44 | - -s 45 | - $(workspaces.maven-settings.path)/settings.xml 46 | - -Dmaven.repo.local=$(workspaces.source.path)/MAVEN_MIRROR 47 | - "$(params.GOALS)" --------------------------------------------------------------------------------
Congratulations, this is a very simple quarkus application
125 | This is a very simple demo application for the article series on OpenSourcerers 126 |
133 | You can find the code on GitHub 134 |
137 | This application is using the smallrye health quarkus extensions 138 | for liveness and readyness probes. 139 |
142 | The docker images can be found on quay.io 143 |
148 | The following endpoints are available: 149 |
org.wanja.quarkus
simple-quarkus
1.0.1
2.6.3.Final
Germany, COVID-19