diff --git a/openshift/README.md b/openshift/README.md new file mode 100644 index 00000000..d9018d94 --- /dev/null +++ b/openshift/README.md @@ -0,0 +1,89 @@ +# How to configure a CI/CD pipeline for eDivorce on OpenShift + +- Create a project to house the Jenkins instance that will be responsible for promoting application images (via OpenShift ImageStreamTagS) across environment; the exact project name used was "edivorce". +- Create the BuildConfiguration within this project using the ```oc``` command and "edivorce-build-template.yaml" file in the templates directory: + +``` +oc process -f edivorce-build-template.yaml -v NAME= -v SOURCE_REPOSITORY_URL= -v SOURCE_REPOSITORY_REF= | oc create -f - +``` + +For example: + +``` +oc process -f edivorce-build-template.yaml -v NAME=edivorce-django -v SOURCE_REPOSITORY_URL=https://github.com/bcgov/eDivorce.git -v SOURCE_REPOSITORY_REF=master | oc create -f - +``` + + + +- Deploy a Jenkins instance with persistent storage into the edivorce project using the web gui +- Install the Promoted Builds Jenkins plugin +- Configure a job that has an OpenShift ImageStream Watcher as its SCM source and promotion states for each environment +- In each promotion configuration, tag the target build's image to the appropriate promotion level; this was done using a shell command because the OpenShift plugins do not appear to handle parameter subsitution inside promotions properly. +- Create an OpenShift project for each "environment" (e.g. DEV, TEST, PROD); Exact names used were jag-csb-edivorce-dev, jag-csb-edivorce-test, jag-csb-edivorce-prod +- Configure the access controls to allow the Jenkins instance to tag imagestreams in the environment projects, and to allow the environment projects to pull images from the eDivorce project: + +``` +oc policy add-role-to-user system:image-puller system:serviceaccount:jag-csb-edivorce-:default -n jag-csb-edivorce-tools +oc policy add-role-to-user edit system:serviceaccount: jag-csb-edivorce-tools:default -n jag-csb-edivorce- +``` + +- Use the YAML files in this directory and `oc` tool to create the necessary resources within each project: + +``` +oc process -f edivorce-environment-template.yaml -v ENVIRONMENT_TYPE= | oc create -f - +``` + +For example: + +``` +oc process -f edivorce-environment-template.yaml -v ENVIRONMENT_TYPE=dev,VOLUME_CAPACITY=1Gi | oc create -f - +``` + +# eDivorce Environments + +There are several environments set up for different purposes within OpenShift. They are available at the URLs below. + +|Environment| URL |Notes| +|-----------|-----|-----| +|DEV|edivorce-dev.pathfinder.gov.bc.ca| | +|TEST|edivorce-test.pathfinder.gov.bc.ca| | +|PROD|edivorce-prod.pathfinder.gov.bc.ca| | + + + +# How to access Jenkins for eDivorce + +- Login to https://edivorce-jenkins-edivorce.pathfinder.gov.bc.ca with the username/password that was provided to you. + +# How to access OpenShift for eDivorce + +## Web UI +- Login to https://console.pathfinder.gov.bc.ca:8443; you'll be prompted for GitHub authorization. + +## Command-line (```oc```) tools +- Download OpenShift [command line tools](https://github.com/openshift/origin/releases/download/v1.2.1/openshift-origin-client-tools-v1.2.1-5e723f6-mac.zip), unzip, and add ```oc``` to your PATH. +- Copy command line login string from https://console.pathfinder.gov.bc.ca:8443/console/command-line. It will look like ```oc login https://console.pathfinder.gov.bc.ca:8443 --token=xtyz123xtyz123xtyz123xtyz123``` +- Paste the login string into a terminal session. You are no authenticated against OpenShift and will be able to execute ```oc``` commands. ```oc -h``` provides a summary of available commands. + +# Project contents + +- The "edivorce-tools" project contains the Jenkins instance and the other jsg-csb-edivorce-* projects contain different "environments". The names are self-explanatory. + +# Data management operations + +todo: add instructions on how to 'oc rsh' into the django pod to manage the postgresql pod + +# Background reading/Resources + +[Free OpenShift book](https://www.openshift.com/promotions/for-developers.html) from RedHat – good overview + +[Red Hat Container Development Kit](http://developers.redhat.com/products/cdk/overview/) + +OpenShift CI/CD pieline Demos: + +- https://www.youtube.com/watch?v=65BnTLcDAJI +- https://www.youtube.com/watch?v=wSFyg6Etwx8 + + + + diff --git a/openshift/create-env.sh b/openshift/create-env.sh new file mode 100755 index 00000000..7216b820 --- /dev/null +++ b/openshift/create-env.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +echo -n "Enter the name of the environment (default=dev): " +read ENVIRONMENT +ENVIRONMENT=${ENVIRONMENT:-dev} + +OS_PROJECT_NAME=jag-csb-edivorce-$ENVIRONMENT + +echo "Changing project to $OS_PROJECT_NAME..." + +oc project $OS_PROJECT_NAME + +echo -n "Enter the path to the environment creation template (default=templates/edivorce-environment-template.yaml): " +read CREATE_SCRIPT +CREATE_SCRIPT=${CREATE_SCRIPT:-templates/edivorce-environment-template.yaml} + +oc create -f $CREATE_SCRIPT + +/bin/bash project_label.sh $OS_PROJECT_NAME team=jag product=edivorce environment=$ENVIRONMENT diff --git a/openshift/destroy-env.sh b/openshift/destroy-env.sh new file mode 100755 index 00000000..fd0a39ef --- /dev/null +++ b/openshift/destroy-env.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +# this is hard-coded to only destroy the dev environment +# you can chage it to 'test' or 'prod' if you are sure you want to destroy EVERYTHING, include the database +oc project jag-csb-edivorce-dev + +# delete all imagestreams +oc delete is --all + +# delete services by name (we don't want to accidentally delete the gluster service!) +oc delete svc weasyprint +oc delete svc postgresql +oc delete svc edivorce-django + +# delete routes +oc delete route --all + +# delete persistent volume claims +oc delete pvc --all + +# delete replication controllers +oc delete rc --all + +# delete deployment configurations +oc delete dc --all + +# delete pods +oc delete po --all \ No newline at end of file diff --git a/openshift/project_label.sh b/openshift/project_label.sh new file mode 100755 index 00000000..1c0c314b --- /dev/null +++ b/openshift/project_label.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# todo: this is an example from https://github.com/bcgov/esm-server/tree/develop/openshift +# todo: it needs to be completely reconfigured for eDivorce!!!! + +#project_label.sh $OS_PROJECT_NAME category=$CATEGORY team=$TEAM product=$PRODUCT environment=$ENVIRONMENT + +PROJECT_NAME=$1 + +echo "Project name is $1" + +for i in "${@:2}"; do + oc label --overwrite namespace/$PROJECT_NAME $i +done diff --git a/openshift/templates/django-postgresql-persistent.json b/openshift/templates/django-postgresql-persistent.json deleted file mode 100644 index a8901a42..00000000 --- a/openshift/templates/django-postgresql-persistent.json +++ /dev/null @@ -1,492 +0,0 @@ -{ - "kind": "Template", - "apiVersion": "v1", - "metadata": { - "name": "django-psql-persistent", - "annotations": { - "description": "An example Django application with a PostgreSQL database", - "tags": "quickstart,python,django,postgresql", - "iconClass": "icon-python" - } - }, - "labels": { - "template": "django-psql-persistent" - }, - "objects": [ - { - "kind": "Service", - "apiVersion": "v1", - "metadata": { - "name": "${NAME}", - "annotations": { - "description": "Exposes and load balances the application pods" - } - }, - "spec": { - "ports": [ - { - "name": "web", - "port": 8080, - "targetPort": 8080 - } - ], - "selector": { - "name": "${NAME}" - } - } - }, - { - "kind": "Route", - "apiVersion": "v1", - "metadata": { - "name": "${NAME}" - }, - "spec": { - "host": "${APPLICATION_DOMAIN}", - "to": { - "kind": "Service", - "name": "${NAME}" - } - } - }, - { - "kind": "ImageStream", - "apiVersion": "v1", - "metadata": { - "name": "${NAME}", - "annotations": { - "description": "Keeps track of changes in the application image" - } - } - }, - { - "kind": "BuildConfig", - "apiVersion": "v1", - "metadata": { - "name": "${NAME}", - "annotations": { - "description": "Defines how to build the application" - } - }, - "spec": { - "source": { - "type": "Git", - "git": { - "uri": "${SOURCE_REPOSITORY_URL}", - "ref": "${SOURCE_REPOSITORY_REF}" - }, - "contextDir": "${CONTEXT_DIR}" - }, - "strategy": { - "type": "Source", - "sourceStrategy": { - "from": { - "kind": "ImageStreamTag", - "namespace": "${NAMESPACE}", - "name": "python:3.5" - }, - "env": [ - { - "name": "PIP_INDEX_URL", - "value": "${PIP_INDEX_URL}" - } - ] - } - }, - "output": { - "to": { - "kind": "ImageStreamTag", - "name": "${NAME}:latest" - } - }, - "triggers": [ - { - "type": "ImageChange" - }, - { - "type": "ConfigChange" - }, - { - "type": "GitHub", - "github": { - "secret": "${GITHUB_WEBHOOK_SECRET}" - } - } - ], - "postCommit": { - "script": "./manage.py test" - } - } - }, - { - "kind": "DeploymentConfig", - "apiVersion": "v1", - "metadata": { - "name": "${NAME}", - "annotations": { - "description": "Defines how to deploy the application server" - } - }, - "spec": { - "strategy": { - "type": "Rolling" - }, - "triggers": [ - { - "type": "ImageChange", - "imageChangeParams": { - "automatic": true, - "containerNames": [ - "django-psql-persistent" - ], - "from": { - "kind": "ImageStreamTag", - "name": "${NAME}:latest" - } - } - }, - { - "type": "ConfigChange" - } - ], - "replicas": 1, - "selector": { - "name": "${NAME}" - }, - "template": { - "metadata": { - "name": "${NAME}", - "labels": { - "name": "${NAME}" - } - }, - "spec": { - "containers": [ - { - "name": "django-psql-persistent", - "image": " ", - "ports": [ - { - "containerPort": 8080 - } - ], - "readinessProbe": { - "timeoutSeconds": 3, - "initialDelaySeconds": 3, - "httpGet": { - "path": "/health", - "port": 8080 - } - }, - "livenessProbe": { - "timeoutSeconds": 3, - "initialDelaySeconds": 30, - "httpGet": { - "path": "/health", - "port": 8080 - } - }, - "env": [ - { - "name": "DATABASE_SERVICE_NAME", - "value": "${DATABASE_SERVICE_NAME}" - }, - { - "name": "DATABASE_ENGINE", - "value": "${DATABASE_ENGINE}" - }, - { - "name": "DATABASE_NAME", - "value": "${DATABASE_NAME}" - }, - { - "name": "DATABASE_USER", - "value": "${DATABASE_USER}" - }, - { - "name": "DATABASE_PASSWORD", - "value": "${DATABASE_PASSWORD}" - }, - { - "name": "APP_CONFIG", - "value": "${APP_CONFIG}" - }, - { - "name": "DJANGO_SECRET_KEY", - "value": "${DJANGO_SECRET_KEY}" - } - ], - "resources": { - "limits": { - "memory": "${MEMORY_LIMIT}" - } - } - } - ] - } - } - } - }, - { - "kind": "PersistentVolumeClaim", - "apiVersion": "v1", - "metadata": { - "name": "${DATABASE_SERVICE_NAME}" - }, - "spec": { - "accessModes": [ - "ReadWriteOnce" - ], - "resources": { - "requests": { - "storage": "${VOLUME_CAPACITY}" - } - } - } - }, - { - "kind": "Service", - "apiVersion": "v1", - "metadata": { - "name": "${DATABASE_SERVICE_NAME}", - "annotations": { - "description": "Exposes the database server" - } - }, - "spec": { - "ports": [ - { - "name": "postgresql", - "port": 5432, - "targetPort": 5432 - } - ], - "selector": { - "name": "${DATABASE_SERVICE_NAME}" - } - } - }, - { - "kind": "DeploymentConfig", - "apiVersion": "v1", - "metadata": { - "name": "${DATABASE_SERVICE_NAME}", - "annotations": { - "description": "Defines how to deploy the database" - } - }, - "spec": { - "strategy": { - "type": "Recreate" - }, - "triggers": [ - { - "type": "ImageChange", - "imageChangeParams": { - "automatic": true, - "containerNames": [ - "postgresql" - ], - "from": { - "kind": "ImageStreamTag", - "namespace": "${NAMESPACE}", - "name": "postgresql:9.5" - } - } - }, - { - "type": "ConfigChange" - } - ], - "replicas": 1, - "selector": { - "name": "${DATABASE_SERVICE_NAME}" - }, - "template": { - "metadata": { - "name": "${DATABASE_SERVICE_NAME}", - "labels": { - "name": "${DATABASE_SERVICE_NAME}" - } - }, - "spec": { - "volumes": [ - { - "name": "${DATABASE_SERVICE_NAME}-data", - "persistentVolumeClaim": { - "claimName": "${DATABASE_SERVICE_NAME}" - } - } - ], - "containers": [ - { - "name": "postgresql", - "image": " ", - "ports": [ - { - "containerPort": 5432 - } - ], - "env": [ - { - "name": "POSTGRESQL_USER", - "value": "${DATABASE_USER}" - }, - { - "name": "POSTGRESQL_PASSWORD", - "value": "${DATABASE_PASSWORD}" - }, - { - "name": "POSTGRESQL_DATABASE", - "value": "${DATABASE_NAME}" - } - ], - "volumeMounts": [ - { - "name": "${DATABASE_SERVICE_NAME}-data", - "mountPath": "/var/lib/pgsql/data" - } - ], - "readinessProbe": { - "timeoutSeconds": 1, - "initialDelaySeconds": 5, - "exec": { - "command": [ "/bin/sh", "-i", "-c", "psql -h 127.0.0.1 -U ${POSTGRESQL_USER} -q -d ${POSTGRESQL_DATABASE} -c 'SELECT 1'"] - } - }, - "livenessProbe": { - "timeoutSeconds": 1, - "initialDelaySeconds": 30, - "tcpSocket": { - "port": 5432 - } - }, - "resources": { - "limits": { - "memory": "${MEMORY_POSTGRESQL_LIMIT}" - } - } - } - ] - } - } - } - } - ], - "parameters": [ - { - "name": "NAME", - "displayName": "Name", - "description": "The name assigned to all of the frontend objects defined in this template.", - "required": true, - "value": "django-psql-persistent" - }, - { - "name": "NAMESPACE", - "displayName": "Namespace", - "required": true, - "description": "The OpenShift Namespace where the ImageStream resides.", - "value": "openshift" - }, - { - "name": "MEMORY_LIMIT", - "displayName": "Memory Limit", - "required": true, - "description": "Maximum amount of memory the Django container can use.", - "value": "512Mi" - }, - { - "name": "MEMORY_POSTGRESQL_LIMIT", - "displayName": "Memory Limit (PostgreSQL)", - "required": true, - "description": "Maximum amount of memory the PostgreSQL container can use.", - "value": "512Mi" - }, - { - "name": "VOLUME_CAPACITY", - "displayName": "Volume Capacity", - "description": "Volume space available for data, e.g. 512Mi, 2Gi", - "value": "1Gi", - "required": true - }, - { - "name": "SOURCE_REPOSITORY_URL", - "displayName": "Git Repository URL", - "required": true, - "description": "The URL of the repository with your application source code.", - "value": "https://github.com/openshift/django-ex.git" - }, - { - "name": "SOURCE_REPOSITORY_REF", - "displayName": "Git Reference", - "description": "Set this to a branch name, tag or other ref of your repository if you are not using the default branch." - }, - { - "name": "CONTEXT_DIR", - "displayName": "Context Directory", - "description": "Set this to the relative path to your project if it is not in the root of your repository." - }, - { - "name": "APPLICATION_DOMAIN", - "displayName": "Application Hostname", - "description": "The exposed hostname that will route to the Django service, if left blank a value will be defaulted.", - "value": "" - }, - { - "name": "GITHUB_WEBHOOK_SECRET", - "displayName": "GitHub Webhook Secret", - "description": "A secret string used to configure the GitHub webhook.", - "generate": "expression", - "from": "[a-zA-Z0-9]{40}" - }, - { - "name": "DATABASE_SERVICE_NAME", - "displayName": "Database Service Name", - "required": true, - "value": "postgresql" - }, - { - "name": "DATABASE_ENGINE", - "displayName": "Database Engine", - "required": true, - "description": "Database engine: postgresql, mysql or sqlite (default).", - "value": "postgresql" - }, - { - "name": "DATABASE_NAME", - "displayName": "Database Name", - "required": true, - "value": "default" - }, - { - "name": "DATABASE_USER", - "displayName": "Database Username", - "required": true, - "value": "django" - }, - { - "name": "DATABASE_PASSWORD", - "displayName": "Database User Password", - "generate": "expression", - "from": "[a-zA-Z0-9]{16}" - }, - { - "name": "APP_CONFIG", - "displayName": "Application Configuration File Path", - "description": "Relative path to Gunicorn configuration file (optional)." - }, - { - "name": "DJANGO_SECRET_KEY", - "displayName": "Django Secret Key", - "description": "Set this to a long random string.", - "generate": "expression", - "from": "[\\w]{50}" - }, - { - "name": "PIP_INDEX_URL", - "displayName": "Custom PyPi Index URL", - "description": "The custom PyPi index URL", - "value": "" - } - ] -} diff --git a/openshift/templates/django-postgresql.json b/openshift/templates/django-postgresql.json deleted file mode 100644 index 7d1dea11..00000000 --- a/openshift/templates/django-postgresql.json +++ /dev/null @@ -1,466 +0,0 @@ -{ - "kind": "Template", - "apiVersion": "v1", - "metadata": { - "name": "django-psql-example", - "annotations": { - "description": "An example Django application with a PostgreSQL database", - "tags": "quickstart,python,django,postgresql", - "iconClass": "icon-python" - } - }, - "labels": { - "template": "django-psql-example" - }, - "objects": [ - { - "kind": "Service", - "apiVersion": "v1", - "metadata": { - "name": "${NAME}", - "annotations": { - "description": "Exposes and load balances the application pods" - } - }, - "spec": { - "ports": [ - { - "name": "web", - "port": 8080, - "targetPort": 8080 - } - ], - "selector": { - "name": "${NAME}" - } - } - }, - { - "kind": "Route", - "apiVersion": "v1", - "metadata": { - "name": "${NAME}" - }, - "spec": { - "host": "${APPLICATION_DOMAIN}", - "to": { - "kind": "Service", - "name": "${NAME}" - } - } - }, - { - "kind": "ImageStream", - "apiVersion": "v1", - "metadata": { - "name": "${NAME}", - "annotations": { - "description": "Keeps track of changes in the application image" - } - } - }, - { - "kind": "BuildConfig", - "apiVersion": "v1", - "metadata": { - "name": "${NAME}", - "annotations": { - "description": "Defines how to build the application" - } - }, - "spec": { - "source": { - "type": "Git", - "git": { - "uri": "${SOURCE_REPOSITORY_URL}", - "ref": "${SOURCE_REPOSITORY_REF}" - }, - "contextDir": "${CONTEXT_DIR}" - }, - "strategy": { - "type": "Source", - "sourceStrategy": { - "from": { - "kind": "ImageStreamTag", - "namespace": "${NAMESPACE}", - "name": "python:3.5" - }, - "env": [ - { - "name": "PIP_INDEX_URL", - "value": "${PIP_INDEX_URL}" - } - ] - } - }, - "output": { - "to": { - "kind": "ImageStreamTag", - "name": "${NAME}:latest" - } - }, - "triggers": [ - { - "type": "ImageChange" - }, - { - "type": "ConfigChange" - }, - { - "type": "GitHub", - "github": { - "secret": "${GITHUB_WEBHOOK_SECRET}" - } - } - ], - "postCommit": { - "script": "./manage.py test" - } - } - }, - { - "kind": "DeploymentConfig", - "apiVersion": "v1", - "metadata": { - "name": "${NAME}", - "annotations": { - "description": "Defines how to deploy the application server" - } - }, - "spec": { - "strategy": { - "type": "Rolling" - }, - "triggers": [ - { - "type": "ImageChange", - "imageChangeParams": { - "automatic": true, - "containerNames": [ - "django-psql-example" - ], - "from": { - "kind": "ImageStreamTag", - "name": "${NAME}:latest" - } - } - }, - { - "type": "ConfigChange" - } - ], - "replicas": 1, - "selector": { - "name": "${NAME}" - }, - "template": { - "metadata": { - "name": "${NAME}", - "labels": { - "name": "${NAME}" - } - }, - "spec": { - "containers": [ - { - "name": "django-psql-example", - "image": " ", - "ports": [ - { - "containerPort": 8080 - } - ], - "readinessProbe": { - "timeoutSeconds": 3, - "initialDelaySeconds": 3, - "httpGet": { - "path": "/health", - "port": 8080 - } - }, - "livenessProbe": { - "timeoutSeconds": 3, - "initialDelaySeconds": 30, - "httpGet": { - "path": "/health", - "port": 8080 - } - }, - "env": [ - { - "name": "DATABASE_SERVICE_NAME", - "value": "${DATABASE_SERVICE_NAME}" - }, - { - "name": "DATABASE_ENGINE", - "value": "${DATABASE_ENGINE}" - }, - { - "name": "DATABASE_NAME", - "value": "${DATABASE_NAME}" - }, - { - "name": "DATABASE_USER", - "value": "${DATABASE_USER}" - }, - { - "name": "DATABASE_PASSWORD", - "value": "${DATABASE_PASSWORD}" - }, - { - "name": "APP_CONFIG", - "value": "${APP_CONFIG}" - }, - { - "name": "DJANGO_SECRET_KEY", - "value": "${DJANGO_SECRET_KEY}" - } - ], - "resources": { - "limits": { - "memory": "${MEMORY_LIMIT}" - } - } - } - ] - } - } - } - }, - { - "kind": "Service", - "apiVersion": "v1", - "metadata": { - "name": "${DATABASE_SERVICE_NAME}", - "annotations": { - "description": "Exposes the database server" - } - }, - "spec": { - "ports": [ - { - "name": "postgresql", - "port": 5432, - "targetPort": 5432 - } - ], - "selector": { - "name": "${DATABASE_SERVICE_NAME}" - } - } - }, - { - "kind": "DeploymentConfig", - "apiVersion": "v1", - "metadata": { - "name": "${DATABASE_SERVICE_NAME}", - "annotations": { - "description": "Defines how to deploy the database" - } - }, - "spec": { - "strategy": { - "type": "Recreate" - }, - "triggers": [ - { - "type": "ImageChange", - "imageChangeParams": { - "automatic": true, - "containerNames": [ - "postgresql" - ], - "from": { - "kind": "ImageStreamTag", - "namespace": "${NAMESPACE}", - "name": "postgresql:9.5" - } - } - }, - { - "type": "ConfigChange" - } - ], - "replicas": 1, - "selector": { - "name": "${DATABASE_SERVICE_NAME}" - }, - "template": { - "metadata": { - "name": "${DATABASE_SERVICE_NAME}", - "labels": { - "name": "${DATABASE_SERVICE_NAME}" - } - }, - "spec": { - "volumes": [ - { - "name": "data", - "emptyDir": {} - } - ], - "containers": [ - { - "name": "postgresql", - "image": " ", - "ports": [ - { - "containerPort": 5432 - } - ], - "env": [ - { - "name": "POSTGRESQL_USER", - "value": "${DATABASE_USER}" - }, - { - "name": "POSTGRESQL_PASSWORD", - "value": "${DATABASE_PASSWORD}" - }, - { - "name": "POSTGRESQL_DATABASE", - "value": "${DATABASE_NAME}" - } - ], - "volumeMounts": [ - { - "name": "data", - "mountPath": "/var/lib/pgsql/data" - } - ], - "readinessProbe": { - "timeoutSeconds": 1, - "initialDelaySeconds": 5, - "exec": { - "command": [ "/bin/sh", "-i", "-c", "psql -h 127.0.0.1 -U ${POSTGRESQL_USER} -q -d ${POSTGRESQL_DATABASE} -c 'SELECT 1'"] - } - }, - "livenessProbe": { - "timeoutSeconds": 1, - "initialDelaySeconds": 30, - "tcpSocket": { - "port": 5432 - } - }, - "resources": { - "limits": { - "memory": "${MEMORY_POSTGRESQL_LIMIT}" - } - } - } - ] - } - } - } - } - ], - "parameters": [ - { - "name": "NAME", - "displayName": "Name", - "description": "The name assigned to all of the frontend objects defined in this template.", - "required": true, - "value": "django-psql-example" - }, - { - "name": "NAMESPACE", - "displayName": "Namespace", - "required": true, - "description": "The OpenShift Namespace where the ImageStream resides.", - "value": "openshift" - }, - { - "name": "MEMORY_LIMIT", - "displayName": "Memory Limit", - "required": true, - "description": "Maximum amount of memory the Django container can use.", - "value": "512Mi" - }, - { - "name": "MEMORY_POSTGRESQL_LIMIT", - "displayName": "Memory Limit (PostgreSQL)", - "required": true, - "description": "Maximum amount of memory the PostgreSQL container can use.", - "value": "512Mi" - }, - { - "name": "SOURCE_REPOSITORY_URL", - "displayName": "Git Repository URL", - "required": true, - "description": "The URL of the repository with your application source code.", - "value": "https://github.com/openshift/django-ex.git" - }, - { - "name": "SOURCE_REPOSITORY_REF", - "displayName": "Git Reference", - "description": "Set this to a branch name, tag or other ref of your repository if you are not using the default branch." - }, - { - "name": "CONTEXT_DIR", - "displayName": "Context Directory", - "description": "Set this to the relative path to your project if it is not in the root of your repository." - }, - { - "name": "APPLICATION_DOMAIN", - "displayName": "Application Hostname", - "description": "The exposed hostname that will route to the Django service, if left blank a value will be defaulted.", - "value": "" - }, - { - "name": "GITHUB_WEBHOOK_SECRET", - "displayName": "GitHub Webhook Secret", - "description": "A secret string used to configure the GitHub webhook.", - "generate": "expression", - "from": "[a-zA-Z0-9]{40}" - }, - { - "name": "DATABASE_SERVICE_NAME", - "displayName": "Database Service Name", - "required": true, - "value": "postgresql" - }, - { - "name": "DATABASE_ENGINE", - "displayName": "Database Engine", - "required": true, - "description": "Database engine: postgresql, mysql or sqlite (default).", - "value": "postgresql" - }, - { - "name": "DATABASE_NAME", - "displayName": "Database Name", - "required": true, - "value": "default" - }, - { - "name": "DATABASE_USER", - "displayName": "Database Username", - "required": true, - "value": "django" - }, - { - "name": "DATABASE_PASSWORD", - "displayName": "Database User Password", - "generate": "expression", - "from": "[a-zA-Z0-9]{16}" - }, - { - "name": "APP_CONFIG", - "displayName": "Application Configuration File Path", - "description": "Relative path to Gunicorn configuration file (optional)." - }, - { - "name": "DJANGO_SECRET_KEY", - "displayName": "Django Secret Key", - "description": "Set this to a long random string.", - "generate": "expression", - "from": "[\\w]{50}" - }, - { - "name": "PIP_INDEX_URL", - "displayName": "Custom PyPi Index URL", - "description": "The custom PyPi index URL", - "value": "" - } - ] -} diff --git a/openshift/templates/django.json b/openshift/templates/django.json deleted file mode 100644 index 1c2e40d7..00000000 --- a/openshift/templates/django.json +++ /dev/null @@ -1,323 +0,0 @@ -{ - "kind": "Template", - "apiVersion": "v1", - "metadata": { - "name": "django-example", - "annotations": { - "description": "An example Django application with no database", - "tags": "quickstart,python,django", - "iconClass": "icon-python" - } - }, - "labels": { - "template": "django-example" - }, - "objects": [ - { - "kind": "Service", - "apiVersion": "v1", - "metadata": { - "name": "${NAME}", - "annotations": { - "description": "Exposes and load balances the application pods" - } - }, - "spec": { - "ports": [ - { - "name": "web", - "port": 8080, - "targetPort": 8080 - } - ], - "selector": { - "name": "${NAME}" - } - } - }, - { - "kind": "Route", - "apiVersion": "v1", - "metadata": { - "name": "${NAME}" - }, - "spec": { - "host": "${APPLICATION_DOMAIN}", - "to": { - "kind": "Service", - "name": "${NAME}" - } - } - }, - { - "kind": "ImageStream", - "apiVersion": "v1", - "metadata": { - "name": "${NAME}", - "annotations": { - "description": "Keeps track of changes in the application image" - } - } - }, - { - "kind": "BuildConfig", - "apiVersion": "v1", - "metadata": { - "name": "${NAME}", - "annotations": { - "description": "Defines how to build the application" - } - }, - "spec": { - "source": { - "type": "Git", - "git": { - "uri": "${SOURCE_REPOSITORY_URL}", - "ref": "${SOURCE_REPOSITORY_REF}" - }, - "contextDir": "${CONTEXT_DIR}" - }, - "strategy": { - "type": "Source", - "sourceStrategy": { - "from": { - "kind": "ImageStreamTag", - "namespace": "${NAMESPACE}", - "name": "python:3.5" - }, - "env": [ - { - "name": "PIP_INDEX_URL", - "value": "${PIP_INDEX_URL}" - } - ] - } - }, - "output": { - "to": { - "kind": "ImageStreamTag", - "name": "${NAME}:latest" - } - }, - "triggers": [ - { - "type": "ImageChange" - }, - { - "type": "ConfigChange" - }, - { - "type": "GitHub", - "github": { - "secret": "${GITHUB_WEBHOOK_SECRET}" - } - } - ], - "postCommit": { - "script": "./manage.py test" - } - } - }, - { - "kind": "DeploymentConfig", - "apiVersion": "v1", - "metadata": { - "name": "${NAME}", - "annotations": { - "description": "Defines how to deploy the application server" - } - }, - "spec": { - "strategy": { - "type": "Rolling" - }, - "triggers": [ - { - "type": "ImageChange", - "imageChangeParams": { - "automatic": true, - "containerNames": [ - "django-example" - ], - "from": { - "kind": "ImageStreamTag", - "name": "${NAME}:latest" - } - } - }, - { - "type": "ConfigChange" - } - ], - "replicas": 1, - "selector": { - "name": "${NAME}" - }, - "template": { - "metadata": { - "name": "${NAME}", - "labels": { - "name": "${NAME}" - } - }, - "spec": { - "containers": [ - { - "name": "django-example", - "image": " ", - "ports": [ - { - "containerPort": 8080 - } - ], - "readinessProbe": { - "timeoutSeconds": 3, - "initialDelaySeconds": 3, - "httpGet": { - "path": "/", - "port": 8080 - } - }, - "livenessProbe": { - "timeoutSeconds": 3, - "initialDelaySeconds": 30, - "httpGet": { - "path": "/", - "port": 8080 - } - }, - "env": [ - { - "name": "DATABASE_SERVICE_NAME", - "value": "${DATABASE_SERVICE_NAME}" - }, - { - "name": "DATABASE_ENGINE", - "value": "${DATABASE_ENGINE}" - }, - { - "name": "DATABASE_NAME", - "value": "${DATABASE_NAME}" - }, - { - "name": "DATABASE_USER", - "value": "${DATABASE_USER}" - }, - { - "name": "DATABASE_PASSWORD", - "value": "${DATABASE_PASSWORD}" - }, - { - "name": "APP_CONFIG", - "value": "${APP_CONFIG}" - }, - { - "name": "DJANGO_SECRET_KEY", - "value": "${DJANGO_SECRET_KEY}" - } - ], - "resources": { - "limits": { - "memory": "${MEMORY_LIMIT}" - } - } - } - ] - } - } - } - } - ], - "parameters": [ - { - "name": "NAME", - "displayName": "Name", - "description": "The name assigned to all of the frontend objects defined in this template.", - "required": true, - "value": "django-example" - }, - { - "name": "NAMESPACE", - "displayName": "Namespace", - "required": true, - "description": "The OpenShift Namespace where the ImageStream resides.", - "value": "openshift" - }, - { - "name": "MEMORY_LIMIT", - "displayName": "Memory Limit", - "required": true, - "description": "Maximum amount of memory the container can use.", - "value": "512Mi" - }, - { - "name": "SOURCE_REPOSITORY_URL", - "displayName": "Git Repository URL", - "required": true, - "description": "The URL of the repository with your application source code.", - "value": "https://github.com/openshift/django-ex.git" - }, - { - "name": "SOURCE_REPOSITORY_REF", - "displayName": "Git Reference", - "description": "Set this to a branch name, tag or other ref of your repository if you are not using the default branch." - }, - { - "name": "CONTEXT_DIR", - "displayName": "Context Directory", - "description": "Set this to the relative path to your project if it is not in the root of your repository." - }, - { - "name": "APPLICATION_DOMAIN", - "displayName": "Application Hostname", - "description": "The exposed hostname that will route to the Django service, if left blank a value will be defaulted.", - "value": "" - }, - { - "name": "GITHUB_WEBHOOK_SECRET", - "displayName": "GitHub Webhook Secret", - "description": "A secret string used to configure the GitHub webhook.", - "generate": "expression", - "from": "[a-zA-Z0-9]{40}" - }, - { - "name": "DATABASE_SERVICE_NAME", - "displayName": "Database Service Name" - }, - { - "name": "DATABASE_ENGINE", - "displayName": "Database Engine", - "description": "Database engine: postgresql, mysql or sqlite (default)." - }, - { - "name": "DATABASE_NAME", - "displayName": "Database Name" - }, - { - "name": "DATABASE_USER", - "displayName": "Database Username" - }, - { - "name": "DATABASE_PASSWORD", - "displayName": "Database User Password" - }, - { - "name": "APP_CONFIG", - "displayName": "Application Configuration File Path", - "description": "Relative path to Gunicorn configuration file (optional)." - }, - { - "name": "DJANGO_SECRET_KEY", - "displayName": "Django Secret Key", - "description": "Set this to a long random string.", - "generate": "expression", - "from": "[\\w]{50}" - }, - { - "name": "PIP_INDEX_URL", - "displayName": "Custom PyPi Index URL", - "description": "The custom PyPi index URL", - "value": "" - } - ] -} diff --git a/openshift/templates/edivorce-build-template.yaml b/openshift/templates/edivorce-build-template.yaml new file mode 100644 index 00000000..9ffc95c4 --- /dev/null +++ b/openshift/templates/edivorce-build-template.yaml @@ -0,0 +1,89 @@ +--- +kind: Template +apiVersion: v1 +metadata: + name: edivorce-build + annotations: + description: An example Django application with a PostgreSQL database + tags: edivorce,python,django,postgresql + iconClass: icon-python +labels: + template: edivorce-build-template +objects: +- kind: ImageStream + apiVersion: v1 + metadata: + name: "${NAME}" + annotations: + description: Keeps track of changes in the application image +- kind: BuildConfig + apiVersion: v1 + metadata: + name: "${NAME}" + annotations: + description: Defines how to build the application + spec: + source: + type: Git + git: + uri: "${SOURCE_REPOSITORY_URL}" + ref: "${SOURCE_REPOSITORY_REF}" + contextDir: "${CONTEXT_DIR}" + strategy: + type: Source + sourceStrategy: + from: + kind: ImageStreamTag + namespace: "${NAMESPACE}" + name: python:3.5 + env: + - name: PIP_INDEX_URL + value: "${PIP_INDEX_URL}" + output: + to: + kind: ImageStreamTag + name: "${NAME}:latest" + triggers: + - type: ImageChange + - type: ConfigChange + - type: GitHub + github: + secret: "${GITHUB_WEBHOOK_SECRET}" + postCommit: + script: "./manage.py test" +parameters: +- name: NAME + displayName: Name + description: The name assigned to all of the frontend objects defined in this template. + required: true + value: edivorce-django +- name: NAMESPACE + displayName: Namespace + required: true + description: The OpenShift Namespace where the ImageStream resides. + value: openshift +- name: SOURCE_REPOSITORY_URL + displayName: Git Repository URL + required: true + description: The URL of the repository with your application source code. + value: https://github.com/bcgov/eDivorce.git +- name: SOURCE_REPOSITORY_REF + displayName: Git Reference + description: Set this to a branch name, tag or other ref of your repository if you are not using the default branch. +- name: CONTEXT_DIR + displayName: Context Directory + description: Set this to the relative path to your project if it is not in the root of your repository. +- name: GITHUB_WEBHOOK_SECRET + displayName: GitHub Webhook Secret + description: A secret string used to configure the GitHub webhook. + generate: expression + from: "[a-zA-Z0-9]{40}" +- name: DJANGO_SECRET_KEY + displayName: Django Secret Key + description: Set this to a long random string. + generate: expression + from: "[\\w]{50}" +- name: PIP_INDEX_URL + displayName: Custom PyPi Index URL + description: The custom PyPi index URL + value: '' diff --git a/openshift/templates/edivorce-environment-template.yaml b/openshift/templates/edivorce-environment-template.yaml new file mode 100644 index 00000000..080a6851 --- /dev/null +++ b/openshift/templates/edivorce-environment-template.yaml @@ -0,0 +1,320 @@ +--- +kind: Template +apiVersion: v1 +metadata: + name: edivorce + annotations: + description: An example Django application with a PostgreSQL database + tags: edivorce,python,django,postgresql + iconClass: icon-python +labels: + template: edivorce-environment-template +objects: +- kind: Service + apiVersion: v1 + metadata: + name: "${NAME}" + annotations: + description: Exposes and load balances the application pods + spec: + ports: + - name: web + port: 8080 + targetPort: 8080 + selector: + name: "${NAME}" +- kind: DeploymentConfig + apiVersion: v1 + metadata: + name: "${NAME}" + annotations: + description: Defines how to deploy the application server + spec: + strategy: + type: Rolling + triggers: + - type: ImageChange + imageChangeParams: + automatic: true + containerNames: + - edivorce-django + from: + kind: ImageStreamTag + namespace: "${APP_IMAGE_NAMESPACE}" + name: "${APP_IMAGE_NAME}:deploy-to-${ENVIRONMENT_TYPE}" + - type: ConfigChange + replicas: 1 + selector: + name: "${NAME}" + template: + metadata: + name: "${NAME}" + labels: + name: "${NAME}" + spec: + containers: + - name: edivorce-django + image: " " + ports: + - containerPort: 8080 + readinessProbe: + timeoutSeconds: 3 + initialDelaySeconds: 3 + httpGet: + path: "/health" + port: 8080 + livenessProbe: + timeoutSeconds: 3 + initialDelaySeconds: 30 + httpGet: + path: "/health" + port: 8080 + env: + - name: DATABASE_SERVICE_NAME + value: "${DATABASE_SERVICE_NAME}" + - name: DATABASE_ENGINE + value: "${DATABASE_ENGINE}" + - name: DATABASE_NAME + value: "${DATABASE_NAME}" + - name: DATABASE_USER + value: "${DATABASE_USER}" + - name: DATABASE_PASSWORD + value: "${DATABASE_PASSWORD}" + - name: APP_CONFIG + value: "${APP_CONFIG}" + - name: DJANGO_SECRET_KEY + value: "${DJANGO_SECRET_KEY}" + - name: ENVIRONMENT_TYPE + value: "${ENVIRONMENT_TYPE}" + resources: + limits: + memory: "${MEMORY_LIMIT}" +- kind: PersistentVolumeClaim + apiVersion: v1 + metadata: + name: "${DATABASE_SERVICE_NAME}" + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: "${VOLUME_CAPACITY}" +- kind: Service + apiVersion: v1 + metadata: + name: "${DATABASE_SERVICE_NAME}" + annotations: + description: Exposes the database server + spec: + ports: + - name: postgresql + port: 5432 + targetPort: 5432 + selector: + name: "${DATABASE_SERVICE_NAME}" +- kind: DeploymentConfig + apiVersion: v1 + metadata: + name: "${DATABASE_SERVICE_NAME}" + annotations: + description: Defines how to deploy the database + spec: + strategy: + type: Recreate + triggers: + - type: ImageChange + imageChangeParams: + automatic: true + containerNames: + - postgresql + from: + kind: ImageStreamTag + namespace: "${NAMESPACE}" + name: postgresql:9.5 + - type: ConfigChange + replicas: 1 + selector: + name: "${DATABASE_SERVICE_NAME}" + template: + metadata: + name: "${DATABASE_SERVICE_NAME}" + labels: + name: "${DATABASE_SERVICE_NAME}" + spec: + volumes: + - name: "${DATABASE_SERVICE_NAME}-data" + persistentVolumeClaim: + claimName: "${DATABASE_SERVICE_NAME}" + containers: + - name: postgresql + image: " " + ports: + - containerPort: 5432 + env: + - name: POSTGRESQL_USER + value: "${DATABASE_USER}" + - name: POSTGRESQL_PASSWORD + value: "${DATABASE_PASSWORD}" + - name: POSTGRESQL_DATABASE + value: "${DATABASE_NAME}" + volumeMounts: + - name: "${DATABASE_SERVICE_NAME}-data" + mountPath: "/var/lib/pgsql/data" + readinessProbe: + timeoutSeconds: 1 + initialDelaySeconds: 5 + exec: + command: + - "/bin/sh" + - "-i" + - "-c" + - psql -h 127.0.0.1 -U ${POSTGRESQL_USER} -q -d ${POSTGRESQL_DATABASE} -c 'SELECT 1' + livenessProbe: + timeoutSeconds: 1 + initialDelaySeconds: 30 + tcpSocket: + port: 5432 + resources: + limits: + memory: "${MEMORY_POSTGRESQL_LIMIT}" +- kind: ImageStream + apiVersion: v1 + metadata: + name: weasyprint + labels: + name: weasyprint + spec: + tags: + - name: latest + annotations: + openshift.io/imported-from: aquavitae/weasyprint + from: + kind: DockerImage + name: aquavitae/weasyprint +- kind: Service + apiVersion: v1 + metadata: + name: weasyprint + labels: + name: weasyprint + spec: + ports: + - name: 5001-tcp + protocol: TCP + port: 5001 + targetPort: 5001 + selector: + name: weasyprint +- kind: DeploymentConfig + apiVersion: v1 + metadata: + name: weasyprint + labels: + app: weasyprint + annotations: + description: Weasyprint microservice using aquavitae/weasyprint + spec: + strategy: + type: Recreate + triggers: + - type: ImageChange + imageChangeParams: + automatic: true + containerNames: + - weasyprint + from: + kind: ImageStreamTag + name: 'aquavitae/weasyprint:latest' + replicas: 1 + selector: + name: weasyprint + template: + metadata: + name: weasyprint + labels: + name: weasyprint + annotations: + openshift.io/container.weasyprint.image.entrypoint: '["/bin/sh","-c","gunicorn --bind 0.0.0.0:5001 wsgi:app"]' + spec: + containers: + - name: weasyprint + image: 'aquavitae/weasyprint' + ports: + - containerPort: 5001 + protocol: TCP + livenessProbe: + httpGet: + path: /health + port: 5001 + scheme: HTTP + initialDelaySeconds: 120 + timeoutSeconds: 30 + periodSeconds: 60 + successThreshold: 1 + failureThreshold: 5 +parameters: +- name: NAME + displayName: Name + description: The name assigned to all of the frontend objects defined in this template. + required: true + value: edivorce-django +- name: NAMESPACE + displayName: Namespace + required: true + description: The OpenShift Namespace where the ImageStream resides. + value: openshift +- name: MEMORY_LIMIT + displayName: Memory Limit + required: true + description: Maximum amount of memory the Django container can use. + value: 512Mi +- name: MEMORY_POSTGRESQL_LIMIT + displayName: Memory Limit (PostgreSQL) + required: true + description: Maximum amount of memory the PostgreSQL container can use. + value: 512Mi +- name: VOLUME_CAPACITY + displayName: Volume Capacity + description: Volume space available for data, e.g. 512Mi, 2Gi + value: 1Gi + required: true +- name: DATABASE_SERVICE_NAME + displayName: Database Service Name + required: true + value: postgresql +- name: DATABASE_ENGINE + displayName: Database Engine + required: true + description: 'Database engine: postgresql, mysql or sqlite (default).' + value: postgresql +- name: DATABASE_NAME + displayName: Database Name + required: true + value: default +- name: DATABASE_USER + displayName: Database Username + required: true + value: django +- name: DATABASE_PASSWORD + displayName: Database User Password + generate: expression + from: "[a-zA-Z0-9]{16}" +- name: APP_CONFIG + displayName: Application Configuration File Path + description: Relative path to Gunicorn configuration file (optional). +- name: DJANGO_SECRET_KEY + displayName: Django Secret Key + description: Set this to a long random string. + generate: expression + from: "[\\w]{50}" +- name: APP_IMAGE_NAME + displayName: Application image name. + value: edivorce-django + required": true +- name: APP_IMAGE_NAMESPACE + displayName: Namespace containing application images. + value: jag-csb-edivorce-tools + required: true +- name: ENVIRONMENT_TYPE + displayName: Type of environnment (dev,test or prod). + required: true