diff --git a/.github/workflows/changelog-enforcer.yml b/.github/workflows/changelog-enforcer.yml index cfa6b4fee..92b1c95be 100644 --- a/.github/workflows/changelog-enforcer.yml +++ b/.github/workflows/changelog-enforcer.yml @@ -8,7 +8,7 @@ jobs: changelog: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.2 - uses: dangoslen/changelog-enforcer@v3 with: changeLogPath: 'CHANGELOG.md' diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 9353d6792..6a8c01875 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. diff --git a/.github/workflows/continuous-integration-workflow.yml b/.github/workflows/continuous-integration-workflow.yml index 7ed91c96a..907bcad8e 100644 --- a/.github/workflows/continuous-integration-workflow.yml +++ b/.github/workflows/continuous-integration-workflow.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 - name: Build UBI8 docker image run: | @@ -27,7 +27,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 - name: Build UBI8 docker image run: | ./.github/workflows/build-docker-image.sh \ @@ -51,12 +51,12 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - version: ['8.9.10.61524'] # 8.9 = LTS + version: ['9.9.4'] # 9.9 = LTS edition: ['community', 'developer', 'enterprise'] steps: - name: Checkout repository - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 - name: Check shell scripts run: | @@ -72,7 +72,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 - name: Check shell scripts run: | @@ -88,7 +88,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 - name: Setup Go 1.18 uses: actions/setup-go@v5 @@ -128,7 +128,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 - name: Check shell scripts run: | @@ -145,7 +145,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 - name: Check jsl expectations run: | @@ -163,7 +163,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 - name: Setup Go 1.18 uses: actions/setup-go@v5 @@ -207,7 +207,7 @@ jobs: # run: jq . <<< "${GITHUB_CONTEXT}" # - # name: Checkout repository -# uses: actions/checkout@v4.1.1 +# uses: actions/checkout@v4.1.2 # with: # fetch-depth: 0 # path: 'ods-core' diff --git a/CHANGELOG.md b/CHANGELOG.md index 445454ab5..aaa2abc6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,22 @@ ## Unreleased +### Fixed + +### Added + +### Changed + +## [4.4.0] - 2024-04-22 + +### Fixed +- Update Nexus to version 3.67.1-java11 for Critical Bug Fix ([#1271](https://github.com/opendevstack/ods-core/pull/1271)) + +### Changed +- Nexus Maintenance (update version to latest, helm migration) ([#1242](https://github.com/opendevstack/ods-core/issues/1242)) +- Update api version in ocp templates for image, buildconfig, route and deploymentconfig ([#1072](https://github.com/opendevstack/ods-jenkins-shared-library/issues/1072)) +- SonarQube Maintenance (LTS update, DB update, SAML setup) ([#1211](https://github.com/opendevstack/ods-core/issues/1211)) +- Update Jenkins and plugins to version v2.426.3, update agent and packages. Switch base image from "registry.redhat.io/openshift4/ose" to "registry.redhat.io/ocp-tools-4" [#1270](https://github.com/opendevstack/ods-core/pull/1270) ## [4.3.1] - 2024-02-19 diff --git a/Makefile b/Makefile index e27d0b09e..041526496 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,10 @@ SHELL = /bin/bash MAKEFLAGS += --warn-undefined-variables MAKEFLAGS += --no-builtin-rules -ODS_NAMESPACE := $(shell $(CURDIR)/scripts/get-config-param.sh ODS_NAMESPACE) -NEXUS_URL := $(shell $(CURDIR)/scripts/get-config-param.sh NEXUS_URL) -SONARQUBE_URL := $(shell $(CURDIR)/scripts/get-config-param.sh SONARQUBE_URL) +# Load environment variables from .env file +include ../ods-configuration/ods-core.env +export $(shell sed 's/=.*//' ../ods-configuration/ods-core.env) + INSECURE := false INSECURE_FLAG := ifeq ($(INSECURE), $(filter $(INSECURE), true yes)) @@ -120,24 +121,19 @@ start-doc-gen-build: # SONARQUBE ## Install or update SonarQube. -install-sonarqube: apply-sonarqube-build start-sonarqube-build apply-sonarqube-deploy configure-sonarqube +install-sonarqube: apply-sonarqube-chart start-sonarqube-build configure-sonarqube .PHONY: install-sonarqube -## Update OpenShift resources related to the SonarQube image. -apply-sonarqube-build: - cd sonarqube/ocp-config && tailor apply --namespace $(ODS_NAMESPACE) bc,is +## Apply OpenShift resources related to the SonarQube. +apply-sonarqube-chart: + cd sonarqube/chart && envsubst < values.yaml.template > values.yaml && helm upgrade --install --namespace $(ODS_NAMESPACE) sonarqube . && rm values.yaml .PHONY: apply-sonarqube-build ## Start build of BuildConfig "sonarqube". start-sonarqube-build: ocp-scripts/start-and-follow-build.sh --namespace $(ODS_NAMESPACE) --build-config sonarqube -.PHONY: start-sonarqube-build - -## Update OpenShift resources related to the SonarQube service. -apply-sonarqube-deploy: - cd sonarqube/ocp-config && tailor apply --namespace $(ODS_NAMESPACE) --exclude bc,is @echo "Visit $(SONARQUBE_URL)/setup to see if any update actions need to be taken." -.PHONY: apply-sonarqube-deploy +.PHONY: start-sonarqube-build ## Configure SonarQube service. configure-sonarqube: @@ -147,27 +143,22 @@ configure-sonarqube: # NEXUS ## Install or update Nexus. -install-nexus: apply-nexus-build start-nexus-build apply-nexus-deploy +install-nexus: apply-nexus-chart start-nexus-build .PHONY: nexus -## Update OpenShift resources related to the Nexus image. -apply-nexus-build: - cd nexus/ocp-config && tailor apply --namespace $(ODS_NAMESPACE) bc,is -.PHONY: apply-nexus-build +## Apply OpenShift resources related to the Nexus. +apply-nexus-chart: + cd nexus/chart && envsubst < values.yaml.template > values.yaml && helm upgrade --install --namespace $(ODS_NAMESPACE) nexus . && rm values.yaml +.PHONY: apply-nexus-chart ## Start build of BuildConfig "nexus". start-nexus-build: ocp-scripts/start-and-follow-build.sh --namespace $(ODS_NAMESPACE) --build-config nexus .PHONY: start-nexus-build -## Update OpenShift resources related to the Nexus service. -apply-nexus-deploy: - cd nexus/ocp-config && tailor apply --namespace $(ODS_NAMESPACE) --exclude bc,is -.PHONY: apply-nexus-deploy - ## Configure Nexus service. configure-nexus: - cd nexus && ./configure.sh --namespace $(ODS_NAMESPACE) --nexus=$(NEXUS_URL) $(INSECURE_FLAG) + cd nexus && ./configure.sh --namespace $(ODS_NAMESPACE) --nexus=$(NEXUS_URL) --admin-password=$(NEXUS_ADMIN_PASSWORD) $(INSECURE_FLAG) .PHONY: configure-nexus ### configure-nexus is not part of install-nexus because it is not idempotent yet. @@ -177,14 +168,14 @@ configure-nexus: backup: backup-sonarqube backup-ocp-config .PHONY: backup -## Create a backup of OpenShift resources in "cd" namespace. +## Create a backup of OpenShift resources in "ods" namespace. backup-ocp-config: - tailor export --namespace $(ODS_NAMESPACE) > backup_cd.yml + tailor export --namespace $(ODS_NAMESPACE) > backup_ods.yml .PHONY: backup-ocp-config -## Create a backup of the SonarQube database in the current directory. +## Create a backup of the SonarQube database in backup storage and in the current directory. backup-sonarqube: - cd sonarqube && ./backup.sh --namespace $(ODS_NAMESPACE) --backup-dir `pwd` + cd sonarqube && ./backup.sh --namespace $(ODS_NAMESPACE) --local-copy=true --backup-dir `pwd` .PHONY: backup-sonarqube diff --git a/configuration-sample/ods-core.env.sample b/configuration-sample/ods-core.env.sample index 9938688db..e75a7ba51 100644 --- a/configuration-sample/ods-core.env.sample +++ b/configuration-sample/ods-core.env.sample @@ -43,8 +43,10 @@ ODS_BITBUCKET_PROJECT=opendevstack ######### # Nexus base image -# See https://hub.docker.com/r/sonatype/nexus3/tags. -NEXUS_FROM_IMAGE=sonatype/nexus3:3.45.1 +# See Dockerhub https://hub.docker.com/r/sonatype/nexus3/tags. +# Officially supported is: +# - 3.67.1-java11 +NEXUS_IMAGE_TAG=3.67.1-java11 # Nexus host without protocol. # The domain should be equal to OPENSHIFT_APPS_BASEDOMAIN (see below). @@ -58,11 +60,16 @@ NEXUS_URL=https://nexus-cd.192.168.56.101.nip.io NEXUS_USERNAME=developer NEXUS_PASSWORD=changeme NEXUS_PASSWORD_B64=changeme +# Password of Nexus administrator - should be set to a secure password +# of your choice. +NEXUS_ADMIN_PASSWORD=changeme +NEXUS_ADMIN_PASSWORD_B64=changeme # Nexus (basic) authentication username:password NEXUS_AUTH=developer:changeme -# All params defined in the template https://github.com/opendevstack/ods-core/blob/master/nexus/ocp-config/bc.yml -# can be overwritten by specifying the param in this file. +# Nexus JVM parameters, adjust acording to organization size +# See https://help.sonatype.com/en/sonatype-nexus-repository-system-requirements.html +NEXUS_JVM_PARAMS="-Xms2703m -Xmx2703m -XX:MaxDirectMemorySize=2703m -Djava.util.prefs.userRoot=/nexus-data/javaprefs" ############# # SonarQube # @@ -85,16 +92,21 @@ SONAR_ADMIN_PASSWORD_B64=changeme # Do not change the value manually - the token is created and set automatically during "make configure-sonarqube". SONAR_AUTH_TOKEN_B64=changeme -# Application in Crowd used for authentication -SONAR_CROWD_APPLICATION=sonarqube -SONAR_CROWD_PASSWORD_B64=changeme +# Toggle authentication via SAML +SONAR_AUTH_SAML='true' + +# SAML Application used for authentication +SONAR_SAML_APPLICATION_ID=https://sonarqube-cd.192.168.56.101.nip.io/sonar/saml +SONAR_SAML_PROVIDER_ID_B64=changeme +SONAR_SAML_LOGIN_URL_B64=changeme +SONAR_SAML_CERTIFICATE_B64=changeme # Postgres DB for SonarQube # Image to use for the PostgreSQL database. This needs to be compatible with # your SonarQube version, see https://docs.sonarqube.org/latest/requirements/requirements/. # Take care when upgrading either database or SQ version. -# E.g. registry.redhat.io/rhel8/postgresql-12 -SONAR_DATABASE_IMAGE=docker-registry.default.svc:5000/openshift/postgresql:9.6 +# E.g. registry.redhat.io/rhel9/postgresql-15 +SONAR_DATABASE_IMAGE=docker-registry.default.svc:5000/openshift/postgresql:15 # Connection string for JDBC. Typically this does not need to be changed. SONAR_DATABASE_JDBC_URL=jdbc:postgresql://sonarqube-postgresql:5432/sonarqube # Database name for SonarQube. Typically this does not need to be changed. @@ -110,20 +122,10 @@ SONAR_DATABASE_USER=sonarqube # - Use "developer", "enterprise" or "datacenter" for commercial editions SONAR_EDITION=community # SonarQube version. +# See Dockerhub https://hub.docker.com/_/sonarqube/tags # Officially supported is: -# - 8.9 (LTS release) -SONAR_VERSION=8.9.10.61524 -https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-8.9.10.61524.zip -# SonarQube distribution URL. -# Must be aligned with both SONAR_VERSION and SONAR_EDITION. -# Check https://binaries.sonarsource.com/ for options. -SONAR_DISTRIBUTION_URL=https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-8.9.10.61524.zip - -# Toggle authentication via Crowd plugin -SONAR_AUTH_CROWD=true - -# All params defined in the template https://github.com/opendevstack/ods-core/blob/master/sonarqube/ocp-config/sonarqube.yml -# can be overwritten by specifying the param in this file. +# - 9.9 (LTS release) +SONAR_VERSION=9.9.4 ######### # Jira # @@ -183,15 +185,12 @@ CONFLUENCE_URL=http://192.168.56.31:8090 # Base image for Jenkins master. # For UBI8-based images (OpenShift 4): -# - RHEL variant: https://catalog.redhat.com/software/containers/openshift4/ose-jenkins/5cdd918ad70cc57c44b2d279 -# - Example: registry.redhat.io/openshift4/ose-jenkins:v4.6 -# - Last tested: registry.redhat.io/openshift4/ose-jenkins:v4.10.0-202305170515.p0.g2988625.assembly.stream +# - RHEL variant: https://catalog.redhat.com/software/containers/ocp-tools-4/jenkins-rhel8/5fe1f38288e9c2f788526306 +# - Example: registry.redhat.io/ocp-tools-4/jenkins-rhel8:v4.14.0 +# - Last tested: registry.redhat.io/ocp-tools-4/jenkins-rhel8:v4.14.0-1706517686 # - Community variant: https://quay.io/repository/openshift/origin-jenkins?tab=tags # - Example: quay.io/openshift/origin-jenkins:4.6 -# For RHEL7-based images (OpenShift 3.11): -# - Available tags listed at: https://catalog.redhat.com/software/containers/openshift3/jenkins-2-rhel7/581d2f4500e5d05639b6517b -# - Example: registry.access.redhat.com/openshift3/jenkins-2-rhel7:v3.11 -JENKINS_MASTER_BASE_FROM_IMAGE=registry.redhat.io/openshift4/ose-jenkins:v4.10.0-202305170515.p0.g2988625.assembly.stream +JENKINS_MASTER_BASE_FROM_IMAGE=registry.redhat.io/ocp-tools-4/jenkins-rhel8:v4.14.0-1706517686 # Dockerfile to use for Jenkins master. # Use "Dockerfile.ubi8" for both OpenShift 3.11 and 4 (UBI8 base image) @@ -199,16 +198,12 @@ JENKINS_MASTER_DOCKERFILE_PATH=Dockerfile.ubi8 # Base image for Jenkins agent base. # For UBI8-based images (OpenShift 4): -# - RHEL variant: https://catalog.redhat.com/software/containers/openshift4/ose-jenkins-agent-base/5cdd8e2fbed8bd5717d66e77 -# - Example: registry.redhat.io/openshift4/ose-jenkins-agent-base:v4.6 -# - Last tested: registry.redhat.io/openshift4/ose-jenkins:v4.10.0-202305170515.p0.g2988625.assembly.stream +# - RHEL variant: https://catalog.redhat.com/software/containers/ocp-tools-4/jenkins-agent-base-rhel8/6241e3457847116cf8577aea +# - Example: registry.redhat.io/ocp-tools-4/jenkins-agent-base-rhel8:v4.14.0 +# - Last tested: registry.redhat.io/ocp-tools-4/jenkins-agent-base-rhel8:v4.14.0-1706516367 # - Community variant: https://quay.io/repository/openshift/origin-jenkins-agent-base?tab=tags # - Example: quay.io/openshift/origin-jenkins-agent-base:4.6 -# For RHEL7-based images (OpenShift 3.11): -# - Available tags listed at: https://catalog.redhat.com/software/containers/openshift3/jenkins-slave-base-rhel7/581d2f3f00e5d05639b6515b. -# - Example: registry.access.redhat.com/openshift3/jenkins-slave-base-rhel7:v3.11 -# - Latest tested tag: v3.11.248 (v3.11 is a moving target) -JENKINS_AGENT_BASE_FROM_IMAGE=registry.redhat.io/openshift4/ose-jenkins-agent-base:v4.10.0-202305170515.p0.g2988625.assembly.stream +JENKINS_AGENT_BASE_FROM_IMAGE=registry.redhat.io/ocp-tools-4/jenkins-agent-base-rhel8:v4.14.0-1706516367 # Dockerfile to use for Jenkins agents. # Use "Dockerfile.ubi8" for both OpenShift 3.11 and 4 (UBI8 base image) @@ -217,25 +212,25 @@ JENKINS_AGENT_DOCKERFILE_PATH=Dockerfile.ubi8 # Snyk CLI binary distribution url # Leave empty to avoid installing Snyk. # Releases are published at https://github.com/snyk/snyk/releases. -# Latest tested version is v1.1097.0. -JENKINS_AGENT_BASE_SNYK_DISTRIBUTION_URL=https://github.com/snyk/snyk/releases/download/v1.1097.0/snyk-linux +# Latest tested version is v1.1284.0. +JENKINS_AGENT_BASE_SNYK_DISTRIBUTION_URL=https://github.com/snyk/snyk/releases/download/v1.1284.0/snyk-linux # AquaSec CLI binary distribution url # Leave empty to avoid installing AquaSec. # Releases are published at https://download.aquasec.com/scanner # Check Aqua versions backward compatibility at https://docs.aquasec.com/docs/version-compatibility-of-components#section-backward-compatibility-across-two-major-versions # To Download the aquaSec scanner cli and check their documentaion requires a valid account on aquasec.com -# Latest tested version is 2022.4.284 -# Example: https://:@download.aquasec.com/scanner/2022.4.284/scannercli +# Latest tested version is 2022.4.517 +# Example: https://:@download.aquasec.com/scanner/2022.4.517/scannercli JENKINS_AGENT_BASE_AQUASEC_SCANNERCLI_URL= # Repository of shared library # You may also point to repository underneath REPO_BASE. SHARED_LIBRARY_REPOSITORY=https://github.com/opendevstack/ods-jenkins-shared-library.git -#################### -# OpenShift (3.11) # -#################### +############# +# OpenShift # +############# # Internal docker registry host and port - this is used # for pulling the agent images in jenkins. diff --git a/docs/modules/administration/nav.adoc b/docs/modules/administration/nav.adoc index 3bb07889b..29cf07b37 100644 --- a/docs/modules/administration/nav.adoc +++ b/docs/modules/administration/nav.adoc @@ -1,6 +1,7 @@ * Administration ** xref:administration:installation.adoc[Installation] ** Upgrade +*** xref:administration:helm-migration.adoc[Helm migration] *** xref:administration:update-2-to-3.adoc[2.x to 3.x] *** xref:administration:update-older.adoc[older] ** xref:provisioning-app:configuration.adoc[Provisioning App] diff --git a/docs/modules/administration/pages/helm-migration.adoc b/docs/modules/administration/pages/helm-migration.adoc new file mode 100644 index 000000000..8a66170ea --- /dev/null +++ b/docs/modules/administration/pages/helm-migration.adoc @@ -0,0 +1,31 @@ += Migrating from Tailor to Helm + +Tailor has been developed for OpenShift 3.11. Back in the days, Helm 2 required the use of a privileged Tiller service and did not work well with OpenShift-specific resources. With Helm 3 and OpenShift 4, this situation has changed. + +While Tailor also works in an OpenShift 4 cluster, OpenShift has integrated Helm into its product, and Helm has a huge and growing community. Therefore, it is recommended to use Helm instead of Tailor in an OpenShift 4 cluster. + +Tailor is based on OpenShift templates, which define the Kubernetes resources to apply. Helm uses a different templating language / engine, but in the end the templates also describe Kubernetes resources. Therefore, migration effort is relatively low as one only needs to change the syntax of the definition, not the definition itself. Further, there are differences between the CLI of the two tools and not all features of Tailor are available in Helm and vice-versa. Once migration to Helm is complete, it is also recommended to look at the best practices in the Helm community and adopt these. + +This document will describe how to adopt resources deployed using Tailor into a Helm release for OpenDevStack installation. + +== Templates preparation + +There are basically two options how to approach this: you can either adopt your existing OpenShift resources to chart templates, or you can start a clean installation. +Once the templates have been made ready, you can continue the installation/update following the normal process + +=== Option 1: Adopting OpenShift resources + +In order to adopt the resources into a Helm release you can use the following script https://github.com/opendevstack/ods-core/blob/master/scripts/tailor2helm.sh + +=== Option 2: Clean Installation + +In this case you will need to remove all existing resources for the component that has been previously deployed using Tailor, you can check existing resources like this: + +[source,sh] +---- +oc -n ods get all -l app=foo-bar +---- + +== Sources + +Check more information about migration from tailor to helm and their differences in https://github.com/opendevstack/tailor/wiki/Migrating-from-Tailor-to-Helm diff --git a/docs/modules/administration/pages/update-older.adoc b/docs/modules/administration/pages/update-older.adoc index 3efe808a7..a91da8869 100644 --- a/docs/modules/administration/pages/update-older.adoc +++ b/docs/modules/administration/pages/update-older.adoc @@ -192,7 +192,7 @@ Then, create the `BuildConfig` and `ImageStream` in `prov-dev` using `oc -n prov apiVersion: template.openshift.io/v1 kind: Template objects: -- apiVersion: v1 +- apiVersion: build.openshift.io/v1 kind: BuildConfig metadata: creationTimestamp: null @@ -217,7 +217,7 @@ objects: dockerStrategy: {} type: Docker triggers: [] -- apiVersion: v1 +- apiVersion: image.openshift.io/v1 kind: ImageStream metadata: labels: diff --git a/docs/modules/nexus/pages/administration.adoc b/docs/modules/nexus/pages/administration.adoc index 72da63fcc..d54b7a728 100644 --- a/docs/modules/nexus/pages/administration.adoc +++ b/docs/modules/nexus/pages/administration.adoc @@ -8,6 +8,8 @@ The Nexus deployment is using an image built in the central ODS namespace. This The Nexus version which is used is determined by which image tag from DockerHub is used, and depending on tag, at which time the ODS image is built. +If the previous version was installed using Tailor, follow the process to migrate from tailor to helm in https://www.opendevstack.org/ods-documentation/opendevstack/5.x/administration/helm-migration.html + To update Nexus, the following steps need to be taken: 1. Configure new version @@ -31,7 +33,7 @@ chmod +x repos.sh ./repos.sh --git-ref $GIT_REF --repos="ods-core,ods-configuration" --source-project https://$BITBUCKET_HOST/scm/$BITBUCKET_PROJECT ---- -The script can also be used in an umbrella directory in which the repositories already exist. Once the repositories are at the desired revision, change `NEXUS_FROM_IMAGE` in `ods-configuration/ods-core.env` to your desired image tag. Commit the change and push it to Bitbucket. +The script can also be used in an umbrella directory in which the repositories already exist. Once the repositories are at the desired revision, change `NEXUS_IMAGE_TAG` in `ods-configuration/ods-core.env` to your desired image tag. Commit the change and push it to Bitbucket. Next, you should ensure that the Nexus `BuildConfig` resource in the central ODS namespace is up-to-date, then trigger a new build so that a new image with the changed base image gets built. Finally, a new deployment should be rolled out which uses the newly built image. All of this can be done from the `ods-core` repository: @@ -40,6 +42,6 @@ Next, you should ensure that the Nexus `BuildConfig` resource in the central ODS make install-nexus ---- -This target depends on the targets `apply-nexus-build`, `start-nexus-build`, and `apply-nexus-deploy` which execute the steps described above (and can of course also be executed individually). +This target depends on the targets `apply-nexus-chart` and `start-nexus-build` which execute the steps described above (and can of course also be executed individually). WARNING: There is also a `configure-nexus` target. However, this is not executed as part of `install-nexus` as it is not idempotent yet (which means it cannot be used against an existing Nexus deployment). For a simple Nexus version update, you don't need to change any configuration, but if you switch between ODS versions you should keep an eye on Nexus configuration. diff --git a/docs/modules/sonarqube/pages/administration.adoc b/docs/modules/sonarqube/pages/administration.adoc index 96521bf0b..75f1ee677 100644 --- a/docs/modules/sonarqube/pages/administration.adoc +++ b/docs/modules/sonarqube/pages/administration.adoc @@ -8,9 +8,9 @@ There is an `admin` user which is allowed to change settings, install plugins, e == Updating SonarQube to a new version -The SonarQube deployment is using an image built in the central ODS namespace. This image is not based on the https://hub.docker.com/_/sonarqube[official SonarQube image on DockerHub], because that requires a specific user to be run under. However, the approach ODS takes is similar to the official image, as can be seen in the https://github.com/opendevstack/ods-core/blob/master/sonarqube/docker/Dockerfile[ODS Dockerfile]. - -The SonarQube version which is used is determined by which ZIP file is used. +The SonarQube deployment is using an image built in the central ODS namespace. This image is based on the https://hub.docker.com/_/sonarqube, as can be seen in the https://github.com/opendevstack/ods-core/blob/master/sonarqube/docker/Dockerfile[ODS Dockerfile]. +If the previous version was installed using Tailor, follow the process to migrate from tailor to helm in https://www.opendevstack.org/ods-documentation/opendevstack/5.x/administration/helm-migration.html +If the previous version was configured to use Atlassian Crowd as Authentication provider, run the script https://github.com/opendevstack/ods-core/tree/master/scripts/migrate-sonar-users.sh in order to migrate current users to use Saml as Authentication provider. To update SonarQube, the following steps need to be taken: @@ -35,7 +35,7 @@ chmod +x repos.sh ./repos.sh --git-ref $GIT_REF --repos="ods-core,ods-configuration" --source-project https://$BITBUCKET_HOST/scm/$BITBUCKET_PROJECT ---- -The script can also be used in an umbrella directory in which the repositories already exist. Once the repositories are at the desired revision, change `SONAR_VERSION` and `SONAR_DISTRIBUTION_URL` in `ods-configuration/ods-core.env` to your desired version. Commit the change and push it to Bitbucket. +The script can also be used in an umbrella directory in which the repositories already exist. Once the repositories are at the desired revision, change `SONAR_VERSION` in `ods-configuration/ods-core.env` to your desired version. Commit the change and push it to Bitbucket. Next, you should ensure that the SonarQube `BuildConfig` resource in the central ODS namespace is up-to-date, then trigger a new build so that a new image gets built. Finally, a new deployment should be rolled out which uses the newly built image. All of this can be done from the `ods-core` repository: @@ -44,4 +44,4 @@ Next, you should ensure that the SonarQube `BuildConfig` resource in the central make install-sonarqube ---- -This target depends on the targets `apply-sonarqube-build`, `start-sonarqube-build`, `apply-sonarqube-deploy` and `configure-sonarqube` which execute the steps described above (and can of course also be executed individually). +This target depends on the targets `apply-sonarqube-chart`, `start-sonarqube-build` and `configure-sonarqube` which execute the steps described above (and can of course also be executed individually). diff --git a/docs/modules/sonarqube/pages/index.adoc b/docs/modules/sonarqube/pages/index.adoc index 79caa7701..8e5352b8b 100644 --- a/docs/modules/sonarqube/pages/index.adoc +++ b/docs/modules/sonarqube/pages/index.adoc @@ -28,11 +28,11 @@ sonar.java.libraries=build/libs sonar.junit.reportPaths=build/test-results/test ``` -The general settings are documented at https://docs.sonarqube.org/display/SONAR/Analysis+Parameters. Plugin-specific parameters can be found in the docs for each plugin, e.g. https://docs.sonarqube.org/display/PLUG/Java+Plugin+and+Bytecode. +The general settings are documented at https://docs.sonarsource.com/sonarqube/9.9/analyzing-source-code/analysis-parameters. == Scanning in Jenkins pipelines -There's a prebuilt stage (`odsComponentStageScanWithSonar`) that you can use, see https://www.opendevstack.org/ods-documentation/ods-jenkins-shared-library/latest/index.html for details. +There's a prebuilt stage (`odsComponentStageScanWithSonar`) that you can use, see https://www.opendevstack.org/ods-documentation/opendevstack/latest/jenkins-shared-library/component-pipeline.html#_odscomponentstagescanwithsonar for details. == Scanning locally: SonarLint IDE Plugin diff --git a/jenkins/agent-base/Dockerfile.ubi8 b/jenkins/agent-base/Dockerfile.ubi8 index 3ad35394c..ce82a754e 100644 --- a/jenkins/agent-base/Dockerfile.ubi8 +++ b/jenkins/agent-base/Dockerfile.ubi8 @@ -2,15 +2,16 @@ FROM quay.io/openshift/origin-jenkins-agent-base SHELL ["/bin/bash", "-o", "pipefail", "-c"] -ENV SONAR_SCANNER_VERSION=4.7.0.2747 \ - CNES_REPORT_VERSION=4.1.2 \ +# SONAR_SCANNER_VERSION above 4.8.x require java 17 to run. +ENV SONAR_SCANNER_VERSION=4.8.1.3023 \ + CNES_REPORT_VERSION=4.2.0 \ TAILOR_VERSION=1.3.4 \ - SOPS_VERSION=3.7.3 \ - HELM_VERSION=3.11.3 \ - HELM_PLUGIN_DIFF_VERSION=3.8.1 \ - HELM_PLUGIN_SECRETS_VERSION=4.2.2 \ - GIT_LFS_VERSION=3.3.0 \ - TRIVY_VERSION=0.42.0 \ + SOPS_VERSION=3.8.1 \ + HELM_VERSION=3.14.3 \ + HELM_PLUGIN_DIFF_VERSION=3.9.5 \ + HELM_PLUGIN_SECRETS_VERSION=4.6.0 \ + GIT_LFS_VERSION=3.5.1 \ + TRIVY_VERSION=0.50.1 \ JAVA_GC_OPTS="-XX:+UseParallelGC -XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=10 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90" ARG APP_DNS @@ -21,6 +22,7 @@ ARG AQUASEC_SCANNERCLI_URL COPY yum.repos.d/ubi.repo /etc/yum.repos.d/ubi.repo COPY ensure_java_jre_is_adequate.sh /usr/local/bin/ + RUN cd /etc/yum.repos.d && rm -f localdev-* ci-rpm-mirrors.repo \ && ensure_java_jre_is_adequate.sh \ && yum -y install make glibc-langpack-en openssl \ @@ -71,7 +73,7 @@ RUN cd /tmp \ # Install Helm. RUN cd /tmp \ - && dnf install -y https://github.com/mozilla/sops/releases/download/v${SOPS_VERSION}/sops-${SOPS_VERSION}-1.x86_64.rpm \ + && dnf install -y https://github.com/mozilla/sops/releases/download/v${SOPS_VERSION}/sops-${SOPS_VERSION}.x86_64.rpm \ && mkdir -p /tmp/helm \ && curl -sSLO https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gz \ && tar -zxvf helm-v${HELM_VERSION}-linux-amd64.tar.gz -C /tmp/helm \ diff --git a/jenkins/master/Dockerfile.ubi8 b/jenkins/master/Dockerfile.ubi8 index c0dc5a460..1e6e95e38 100644 --- a/jenkins/master/Dockerfile.ubi8 +++ b/jenkins/master/Dockerfile.ubi8 @@ -1,6 +1,6 @@ FROM quay.io/openshift/origin-jenkins -ENV JAVA_HOME /usr/lib/jvm/jre +ENV JAVA_HOME /usr/lib/jvm/jre-11 # ODS defaults, available to use within pipelines. ARG ODS_NAMESPACE diff --git a/jenkins/master/plugins.ubi8.txt b/jenkins/master/plugins.ubi8.txt index f5371c143..302e4b2ba 100644 --- a/jenkins/master/plugins.ubi8.txt +++ b/jenkins/master/plugins.ubi8.txt @@ -1,16 +1,14 @@ -commons-lang3-api:3.12.0-36.vd97de6465d5b_ greenballs:1.15.1 -email-ext:2.97 -sonar:2.15 -audit-trail:333.vb_e1b_b_0f1238c -ansicolor:1.0.2 -blueocean:1.27.4 -blueocean-display-url:2.4.2 -junit:1202.v79a_986785076 -parameterized-trigger:2.45 -pipeline-rest-api:2.32 -token-macro:359.vb_cde11682e0c -openshift-sync:1.1.0.790.v2051fca_5ed8d -kubernetes-credentials:0.10.0 -kubernetes-client-api:6.4.1-215.v2ed17097a_8e9 -kubernetes:3923.v294a_d4250b_91 \ No newline at end of file +sonar:2.17.2 +blueocean:1.27.9 +email-ext:2.104 +ansicolor:1.0.4 +kubernetes-credentials:0.11 +kubernetes-client-api:6.10.0-240.v57880ce8b_0b_2 +kubernetes:4186.v1d804571d5d4 +junit:1259.v65ffcef24a_88 +audit-trail:361.v82cde86c784e +credentials:1337.v60b_d7b_c7b_c9f +workflow-multibranch:773.vc4fe1378f1d5 +git:5.2.1 +openshift-sync:1.1.0.802.v45585f8cdc07 diff --git a/jenkins/ocp-config/build/bc.yml b/jenkins/ocp-config/build/bc.yml index 7c99a7a81..abb2decd9 100644 --- a/jenkins/ocp-config/build/bc.yml +++ b/jenkins/ocp-config/build/bc.yml @@ -66,7 +66,7 @@ parameters: value: 1Gi objects: - kind: BuildConfig - apiVersion: v1 + apiVersion: build.openshift.io/v1 metadata: name: jenkins-master labels: @@ -119,7 +119,7 @@ objects: name: ${JENKINS_MASTER_BASE_FROM_IMAGE} successfulBuildsHistoryLimit: 20 - kind: BuildConfig - apiVersion: v1 + apiVersion: build.openshift.io/v1 metadata: name: jenkins-agent-base labels: @@ -166,7 +166,7 @@ objects: value: ${JENKINS_AGENT_BASE_AQUASEC_SCANNERCLI_URL} type: Docker successfulBuildsHistoryLimit: 20 -- apiVersion: v1 +- apiVersion: build.openshift.io/v1 kind: BuildConfig metadata: name: jenkins-webhook-proxy diff --git a/jenkins/ocp-config/build/is.yml b/jenkins/ocp-config/build/is.yml index 122ce2651..4ba6c5546 100644 --- a/jenkins/ocp-config/build/is.yml +++ b/jenkins/ocp-config/build/is.yml @@ -3,7 +3,7 @@ kind: Template metadata: name: jenkins objects: -- apiVersion: v1 +- apiVersion: image.openshift.io/v1 kind: ImageStream metadata: name: jenkins-master @@ -12,7 +12,7 @@ objects: spec: lookupPolicy: local: false -- apiVersion: v1 +- apiVersion: image.openshift.io/v1 kind: ImageStream metadata: name: jenkins-agent-base @@ -21,7 +21,7 @@ objects: spec: lookupPolicy: local: false -- apiVersion: v1 +- apiVersion: image.openshift.io/v1 kind: ImageStream metadata: name: jenkins-webhook-proxy diff --git a/jenkins/ocp-config/deploy/jenkins-master.yml b/jenkins/ocp-config/deploy/jenkins-master.yml index 7685dbca7..4cfa0aa8a 100644 --- a/jenkins/ocp-config/deploy/jenkins-master.yml +++ b/jenkins/ocp-config/deploy/jenkins-master.yml @@ -93,7 +93,7 @@ objects: app: jenkins name: nexus type: opaque -- apiVersion: v1 +- apiVersion: route.openshift.io/v1 kind: Route metadata: creationTimestamp: null @@ -128,7 +128,7 @@ objects: storage: '${JENKINS_VOLUME_CAPACITY}' storageClassName: '${STORAGE_CLASS_DATA}' volumeMode: Filesystem -- apiVersion: v1 +- apiVersion: apps.openshift.io/v1 kind: DeploymentConfig metadata: creationTimestamp: null diff --git a/jenkins/ocp-config/deploy/jenkins-webhook-proxy.yml b/jenkins/ocp-config/deploy/jenkins-webhook-proxy.yml index c8ea46d0b..5eed693a7 100644 --- a/jenkins/ocp-config/deploy/jenkins-webhook-proxy.yml +++ b/jenkins/ocp-config/deploy/jenkins-webhook-proxy.yml @@ -29,7 +29,7 @@ parameters: - name: WEBHOOK_PROXY_MEMORY_LIMIT value: 128Mi objects: -- apiVersion: v1 +- apiVersion: route.openshift.io/v1 kind: Route metadata: labels: @@ -63,7 +63,7 @@ objects: app: jenkins-webhook-proxy sessionAffinity: None type: ClusterIP -- apiVersion: v1 +- apiVersion: apps.openshift.io/v1 kind: DeploymentConfig metadata: labels: diff --git a/nexus/README.md b/nexus/README.md index 608523e55..7a0610218 100644 --- a/nexus/README.md +++ b/nexus/README.md @@ -2,8 +2,26 @@ Nexus is a repository manager. It allows you to proxy, collect, and manage your dependencies so that you are not constantly juggling a collection of artifacts. In essence. it makes it easy to distribute your software. -# Setup +## Setup -The OpenShift templates are located in `ocp-config` and can be compared with the OC cluster using [tailor](https://github.com/opendevstack/tailor). For example, run `cd oc-config && tailor status -l app=nexus -n ods` to see if there is any drift between current and desired state. +The OpenShift templates are located in `chart` and can be compared with the OC cluster using [Helm](https://github.com/helm/helm). For example, run `cd chart && helm secrets diff upgrade` to see if there is any drift between current and desired state. To install Nexus, run `make install-nexus`. + +## Administration + +There is an `admin` user which is allowed to change settings, install plugins, etc. The password is located in the OC project `ods`, under the `nexus-app` secrets. + +## Building a new image + +Push to this repository, then go to the build config in OC and start a new build. + +Aditionally you can run `make start-nexus-build`. + +## Manual steps performed after booting the instance + +1. Admin password changed (see OC secrets `sonarqube-app`). +2. Anonymous access to Nexus removed. +3. Blob stores created e.g docker, leva-documentation, releases, etc. +4. Repositories created e.g docker-group, leva-documentation, pypi-all, etc. +5. Developer account created. \ No newline at end of file diff --git a/nexus/chart/Chart.yaml b/nexus/chart/Chart.yaml new file mode 100644 index 000000000..8737a070a --- /dev/null +++ b/nexus/chart/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: Nexus +description: Nexus repository chart + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 1.0.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "3.67.1-java11" diff --git a/nexus/chart/templates/NOTES.txt b/nexus/chart/templates/NOTES.txt new file mode 100644 index 000000000..779239719 --- /dev/null +++ b/nexus/chart/templates/NOTES.txt @@ -0,0 +1 @@ +OpenDevStack Nexus OSS edition on version {{ .Values.global.nexusImageTag }} released with Helm! diff --git a/nexus/chart/templates/buildconfig.yaml b/nexus/chart/templates/buildconfig.yaml new file mode 100644 index 000000000..08848286c --- /dev/null +++ b/nexus/chart/templates/buildconfig.yaml @@ -0,0 +1,39 @@ +apiVersion: build.openshift.io/v1 +kind: BuildConfig +metadata: + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }} +spec: + failedBuildsHistoryLimit: 5 + nodeSelector: null + output: + to: + kind: ImageStreamTag + name: {{ printf "%s:%s" .Values.global.appName .Values.global.odsImageTag }} + postCommit: {} + resources: + limits: + cpu: {{ .Values.buildConfig.cpuLimit }} + memory: {{ .Values.buildConfig.memLimit }} + requests: + cpu: {{ .Values.buildConfig.cpuRequest }} + memory: {{ .Values.buildConfig.memRequest }} + runPolicy: Serial + source: + contextDir: nexus/docker + git: + uri: {{ .Values.global.repoBase }}/{{ .Values.global.odsBitBucketProject }}/ods-core.git + ref: {{ .Values.global.odsGitRef }} + sourceSecret: + name: cd-user-token + type: Git + strategy: + type: Docker + dockerStrategy: + from: + kind: DockerImage + name: sonatype/nexus3:{{ .Values.global.nexusImageTag }} + forcePull: true + noCache: true + successfulBuildsHistoryLimit: 5 diff --git a/nexus/chart/templates/deploymentconfig.yml b/nexus/chart/templates/deploymentconfig.yml new file mode 100644 index 000000000..62d1e4184 --- /dev/null +++ b/nexus/chart/templates/deploymentconfig.yml @@ -0,0 +1,99 @@ +kind: DeploymentConfig +apiVersion: apps.openshift.io/v1 +metadata: + name: {{ .Values.global.appName }} + labels: + app: {{ .Values.global.appName }} +spec: + strategy: + type: Recreate + recreateParams: + timeoutSeconds: 600 + resources: {} + activeDeadlineSeconds: 21600 + triggers: + - imageChangeParams: + automatic: true + containerNames: + - {{ .Values.global.appName }} + from: + kind: ImageStreamTag + name: {{ .Values.global.appName }}:{{ .Values.global.odsImageTag }} + namespace: {{ .Values.global.odsNamespace }} + type: ImageChange + - type: ConfigChange + replicas: 1 + revisionHistoryLimit: 10 + test: false + selector: + app: {{ .Values.global.appName }} + deploymentconfig: {{ .Values.global.appName }} + template: + metadata: + labels: + app: {{ .Values.global.appName }} + deploymentconfig: {{ .Values.global.appName }} + spec: + volumes: + - name: {{ .Values.global.appName }}-data + persistentVolumeClaim: + claimName: {{ .Values.global.appName }}-data + - name: {{ .Values.global.appName }}-db-backup + persistentVolumeClaim: + claimName: {{ .Values.global.appName }}-db-backup + containers: + - resources: + limits: + cpu: {{ .Values.nexus.cpuLimit }} + memory: {{ .Values.nexus.memLimit }} + requests: + cpu: {{ .Values.nexus.cpuRequest }} + memory: {{ .Values.nexus.memRequest }} + terminationMessagePath: /dev/termination-log + name: {{ .Values.global.appName }} + livenessProbe: + httpGet: + path: /service/rest/v1/status/writable + port: 8081 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 2 + failureThreshold: 10 + readinessProbe: + httpGet: + path: /service/rest/v1/status/writable + port: 8081 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 2 + failureThreshold: 3 + env: + - name: INSTALL4J_ADD_VM_PARAMS + value: '{{ .Values.global.nexusJvmParams }}' + ports: + - containerPort: 8081 + protocol: TCP + imagePullPolicy: Always + startupProbe: + httpGet: + path: /service/rest/v1/status/writable + port: 8081 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 30 + volumeMounts: + - name: {{ .Values.global.appName }}-data + mountPath: /nexus-data + - name: {{ .Values.global.appName }}-db-backup + mountPath: /nexus-backup + terminationMessagePolicy: File + image: {{ .Values.global.registry }}/{{ .Values.global.odsNamespace }}/{{ .Values.global.appName }}:{{ .Values.global.odsImageTag }} + restartPolicy: Always + terminationGracePeriodSeconds: 30 + dnsPolicy: ClusterFirst + securityContext: {} + schedulerName: default-scheduler diff --git a/nexus/chart/templates/imagestream.yml b/nexus/chart/templates/imagestream.yml new file mode 100644 index 000000000..f81d0a3ba --- /dev/null +++ b/nexus/chart/templates/imagestream.yml @@ -0,0 +1,9 @@ +apiVersion: image.openshift.io/v1 +kind: ImageStream +metadata: + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }} +spec: + lookupPolicy: + local: false diff --git a/nexus/chart/templates/pvc-data.yml b/nexus/chart/templates/pvc-data.yml new file mode 100644 index 000000000..1c1c1be71 --- /dev/null +++ b/nexus/chart/templates/pvc-data.yml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + annotations: + volume.beta.kubernetes.io/storage-provisioner: {{ .Values.global.storageProvisioner }} + finalizers: + - kubernetes.io/pvc-protection + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }}-data +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 60Gi + storageClassName: {{ .Values.global.storageClassData }} + volumeMode: Filesystem diff --git a/nexus/chart/templates/pvc-db-backup.yml b/nexus/chart/templates/pvc-db-backup.yml new file mode 100644 index 000000000..ee9355c24 --- /dev/null +++ b/nexus/chart/templates/pvc-db-backup.yml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + annotations: + volume.beta.kubernetes.io/storage-provisioner: {{ .Values.global.storageProvisioner }} + finalizers: + - kubernetes.io/pvc-protection + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }}-db-backup +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + storageClassName: {{ .Values.global.storageClassData }} + volumeMode: Filesystem diff --git a/nexus/chart/templates/route-docker.yaml b/nexus/chart/templates/route-docker.yaml new file mode 100644 index 000000000..7debcf31e --- /dev/null +++ b/nexus/chart/templates/route-docker.yaml @@ -0,0 +1,18 @@ +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + labels: + app: {{ .Values.global.appName }} + name: docker-group +spec: + host: {{ .Values.global.nexusDockerGroup }}-{{ .Values.global.odsNamespace }}{{ .Values.global.openshiftAppDomain}} + port: + targetPort: 5000-docker + tls: + insecureEdgeTerminationPolicy: Redirect + termination: edge + to: + kind: Service + name: {{ .Values.global.appName }} + weight: 100 + wildcardPolicy: None diff --git a/nexus/chart/templates/route-server.yaml b/nexus/chart/templates/route-server.yaml new file mode 100644 index 000000000..3900c23f8 --- /dev/null +++ b/nexus/chart/templates/route-server.yaml @@ -0,0 +1,18 @@ +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }} +spec: + host: {{ .Values.global.nexusHost }} + port: + targetPort: 8081-tcp + tls: + insecureEdgeTerminationPolicy: Redirect + termination: edge + to: + kind: Service + name: {{ .Values.global.appName }} + weight: 100 + wildcardPolicy: None diff --git a/nexus/chart/templates/secret.yaml b/nexus/chart/templates/secret.yaml new file mode 100644 index 000000000..339f2d79f --- /dev/null +++ b/nexus/chart/templates/secret.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +data: + admin-password: {{ .Values.global.nexusAdminPasswordB64 }} +metadata: + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }}-app +type: Opaque diff --git a/nexus/chart/templates/service.yaml b/nexus/chart/templates/service.yaml new file mode 100644 index 000000000..3d6b1c2f2 --- /dev/null +++ b/nexus/chart/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }} +spec: + ports: + - name: 8081-tcp + port: 8081 + protocol: TCP + targetPort: 8081 + - name: 5000-docker + port: 5000 + protocol: TCP + targetPort: 5000 + selector: + deploymentconfig: {{ .Values.global.appName }} + sessionAffinity: None + type: ClusterIP diff --git a/nexus/chart/values.yaml.template b/nexus/chart/values.yaml.template new file mode 100644 index 000000000..667ac4959 --- /dev/null +++ b/nexus/chart/values.yaml.template @@ -0,0 +1,26 @@ +global: + odsImageTag: $ODS_IMAGE_TAG + repoBase: $REPO_BASE + odsBitBucketProject: $ODS_BITBUCKET_PROJECT + odsGitRef: $ODS_GIT_REF + odsNamespace: $ODS_NAMESPACE + nexusImageTag: $NEXUS_IMAGE_TAG + appName: 'nexus' + storageProvisioner: $STORAGE_PROVISIONER + storageClassData: $STORAGE_CLASS_DATA + nexusHost: $NEXUS_HOST + nexusAdminPasswordB64: $NEXUS_ADMIN_PASSWORD_B64 + registry: $DOCKER_REGISTRY + openshiftAppDomain: $OPENSHIFT_APPS_BASEDOMAIN + nexusDockerGroup: 'docker-group' + nexusJvmParams: $NEXUS_JVM_PARAMS +nexus: + cpuRequest: 200m + cpuLimit: 1 + memRequest: 2Gi + memLimit: 4Gi +buildConfig: + cpuRequest: 200m + cpuLimit: 1 + memRequest: 1Gi + memLimit: 2Gi diff --git a/nexus/docker/Dockerfile b/nexus/docker/Dockerfile index dbcadd434..b2ebde6ae 100644 --- a/nexus/docker/Dockerfile +++ b/nexus/docker/Dockerfile @@ -1,2 +1,2 @@ -# FROM instruction is overwritten with NEXUS_FROM_IMAGE. +# FROM instruction is overwritten with BuildConfig and NEXUS_IMAGE_TAG. FROM sonatype/nexus3:latest diff --git a/nexus/ocp-config/Tailorfile b/nexus/ocp-config/Tailorfile deleted file mode 100644 index c27899cf7..000000000 --- a/nexus/ocp-config/Tailorfile +++ /dev/null @@ -1,10 +0,0 @@ -namespace ods -selector app=nexus -param-file ../../../ods-configuration/ods-core.env -ignore-unknown-parameters true -preserve-immutable-fields true -preserve pvc:/spec/volumeMode -preserve svc:/spec/clusterIPs -preserve pvc:/metadata/annotations/volume.beta.kubernetes.io/storage-class - -dc,is,pvc,route,svc diff --git a/nexus/ocp-config/bc.yml b/nexus/ocp-config/bc.yml deleted file mode 100644 index ff60b05ea..000000000 --- a/nexus/ocp-config/bc.yml +++ /dev/null @@ -1,61 +0,0 @@ -apiVersion: template.openshift.io/v1 -kind: Template -parameters: -- name: ODS_BITBUCKET_PROJECT - value: opendevstack -- name: ODS_IMAGE_TAG - required: true -- name: ODS_GIT_REF - required: true -- name: REPO_BASE - required: true -- name: NEXUS_FROM_IMAGE - required: true -- name: NEXUS_BUILD_CPU_REQUEST - value: 200m -- name: NEXUS_BUILD_CPU_LIMIT - value: "1" -- name: NEXUS_BUILD_MEMORY_REQUEST - value: 1Gi -- name: NEXUS_BUILD_MEMORY_LIMIT - value: 2Gi -objects: -- apiVersion: v1 - kind: BuildConfig - metadata: - labels: - app: nexus - name: nexus - spec: - failedBuildsHistoryLimit: 5 - nodeSelector: null - output: - to: - kind: ImageStreamTag - name: nexus:${ODS_IMAGE_TAG} - postCommit: {} - resources: - limits: - cpu: ${NEXUS_BUILD_CPU_LIMIT} - memory: ${NEXUS_BUILD_MEMORY_LIMIT} - requests: - cpu: ${NEXUS_BUILD_CPU_REQUEST} - memory: ${NEXUS_BUILD_MEMORY_REQUEST} - runPolicy: Serial - source: - contextDir: nexus/docker - git: - uri: ${REPO_BASE}/${ODS_BITBUCKET_PROJECT}/ods-core.git - ref: ${ODS_GIT_REF} - sourceSecret: - name: cd-user-token - type: Git - strategy: - dockerStrategy: - forcePull: true - noCache: true - from: - kind: DockerImage - name: ${NEXUS_FROM_IMAGE} - type: Docker - successfulBuildsHistoryLimit: 5 diff --git a/nexus/ocp-config/dc.yml b/nexus/ocp-config/dc.yml deleted file mode 100644 index 04e9db0d0..000000000 --- a/nexus/ocp-config/dc.yml +++ /dev/null @@ -1,87 +0,0 @@ -apiVersion: template.openshift.io/v1 -kind: Template -parameters: -- name: ODS_NAMESPACE - value: ods -- name: ODS_IMAGE_TAG - required: true -- name: NEXUS_NAME - value: nexus -- name: NEXUS_CPU_REQUEST - value: 200m -- name: NEXUS_CPU_LIMIT - value: "1" -- name: NEXUS_MEMORY_REQUEST - value: 2560Mi -- name: NEXUS_MEMORY_LIMIT - value: 4Gi -objects: -- apiVersion: v1 - kind: DeploymentConfig - metadata: - labels: - app: ${NEXUS_NAME} - name: ${NEXUS_NAME} - spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - app: ${NEXUS_NAME} - deploymentconfig: ${NEXUS_NAME} - strategy: - activeDeadlineSeconds: 21600 - resources: {} - recreateParams: - timeoutSeconds: 600 - type: Recreate - template: - metadata: - labels: - app: ${NEXUS_NAME} - deploymentconfig: ${NEXUS_NAME} - spec: - containers: - - image: ${ODS_NAMESPACE}/${NEXUS_NAME}:${ODS_IMAGE_TAG} - imagePullPolicy: Always - name: ${NEXUS_NAME} - ports: - - containerPort: 8081 - protocol: TCP - resources: - limits: - cpu: ${NEXUS_CPU_LIMIT} - memory: ${NEXUS_MEMORY_LIMIT} - requests: - cpu: ${NEXUS_CPU_REQUEST} - memory: ${NEXUS_MEMORY_REQUEST} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - volumeMounts: - - mountPath: /nexus-data - name: volume-fmcqy - - mountPath: /nexus-backup - name: volume-8dv8t - dnsPolicy: ClusterFirst - restartPolicy: Always - schedulerName: default-scheduler - securityContext: {} - terminationGracePeriodSeconds: 30 - volumes: - - name: volume-fmcqy - persistentVolumeClaim: - claimName: nexus-data - - name: volume-8dv8t - persistentVolumeClaim: - claimName: nexus-db-backup - test: false - triggers: - - imageChangeParams: - automatic: true - containerNames: - - ${NEXUS_NAME} - from: - kind: ImageStreamTag - name: ${NEXUS_NAME}:${ODS_IMAGE_TAG} - namespace: ${ODS_NAMESPACE} - type: ImageChange - - type: ConfigChange diff --git a/nexus/ocp-config/is.yml b/nexus/ocp-config/is.yml deleted file mode 100644 index 0864ee5da..000000000 --- a/nexus/ocp-config/is.yml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: template.openshift.io/v1 -kind: Template -objects: -- apiVersion: v1 - kind: ImageStream - metadata: - labels: - app: nexus - name: nexus - spec: - lookupPolicy: - local: false diff --git a/nexus/ocp-config/pvc.yml b/nexus/ocp-config/pvc.yml deleted file mode 100644 index 354d4a9a8..000000000 --- a/nexus/ocp-config/pvc.yml +++ /dev/null @@ -1,55 +0,0 @@ -apiVersion: template.openshift.io/v1 -kind: Template -parameters: -- name: NEXUS_NAME - value: nexus -- name: STORAGE_PROVISIONER - description: storage class provisioner. For AWS this could be kubernetes.io/aws-ebs. Leave empty for local (e.g. vagrant) deployments - value: "" -- name: STORAGE_CLASS_DATA - description: storage class for data. For AWS this could be gp2. Leave empty for local (e.g. vagrant) deployments - value: "" -- name: STORAGE_CLASS_BACKUP - description: Storage class for data backup. For AWS this could be gp2-encrypted. Leave empty for local (e.g. vagrant) deployments - value: "" -- name: NEXUS_DATA_CAPACITY - value: 60Gi -- name: NEXUS_BACKUP_CAPACITY - value: 10Gi -objects: -- apiVersion: v1 - kind: PersistentVolumeClaim - metadata: - annotations: - volume.beta.kubernetes.io/storage-provisioner: ${STORAGE_PROVISIONER} - finalizers: - - kubernetes.io/pvc-protection - labels: - app: ${NEXUS_NAME} - name: nexus-data - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: ${NEXUS_DATA_CAPACITY} - storageClassName: ${STORAGE_CLASS_DATA} - volumeMode: Filesystem -- apiVersion: v1 - kind: PersistentVolumeClaim - metadata: - annotations: - volume.beta.kubernetes.io/storage-provisioner: ${STORAGE_PROVISIONER} - finalizers: - - kubernetes.io/pvc-protection - labels: - app: ${NEXUS_NAME} - name: nexus-db-backup - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: ${NEXUS_BACKUP_CAPACITY} - storageClassName: ${STORAGE_CLASS_BACKUP} - volumeMode: Filesystem diff --git a/nexus/ocp-config/route.yml b/nexus/ocp-config/route.yml deleted file mode 100644 index f1b78b6f1..000000000 --- a/nexus/ocp-config/route.yml +++ /dev/null @@ -1,53 +0,0 @@ -apiVersion: template.openshift.io/v1 -kind: Template -parameters: -- name: NEXUS_NAME - value: nexus -- name: NEXUS_DOCKER_NAME - value: docker-group -- name: NEXUS_HOST - description: Nexus host without protocol - which is attached based on the configuration in the route.yml - required: true -- name: OPENSHIFT_APPS_BASEDOMAIN - description: the domain of routes exposed on OCP. - required: true -- name: ODS_NAMESPACE - description: Central ODS namespace in OpenShift. - required: true -objects: -- apiVersion: v1 - kind: Route - metadata: - labels: - app: ${NEXUS_NAME} - name: ${NEXUS_NAME} - spec: - host: ${NEXUS_HOST} - port: - targetPort: 8081-tcp - tls: - insecureEdgeTerminationPolicy: Redirect - termination: edge - to: - kind: Service - name: ${NEXUS_NAME} - weight: 100 - wildcardPolicy: None -- apiVersion: v1 - kind: Route - metadata: - labels: - app: ${NEXUS_NAME} - name: ${NEXUS_DOCKER_NAME} - spec: - host: ${NEXUS_DOCKER_NAME}-${ODS_NAMESPACE}${OPENSHIFT_APPS_BASEDOMAIN} - port: - targetPort: 5000-docker - tls: - insecureEdgeTerminationPolicy: Redirect - termination: edge - to: - kind: Service - name: ${NEXUS_NAME} - weight: 100 - wildcardPolicy: None diff --git a/nexus/ocp-config/svc.yml b/nexus/ocp-config/svc.yml deleted file mode 100644 index d75a5986e..000000000 --- a/nexus/ocp-config/svc.yml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: template.openshift.io/v1 -kind: Template -parameters: -- name: NEXUS_NAME - value: nexus -objects: -- apiVersion: v1 - kind: Service - metadata: - labels: - app: ${NEXUS_NAME} - name: ${NEXUS_NAME} - spec: - ports: - - name: 8081-tcp - port: 8081 - protocol: TCP - targetPort: 8081 - - name: 5000-docker - port: 5000 - protocol: TCP - targetPort: 5000 - selector: - deploymentconfig: ${NEXUS_NAME} - sessionAffinity: None - type: ClusterIP diff --git a/nexus/test.sh b/nexus/test.sh index 45d975fd4..c7f045704 100755 --- a/nexus/test.sh +++ b/nexus/test.sh @@ -6,7 +6,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ODS_CORE_DIR=${SCRIPT_DIR%/*} ODS_CONFIGURATION_DIR="${ODS_CORE_DIR}/../ods-configuration" -NEXUS_IMAGE=$("${ODS_CORE_DIR}"/scripts/get-sample-param.sh NEXUS_FROM_IMAGE) +NEXUS_IMAGE=$("${ODS_CORE_DIR}"/scripts/get-sample-param.sh NEXUS_IMAGE_TAG) function usage { printf "Test Nexus setup.\n\n" @@ -62,7 +62,7 @@ if ! $VERIFY_ONLY; then NO_PROXY= echo "Run container using image ${NEXUS_IMAGE}" - containerId=$(docker run -d -p "${HOST_PORT}:8081" -e HTTP_PROXY="${HTTP_PROXY}" -e HTTPS_PROXY="${HTTPS_PROXY}" -e NO_PROXY="${NO_PROXY}" "${NEXUS_IMAGE}") + containerId=$(docker run -d -p "${HOST_PORT}:8081" -e HTTP_PROXY="${HTTP_PROXY}" -e HTTPS_PROXY="${HTTPS_PROXY}" -e NO_PROXY="${NO_PROXY}" "sonatype/nexus3:${NEXUS_IMAGE}") function cleanup { echo "Cleanup" diff --git a/ods-document-generation-svc/ocp-config/bc.yml b/ods-document-generation-svc/ocp-config/bc.yml index 21f8a94d3..0300f502c 100644 --- a/ods-document-generation-svc/ocp-config/bc.yml +++ b/ods-document-generation-svc/ocp-config/bc.yml @@ -29,7 +29,7 @@ parameters: labels: app: ods-doc-gen-svc objects: -- apiVersion: v1 +- apiVersion: build.openshift.io/v1 kind: BuildConfig metadata: name: ods-doc-gen-svc diff --git a/ods-document-generation-svc/ocp-config/is.yml b/ods-document-generation-svc/ocp-config/is.yml index 0da9d7a27..a00bfb658 100644 --- a/ods-document-generation-svc/ocp-config/is.yml +++ b/ods-document-generation-svc/ocp-config/is.yml @@ -3,7 +3,7 @@ kind: Template labels: app: ods-doc-gen-svc objects: -- apiVersion: v1 +- apiVersion: image.openshift.io/v1 kind: ImageStream metadata: name: ods-doc-gen-svc diff --git a/ods-provisioning-app/ocp-config/bc.yml b/ods-provisioning-app/ocp-config/bc.yml index adad759f4..11dc4dfbf 100644 --- a/ods-provisioning-app/ocp-config/bc.yml +++ b/ods-provisioning-app/ocp-config/bc.yml @@ -21,7 +21,7 @@ parameters: labels: app: ods-provisioning-app objects: -- apiVersion: v1 +- apiVersion: build.openshift.io/v1 kind: BuildConfig metadata: name: ods-provisioning-app diff --git a/ods-provisioning-app/ocp-config/dc.yml b/ods-provisioning-app/ocp-config/dc.yml index de91cdf53..af8584d44 100644 --- a/ods-provisioning-app/ocp-config/dc.yml +++ b/ods-provisioning-app/ocp-config/dc.yml @@ -18,7 +18,7 @@ parameters: labels: app: ods-provisioning-app objects: -- apiVersion: v1 +- apiVersion: apps.openshift.io/v1 kind: DeploymentConfig metadata: name: ods-provisioning-app diff --git a/ods-provisioning-app/ocp-config/is.yml b/ods-provisioning-app/ocp-config/is.yml index 860e6248a..d5ed913e9 100644 --- a/ods-provisioning-app/ocp-config/is.yml +++ b/ods-provisioning-app/ocp-config/is.yml @@ -3,7 +3,7 @@ kind: Template labels: app: ods-provisioning-app objects: -- apiVersion: v1 +- apiVersion: image.openshift.io/v1 kind: ImageStream metadata: name: ods-provisioning-app diff --git a/ods-provisioning-app/ocp-config/route.yml b/ods-provisioning-app/ocp-config/route.yml index b262e7e3c..0a944c9b8 100644 --- a/ods-provisioning-app/ocp-config/route.yml +++ b/ods-provisioning-app/ocp-config/route.yml @@ -8,7 +8,7 @@ parameters: labels: app: ods-provisioning-app objects: -- apiVersion: v1 +- apiVersion: route.openshift.io/v1 kind: Route metadata: annotations: diff --git a/scripts/migrate-sonar-users.sh b/scripts/migrate-sonar-users.sh new file mode 100644 index 000000000..a20681284 --- /dev/null +++ b/scripts/migrate-sonar-users.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +set -ue + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ODS_CORE_DIR=${SCRIPT_DIR%/*} +ODS_CONFIGURATION_DIR="${ODS_CORE_DIR}/../ods-configuration" + +echo_done(){ + echo -e "\033[92mDONE\033[39m: $1" +} + +echo_warn(){ + echo -e "\033[93mWARN\033[39m: $1" +} + +echo_error(){ + echo -e "\033[31mERROR\033[39m: $1" +} + +echo_info(){ + echo -e "\033[94mINFO\033[39m: $1" +} + + +SONARQUBE_URL="" +SONAR_ADMIN_USERNAME="" +SONAR_ADMIN_PASSWORD="" +INSECURE="" + +function usage { + printf "Migrate SonarQube users from Atlassian Crowd provider to Saml provider.\n\n" + printf "This script will ask interactively for parameters if not in ods-configuraion.\n" + printf "However, you can also pass them directly. Usage:\n\n" + printf "\t-h|--help\t\tPrint usage\n" + printf "\t-v|--verbose\t\tEnable verbose mode\n" + printf "\t-i|--insecure\t\tAllow insecure server connections when using SSL\n" + printf "\n" + printf "\t-s|--sonarqube\t\tSonarQube URL, e.g. 'https://sonarqube.example.com'\n" + printf "\t-u|--admin-user\tAdmin user\n" + printf "\t-p|--admin-password\tAdmin password\n" +} + +while [[ "$#" -gt 0 ]]; do + case $1 in + + -v|--verbose) set -x;; + + -h|--help) usage; exit 0;; + + -i|--insecure) INSECURE="--insecure";; + + -p|--admin-password) SONAR_ADMIN_PASSWORD="$2"; shift;; + -p=*|--admin-password=*) SONAR_ADMIN_PASSWORD="${1#*=}";; + + -u|--admin-user) SONAR_ADMIN_USERNAME="$2"; shift;; + -u=*|--admin-user=*) SONAR_ADMIN_USERNAME="${1#*=}";; + + -s|--sonarqube) SONARQUBE_URL="$2"; shift;; + -s=*|--sonarqube=*) SONARQUBE_URL="${1#*=}";; + + *) echo_error "Unknown parameter passed: $1"; exit 1;; +esac; shift; done + +if [ -f "${ODS_CONFIGURATION_DIR}/ods-core.env" ]; then + + if [ -z "${SONARQUBE_URL}" ]; then + SONARQUBE_URL=$(../scripts/get-config-param.sh SONARQUBE_URL) + fi + + if [ -z "${SONAR_ADMIN_USERNAME}" ]; then + SONAR_ADMIN_USERNAME=$(../scripts/get-config-param.sh SONAR_ADMIN_USERNAME) + fi + + if [ -z "${SONAR_ADMIN_PASSWORD}" ]; then + SONAR_ADMIN_PASSWORD=$(../scripts/get-config-param.sh SONAR_ADMIN_PASSWORD_B64 | base64 -d) + fi + +fi + +Email_list=$( curl ${INSECURE} ${SONAR_URL}/api/users/search -u admin:${SONAR_ADMIN_TOKEN} | jq .users | grep login | grep @ | tr -d '"' | tr -d "," | cut -f2 -d ":" ) +email_list_array=($Email_list) + +for email in "${email_list_array[@]}" +do + curl ${INSECURE} -X POST -sSf -u admin:${SONAR_ADMIN_TOKEN} "${SONAR_URL}/api/users/update_identity_provider?newExternalProvider=saml&login=${email}" > /dev/null + echo "User ${email} migrated to Saml" +done diff --git a/scripts/tailor2helm.sh b/scripts/tailor2helm.sh new file mode 100644 index 000000000..e65efdb63 --- /dev/null +++ b/scripts/tailor2helm.sh @@ -0,0 +1,83 @@ +#bin/bash + +set -eu + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ODS_CORE_DIR=${SCRIPT_DIR%/*} +ODS_CONFIGURATION_DIR="${ODS_CORE_DIR}/../ods-configuration" + +echo_done(){ + echo -e "\033[92mDONE\033[39m: $1" +} + +echo_warn(){ + echo -e "\033[93mWARN\033[39m: $1" +} + +echo_error(){ + echo -e "\033[31mERROR\033[39m: $1" +} + +echo_info(){ + echo -e "\033[94mINFO\033[39m: $1" +} + +LABEL="" +RELEASE="" +NAMESPACE="" + +function usage { + printf "Adopt Tailor resources into Helm release.\n\n" + printf "This script will ask interactively for parameters by default.\n" + printf "Namespace is optional, but will be read from ods-core.env if available.\n" + printf "However, you can also pass them directly. Usage:\n\n" + printf "\t-h|--help\t\tPrint usage\n" + printf "\t-v|--verbose\t\tEnable verbose mode\n" + printf "\n" + printf "\t-l|--label\t\tResources label, e.g. 'app=component'\n" + printf "\t-r|--release\t\tHelm relese\n" + printf "\t-n|--namespace\t\tODS namespace\n" +} + +while [[ "$#" -gt 0 ]]; do + case $1 in + + -v|--verbose) set -x;; + + -h|--help) usage; exit 0;; + + -l|--label) LABEL="$2"; shift;; + -l=*|--label=*) LABEL="${1#*=}";; + + -r|--release) RELEASE="$2"; shift;; + -r=*|--release=*) RELEASE="${1#*=}";; + + -o|--namespace) NAMESPACE="$2"; shift;; + -o=*|--namespace=*) NAMESPACE="${1#*=}";; + + *) echo_error "Unknown parameter passed: $1"; exit 1;; +esac; shift; done + +if [ -f "${ODS_CONFIGURATION_DIR}/ods-core.env" ] && [ -z "${NAMESPACE}" ]; then + NAMESPACE=$(../scripts/get-config-param.sh ODS_NAMESPACE) +fi + +if [ -z "${LABEL}" ]; then + read -r -e -p "Enter label of the resources to adopt: " input + LABEL="${input}" +fi + +if [ -z "${RELEASE}" ]; then + read -r -e -p "Enter helm release name: " input + RELEASE="${input}" +fi + +KINDS='ImageStream,BuildConfig,Service,DeploymentConfig,Deployment,Route,ConfigMap,Secret,PersistentVolumeClaim,ServiceAccount,RoleBinding' +RESOURCES=$(oc -n $NAMESPACE get $KINDS -l $LABEL -o template='{{range .items}}{{.kind}}/{{.metadata.name}} {{end}}') + +for RESOURCE in $RESOURCES; do + echo "Adopting $RESOURCE ..." + oc -n $NAMESPACE annotate $RESOURCE meta.helm.sh/release-name=$RELEASE + oc -n $NAMESPACE annotate $RESOURCE meta.helm.sh/release-namespace=$NAMESPACE + oc -n $NAMESPACE label $RESOURCE app.kubernetes.io/managed-by=Helm +done diff --git a/sonarqube/README.md b/sonarqube/README.md index eac394d9a..51da7efa2 100644 --- a/sonarqube/README.md +++ b/sonarqube/README.md @@ -2,21 +2,24 @@ SonarQube is an open source platform developed by SonarSource for continuous inspection of code quality to perform automatic reviews with static analysis of code to detect bugs, code smells, and security vulnerabilities. -This repo contains the build recipe for a central SonarQube instance to which all Jenkins instances send reports to. The remainder of this readme describes how that setup is done. -If you are looking for instructions how to analyse your repositories, please see [USAGE.md](https://github.com/opendevstack/ods-core/blob/master/USAGE.md). +This repo contains the build recipe for a central SonarQube instance to which all Jenkins instances send reports to. ## Setup -The OpenShift templates are located in `ocp-config` and can be compared with the OC cluster using [tailor](https://github.com/opendevstack/tailor). For example, run `cd ocp-config && tailor status` to see if there is any drift between current and desired state. +The OpenShift templates are located in `chart` and can be compared with the OC cluster using [helm](https://github.com/helm/helm). For example, run `cd chart && helm secrets diff upgrade` to see if there is any drift between current and desired state. + +To install SonarQube, run `make install-sonarqube`. ## Administration -There is an `admin` user which is allowed to change settings, install plugins, etc. The password is located in the OC project `cd`, under the `sonarqube-app` secrets. +There is an `admin` user which is allowed to change settings, install plugins, etc. The password is located in the OC project `ods`, under the `sonarqube-app` secrets. ## Building a new image Push to this repository, then go to the build config in OC and start a new build. +Aditionally you can run `make start-sonarqube-build`. + ## Manual steps performed after booting the instance 1. Admin password changed (see OC secrets `sonarqube-app`). diff --git a/sonarqube/backup.sh b/sonarqube/backup.sh index 8dcaa8fc5..b064ea678 100755 --- a/sonarqube/backup.sh +++ b/sonarqube/backup.sh @@ -1,15 +1,23 @@ #!/bin/bash set -eu -NAMESPACE="ods" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ODS_CORE_DIR=${SCRIPT_DIR%/*} +ODS_CONFIGURATION_DIR="${ODS_CORE_DIR}/../ods-configuration" + +NAMESPACE="" BACKUP_DIR="." +PROGRESS=false +LOCAL=false function usage { - printf "usage: %s [options]\n" "$0" + printf "usage: %s [options]\n" "$0" printf "\t-h|--help\tPrints the usage\n" printf "\t-v|--verbose\tVerbose output\n" printf "\t-b|--backup-dir\tLocation of backup directory\n" - printf "\t-n|--namespace\tNamespace (defaults to '%s')\n" "${NAMESPACE}" + printf "\t-n|--namespace\tNamespace, optional param as it will be read from ods-core.env if available\n" + printf "\t-p|--progress\tShow progress during transfer (defaults to '%s')\n" "${PROGRESS}" + printf "\t-l|--local-copy\tCopy the database dump in local (defaults to '%s')\n" "${LOCAL}" } while [[ "$#" -gt 0 ]]; do case $1 in @@ -23,22 +31,32 @@ while [[ "$#" -gt 0 ]]; do case $1 in -n=*|--namespace=*) NAMESPACE="${1#*=}";; -n|--namespace) NAMESPACE="$2"; shift;; + -p=*|--progress=*) PROGRESS="${1#*=}";; + -p|--progress) PROGRESS="$2"; shift;; + + -l=*|--local-copy=*) LOCAL="${1#*=}";; + -l|--local-copy) LOCAL="$2"; shift;; + *) echo "Unknown parameter passed: $1"; usage; exit 1;; esac; shift; done +if [ -f "${ODS_CONFIGURATION_DIR}/ods-core.env" ] && [ -z "${NAMESPACE}" ]; then + NAMESPACE=$(../scripts/get-config-param.sh ODS_NAMESPACE) +fi + if ! oc whoami > /dev/null; then echo "You need to log into OpenShift first" exit 1 fi # Dump database -destinationFile="${BACKUP_DIR}/sonarqube.sql" podWithPrefix=$(oc get pods -n "${NAMESPACE}" --selector name=sonarqube-postgresql --no-headers -o name) pod=${podWithPrefix#"pod/"} -oc rsh -n "${NAMESPACE}" "pod/${pod}" bash -c "mkdir -p /var/lib/pgsql/backup && pg_dump sonarqube > /var/lib/pgsql/backup/sonarqube.sql" -# Copy export -oc -n "${NAMESPACE}" cp "${pod}:/var/lib/pgsql/backup/sonarqube.sql" "${destinationFile}" -# Delete export in pod -oc rsh -n "${NAMESPACE}" "pod/${pod}" bash -c "rm /var/lib/pgsql/backup/sonarqube.sql" +oc rsh -n "${NAMESPACE}" "pod/${pod}" bash -c "pg_dump sonarqube > /var/lib/pgsql/backups/sonarqube.sql" +echo "Database 'sonarqube' dumped and stored in /var/lib/pgsql/backups/sonarqube.sql." -echo "Database 'sonarqube' backed up to ${destinationFile}." +if [ "${LOCAL}" == true ]; then +# Copy export locally +oc -n "${NAMESPACE}" rsync --progress="${PROGRESS}" "${pod}:/var/lib/pgsql/backups/sonarqube.sql" "${BACKUP_DIR}" +echo "Database 'sonarqube' backed up to ${BACKUP_DIR}." +fi diff --git a/sonarqube/chart/Chart.yaml b/sonarqube/chart/Chart.yaml new file mode 100644 index 000000000..080ee4f65 --- /dev/null +++ b/sonarqube/chart/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: SonarQube +description: Sonarqube chart + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 1.0.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "9.9.4" diff --git a/sonarqube/chart/templates/NOTES.txt b/sonarqube/chart/templates/NOTES.txt new file mode 100644 index 000000000..3790041bd --- /dev/null +++ b/sonarqube/chart/templates/NOTES.txt @@ -0,0 +1 @@ +OpenDevStack SonarQube {{ .Values.global.sonarEdition }} edition on version {{ .Values.global.sonarVersion }} released with Helm! diff --git a/sonarqube/chart/templates/buildconfig.yaml b/sonarqube/chart/templates/buildconfig.yaml new file mode 100644 index 000000000..4fa748ed8 --- /dev/null +++ b/sonarqube/chart/templates/buildconfig.yaml @@ -0,0 +1,46 @@ +apiVersion: build.openshift.io/v1 +kind: BuildConfig +metadata: + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }} +spec: + failedBuildsHistoryLimit: 5 + nodeSelector: null + output: + to: + kind: ImageStreamTag + name: {{ printf "%s:%s" .Values.global.appName .Values.global.odsImageTag }} + postCommit: {} + resources: + limits: + cpu: {{ .Values.buildConfig.cpuLimit }} + memory: {{ .Values.buildConfig.memLimit }} + requests: + cpu: {{ .Values.buildConfig.cpuRequest }} + memory: {{ .Values.buildConfig.memRequest }} + runPolicy: Serial + source: + contextDir: sonarqube/docker + git: + uri: {{ .Values.global.repoBase }}/{{ .Values.global.odsBitBucketProject }}/ods-core.git + ref: {{ .Values.global.odsGitRef }} + sourceSecret: + name: cd-user-token + type: Git + strategy: + type: Docker + dockerStrategy: + from: + kind: DockerImage + name: sonarqube:{{ .Values.global.sonarVersion }}-{{ .Values.global.sonarEdition }} + forcePull: true + noCache: true + buildArgs: + - name: sonarVersion + value: {{ .Values.global.sonarVersion }} + - name: APP_DNS + value: {{ .Values.global.appDNS }} + - name: sonarEdition + value: {{ .Values.global.sonarEdition }} + successfulBuildsHistoryLimit: 5 diff --git a/sonarqube/chart/templates/cm.yaml b/sonarqube/chart/templates/cm.yaml new file mode 100644 index 000000000..f44716e0e --- /dev/null +++ b/sonarqube/chart/templates/cm.yaml @@ -0,0 +1,11 @@ +kind: ConfigMap +metadata: + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }} +apiVersion: v1 +data: + database-jdbc-url: {{ .Values.global.sonarDatabaseJdbcUrl }} + database-name: {{ .Values.global.sonarDatabaseName }} + database-user: {{ .Values.global.sonarDatabaseUser }} + sonarqube-admin-user: {{ .Values.global.sonarAdminUsername }} diff --git a/sonarqube/chart/templates/dc-postgresql.yaml b/sonarqube/chart/templates/dc-postgresql.yaml new file mode 100644 index 000000000..4e4dc6673 --- /dev/null +++ b/sonarqube/chart/templates/dc-postgresql.yaml @@ -0,0 +1,101 @@ +kind: DeploymentConfig +apiVersion: apps.openshift.io/v1 +metadata: + annotations: + template.alpha.openshift.io/wait-for-ready: "true" + labels: + app: {{ .Values.global.appName }} + template: postgresql-persistent-template + name: {{ .Values.global.appName }}-postgresql +spec: + replicas: 1 + revisionHistoryLimit: 10 + selector: + name: {{ .Values.global.appName }}-postgresql + strategy: + activeDeadlineSeconds: 21600 + recreateParams: + timeoutSeconds: 600 + resources: {} + type: Recreate + template: + metadata: + labels: + name: {{ .Values.global.appName }}-postgresql + spec: + containers: + - env: + - name: POSTGRESQL_USER + valueFrom: + configMapKeyRef: + key: database-user + name: {{ .Values.global.appName }} + - name: POSTGRESQL_PASSWORD + valueFrom: + secretKeyRef: + key: database-password + name: {{ .Values.global.appName }}-postgresql + - name: POSTGRESQL_DATABASE + valueFrom: + configMapKeyRef: + key: database-name + name: {{ .Values.global.appName }} + image: {{ .Values.global.sonarDatabaseImage}} + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + tcpSocket: + port: 5432 + timeoutSeconds: 1 + name: {{ .Values.postgresql.name }} + ports: + - containerPort: 5432 + protocol: TCP + readinessProbe: + exec: + command: + - /bin/sh + - -i + - -c + - psql -h 127.0.0.1 -U $POSTGRESQL_USER -q -d $POSTGRESQL_DATABASE -c + 'SELECT 1' + failureThreshold: 3 + initialDelaySeconds: 5 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + cpu: {{ .Values.postgresql.cpuLimit }} + memory: {{ .Values.postgresql.memLimit }} + requests: + cpu: {{ .Values.postgresql.cpuRequest }} + memory: {{ .Values.postgresql.memRequest }} + securityContext: + capabilities: {} + privileged: false + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /var/lib/pgsql/data + name: {{ .Values.global.appName }}-postgresql-data + - mountPath: /var/lib/pgsql/backups + name: {{ .Values.global.appName }}-postgresql-backup + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - name: {{ .Values.global.appName }}-postgresql-data + persistentVolumeClaim: + claimName: {{ .Values.global.appName }}-postgresql + - name: {{ .Values.global.appName }}-postgresql-backup + persistentVolumeClaim: + claimName: {{ .Values.global.appName }}-postgresql-backup + test: false + triggers: + - type: ConfigChange diff --git a/sonarqube/chart/templates/dc-sonar.yaml b/sonarqube/chart/templates/dc-sonar.yaml new file mode 100644 index 000000000..6355cc1d1 --- /dev/null +++ b/sonarqube/chart/templates/dc-sonar.yaml @@ -0,0 +1,147 @@ +kind: DeploymentConfig +apiVersion: apps.openshift.io/v1 +metadata: + name: {{ .Values.global.appName }} + labels: + app: {{ .Values.global.appName }} +spec: + strategy: + type: Recreate + recreateParams: + timeoutSeconds: 600 + resources: {} + activeDeadlineSeconds: 21600 + triggers: + - imageChangeParams: + automatic: true + containerNames: + - {{ .Values.global.appName }} + from: + kind: ImageStreamTag + name: {{ .Values.global.appName }}:{{ .Values.global.odsImageTag }} + namespace: {{ .Values.global.odsNamespace }} + type: ImageChange + - type: ConfigChange + replicas: 1 + revisionHistoryLimit: 10 + test: false + selector: + app: {{ .Values.global.appName }} + deploymentconfig: {{ .Values.global.appName }} + template: + metadata: + labels: + app: {{ .Values.global.appName }} + deploymentconfig: {{ .Values.global.appName }} + tuned.openshift.io/elasticsearch: "" + spec: + volumes: + - name: {{ .Values.global.appName }}-data + persistentVolumeClaim: + claimName: {{ .Values.global.appName }}-data + - name: {{ .Values.global.appName }}-extensions + persistentVolumeClaim: + claimName: {{ .Values.global.appName }}-extensions + containers: + - resources: + limits: + cpu: {{ .Values.sonarqube.cpuLimit }} + memory: {{ .Values.sonarqube.memLimit }} + requests: + cpu: {{ .Values.sonarqube.cpuRequest }} + memory: {{ .Values.sonarqube.memRequest }} + terminationMessagePath: /dev/termination-log + name: {{ .Values.global.appName }} + livenessProbe: + httpGet: + path: /api/system/status + port: 9000 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 2 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /api/system/status + port: 9000 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 2 + failureThreshold: 3 + env: + - name: SONARQUBE_JDBC_USERNAME + valueFrom: + configMapKeyRef: + name: {{ .Values.global.appName }} + key: database-user + - name: SONARQUBE_JDBC_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.global.appName }}-postgresql + key: database-password + - name: SONAR_SEARCH_JAVAADDITIONALOPTS + value: '-Dlog4j2.formatMsgNoLookups=true' + - name: SONARQUBE_JDBC_URL + value: 'jdbc:postgresql://{{ .Values.global.appName }}-postgresql:5432/sonarqube' + - name: SONAR_FORCEAUTHENTICATION + value: 'true' + - name: SONAR_AUTH_SAML_ENABLED + value: '{{ .Values.sonarqube.sonarAuthSaml }}' + {{ if ( eq .Values.sonarqube.sonarAuthSaml "true" )}} + - name: SONAR_AUTH_SAML_APPLICATIONID + value: {{ .Values.sonarqube.sonarAuthSamlApplicationId }} + - name: SONAR_CORE_SERVERBASEURL + value: {{ .Values.sonarqube.sonarAuthSamlServerBaseUrl }} + - name: SONAR_AUTH_SAML_PROVIDERID + valueFrom: + secretKeyRef: + name: {{ .Values.global.appName }}-app + key: saml-provider-id + - name: SONAR_AUTH_SAML_LOGINURL + valueFrom: + secretKeyRef: + name: {{ .Values.global.appName }}-app + key: saml-login-url + - name: SONAR_AUTH_SAML_CERTIFICATE_SECURED + valueFrom: + secretKeyRef: + name: {{ .Values.global.appName }}-app + key: saml-cert + - name: SONAR_AUTH_SAML_PROVIDERNAME + value: Azure AD + - name: SONAR_AUTH_SAML_USER_LOGIN + value: Email + - name: SONAR_AUTH_SAML_USER_NAME + value: Email + - name: SONAR_AUTH_SAML_USER_EMAIL + value: Email + - name: SONAR_AUTH_SAML_GROUP_NAME + value: Group + {{ end }} + ports: + - containerPort: 9000 + protocol: TCP + imagePullPolicy: Always + startupProbe: + httpGet: + path: /api/system/status + port: 9000 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 30 + volumeMounts: + - name: {{ .Values.global.appName }}-data + mountPath: /opt/sonarqube/data + - name: {{ .Values.global.appName }}-extensions + mountPath: /opt/sonarqube/extensions + terminationMessagePolicy: File + image: {{ .Values.global.registry }}/{{ .Values.global.odsNamespace }}/{{ .Values.global.appName }}:{{ .Values.global.odsImageTag }} + restartPolicy: Always + terminationGracePeriodSeconds: 30 + dnsPolicy: ClusterFirst + securityContext: {} + schedulerName: default-scheduler diff --git a/sonarqube/chart/templates/imagestream.yaml b/sonarqube/chart/templates/imagestream.yaml new file mode 100644 index 000000000..f81d0a3ba --- /dev/null +++ b/sonarqube/chart/templates/imagestream.yaml @@ -0,0 +1,9 @@ +apiVersion: image.openshift.io/v1 +kind: ImageStream +metadata: + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }} +spec: + lookupPolicy: + local: false diff --git a/sonarqube/chart/templates/pvc-extensions.yaml b/sonarqube/chart/templates/pvc-extensions.yaml new file mode 100644 index 000000000..5a3da8ab7 --- /dev/null +++ b/sonarqube/chart/templates/pvc-extensions.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + annotations: + volume.beta.kubernetes.io/storage-provisioner: {{ .Values.global.storageProvisioner }} + finalizers: + - kubernetes.io/pvc-protection + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }}-extensions +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: {{ .Values.global.storageClassData }} + volumeMode: Filesystem diff --git a/sonarqube/chart/templates/pvc-postgresql-backup.yaml b/sonarqube/chart/templates/pvc-postgresql-backup.yaml new file mode 100644 index 000000000..4cc73b5ad --- /dev/null +++ b/sonarqube/chart/templates/pvc-postgresql-backup.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + annotations: + volume.beta.kubernetes.io/storage-provisioner: {{ .Values.global.storageProvisioner }} + finalizers: + - kubernetes.io/pvc-protection + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }}-postgresql-backup +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: {{ .Values.global.storageClassData }} + volumeMode: Filesystem diff --git a/sonarqube/chart/templates/pvc-postgresql.yaml b/sonarqube/chart/templates/pvc-postgresql.yaml new file mode 100644 index 000000000..f07b0712a --- /dev/null +++ b/sonarqube/chart/templates/pvc-postgresql.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + annotations: + volume.beta.kubernetes.io/storage-provisioner: {{ .Values.global.storageProvisioner }} + finalizers: + - kubernetes.io/pvc-protection + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }}-postgresql +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi + storageClassName: {{ .Values.global.storageClassData }} + volumeMode: Filesystem diff --git a/sonarqube/chart/templates/pvc-sonar-data.yaml b/sonarqube/chart/templates/pvc-sonar-data.yaml new file mode 100644 index 000000000..0481d513a --- /dev/null +++ b/sonarqube/chart/templates/pvc-sonar-data.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + annotations: + volume.beta.kubernetes.io/storage-provisioner: {{ .Values.global.storageProvisioner }} + finalizers: + - kubernetes.io/pvc-protection + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }}-data +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi + storageClassName: {{ .Values.global.storageClassData }} + volumeMode: Filesystem diff --git a/sonarqube/chart/templates/route.yaml b/sonarqube/chart/templates/route.yaml new file mode 100644 index 000000000..ae08a6d0c --- /dev/null +++ b/sonarqube/chart/templates/route.yaml @@ -0,0 +1,18 @@ +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }} +spec: + host: {{ .Values.global.sonarqubeHost }} + port: + targetPort: 9000-tcp + tls: + insecureEdgeTerminationPolicy: Redirect + termination: edge + to: + kind: Service + name: {{ .Values.global.appName }} + weight: 100 + wildcardPolicy: None diff --git a/sonarqube/chart/templates/secret.yaml b/sonarqube/chart/templates/secret.yaml new file mode 100644 index 000000000..bda720a03 --- /dev/null +++ b/sonarqube/chart/templates/secret.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Secret +data: + admin-password: {{ .Values.global.sonarAdminPasswordB64 }} + {{ if ( eq .Values.sonarqube.sonarAuthSaml "true" )}} + saml-provider-id: {{ .Values.sonarqube.sonarAuthSamlProviderIdB64 }} + saml-login-url: {{ .Values.sonarqube.sonarAuthSamlLoginUrlB64 }} + saml-cert: {{ .Values.sonarqube.sonarAuthSamlCertficateB64 }} + {{ end }} +metadata: + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }}-app +type: Opaque diff --git a/sonarqube/chart/templates/secrets-postgresql.yaml b/sonarqube/chart/templates/secrets-postgresql.yaml new file mode 100644 index 000000000..23a61a175 --- /dev/null +++ b/sonarqube/chart/templates/secrets-postgresql.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +data: + database-password: {{ .Values.global.sonarDatabasePasswordB64 }} +kind: Secret +metadata: + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }}-postgresql +type: Opaque diff --git a/sonarqube/chart/templates/service-postgresql.yaml b/sonarqube/chart/templates/service-postgresql.yaml new file mode 100644 index 000000000..1a4c2e357 --- /dev/null +++ b/sonarqube/chart/templates/service-postgresql.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + template.openshift.io/expose-uri: postgres://{.spec.clusterIP}:{.spec.ports[?(.name=="postgresql")].port} + labels: + app: {{ .Values.global.appName }} + template: postgresql-persistent-template + name: {{ .Values.global.appName }}-postgresql +spec: + ports: + - name: postgresql + port: 5432 + protocol: TCP + targetPort: 5432 + selector: + name: {{ .Values.global.appName }}-postgresql + sessionAffinity: None + type: ClusterIP diff --git a/sonarqube/chart/templates/service-sonarqube.yaml b/sonarqube/chart/templates/service-sonarqube.yaml new file mode 100644 index 000000000..4745edf16 --- /dev/null +++ b/sonarqube/chart/templates/service-sonarqube.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ .Values.global.appName }} + name: {{ .Values.global.appName }} +spec: + ports: + - name: 9000-tcp + port: 9000 + protocol: TCP + targetPort: 9000 + selector: + deploymentconfig: {{ .Values.global.appName }} + sessionAffinity: None + type: ClusterIP diff --git a/sonarqube/chart/values.yaml.template b/sonarqube/chart/values.yaml.template new file mode 100644 index 000000000..1b514269d --- /dev/null +++ b/sonarqube/chart/values.yaml.template @@ -0,0 +1,44 @@ +global: + odsImageTag: $ODS_IMAGE_TAG + repoBase: $REPO_BASE + odsBitBucketProject: $ODS_BITBUCKET_PROJECT + odsGitRef: $ODS_GIT_REF + sonarVersion: $SONAR_VERSION + sonarEdition: $SONAR_EDITION + odsNamespace: $ODS_NAMESPACE + appDNS: $APP_DNS + appName: 'sonarqube' + storageProvisioner: $STORAGE_PROVISIONER + storageClassData: $STORAGE_CLASS_DATA + sonarqubeUrl: $SONARQUBE_URL + sonarqubeHost: $SONARQUBE_HOST + sonarAdminPasswordB64: $SONAR_ADMIN_PASSWORD_B64 + sonarDatabaseJdbcUrl: $SONAR_DATABASE_JDBC_URL + sonarDatabaseName: $SONAR_DATABASE_NAME + sonarDatabaseUser: $SONAR_DATABASE_USER + sonarAdminUsername: $SONAR_ADMIN_USERNAME + sonarDatabasePasswordB64: $SONAR_DATABASE_PASSWORD_B64 + registry: $DOCKER_REGISTRY + sonarDatabaseImage: $SONAR_DATABASE_IMAGE +postgresql: + name: 'sonarqube-postgresql' + cpuRequest: 100m + cpuLimit: 1 + memRequest: 256Mi + memLimit: 512Mi +sonarqube: + cpuRequest: 200m + cpuLimit: 1 + memRequest: 2Gi + memLimit: 4Gi + sonarAuthSaml: $SONAR_AUTH_SAML + sonarAuthSamlApplicationId: $SONAR_SAML_APPLICATION_ID + sonarAuthSamlProviderIdB64: $SONAR_SAML_PROVIDER_ID_B64 + sonarAuthSamlLoginUrlB64: $SONAR_SAML_LOGIN_URL_B64 + sonarAuthSamlServerBaseUrl: $SONARQUBE_URL + sonarAuthSamlCertficateB64: $SONAR_SAML_CERTIFICATE_B64 +buildConfig: + cpuRequest: 200m + cpuLimit: 1 + memRequest: 1Gi + memLimit: 2Gi diff --git a/sonarqube/docker/Dockerfile b/sonarqube/docker/Dockerfile index ddf89a195..62446da60 100644 --- a/sonarqube/docker/Dockerfile +++ b/sonarqube/docker/Dockerfile @@ -1,71 +1,37 @@ -FROM adoptopenjdk/openjdk11:x86_64-alpine-jre-11.0.10_9 +ARG sonarVersion=9.9.4 +ARG sonarEdition=community -ARG sonarDistributionUrl -ARG sonarVersion -ARG APP_DNS -ARG sonarEdition - -ENV SONARQUBE_HOME=/opt/sonarqube \ - SONARQUBE_JDBC_USERNAME=sonar \ - SONARQUBE_JDBC_PASSWORD=sonar \ - SONARQUBE_JDBC_URL= \ - SONAR_VERSION=${sonarVersion} +FROM sonarqube:${sonarVersion}-${sonarEdition} -# Http port -EXPOSE 9000 +ARG APP_DNS -RUN adduser -S -G root sonarqube +USER root -RUN set -x \ - && apk update \ - && apk add --no-cache ca-certificates \ - && apk add --no-cache gnupg unzip \ - && apk add --no-cache openssl wget \ - && apk add --no-cache su-exec \ - && apk add --no-cache bash \ - && apk fix \ - && mkdir -p /opt \ - && cd /opt \ - && wget -O sonarqube.zip --no-verbose $sonarDistributionUrl \ - && unzip -qq sonarqube.zip \ - && mv sonarqube-$SONAR_VERSION sonarqube \ - && chown -R sonarqube:root sonarqube \ - && chmod -R g+w sonarqube \ - && rm sonarqube.zip* \ - && rm -rf $SONARQUBE_HOME/bin/* \ - && mkdir -p /opt/configuration/sonarqube \ - && chown -R sonarqube:root /opt/configuration/sonarqube +#Installing certificates COPY ./import_certs.sh /usr/local/bin/import_certs.sh -RUN import_certs.sh - -VOLUME "$SONARQUBE_HOME/data" - -WORKDIR $SONARQUBE_HOME +RUN chmod -R 755 /usr/local/share/ca-certificates \ + && import_certs.sh # Set proxy settings COPY set-proxy.sh /tmp/set-proxy.sh RUN chmod +x /tmp/set-proxy.sh \ && /tmp/set-proxy.sh conf/sonar.properties -COPY run.sh $SONARQUBE_HOME/bin/ - # Add plugins (mainly from https://docs.sonarqube.org/display/PLUG/Plugin+Library) RUN mkdir -p /opt/configuration/sonarqube/plugins -# General plugins -ADD https://github.com/deepy/sonar-crowd/releases/download/2.1.3/sonar-crowd-plugin-2.1.3.jar /opt/configuration/sonarqube/plugins/ -ADD https://github.com/vaulttec/sonar-auth-oidc/releases/download/v2.1.1/sonar-auth-oidc-plugin-2.1.1.jar /opt/configuration/sonarqube/plugins/ # Language plugins not bundled -ADD https://github.com/Inform-Software/sonar-groovy/releases/download/1.7/sonar-groovy-plugin-1.7.jar /opt/configuration/sonarqube/plugins/ -ADD https://github.com/Merck/sonar-r-plugin/releases/download/0.2.1/sonar-r-plugin-0.2.1.jar /opt/configuration/sonarqube/plugins/ -# When running SonarQube 9.9LTS this plugin can be upgraded to 0.2.x -ADD https://github.com/elegoff/sonar-rust/releases/download/v0.1.0/community-rust-plugin-0.1.0.jar /opt/configuration/sonarqube/plugins/ +ADD https://github.com/Inform-Software/sonar-groovy/releases/download/1.8/sonar-groovy-plugin-1.8.jar /opt/configuration/sonarqube/plugins/ +ADD https://github.com/Merck/sonar-r-plugin/releases/download/0.2.2/sonar-r-plugin-0.2.2.jar /opt/configuration/sonarqube/plugins/ +ADD https://github.com/elegoff/sonar-rust/releases/download/v0.2.1/community-rust-plugin-0.2.1.jar /opt/configuration/sonarqube/plugins/ + +COPY run.sh $SONARQUBE_HOME/bin/ -RUN chown -R :0 /opt/configuration/sonarqube/plugins; \ - chmod -R g=u /opt/configuration/sonarqube/plugins; \ - chown -R :0 $SONARQUBE_HOME/bin; \ - chmod g+w $JAVA_HOME/lib/security/cacerts; \ - chmod -R g+x $SONARQUBE_HOME/bin/run.sh +RUN chmod go+w $JAVA_HOME/lib/security/cacerts; \ + chmod -R go+x $SONARQUBE_HOME/bin/run.sh; \ + chmod -R go+w $SONARQUBE_HOME/conf; \ + chmod -R go=u /opt/configuration/sonarqube/plugins; \ + chmod -R ugo+wrX "${SONARQUBE_HOME}/data" "${SONARQUBE_HOME}/extensions" USER sonarqube diff --git a/sonarqube/docker/run.sh b/sonarqube/docker/run.sh index 35c6122a2..a99e3a8fd 100755 --- a/sonarqube/docker/run.sh +++ b/sonarqube/docker/run.sh @@ -2,20 +2,6 @@ set -e -if [ "${SONAR_AUTH_CROWD}" = "true" ]; then - # Update sonar.properties for crowd plugin - { - echo "sonar.security.realm=Crowd" - echo "crowd.url=$SONARQUBE_CROWD_URL" - echo "crowd.application=$SONARQUBE_CROWD_APP" - echo "crowd.password=$SONARQUBE_CROWD_PWD" - echo "sonar.security.localUsers=admin" - } >> conf/sonar.properties -fi - -# enforce authentication to sonar -echo "sonar.forceAuthentication=true" >> conf/sonar.properties - # Copy plugins into volume rm "${SONARQUBE_HOME}"/extensions/plugins/*.jar || true ls -lah /opt/configuration/sonarqube/plugins @@ -36,7 +22,7 @@ else echo "INFO: skip import" fi -exec java -jar "lib/sonar-application-${SONAR_VERSION}.jar" \ +exec java -jar "lib/sonarqube.jar" \ -Dsonar.log.console=true \ -Dsonar.jdbc.username="${SONARQUBE_JDBC_USERNAME}" \ -Dsonar.jdbc.password="${SONARQUBE_JDBC_PASSWORD}" \ diff --git a/sonarqube/ocp-config/Tailorfile b/sonarqube/ocp-config/Tailorfile deleted file mode 100644 index 521da31a3..000000000 --- a/sonarqube/ocp-config/Tailorfile +++ /dev/null @@ -1,9 +0,0 @@ -namespace ods -selector app=sonarqube -param-file ../../../ods-configuration/ods-core.env -ignore-unknown-parameters true -preserve-immutable-fields true -preserve pvc:/spec/volumeMode -preserve svc:/spec/clusterIPs - -bc,dc,is,pvc,route,svc,secret,configmap diff --git a/sonarqube/ocp-config/sonarqube.yml b/sonarqube/ocp-config/sonarqube.yml deleted file mode 100644 index 1f1fec4c1..000000000 --- a/sonarqube/ocp-config/sonarqube.yml +++ /dev/null @@ -1,515 +0,0 @@ -apiVersion: template.openshift.io/v1 -kind: Template -metadata: - name: sonarqube -parameters: -- name: ODS_BITBUCKET_PROJECT - description: Bitbucket project name. - value: opendevstack -- name: ODS_NAMESPACE - description: OpenDevStack namespace to use. - value: ods -- name: ODS_IMAGE_TAG - description: OpenDevStack image tag to use. - required: true -- name: ODS_GIT_REF - description: Git ref to use for source code. - required: true -- displayName: Admin Password - name: SONAR_ADMIN_PASSWORD_B64 - description: The base64 encoded admin password - required: true -- displayName: Admin Username - name: SONAR_ADMIN_USERNAME - description: the sonarqube admin username - required: true -- displayName: Auth Token - name: SONAR_AUTH_TOKEN_B64 - required: true -- displayName: Crowd Application - name: SONAR_CROWD_APPLICATION - description: application name as setup in crowd for authn/z -- displayName: Crowd Password - name: SONAR_CROWD_PASSWORD_B64 - description: base64 encoded application password as setup in crowd for authn/z -- displayName: Crowd URL - name: CROWD_URL - description: url under which crowd is reachable from sonaruqbe -- displayName: Database JDBC URL - name: SONAR_DATABASE_IMAGE - description: Image to use for the PostgreSQL database, e.g. registry.redhat.io/rhel8/postgresql-12 - required: true -- displayName: Database JDBC URL - name: SONAR_DATABASE_JDBC_URL - description: database jdbc url, e.g. jdbc:postgresql://sonarqube-postgresql:5432/sonarqube - required: true -- displayName: Database Name - name: SONAR_DATABASE_NAME - description: database name, e.g. sonarqube - required: true -- displayName: Database Password - name: SONAR_DATABASE_PASSWORD_B64 - description: base64 encoded database user password - required: true -- displayName: Database User - name: SONAR_DATABASE_USER - description: the database user to connect ot the database - required: true -- name: SONARQUBE_HOST - description: Host without protocol exposed by the sonarqube route - required: true -- name: REPO_BASE - required: true - description: Repository base url. In case bitbucket is used, needs to include /scm - so it's the path in front on opendevstack/.. -- name: STORAGE_CLASS_DATA - # for AWS the default is gp2 - description: Storage class for data for AWS, e.g. gp2. Leave empty for local (e.g. vagrant) deployment - value: "" -- name: STORAGE_PROVISIONER - description: The kubernetes provisioner, e.g. kubernetes.io/aws-ebs. Leave empty for local (e.g. vagrant) deployment -- name: STORAGE_CLASS_BACKUP - # for AWS the default would be gp2-encrypted - description: Storage class for backup for AWS, e.g. gp2-encrypted. Leave empty for local (e.g. vagrant) deployment -- name: SONAR_DISTRIBUTION_URL - description: "Sonarqube distribution url. Example community edition: https://sonarsource.bintray.com/Distribution/sonarqube/sonarqube-7.3.zip" -- name: SONAR_VERSION - description: "Sonarqube version specified in the variable SONAR_DISTRIBUTION_URL" -- name: SONAR_EDITION - description: "Sonarqube edition specified in the variable SONAR_EDITION" -- name: SONAR_AUTH_CROWD - description: "Set to true, if you want to use crowd as identity provider" -- name: APP_DNS - description: OpenShift application base dns - used for grabbing the root ca and adding into the agent -- name: SONAR_CPU_REQUEST - value: 200m -- name: SONAR_CPU_LIMIT - value: "1" -- name: SONAR_MEMORY_REQUEST - value: 2560Mi -- name: SONAR_MEMORY_LIMIT - value: 4Gi -- name: SONAR_BUILD_CPU_REQUEST - value: 200m -- name: SONAR_BUILD_CPU_LIMIT - value: "1" -- name: SONAR_BUILD_MEMORY_REQUEST - value: 1Gi -- name: SONAR_BUILD_MEMORY_LIMIT - value: 2Gi -- name: SONAR_POSTGRESQL_CPU_REQUEST - value: 100m -- name: SONAR_POSTGRESQL_CPU_LIMIT - value: "1" -- name: SONAR_POSTGRESQL_MEMORY_REQUEST - value: 256Mi -- name: SONAR_POSTGRESQL_MEMORY_LIMIT - value: 512Mi -objects: -- apiVersion: v1 - kind: BuildConfig - metadata: - labels: - app: sonarqube - name: sonarqube - spec: - failedBuildsHistoryLimit: 5 - nodeSelector: null - output: - to: - kind: ImageStreamTag - name: sonarqube:${ODS_IMAGE_TAG} - postCommit: {} - resources: - limits: - cpu: ${SONAR_BUILD_CPU_LIMIT} - memory: ${SONAR_BUILD_MEMORY_LIMIT} - requests: - cpu: ${SONAR_BUILD_CPU_REQUEST} - memory: ${SONAR_BUILD_MEMORY_REQUEST} - runPolicy: Serial - source: - contextDir: sonarqube/docker - git: - uri: ${REPO_BASE}/${ODS_BITBUCKET_PROJECT}/ods-core.git - ref: ${ODS_GIT_REF} - sourceSecret: - name: cd-user-token - type: Git - strategy: - dockerStrategy: - forcePull: true - noCache: true - buildArgs: - - name: sonarVersion - value: ${SONAR_VERSION} - - name: sonarDistributionUrl - value: ${SONAR_DISTRIBUTION_URL} - - name: APP_DNS - value: ${APP_DNS} - - name: sonarEdition - value: ${SONAR_EDITION} - type: Docker - successfulBuildsHistoryLimit: 5 -- apiVersion: v1 - kind: DeploymentConfig - metadata: - annotations: - template.alpha.openshift.io/wait-for-ready: "true" - labels: - app: sonarqube - template: postgresql-persistent-template - name: sonarqube-postgresql - spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - name: sonarqube-postgresql - strategy: - activeDeadlineSeconds: 21600 - recreateParams: - timeoutSeconds: 600 - resources: {} - type: Recreate - template: - metadata: - labels: - name: sonarqube-postgresql - spec: - containers: - - env: - - name: POSTGRESQL_USER - valueFrom: - configMapKeyRef: - key: database-user - name: sonarqube - - name: POSTGRESQL_PASSWORD - valueFrom: - secretKeyRef: - key: database-password - name: sonarqube-postgresql - - name: POSTGRESQL_DATABASE - valueFrom: - configMapKeyRef: - key: database-name - name: sonarqube - image: ${SONAR_DATABASE_IMAGE} - imagePullPolicy: IfNotPresent - livenessProbe: - failureThreshold: 3 - initialDelaySeconds: 30 - periodSeconds: 10 - successThreshold: 1 - tcpSocket: - port: 5432 - timeoutSeconds: 1 - name: postgresql - ports: - - containerPort: 5432 - protocol: TCP - readinessProbe: - exec: - command: - - /bin/sh - - -i - - -c - - psql -h 127.0.0.1 -U $POSTGRESQL_USER -q -d $POSTGRESQL_DATABASE -c - 'SELECT 1' - failureThreshold: 3 - initialDelaySeconds: 5 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - resources: - limits: - cpu: ${SONAR_POSTGRESQL_CPU_LIMIT} - memory: ${SONAR_POSTGRESQL_MEMORY_LIMIT} - requests: - cpu: ${SONAR_POSTGRESQL_CPU_REQUEST} - memory: ${SONAR_POSTGRESQL_MEMORY_REQUEST} - securityContext: - capabilities: {} - privileged: false - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - volumeMounts: - - mountPath: /var/lib/pgsql/data - name: sonarqube-postgresql-data - dnsPolicy: ClusterFirst - restartPolicy: Always - schedulerName: default-scheduler - securityContext: {} - terminationGracePeriodSeconds: 30 - volumes: - - name: sonarqube-postgresql-data - persistentVolumeClaim: - claimName: sonarqube-postgresql - test: false - triggers: - - type: ConfigChange -- apiVersion: v1 - kind: DeploymentConfig - metadata: - labels: - app: sonarqube - name: sonarqube - spec: - replicas: 1 - revisionHistoryLimit: 10 - selector: - app: sonarqube - deploymentconfig: sonarqube - strategy: - activeDeadlineSeconds: 21600 - recreateParams: - timeoutSeconds: 600 - resources: {} - type: Recreate - template: - metadata: - labels: - app: sonarqube - deploymentconfig: sonarqube - tuned.openshift.io/elasticsearch: "" - spec: - containers: - - name: sonarqube - image: ${ODS_NAMESPACE}/sonarqube:${ODS_IMAGE_TAG} - env: - - name: SONARQUBE_JDBC_URL - valueFrom: - configMapKeyRef: - key: database-jdbc-url - name: sonarqube - - name: SONARQUBE_JDBC_USERNAME - valueFrom: - configMapKeyRef: - key: database-user - name: sonarqube - - name: SONARQUBE_JDBC_PASSWORD - valueFrom: - secretKeyRef: - key: database-password - name: sonarqube-postgresql - - name: SONARQUBE_CROWD_URL - valueFrom: - configMapKeyRef: - key: crowd-url - name: sonarqube - - name: SONARQUBE_CROWD_APP - valueFrom: - configMapKeyRef: - key: crowd-application - name: sonarqube - - name: SONARQUBE_CROWD_PWD - valueFrom: - secretKeyRef: - key: crowd-password - name: sonarqube-app - - name: SONAR_AUTH_CROWD - value: ${SONAR_AUTH_CROWD} - imagePullPolicy: Always - ports: - - containerPort: 9000 - protocol: TCP - readinessProbe: - failureThreshold: 3 - httpGet: - path: /api/server/version - port: 9000 - scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 2 - resources: - limits: - cpu: ${SONAR_CPU_LIMIT} - memory: ${SONAR_MEMORY_LIMIT} - requests: - cpu: ${SONAR_CPU_REQUEST} - memory: ${SONAR_MEMORY_REQUEST} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - volumeMounts: - - mountPath: /opt/sonarqube/data - name: sonarqube-data - - mountPath: /opt/sonarqube/extensions - name: sonarqube-extensions - dnsPolicy: ClusterFirst - restartPolicy: Always - schedulerName: default-scheduler - securityContext: {} - terminationGracePeriodSeconds: 30 - volumes: - - name: sonarqube-data - persistentVolumeClaim: - claimName: sonarqube-data - - name: sonarqube-extensions - persistentVolumeClaim: - claimName: sonarqube-extensions - test: false - triggers: - - imageChangeParams: - automatic: true - containerNames: - - sonarqube - from: - kind: ImageStreamTag - name: sonarqube:${ODS_IMAGE_TAG} - namespace: ${ODS_NAMESPACE} - type: ImageChange - - type: ConfigChange -- apiVersion: v1 - kind: ImageStream - metadata: - labels: - app: sonarqube - name: sonarqube - spec: - lookupPolicy: - local: false -- apiVersion: v1 - kind: PersistentVolumeClaim - metadata: - annotations: - volume.beta.kubernetes.io/storage-provisioner: ${STORAGE_PROVISIONER} - finalizers: - - kubernetes.io/pvc-protection - labels: - app: sonarqube - template: postgresql-persistent-template - name: sonarqube-postgresql - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 2Gi - storageClassName: ${STORAGE_CLASS_DATA} - volumeMode: Filesystem -- apiVersion: v1 - kind: PersistentVolumeClaim - metadata: - annotations: - volume.beta.kubernetes.io/storage-provisioner: ${STORAGE_PROVISIONER} - finalizers: - - kubernetes.io/pvc-protection - labels: - app: sonarqube - name: sonarqube-data - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 2Gi - storageClassName: ${STORAGE_CLASS_DATA} - volumeMode: Filesystem -- apiVersion: v1 - kind: PersistentVolumeClaim - metadata: - annotations: - volume.beta.kubernetes.io/storage-provisioner: ${STORAGE_PROVISIONER} - finalizers: - - kubernetes.io/pvc-protection - labels: - app: sonarqube - name: sonarqube-extensions - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi - storageClassName: ${STORAGE_CLASS_DATA} - volumeMode: Filesystem -- apiVersion: v1 - kind: Route - metadata: - labels: - app: sonarqube - name: sonarqube - spec: - host: ${SONARQUBE_HOST} - port: - targetPort: 9000-tcp - tls: - insecureEdgeTerminationPolicy: Redirect - termination: edge - to: - kind: Service - name: sonarqube - weight: 100 - wildcardPolicy: None -- apiVersion: v1 - data: - admin-password: ${SONAR_ADMIN_PASSWORD_B64} - crowd-password: ${SONAR_CROWD_PASSWORD_B64} - kind: Secret - metadata: - labels: - app: sonarqube - name: sonarqube-app - type: Opaque -- kind: ConfigMap - metadata: - labels: - app: sonarqube - name: sonarqube - apiVersion: v1 - data: - crowd-application: ${SONAR_CROWD_APPLICATION} - crowd-url: ${CROWD_URL} - database-jdbc-url: ${SONAR_DATABASE_JDBC_URL} - database-name: ${SONAR_DATABASE_NAME} - database-user: ${SONAR_DATABASE_USER} - sonarqube-admin-user: ${SONAR_ADMIN_USERNAME} -- apiVersion: v1 - data: - database-password: ${SONAR_DATABASE_PASSWORD_B64} - kind: Secret - metadata: - annotations: - template.openshift.io/expose-database_name: '{.data[''database-name'']}' - template.openshift.io/expose-password: '{.data[''database-password'']}' - template.openshift.io/expose-username: '{.data[''database-user'']}' - labels: - app: sonarqube - template: postgresql-persistent-template - name: sonarqube-postgresql - type: Opaque -- apiVersion: v1 - kind: Service - metadata: - annotations: - template.openshift.io/expose-uri: postgres://{.spec.clusterIP}:{.spec.ports[?(.name=="postgresql")].port} - labels: - app: sonarqube - template: postgresql-persistent-template - name: sonarqube-postgresql - spec: - ports: - - name: postgresql - port: 5432 - protocol: TCP - targetPort: 5432 - selector: - name: sonarqube-postgresql - sessionAffinity: None - type: ClusterIP -- apiVersion: v1 - kind: Service - metadata: - labels: - app: sonarqube - name: sonarqube - spec: - ports: - - name: 9000-tcp - port: 9000 - protocol: TCP - targetPort: 9000 - selector: - deploymentconfig: sonarqube - sessionAffinity: None - type: ClusterIP diff --git a/sonarqube/test.sh b/sonarqube/test.sh index 9bd2b32a6..97975f531 100755 --- a/sonarqube/test.sh +++ b/sonarqube/test.sh @@ -6,14 +6,14 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ODS_CORE_DIR=${SCRIPT_DIR%/*} ODS_CONFIGURATION_DIR="${ODS_CORE_DIR}/../ods-configuration" -SONAR_VERSION=8.9.10.61524 +SONAR_VERSION=9.9.4 SONAR_EDITION="community" function usage { printf "Test SonarQube setup.\n\n" printf "\t-h|--help\t\tPrint usage\n" printf "\t-v|--verbose\t\tEnable verbose mode\n" - printf "\t-s|--sq-version\t\tSonarQube version, e.g. '8.9.10.61524' (defaults to %s)\n" "${SONAR_VERSION}" + printf "\t-s|--sq-version\t\tSonarQube version, e.g. '9.9.4' (defaults to %s)\n" "${SONAR_VERSION}" printf "\t-e|--sq-edition\t\tSonarQube edition, e.g. 'community' or 'enterprise' (defaults to %s)\n" "${SONAR_EDITION}" printf "\t-i|--insecure\t\tAllow insecure server connections when using SSL\n" printf "\t--verify\t\tSkips setup of local docker container and instead checks existing sonarqube setup based on ods-core.env\n" @@ -63,29 +63,6 @@ ADMIN_USER_DEFAULT_PASSWORD="admin" if ! $VERIFY_ONLY; then - case $SONAR_EDITION in - - community) - SONAR_DISTRIBUTION_URL="https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-${SONAR_VERSION}.zip" - ;; - - developer) - SONAR_DISTRIBUTION_URL="https://binaries.sonarsource.com/CommercialDistribution/sonarqube-developer/sonarqube-developer-${SONAR_VERSION}.zip" - ;; - - enterprise) - SONAR_DISTRIBUTION_URL="https://binaries.sonarsource.com/CommercialDistribution/sonarqube-enterprise/sonarqube-enterprise-${SONAR_VERSION}.zip" - ;; - - datacenter) - SONAR_DISTRIBUTION_URL="https://binaries.sonarsource.com/CommercialDistribution/sonarqube-datacenter/sonarqube-datacenter-${SONAR_VERSION}.zip" - ;; - - *) - echo -n "Sonar edition provided ${SONAR_EDITION} is not valid"; exit 1;; - - esac - HOST_PORT="9000" CONTAINER_IMAGE="sqtest" @@ -100,7 +77,6 @@ if ! $VERIFY_ONLY; then echo "Build image" docker build \ -t "${CONTAINER_IMAGE}" \ - --build-arg sonarDistributionUrl="${SONAR_DISTRIBUTION_URL}" \ --build-arg sonarVersion="${SONAR_VERSION}" \ --build-arg sonarEdition="${SONAR_EDITION}" \ --build-arg idpDns="" \ @@ -213,26 +189,24 @@ echo "Check if plugins are installed in correct versions" case $SONAR_EDITION in community | developer | enterprise | datacenter) - expectedPlugins=( "crowd:2.1.3" - "authoidc:2.1.1" - "groovy:1.7" - "r:0.2.1" - "communityrust:0.1.0" ) + expectedPlugins=("groovy:1.8" + "r:0.2.2" + "communityrust:0.2.1" ) ;; *) - echo -n "Sonar edition provided ${SONAR_EDITION} is not valid"; exit 1;; + echo -n "Sonar edition provided ${SONAR_EDITION} is not valid"; exit 1;; esac actualPlugins=$(curl -sSf ${INSECURE} \ --user "$CURL_ADMIN_AUTH" \ - "${SONARQUBE_URL}/api/system/info" | jq '.Statistics.plugins') + "${SONARQUBE_URL}/api/plugins/installed" | jq '.plugins') for plugin in "${expectedPlugins[@]}"; do pluginName=${plugin%%:*} pluginVersion=${plugin#*:} - actualVersion=$(echo "${actualPlugins}" | jq -r ".[] | select(.name == \"${pluginName}\") | .version") + actualVersion=$(echo "${actualPlugins}" | jq -r ".[] | select(.key == \"${pluginName}\") | .version") if [ "${actualVersion}" == "${pluginVersion}" ]; then echo "Plugin ${pluginName} has expected version ${pluginVersion}" else