From 8239a8b1d0f31eafc37a4844a483c88efa581e38 Mon Sep 17 00:00:00 2001 From: Siamak Sadeghianfar Date: Fri, 2 Mar 2018 15:59:52 +0100 Subject: [PATCH] added solutions --- solutions/lab-10/Dockerfile | 17 + solutions/lab-3/cart-template.yaml | 169 +++ solutions/lab-4/cart-pipeline.yaml | 24 + solutions/lab-5/Jenkinsfile | 20 + solutions/lab-5/cart-pipeline-scm.yaml | 18 + solutions/lab-6/Jenkinsfile | 35 + solutions/lab-6/coolstore-template.yaml | 857 ++++++++++++++++ solutions/lab-7/cart-blue.yaml | 100 ++ solutions/lab-7/cart-green.yaml | 100 ++ .../lab-7/coolstore-bluegreen-template.yaml | 965 ++++++++++++++++++ solutions/lab-8/Jenkinsfile | 53 + solutions/support/lab-clean.sh | 8 + solutions/support/lab-prepare.sh | 144 +++ solutions/support/lab-solve.sh | 43 + 14 files changed, 2553 insertions(+) create mode 100644 solutions/lab-10/Dockerfile create mode 100644 solutions/lab-3/cart-template.yaml create mode 100644 solutions/lab-4/cart-pipeline.yaml create mode 100644 solutions/lab-5/Jenkinsfile create mode 100644 solutions/lab-5/cart-pipeline-scm.yaml create mode 100644 solutions/lab-6/Jenkinsfile create mode 100644 solutions/lab-6/coolstore-template.yaml create mode 100644 solutions/lab-7/cart-blue.yaml create mode 100644 solutions/lab-7/cart-green.yaml create mode 100644 solutions/lab-7/coolstore-bluegreen-template.yaml create mode 100644 solutions/lab-8/Jenkinsfile create mode 100755 solutions/support/lab-clean.sh create mode 100755 solutions/support/lab-prepare.sh create mode 100755 solutions/support/lab-solve.sh diff --git a/solutions/lab-10/Dockerfile b/solutions/lab-10/Dockerfile new file mode 100644 index 0000000..38b2d25 --- /dev/null +++ b/solutions/lab-10/Dockerfile @@ -0,0 +1,17 @@ +FROM registry.access.redhat.com/openshift3/jenkins-slave-maven-rhel7 + +MAINTAINER Siamak Sadeghianfar + +ENV GRADLE_VERSION=3.4.1 + +USER root + +RUN curl -skL -o /tmp/gradle-bin.zip https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip && \ + mkdir -p /opt/gradle && \ + unzip -q /tmp/gradle-bin.zip -d /opt/gradle && \ + ln -sf /opt/gradle/gradle-$GRADLE_VERSION/bin/gradle /usr/local/bin/gradle + +RUN chown -R 1001:0 /opt/gradle && \ + chmod -R g+rw /opt/gradle + +USER 1001 \ No newline at end of file diff --git a/solutions/lab-3/cart-template.yaml b/solutions/lab-3/cart-template.yaml new file mode 100644 index 0000000..6b59f1a --- /dev/null +++ b/solutions/lab-3/cart-template.yaml @@ -0,0 +1,169 @@ +apiVersion: v1 +kind: Template +metadata: + annotations: + iconClass: icon-java + tags: microservice,jboss + name: cart +objects: +- apiVersion: v1 + kind: ImageStream + metadata: + name: cart + labels: + application: cart + spec: + tags: + - name: latest +- apiVersion: v1 + kind: BuildConfig + metadata: + name: cart + labels: + application: cart + spec: + output: + to: + kind: ImageStreamTag + name: cart:latest + source: + git: + ref: ${GIT_REF} + uri: ${GIT_URI} + type: Git + strategy: + sourceStrategy: + env: + - name: MAVEN_MIRROR_URL + value: ${MAVEN_MIRROR_URL} + from: + kind: ImageStreamTag + name: redhat-openjdk18-openshift:1.0 + namespace: openshift + type: Source + triggers: + - type: ConfigChange + - imageChange: {} + type: ImageChange +- apiVersion: v1 + kind: DeploymentConfig + metadata: + name: cart + labels: + application: cart + spec: + replicas: 1 + selector: + deploymentconfig: cart + strategy: + resources: {} + type: Recreate + template: + metadata: + labels: + application: cart + deploymentconfig: cart + name: cart + spec: + containers: + - env: + - name: CATALOG_ENDPOINT + value: "http://catalog:8080" + image: cart + imagePullPolicy: Always + livenessProbe: + failureThreshold: 5 + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 45 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + name: cart + ports: + - containerPort: 8778 + name: jolokia + protocol: TCP + - containerPort: 8080 + name: http + protocol: TCP + - containerPort: 8443 + name: https + protocol: TCP + readinessProbe: + failureThreshold: 10 + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 45 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + memory: 1Gi + requests: + memory: 200Mi + terminationMessagePath: /dev/termination-log + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: {} + terminationGracePeriodSeconds: 75 + triggers: + - imageChangeParams: + automatic: true + containerNames: + - cart + from: + kind: ImageStreamTag + name: cart:latest + type: ImageChange + - type: ConfigChange +- apiVersion: v1 + kind: Service + metadata: + labels: + app: cart + application: cart + name: cart + spec: + ports: + - port: 8080 + protocol: TCP + targetPort: 8080 + selector: + deploymentconfig: cart +- apiVersion: v1 + kind: Route + metadata: + labels: + app: cart + application: cart + name: cart + spec: + to: + kind: Service + name: cart + weight: 100 + wildcardPolicy: None +parameters: +- displayName: Application name + name: APPLICATION_NAME + required: true + value: cart +- description: Git source URI for application + displayName: Git source repository + name: GIT_URI + required: true +- description: Git branch/tag reference + displayName: Git branch/tag reference + name: GIT_REF +- description: Sub-directory in the Git repo for cart service + displayName: Git context dir + name: GIT_CONTEXT_DIR +- description: Maven mirror url. If nexus is deployed locally, use nexus url (e.g. http://nexus.ci:8081/content/groups/public/) + displayName: Maven mirror url + name: MAVEN_MIRROR_URL diff --git a/solutions/lab-4/cart-pipeline.yaml b/solutions/lab-4/cart-pipeline.yaml new file mode 100644 index 0000000..5eae100 --- /dev/null +++ b/solutions/lab-4/cart-pipeline.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: BuildConfig +metadata: + annotations: + pipeline.alpha.openshift.io/uses: '[{"name": "cart", "namespace": "", "kind": "DeploymentConfig"}]' + name: cart-pipeline +spec: + strategy: + jenkinsPipelineStrategy: + jenkinsfile: |- + node('maven') { + stage('Build') { + openshiftBuild(buildConfig: 'cart', showBuildLogs: 'true') + } + stage('Deploy') { + openshiftDeploy(deploymentConfig: 'cart') + openshiftVerifyDeployment(deploymentConfig: "cart", replicaCount: 1, verifyReplicaCount: true) + } + stage('Test') { + sh "curl -s -X POST http://cart.dev.svc.cluster.local:8080/api/cart/dummy/666/1" + sh "curl -s http://cart.dev.svc.cluster.local:8080/api/cart/dummy | grep 'Dummy Product'" + } + } + type: JenkinsPipeline \ No newline at end of file diff --git a/solutions/lab-5/Jenkinsfile b/solutions/lab-5/Jenkinsfile new file mode 100644 index 0000000..56796e1 --- /dev/null +++ b/solutions/lab-5/Jenkinsfile @@ -0,0 +1,20 @@ +node('maven') { + stage('Build App') { + git url: "http://gogs.lab-infra.svc.cluster.local:3000/developer/cart-service.git" + sh "mvn clean package -s src/main/config/settings.xml" + } + stage('Integration Test') { + sh "mvn verify -s src/main/config/settings.xml" + } + stage('Build Image') { + sh "oc start-build cart --from-file=target/cart.jar --follow" + } + stage('Deploy') { + openshiftDeploy deploymentConfig: 'cart' + openshiftVerifyDeployment deploymentConfig: "cart", replicaCount: 1, verifyReplicaCount: true + } + stage('Component Test') { + sh "curl -s -X POST http://cart.dev.svc.cluster.local:8080/api/cart/dummy/666/1" + sh "curl -s http://cart.dev.svc.cluster.local:8080/api/cart/dummy | grep 'Dummy Product'" + } +} diff --git a/solutions/lab-5/cart-pipeline-scm.yaml b/solutions/lab-5/cart-pipeline-scm.yaml new file mode 100644 index 0000000..8e6077d --- /dev/null +++ b/solutions/lab-5/cart-pipeline-scm.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: BuildConfig +metadata: + annotations: + pipeline.alpha.openshift.io/uses: '[{"name": "cart", "namespace": "", "kind": "DeploymentConfig"}]' + name: cart-pipeline-git +spec: + source: + git: + uri: http://gogs.lab-infra.svc.cluster.local:3000/developer/pipelines.git + type: Git + strategy: + type: JenkinsPipeline + jenkinsPipelineStrategy: {} + triggers: + - generic: + secret: FiArdDBH + type: Generic diff --git a/solutions/lab-6/Jenkinsfile b/solutions/lab-6/Jenkinsfile new file mode 100644 index 0000000..6fd5023 --- /dev/null +++ b/solutions/lab-6/Jenkinsfile @@ -0,0 +1,35 @@ +node('maven') { + stage('Build App') { + git url: "http://gogs.lab-infra.svc.cluster.local:3000/developer/cart-service.git" + sh "mvn clean package -s src/main/config/settings.xml" + } + stage('Integration Test') { + sh "mvn verify -s src/main/config/settings.xml" + } + stage('Build Image') { + sh "oc start-build cart --from-file=target/cart.jar --follow" + } + stage('Deploy') { + openshiftDeploy depCfg: 'cart' + openshiftVerifyDeployment depCfg: 'cart', replicaCount: 1, verifyReplicaCount: true + } + stage('Component Test') { + sh "curl -s -X POST http://cart.dev.svc.cluster.local:8080/api/cart/dummy/666/1" + sh "curl -s http://cart.dev.svc.cluster.local:8080/api/cart/dummy | grep 'Dummy Product'" + } + stage('Approve') { + timeout(time:15, unit:'MINUTES') { + input message:'Approve Deploy to Prod?' + } + } + stage('Promote') { + openshiftTag srcStream: 'cart', srcTag: 'latest', namespace: 'dev', destStream: 'cart', destTag: 'prod', destinationNamespace: 'prod' + sleep 10 + openshiftVerifyDeployment depCfg: 'cart', replicaCount: 1, verifyReplicaCount: true, namespace: 'prod' + } + + stage('End-To-End Test') { + sh "curl -s -X POST http://cart.prod.svc.cluster.local:8080/api/cart/dummy/444434/1" + sh "curl -s http://cart.prod.svc.cluster.local:8080/api/cart/dummy | grep 'Pebble Smart Watch'" + } +} diff --git a/solutions/lab-6/coolstore-template.yaml b/solutions/lab-6/coolstore-template.yaml new file mode 100644 index 0000000..e6ffd1f --- /dev/null +++ b/solutions/lab-6/coolstore-template.yaml @@ -0,0 +1,857 @@ +apiVersion: v1 +kind: Template +metadata: + annotations: + description: CoolStore Microservices Application Template + iconClass: icon-java + tags: microservice,jboss,spring + name: coolstore +objects: +- apiVersion: v1 + groupNames: null + kind: RoleBinding + metadata: + name: default_edit + roleRef: + name: view + subjects: + - kind: ServiceAccount + name: default +# UI +- apiVersion: v1 + kind: DeploymentConfig + metadata: + name: web-ui + labels: + application: coolstore + component: web-ui + spec: + replicas: 1 + selector: + deploymentconfig: web-ui + strategy: + resources: {} + type: Recreate + template: + metadata: + labels: + application: coolstore + component: web-ui + deploymentconfig: web-ui + spec: + containers: + - env: + - name: COOLSTORE_GW_SERVICE + value: coolstore-gw + - name: HOSTNAME_HTTP + value: web-ui:8080 + image: web-ui + imagePullPolicy: Always + name: web-ui + ports: + - containerPort: 8080 + protocol: TCP + livenessProbe: + failureThreshold: 5 + httpGet: + path: / + port: 8080 + scheme: HTTP + initialDelaySeconds: 120 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 5 + readinessProbe: + failureThreshold: 5 + httpGet: + path: / + port: 8080 + scheme: HTTP + initialDelaySeconds: 15 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + cpu: 500m + memory: 1Gi + requests: + cpu: 50m + memory: 128Mi + terminationMessagePath: /dev/termination-log + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: {} + terminationGracePeriodSeconds: 30 + triggers: + - imageChangeParams: + automatic: true + containerNames: + - web-ui + from: + kind: ImageStreamTag + namespace: ${IMAGESTREAM_NAMESPACE} + name: coolstore-web-ui:${APP_VERSION} + type: ImageChange + - type: ConfigChange +- apiVersion: v1 + kind: Service + metadata: + labels: + app: web-ui + application: coolstore + component: web-ui + name: web-ui + spec: + ports: + - name: 8080-tcp + port: 8080 + protocol: TCP + targetPort: 8080 + selector: + deploymentconfig: web-ui +- apiVersion: v1 + kind: Route + metadata: + name: web-ui + labels: + application: coolstore + component: web-ui + spec: + host: web-ui-${HOSTNAME_SUFFIX} + to: + kind: Service + name: web-ui +# Coolstore Gateway +- apiVersion: v1 + kind: DeploymentConfig + metadata: + name: coolstore-gw + labels: + application: coolstore + component: coolstore-gw + spec: + replicas: 1 + selector: + deploymentconfig: coolstore-gw + strategy: + resources: {} + type: Recreate + template: + metadata: + labels: + application: coolstore + component: coolstore-gw + deploymentconfig: coolstore-gw + name: coolstore-gw + spec: + containers: + - env: + - name: KUBERNETES_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: CART_ENDPOINT + value: cart-${HOSTNAME_SUFFIX} + - name: INVENTORY_ENDPOINT + value: inventory-${HOSTNAME_SUFFIX} + - name: CATALOG_ENDPOINT + value: catalog-${HOSTNAME_SUFFIX} + image: library/coolstore-gw:${APP_VERSION} + livenessProbe: + httpGet: + path: /health + port: 8081 + initialDelaySeconds: 180 + name: coolstore-gw + ports: + - containerPort: 8778 + name: jolokia + readinessProbe: + httpGet: + path: /health + port: 8081 + initialDelaySeconds: 10 + resources: + limits: + cpu: 1 + memory: 2Gi + requests: + cpu: 100m + memory: 512Mi + triggers: + - imageChangeParams: + automatic: true + containerNames: + - coolstore-gw + from: + kind: ImageStreamTag + namespace: ${IMAGESTREAM_NAMESPACE} + name: coolstore-gateway:${APP_VERSION} + type: ImageChange + - type: ConfigChange +- apiVersion: v1 + kind: Service + metadata: + labels: + app: coolstore-gw + application: coolstore + component: coolstore-gw + hystrix.enabled: "true" + name: coolstore-gw + spec: + ports: + - port: 8080 + protocol: TCP + targetPort: 8080 + selector: + deploymentconfig: coolstore-gw +- apiVersion: v1 + kind: Route + metadata: + name: coolstore-gw + labels: + application: coolstore + component: coolstore-gw + spec: + host: gw-${HOSTNAME_SUFFIX} + to: + kind: Service + name: coolstore-gw +# Catalog Service +- apiVersion: v1 + kind: ImageStream + metadata: + name: catalog + labels: + application: coolstore + component: catalog + spec: + tags: + - name: latest +- apiVersion: v1 + kind: DeploymentConfig + metadata: + name: catalog + labels: + application: coolstore + component: catalog + spec: + replicas: 1 + selector: + deploymentconfig: catalog + strategy: + resources: {} + type: Recreate + template: + metadata: + labels: + application: coolstore + component: catalog + deploymentconfig: catalog + name: catalog + spec: + containers: + - env: + - name: JWS_ADMIN_USERNAME + value: Skq3VtCd + - name: JWS_ADMIN_PASSWORD + value: oktt6yhw + - name: DB_USERNAME + value: ${CATALOG_DB_USERNAME} + - name: DB_PASSWORD + value: ${CATALOG_DB_PASSWORD} + - name: DB_NAME + value: catalogdb + - name: DB_SERVER + value: catalog-mongodb + image: catalog + imagePullPolicy: Always + name: catalog + ports: + - containerPort: 8778 + name: jolokia + protocol: TCP + - containerPort: 8080 + name: http + protocol: TCP + readinessProbe: + failureThreshold: 10 + exec: + command: + - /bin/bash + - -c + - curl -s -u Skq3VtCd:oktt6yhw 'http://localhost:8080/manager/jmxproxy/?get=Catalina%3Atype%3DServer&att=stateName' + |grep -iq 'stateName *= *STARTED' + initialDelaySeconds: 15 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + cpu: 2 + memory: 2Gi + requests: + cpu: 100m + memory: 256Mi + terminationMessagePath: /dev/termination-log + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: {} + terminationGracePeriodSeconds: 75 + triggers: + - imageChangeParams: + automatic: true + containerNames: + - catalog + from: + kind: ImageStreamTag + name: coolstore-catalog:${APP_VERSION} + namespace: ${IMAGESTREAM_NAMESPACE} + type: ImageChange + - type: ConfigChange +- apiVersion: v1 + kind: Service + metadata: + annotations: + service.alpha.openshift.io/dependencies: '[{"name":"catalog-mongodb","namespace":"","kind":"Service"}]' + labels: + app: catalog + application: coolstore + component: catalog + name: catalog + spec: + ports: + - port: 8080 + protocol: TCP + targetPort: 8080 + selector: + deploymentconfig: catalog +- apiVersion: v1 + kind: Route + metadata: + labels: + application: coolstore + component: catalog + name: catalog + spec: + host: catalog-${HOSTNAME_SUFFIX} + to: + kind: Service + name: catalog + weight: 100 +- apiVersion: v1 + kind: Service + metadata: + labels: + app: catalog + application: coolstore + component: catalog + name: catalog-mongodb + spec: + ports: + - name: mongo + port: 27017 + protocol: TCP + targetPort: 27017 + selector: + deploymentconfig: catalog-mongodb + sessionAffinity: None + type: ClusterIP +- apiVersion: v1 + kind: DeploymentConfig + metadata: + labels: + application: coolstore + component: catalog + name: catalog-mongodb + spec: + replicas: 1 + selector: + deploymentconfig: catalog-mongodb + strategy: + recreateParams: + timeoutSeconds: 600 + resources: {} + type: Recreate + template: + metadata: + labels: + application: coolstore + component: catalog + deploymentconfig: catalog-mongodb + spec: + containers: + - env: + - name: KUBERNETES_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MONGODB_USER + value: ${CATALOG_DB_USERNAME} + - name: MONGODB_PASSWORD + value: ${CATALOG_DB_PASSWORD} + - name: MONGODB_DATABASE + value: catalogdb + - name: MONGODB_ADMIN_PASSWORD + value: ${CATALOG_DB_PASSWORD} + image: mongodb + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + tcpSocket: + port: 27017 + timeoutSeconds: 1 + name: catalog-mongodb + ports: + - containerPort: 27017 + protocol: TCP + readinessProbe: + exec: + command: + - /bin/sh + - -i + - -c + - mongo 127.0.0.1:27017/$MONGODB_DATABASE -u $MONGODB_USER -p $MONGODB_PASSWORD + --eval="quit()" + failureThreshold: 3 + initialDelaySeconds: 3 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + cpu: 500m + memory: 1Gi + requests: + cpu: 100m + memory: 256Mi + securityContext: + capabilities: {} + privileged: false + terminationMessagePath: /dev/termination-log + volumeMounts: + - mountPath: /var/lib/mongodb/data + name: mongodb-data + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - name: mongodb-data + persistentVolumeClaim: + claimName: mongodb-data-pv + test: false + triggers: + - imageChangeParams: + automatic: true + containerNames: + - catalog-mongodb + from: + kind: ImageStreamTag + name: mongodb:3.2 + namespace: openshift + type: ImageChange + - type: ConfigChange +- apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + labels: + application: coolstore + component: catalog + name: mongodb-data-pv + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 512Mi +# Cart Service +- apiVersion: v1 + kind: DeploymentConfig + metadata: + name: cart + labels: + application: coolstore + component: cart + spec: + replicas: 1 + selector: + deploymentconfig: cart + strategy: + resources: {} + type: Recreate + template: + metadata: + labels: + application: coolstore + component: cart + deploymentconfig: cart + name: cart + spec: + containers: + - env: + - name: CATALOG_ENDPOINT + value: "http://catalog:8080" + - name: APPLICATION_MODE + value: prod + image: cart + imagePullPolicy: Always + livenessProbe: + failureThreshold: 5 + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 45 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + name: cart + ports: + - containerPort: 8778 + name: jolokia + protocol: TCP + - containerPort: 8080 + name: http + protocol: TCP + - containerPort: 8443 + name: https + protocol: TCP + readinessProbe: + failureThreshold: 10 + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 45 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + memory: 1Gi + requests: + memory: 200Mi + terminationMessagePath: /dev/termination-log + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: {} + terminationGracePeriodSeconds: 75 + triggers: + - imageChangeParams: + automatic: true + containerNames: + - cart + from: + kind: ImageStreamTag + name: cart:${APP_VERSION} + type: ImageChange + - type: ConfigChange +- apiVersion: v1 + kind: Service + metadata: + labels: + app: cart + application: coolstore + component: cart + name: cart + spec: + ports: + - port: 8080 + protocol: TCP + targetPort: 8080 + selector: + deploymentconfig: cart +- apiVersion: v1 + kind: Route + metadata: + labels: + application: coolstore + component: cart + name: cart + spec: + host: cart-${HOSTNAME_SUFFIX} + to: + kind: Service + name: cart + weight: 100 +# Inventory Service +- apiVersion: v1 + kind: DeploymentConfig + metadata: + name: inventory + labels: + application: coolstore + component: inventory + spec: + replicas: 1 + selector: + deploymentconfig: inventory + strategy: + resources: {} + type: Recreate + template: + metadata: + labels: + deploymentconfig: inventory + application: coolstore + component: inventory + name: inventory + spec: + containers: + - env: + - name: OPENSHIFT_KUBE_PING_LABELS + value: application=inventory + - name: OPENSHIFT_KUBE_PING_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MQ_CLUSTER_PASSWORD + value: 7mzX0pLV03 + - name: JGROUPS_CLUSTER_PASSWORD + value: CqUo3fYDTv + - name: AUTO_DEPLOY_EXPLODED + value: "false" + - name: DB_SERVICE_PREFIX_MAPPING + value: inventory-postgresql=DB + - name: DB_JNDI + value: java:jboss/datasources/InventoryDS + - name: DB_USERNAME + value: ${INVENTORY_DB_USERNAME} + - name: DB_PASSWORD + value: ${INVENTORY_DB_PASSWORD} + - name: DB_DATABASE + value: inventorydb + image: inventory + imagePullPolicy: Always + lifecycle: + preStop: + exec: + command: + - /opt/eap/bin/jboss-cli.sh + - -c + - :shutdown(timeout=60) + livenessProbe: + failureThreshold: 5 + httpGet: + path: / + port: 8080 + scheme: HTTP + initialDelaySeconds: 120 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 5 + name: inventory + ports: + - containerPort: 8778 + name: jolokia + protocol: TCP + - containerPort: 8080 + name: http + protocol: TCP + - containerPort: 8888 + name: ping + protocol: TCP + readinessProbe: + failureThreshold: 5 + httpGet: + path: / + port: 8080 + scheme: HTTP + initialDelaySeconds: 15 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + cpu: 500m + memory: 1Gi + requests: + cpu: 100m + memory: 512Mi + terminationMessagePath: /dev/termination-log + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: {} + terminationGracePeriodSeconds: 75 + triggers: + - imageChangeParams: + automatic: true + containerNames: + - inventory + from: + kind: ImageStreamTag + name: coolstore-inventory:${APP_VERSION} + namespace: ${IMAGESTREAM_NAMESPACE} + type: ImageChange + - type: ConfigChange +- apiVersion: v1 + kind: Service + metadata: + annotations: + service.alpha.openshift.io/dependencies: '[{"name":"inventory-postgresql","namespace":"","kind":"Service"}]' + labels: + app: inventory + application: inventory + name: inventory + spec: + ports: + - port: 8080 + protocol: TCP + targetPort: 8080 + selector: + deploymentconfig: inventory +- apiVersion: v1 + kind: Route + metadata: + labels: + application: inventory + name: inventory + spec: + host: inventory-${HOSTNAME_SUFFIX} + to: + kind: Service + name: inventory + weight: 100 +- apiVersion: v1 + kind: DeploymentConfig + metadata: + name: inventory-postgresql + labels: + component: inventory + application: coolstore + spec: + replicas: 1 + selector: + deploymentconfig: inventory-postgresql + strategy: + type: Recreate + template: + metadata: + labels: + application: coolstore + component: inventory + deploymentconfig: inventory-postgresql + name: inventory-postgresql + spec: + containers: + - env: + - name: POSTGRESQL_USER + value: ${INVENTORY_DB_USERNAME} + - name: POSTGRESQL_PASSWORD + value: ${INVENTORY_DB_PASSWORD} + - name: POSTGRESQL_DATABASE + value: inventorydb + image: postgresql + imagePullPolicy: Always + name: inventory-postgresql + ports: + - containerPort: 5432 + protocol: TCP + volumeMounts: + - mountPath: /var/lib/pgsql/data + name: inventory-postgresql-data + livenessProbe: + initialDelaySeconds: 30 + tcpSocket: + port: 5432 + timeoutSeconds: 1 + readinessProbe: + exec: + command: + - /bin/sh + - -i + - -c + - psql -h 127.0.0.1 -U $POSTGRESQL_USER -q -d $POSTGRESQL_DATABASE -c 'SELECT 1' + initialDelaySeconds: 5 + timeoutSeconds: 1 + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 50m + memory: 128Mi + terminationGracePeriodSeconds: 60 + volumes: + - name: inventory-postgresql-data + persistentVolumeClaim: + claimName: inventory-postgresql-pv + triggers: + - imageChangeParams: + automatic: true + containerNames: + - inventory-postgresql + from: + kind: ImageStreamTag + name: postgresql:latest + namespace: openshift + type: ImageChange + - type: ConfigChange +- apiVersion: v1 + kind: Service + metadata: + labels: + application: inventory + name: inventory-postgresql + spec: + ports: + - port: 5432 + targetPort: 5432 + selector: + deploymentconfig: inventory-postgresql +- apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + labels: + application: inventory + name: inventory-postgresql-pv + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +parameters: +- description: Namespace in which the ImageStreams for CoolStore services are installed + displayName: ImageStream Namespace + name: IMAGESTREAM_NAMESPACE + required: true + value: openshift +- description: CoolStore application image version to be deployed (imagestreams should exist) + displayName: CoolStore Version + name: APP_VERSION + required: true + value: prod +- description: Hostname suffix used for routes e.g. cart- inventory- + displayName: Hostname Suffix + name: HOSTNAME_SUFFIX + required: true +- description: Catalog Service database user name + displayName: Catalog Database Username + from: user[a-zA-Z0-9]{3} + generate: expression + name: CATALOG_DB_USERNAME + required: true +- description: Catalog Service database user password + displayName: Catalog Database Password + from: '[a-zA-Z0-9]{8}' + generate: expression + name: CATALOG_DB_PASSWORD + required: true +- description: Inventory Service database user name + displayName: Inventory Database Username + from: user[a-zA-Z0-9]{3} + generate: expression + name: INVENTORY_DB_USERNAME + required: true +- description: Inventory Service database user password + displayName: Inventory Database Password + from: '[a-zA-Z0-9]{8}' + generate: expression + name: INVENTORY_DB_PASSWORD + required: true diff --git a/solutions/lab-7/cart-blue.yaml b/solutions/lab-7/cart-blue.yaml new file mode 100644 index 0000000..00321de --- /dev/null +++ b/solutions/lab-7/cart-blue.yaml @@ -0,0 +1,100 @@ +apiVersion: v1 +kind: List +items: +- apiVersion: v1 + kind: Service + metadata: + labels: + app: cart-blue + application: coolstore + component: cart-blue + name: cart-blue + spec: + ports: + - port: 8080 + protocol: TCP + targetPort: 8080 + selector: + deploymentconfig: cart-blue + sessionAffinity: None + type: ClusterIP +- apiVersion: v1 + kind: DeploymentConfig + metadata: + labels: + application: coolstore + component: cart-blue + name: cart-blue + spec: + replicas: 1 + selector: + deploymentconfig: cart-blue + strategy: + type: Recreate + template: + metadata: + labels: + application: coolstore + component: cart-blue + deploymentconfig: cart-blue + name: cart-blue + spec: + containers: + - env: + - name: CATALOG_ENDPOINT + value: http://catalog:8080 + image: cart + imagePullPolicy: Always + livenessProbe: + failureThreshold: 5 + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 45 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + name: cart-blue + ports: + - containerPort: 8778 + name: jolokia + protocol: TCP + - containerPort: 8080 + name: http + protocol: TCP + - containerPort: 8443 + name: https + protocol: TCP + readinessProbe: + failureThreshold: 10 + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 45 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + memory: 1Gi + requests: + memory: 200Mi + terminationMessagePath: /dev/termination-log + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: {} + terminationGracePeriodSeconds: 75 + test: false + triggers: + - imageChangeParams: + automatic: true + containerNames: + - cart-blue + from: + kind: ImageStreamTag + name: cart:prod-blue + namespace: prod + type: ImageChange + - type: ConfigChange \ No newline at end of file diff --git a/solutions/lab-7/cart-green.yaml b/solutions/lab-7/cart-green.yaml new file mode 100644 index 0000000..bc6bfd3 --- /dev/null +++ b/solutions/lab-7/cart-green.yaml @@ -0,0 +1,100 @@ +apiVersion: v1 +kind: List +items: +- apiVersion: v1 + kind: Service + metadata: + labels: + app: cart-green + application: coolstore + component: cart-green + name: cart-green + spec: + ports: + - port: 8080 + protocol: TCP + targetPort: 8080 + selector: + deploymentconfig: cart-green + sessionAffinity: None + type: ClusterIP +- apiVersion: v1 + kind: DeploymentConfig + metadata: + labels: + application: coolstore + component: cart-green + name: cart-green + spec: + replicas: 1 + selector: + deploymentconfig: cart-green + strategy: + type: Recreate + template: + metadata: + labels: + application: coolstore + component: cart-green + deploymentconfig: cart-green + name: cart-green + spec: + containers: + - env: + - name: CATALOG_ENDPOINT + value: http://catalog:8080 + image: cart + imagePullPolicy: Always + livenessProbe: + failureThreshold: 5 + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 45 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + name: cart-green + ports: + - containerPort: 8778 + name: jolokia + protocol: TCP + - containerPort: 8080 + name: http + protocol: TCP + - containerPort: 8443 + name: https + protocol: TCP + readinessProbe: + failureThreshold: 10 + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 45 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + memory: 1Gi + requests: + memory: 200Mi + terminationMessagePath: /dev/termination-log + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: {} + terminationGracePeriodSeconds: 75 + test: false + triggers: + - imageChangeParams: + automatic: true + containerNames: + - cart-green + from: + kind: ImageStreamTag + name: cart:prod-green + namespace: prod + type: ImageChange + - type: ConfigChange \ No newline at end of file diff --git a/solutions/lab-7/coolstore-bluegreen-template.yaml b/solutions/lab-7/coolstore-bluegreen-template.yaml new file mode 100644 index 0000000..14bda94 --- /dev/null +++ b/solutions/lab-7/coolstore-bluegreen-template.yaml @@ -0,0 +1,965 @@ +apiVersion: v1 +kind: Template +metadata: + annotations: + description: CoolStore Microservices Application Template + iconClass: icon-java + tags: microservice,jboss,spring + name: coolstore +objects: +- apiVersion: v1 + groupNames: null + kind: RoleBinding + metadata: + name: default_edit + roleRef: + name: view + subjects: + - kind: ServiceAccount + name: default +# UI +- apiVersion: v1 + kind: DeploymentConfig + metadata: + name: web-ui + labels: + application: coolstore + component: web-ui + spec: + replicas: 1 + selector: + deploymentconfig: web-ui + strategy: + resources: {} + type: Recreate + template: + metadata: + labels: + application: coolstore + component: web-ui + deploymentconfig: web-ui + spec: + containers: + - env: + - name: COOLSTORE_GW_ENDPOINT + value: http://gw-${HOSTNAME_SUFFIX} + - name: HOSTNAME_HTTP + value: web-ui:8080 + image: web-ui + imagePullPolicy: Always + name: web-ui + ports: + - containerPort: 8080 + protocol: TCP + livenessProbe: + failureThreshold: 5 + httpGet: + path: / + port: 8080 + scheme: HTTP + initialDelaySeconds: 120 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 5 + readinessProbe: + failureThreshold: 5 + httpGet: + path: / + port: 8080 + scheme: HTTP + initialDelaySeconds: 15 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + cpu: 500m + memory: 1Gi + requests: + cpu: 50m + memory: 128Mi + terminationMessagePath: /dev/termination-log + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: {} + terminationGracePeriodSeconds: 30 + triggers: + - imageChangeParams: + automatic: true + containerNames: + - web-ui + from: + kind: ImageStreamTag + namespace: ${IMAGESTREAM_NAMESPACE} + name: coolstore-web-ui:${APP_VERSION} + type: ImageChange + - type: ConfigChange +- apiVersion: v1 + kind: Service + metadata: + labels: + app: web-ui + application: coolstore + component: web-ui + name: web-ui + spec: + ports: + - name: 8080-tcp + port: 8080 + protocol: TCP + targetPort: 8080 + selector: + deploymentconfig: web-ui +- apiVersion: v1 + kind: Route + metadata: + name: web-ui + labels: + application: coolstore + component: web-ui + spec: + host: web-ui-${HOSTNAME_SUFFIX} + to: + kind: Service + name: web-ui +# Coolstore Gateway +- apiVersion: v1 + kind: DeploymentConfig + metadata: + name: coolstore-gw + labels: + application: coolstore + component: coolstore-gw + spec: + replicas: 1 + selector: + deploymentconfig: coolstore-gw + strategy: + resources: {} + type: Recreate + template: + metadata: + labels: + application: coolstore + component: coolstore-gw + deploymentconfig: coolstore-gw + name: coolstore-gw + spec: + containers: + - env: + - name: KUBERNETES_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: CART_ENDPOINT + value: cart-${HOSTNAME_SUFFIX} + - name: INVENTORY_ENDPOINT + value: inventory-${HOSTNAME_SUFFIX} + - name: CATALOG_ENDPOINT + value: catalog-${HOSTNAME_SUFFIX} + image: library/coolstore-gw:${APP_VERSION} + livenessProbe: + httpGet: + path: /health + port: 8081 + initialDelaySeconds: 180 + name: coolstore-gw + ports: + - containerPort: 8778 + name: jolokia + readinessProbe: + httpGet: + path: /health + port: 8081 + initialDelaySeconds: 10 + resources: + limits: + cpu: 1 + memory: 2Gi + requests: + cpu: 100m + memory: 512Mi + triggers: + - imageChangeParams: + automatic: true + containerNames: + - coolstore-gw + from: + kind: ImageStreamTag + namespace: ${IMAGESTREAM_NAMESPACE} + name: coolstore-gateway:${APP_VERSION} + type: ImageChange + - type: ConfigChange +- apiVersion: v1 + kind: Service + metadata: + labels: + app: coolstore-gw + application: coolstore + component: coolstore-gw + hystrix.enabled: "true" + name: coolstore-gw + spec: + ports: + - port: 8080 + protocol: TCP + targetPort: 8080 + selector: + deploymentconfig: coolstore-gw +- apiVersion: v1 + kind: Route + metadata: + name: coolstore-gw + labels: + application: coolstore + component: coolstore-gw + spec: + host: gw-${HOSTNAME_SUFFIX} + to: + kind: Service + name: coolstore-gw +# Catalog Service +- apiVersion: v1 + kind: ImageStream + metadata: + name: catalog + labels: + application: coolstore + component: catalog + spec: + tags: + - name: latest +- apiVersion: v1 + kind: DeploymentConfig + metadata: + name: catalog + labels: + application: coolstore + component: catalog + spec: + replicas: 1 + selector: + deploymentconfig: catalog + strategy: + resources: {} + type: Recreate + template: + metadata: + labels: + application: coolstore + component: catalog + deploymentconfig: catalog + name: catalog + spec: + containers: + - env: + - name: JWS_ADMIN_USERNAME + value: Skq3VtCd + - name: JWS_ADMIN_PASSWORD + value: oktt6yhw + - name: DB_USERNAME + value: ${CATALOG_DB_USERNAME} + - name: DB_PASSWORD + value: ${CATALOG_DB_PASSWORD} + - name: DB_NAME + value: catalogdb + - name: DB_SERVER + value: catalog-mongodb + image: catalog + imagePullPolicy: Always + name: catalog + ports: + - containerPort: 8778 + name: jolokia + protocol: TCP + - containerPort: 8080 + name: http + protocol: TCP + readinessProbe: + failureThreshold: 10 + exec: + command: + - /bin/bash + - -c + - curl -s -u Skq3VtCd:oktt6yhw 'http://localhost:8080/manager/jmxproxy/?get=Catalina%3Atype%3DServer&att=stateName' + |grep -iq 'stateName *= *STARTED' + initialDelaySeconds: 15 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + cpu: 2 + memory: 2Gi + requests: + cpu: 100m + memory: 256Mi + terminationMessagePath: /dev/termination-log + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: {} + terminationGracePeriodSeconds: 75 + triggers: + - imageChangeParams: + automatic: true + containerNames: + - catalog + from: + kind: ImageStreamTag + name: coolstore-catalog:${APP_VERSION} + namespace: ${IMAGESTREAM_NAMESPACE} + type: ImageChange + - type: ConfigChange +- apiVersion: v1 + kind: Service + metadata: + annotations: + service.alpha.openshift.io/dependencies: '[{"name":"catalog-mongodb","namespace":"","kind":"Service"}]' + labels: + app: catalog + application: coolstore + component: catalog + name: catalog + spec: + ports: + - port: 8080 + protocol: TCP + targetPort: 8080 + selector: + deploymentconfig: catalog +- apiVersion: v1 + kind: Route + metadata: + labels: + application: coolstore + component: catalog + name: catalog + spec: + host: catalog-${HOSTNAME_SUFFIX} + to: + kind: Service + name: catalog + weight: 100 +- apiVersion: v1 + kind: Service + metadata: + labels: + app: catalog + application: coolstore + component: catalog + name: catalog-mongodb + spec: + ports: + - name: mongo + port: 27017 + protocol: TCP + targetPort: 27017 + selector: + deploymentconfig: catalog-mongodb + sessionAffinity: None + type: ClusterIP +- apiVersion: v1 + kind: DeploymentConfig + metadata: + labels: + application: coolstore + component: catalog + name: catalog-mongodb + spec: + replicas: 1 + selector: + deploymentconfig: catalog-mongodb + strategy: + recreateParams: + timeoutSeconds: 600 + resources: {} + type: Recreate + template: + metadata: + labels: + application: coolstore + component: catalog + deploymentconfig: catalog-mongodb + spec: + containers: + - env: + - name: KUBERNETES_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MONGODB_USER + value: ${CATALOG_DB_USERNAME} + - name: MONGODB_PASSWORD + value: ${CATALOG_DB_PASSWORD} + - name: MONGODB_DATABASE + value: catalogdb + - name: MONGODB_ADMIN_PASSWORD + value: ${CATALOG_DB_PASSWORD} + image: mongodb + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + tcpSocket: + port: 27017 + timeoutSeconds: 1 + name: catalog-mongodb + ports: + - containerPort: 27017 + protocol: TCP + readinessProbe: + exec: + command: + - /bin/sh + - -i + - -c + - mongo 127.0.0.1:27017/$MONGODB_DATABASE -u $MONGODB_USER -p $MONGODB_PASSWORD + --eval="quit()" + failureThreshold: 3 + initialDelaySeconds: 3 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + cpu: 500m + memory: 1Gi + requests: + cpu: 100m + memory: 256Mi + securityContext: + capabilities: {} + privileged: false + terminationMessagePath: /dev/termination-log + volumeMounts: + - mountPath: /var/lib/mongodb/data + name: mongodb-data + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - name: mongodb-data + persistentVolumeClaim: + claimName: mongodb-data-pv + test: false + triggers: + - imageChangeParams: + automatic: true + containerNames: + - catalog-mongodb + from: + kind: ImageStreamTag + name: mongodb:3.2 + namespace: openshift + type: ImageChange + - type: ConfigChange +- apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + labels: + application: coolstore + component: catalog + name: mongodb-data-pv + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 512Mi +# Cart Service Blue +- apiVersion: v1 + kind: Service + metadata: + labels: + app: cart + application: coolstore + component: cart-blue + name: cart-blue + spec: + ports: + - port: 8080 + protocol: TCP + targetPort: 8080 + selector: + deploymentconfig: cart-blue + sessionAffinity: None + type: ClusterIP +- apiVersion: v1 + kind: DeploymentConfig + metadata: + labels: + application: coolstore + component: cart-blue + name: cart-blue + spec: + replicas: 1 + selector: + deploymentconfig: cart-blue + strategy: + type: Recreate + template: + metadata: + labels: + application: coolstore + component: cart-blue + deploymentconfig: cart-blue + name: cart-blue + spec: + containers: + - env: + - name: CATALOG_ENDPOINT + value: http://catalog:8080 + - name: APPLICATION_MODE + value: prod + image: cart + imagePullPolicy: Always + livenessProbe: + failureThreshold: 5 + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 45 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + name: cart-blue + ports: + - containerPort: 8778 + name: jolokia + protocol: TCP + - containerPort: 8080 + name: http + protocol: TCP + - containerPort: 8443 + name: https + protocol: TCP + readinessProbe: + failureThreshold: 10 + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 45 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + memory: 1Gi + requests: + memory: 200Mi + terminationMessagePath: /dev/termination-log + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: {} + terminationGracePeriodSeconds: 75 + test: false + triggers: + - imageChangeParams: + automatic: true + containerNames: + - cart-blue + from: + kind: ImageStreamTag + name: cart:prod-blue + namespace: prod + type: ImageChange + - type: ConfigChange +# Cart Service Green +- apiVersion: v1 + kind: Service + metadata: + labels: + app: cart + application: coolstore + component: cart-green + name: cart-green + spec: + ports: + - port: 8080 + protocol: TCP + targetPort: 8080 + selector: + deploymentconfig: cart-green + sessionAffinity: None + type: ClusterIP +- apiVersion: v1 + kind: DeploymentConfig + metadata: + labels: + application: coolstore + component: cart-green + name: cart-green + spec: + replicas: 1 + selector: + deploymentconfig: cart-green + strategy: + type: Recreate + template: + metadata: + labels: + application: coolstore + component: cart-green + deploymentconfig: cart-green + name: cart-green + spec: + containers: + - env: + - name: CATALOG_ENDPOINT + value: http://catalog:8080 + - name: APPLICATION_MODE + value: prod + image: cart + imagePullPolicy: Always + livenessProbe: + failureThreshold: 5 + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 45 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + name: cart-green + ports: + - containerPort: 8778 + name: jolokia + protocol: TCP + - containerPort: 8080 + name: http + protocol: TCP + - containerPort: 8443 + name: https + protocol: TCP + readinessProbe: + failureThreshold: 10 + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 45 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + memory: 1Gi + requests: + memory: 200Mi + terminationMessagePath: /dev/termination-log + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: {} + terminationGracePeriodSeconds: 75 + test: false + triggers: + - imageChangeParams: + automatic: true + containerNames: + - cart-green + from: + kind: ImageStreamTag + name: cart:prod-green + namespace: prod + type: ImageChange + - type: ConfigChange +# Cart Service +- apiVersion: v1 + kind: Route + metadata: + labels: + application: coolstore + component: cart + name: cart + spec: + alternateBackends: + - kind: Service + name: cart-blue + weight: 100 + host: cart-${HOSTNAME_SUFFIX} + to: + kind: Service + name: cart-green + weight: 0 +# Inventory Service +- apiVersion: v1 + kind: DeploymentConfig + metadata: + name: inventory + labels: + application: coolstore + component: inventory + spec: + replicas: 1 + selector: + deploymentconfig: inventory + strategy: + resources: {} + type: Recreate + template: + metadata: + labels: + deploymentconfig: inventory + application: coolstore + component: inventory + name: inventory + spec: + containers: + - env: + - name: OPENSHIFT_KUBE_PING_LABELS + value: application=inventory + - name: OPENSHIFT_KUBE_PING_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MQ_CLUSTER_PASSWORD + value: 7mzX0pLV03 + - name: JGROUPS_CLUSTER_PASSWORD + value: CqUo3fYDTv + - name: AUTO_DEPLOY_EXPLODED + value: "false" + - name: DB_SERVICE_PREFIX_MAPPING + value: inventory-postgresql=DB + - name: DB_JNDI + value: java:jboss/datasources/InventoryDS + - name: DB_USERNAME + value: ${INVENTORY_DB_USERNAME} + - name: DB_PASSWORD + value: ${INVENTORY_DB_PASSWORD} + - name: DB_DATABASE + value: inventorydb + image: inventory + imagePullPolicy: Always + lifecycle: + preStop: + exec: + command: + - /opt/eap/bin/jboss-cli.sh + - -c + - :shutdown(timeout=60) + livenessProbe: + failureThreshold: 5 + httpGet: + path: / + port: 8080 + scheme: HTTP + initialDelaySeconds: 120 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 5 + name: inventory + ports: + - containerPort: 8778 + name: jolokia + protocol: TCP + - containerPort: 8080 + name: http + protocol: TCP + - containerPort: 8888 + name: ping + protocol: TCP + readinessProbe: + failureThreshold: 5 + httpGet: + path: / + port: 8080 + scheme: HTTP + initialDelaySeconds: 15 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + cpu: 500m + memory: 1Gi + requests: + cpu: 100m + memory: 512Mi + terminationMessagePath: /dev/termination-log + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: {} + terminationGracePeriodSeconds: 75 + triggers: + - imageChangeParams: + automatic: true + containerNames: + - inventory + from: + kind: ImageStreamTag + name: coolstore-inventory:${APP_VERSION} + namespace: ${IMAGESTREAM_NAMESPACE} + type: ImageChange + - type: ConfigChange +- apiVersion: v1 + kind: Service + metadata: + annotations: + service.alpha.openshift.io/dependencies: '[{"name":"inventory-postgresql","namespace":"","kind":"Service"}]' + labels: + app: inventory + application: inventory + name: inventory + spec: + ports: + - port: 8080 + protocol: TCP + targetPort: 8080 + selector: + deploymentconfig: inventory +- apiVersion: v1 + kind: Route + metadata: + labels: + application: inventory + name: inventory + spec: + host: inventory-${HOSTNAME_SUFFIX} + to: + kind: Service + name: inventory + weight: 100 +- apiVersion: v1 + kind: DeploymentConfig + metadata: + name: inventory-postgresql + labels: + component: inventory + application: coolstore + spec: + replicas: 1 + selector: + deploymentconfig: inventory-postgresql + strategy: + type: Recreate + template: + metadata: + labels: + application: coolstore + component: inventory + deploymentconfig: inventory-postgresql + name: inventory-postgresql + spec: + containers: + - env: + - name: POSTGRESQL_USER + value: ${INVENTORY_DB_USERNAME} + - name: POSTGRESQL_PASSWORD + value: ${INVENTORY_DB_PASSWORD} + - name: POSTGRESQL_DATABASE + value: inventorydb + image: postgresql + imagePullPolicy: Always + name: inventory-postgresql + ports: + - containerPort: 5432 + protocol: TCP + volumeMounts: + - mountPath: /var/lib/pgsql/data + name: inventory-postgresql-data + livenessProbe: + initialDelaySeconds: 30 + tcpSocket: + port: 5432 + timeoutSeconds: 1 + readinessProbe: + exec: + command: + - /bin/sh + - -i + - -c + - psql -h 127.0.0.1 -U $POSTGRESQL_USER -q -d $POSTGRESQL_DATABASE -c 'SELECT 1' + initialDelaySeconds: 5 + timeoutSeconds: 1 + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 50m + memory: 128Mi + terminationGracePeriodSeconds: 60 + volumes: + - name: inventory-postgresql-data + persistentVolumeClaim: + claimName: inventory-postgresql-pv + triggers: + - imageChangeParams: + automatic: true + containerNames: + - inventory-postgresql + from: + kind: ImageStreamTag + name: postgresql:latest + namespace: openshift + type: ImageChange + - type: ConfigChange +- apiVersion: v1 + kind: Service + metadata: + labels: + application: inventory + name: inventory-postgresql + spec: + ports: + - port: 5432 + targetPort: 5432 + selector: + deploymentconfig: inventory-postgresql +- apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + labels: + application: inventory + name: inventory-postgresql-pv + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +parameters: +- description: Namespace in which the ImageStreams for CoolStore services are installed + displayName: ImageStream Namespace + name: IMAGESTREAM_NAMESPACE + required: true + value: openshift +- description: CoolStore application image version to be deployed (imagestreams should exist) + displayName: CoolStore Version + name: APP_VERSION + required: true + value: prod +- description: Hostname suffix used for routes e.g. cart- inventory- + displayName: Hostname Suffix + name: HOSTNAME_SUFFIX + required: true +- description: Catalog Service database user name + displayName: Catalog Database Username + from: user[a-zA-Z0-9]{3} + generate: expression + name: CATALOG_DB_USERNAME + required: true +- description: Catalog Service database user password + displayName: Catalog Database Password + from: '[a-zA-Z0-9]{8}' + generate: expression + name: CATALOG_DB_PASSWORD + required: true +- description: Inventory Service database user name + displayName: Inventory Database Username + from: user[a-zA-Z0-9]{3} + generate: expression + name: INVENTORY_DB_USERNAME + required: true +- description: Inventory Service database user password + displayName: Inventory Database Password + from: '[a-zA-Z0-9]{8}' + generate: expression + name: INVENTORY_DB_PASSWORD + required: true diff --git a/solutions/lab-8/Jenkinsfile b/solutions/lab-8/Jenkinsfile new file mode 100644 index 0000000..dea88d0 --- /dev/null +++ b/solutions/lab-8/Jenkinsfile @@ -0,0 +1,53 @@ +node('maven') { + stage('Build App') { + git url: "http://gogs.lab-infra.svc.cluster.local:3000/developer/cart-service.git" + sh "mvn clean package -s src/main/config/settings.xml" + } + stage('Integration Test') { + sh "mvn verify -s src/main/config/settings.xml" + } + stage('Build Image') { + sh "oc start-build cart --from-file=target/cart.jar --follow" + } + stage('Deploy') { + openshiftDeploy depCfg: 'cart' + openshiftVerifyDeployment depCfg: 'cart', replicaCount: 1, verifyReplicaCount: true + } + stage('Component Test') { + sh "curl -s -X POST http://cart.dev.svc.cluster.local:8080/api/cart/dummy/666/1" + sh "curl -s http://cart.dev.svc.cluster.local:8080/api/cart/dummy | grep 'Dummy Product'" + } + + def tag="blue" + def altTag="green" + + stage('Promote') { + sh "oc project prod" + sh "oc get route cart -n prod -o jsonpath='{ .spec.to.name }' > activeservice" + activeService = readFile('activeservice').trim() + if (activeService == "cart-blue") { + tag = "green" + altTag = "blue" + } + openshiftTag sourceStream: 'cart', sourceTag: 'latest', namespace: 'dev', destinationStream: 'cart', destinationTag: "prod-${tag}", destinationNamespace: 'prod' + sleep 10 + openshiftVerifyDeployment deploymentConfig: "cart-${tag}", replicaCount: '1', verifyReplicaCount: true, namespace: 'prod' + sleep 5 + } + + stage('End-To-End Test') { + sh "curl -s -X POST http://cart-${tag}.prod.svc.cluster.local:8080/api/cart/dummy/444434/1" + sh "curl -s http://cart-${tag}.prod.svc.cluster.local:8080/api/cart/dummy | grep 'Pebble Smart Watch'" + } + + stage('Approve Go Live') { + timeout(time:15, unit:'MINUTES') { + input message:'Go Live in Prod?' + } + } + + stage('Go Live') { + sh "oc project prod" + sh "oc set route-backends cart cart-${tag}=100 cart-${altTag}=0 -n prod" + } +} diff --git a/solutions/support/lab-clean.sh b/solutions/support/lab-clean.sh new file mode 100755 index 0000000..ea74378 --- /dev/null +++ b/solutions/support/lab-clean.sh @@ -0,0 +1,8 @@ + + +# Delete Lab Resources +oc delete project dev prod lab-infra 2>/dev/null +oc delete bc --all -n openshift --as=system:admin +oc delete is -l demo=coolstore-microservice -n openshift --as=system:admin +oc delete template coolstore -n openshift --as=system:admin +echo "Done!" \ No newline at end of file diff --git a/solutions/support/lab-prepare.sh b/solutions/support/lab-prepare.sh new file mode 100755 index 0000000..56e32f1 --- /dev/null +++ b/solutions/support/lab-prepare.sh @@ -0,0 +1,144 @@ + +# Create Project +function create_project() { + oc new-project lab-infra --display-name="Lab Infra" +} + +# waits while the condition is true until it becomes false or it times out +function wait_while_empty() { + local _NAME=$1 + local _TIMEOUT=$(($2/5)) + local _CONDITION=$3 + + echo "Waiting for $_NAME to be ready..." + local x=1 + while [ -z "$(eval ${_CONDITION})" ] + do + echo "." + sleep 5 + x=$(( $x + 1 )) + if [ $x -gt $_TIMEOUT ] + then + echo "$_NAME still not ready, I GIVE UP!" + exit 255 + fi + done + + echo "$_NAME is ready." +} + +# Deploy Nexus +function deploy_nexus() { + oc process -f https://raw.githubusercontent.com/OpenShiftDemos/nexus/master/nexus2-persistent-template.yaml | oc create -f - -n lab-infra + oc set resources dc/nexus --limits=cpu=1,memory=2Gi --requests=cpu=200m,memory=1Gi -n lab-infra +} + +# Extract domain name for Gogs +function deploy_gogs() { + oc create route edge dummyroute --service=dummysvc --port=80 -n lab-infra >/dev/null + GOGS_HOSTNAME=$(oc get route dummyroute -o template --template='{{.spec.host}}' -n lab-infra | sed "s/dummyroute/gogs/g") + oc delete route dummyroute -n lab-infra >/dev/null + + # Deploy Gogs + oc process -f https://raw.githubusercontent.com/OpenShiftDemos/gogs-openshift-docker/master/openshift/gogs-persistent-template.yaml \ + --param=SKIP_TLS_VERIFY=true \ + --param=HOSTNAME=$GOGS_HOSTNAME \ + --param=GOGS_VERSION=0.11.4 \ + -n lab-infra \ + | oc create -f - -n lab-infra + + wait_while_empty "Gogs PostgreSQL" 600 "oc get ep gogs-postgresql -o yaml -n lab-infra | grep '\- addresses:'" + wait_while_empty "Gogs" 600 "oc get ep gogs -o yaml -n lab-infra | grep '\- addresses:'" + + # Create Gogs user + curl -sL -o /dev/null --post302 http://$GOGS_HOSTNAME/user/sign_up \ + --form user_name=developer \ + --form password=developer \ + --form retype=developer \ + --form email=developer@gogs.com + + # Import cart-service GitHub repo + read -r -d '' _DATA_JSON << EOM +{ + "clone_addr": "https://github.com/siamaksade/cart-service.git", + "uid": 1, + "repo_name": "cart-service" +} +EOM + + curl -sL -H "Content-Type: application/json" \ + -d "$_DATA_JSON" \ + -u developer:developer \ + -X POST http://$GOGS_HOSTNAME/api/v1/repos/migrate + + # Create pipelines repository + read -r -d '' _DATA_JSON << EOM +{ + "name": "pipelines", + "private": false, + "auto_init": true, + "gitignores": "Java", + "license": "Apache License 2.0", + "readme": "Default" +} +EOM + + curl -sL -H "Content-Type: application/json" \ + -d "$_DATA_JSON" \ + -u developer:developer \ + -X POST http://$GOGS_HOSTNAME/api/v1/user/repos +} + +# Import Image Streams +function import_imagestreams() { + oc apply -f https://raw.githubusercontent.com/openshift/openshift-ansible/master/roles/openshift_examples/files/examples/v1.5/image-streams/image-streams-rhel7.json -n openshift --as=system:admin + oc apply -f https://raw.githubusercontent.com/openshift/openshift-ansible/master/roles/openshift_examples/files/examples/v1.5/xpaas-streams/jboss-image-streams.json -n openshift --as=system:admin + oc apply -f https://raw.githubusercontent.com/openshift/openshift-ansible/master/roles/openshift_examples/files/examples/v1.5/xpaas-streams/fis-image-streams.json -n openshift --as=system:admin + sleep 5 +} + +# Create Builds +function build_images() { + wait_while_empty "Nexus" 600 "oc get ep nexus -o yaml -n lab-infra | grep '\- addresses:'" + + oc process -f https://raw.githubusercontent.com/jbossdemocentral/coolstore-microservice/stable-ocp-3.5/openshift/templates/coolstore-builds-template.yaml \ + --param=MAVEN_MIRROR_URL=http://nexus.lab-infra.svc.cluster.local:8081/content/groups/public/ \ + -n lab-infra | oc create -f - -n openshift --as=system:admin + sleep 10 + + # Build images + oc delete bc cart -n openshift --as=system:admin + oc start-build web-ui -n openshift --follow --as=system:admin + oc start-build inventory -n openshift --follow --as=system:admin + oc start-build catalog -n openshift --follow --as=system:admin + oc start-build coolstore-gw -n openshift --follow --as=system:admin + + sleep 5 + oc tag openshift/web-ui:latest openshift/coolstore-web-ui:prod --as=system:admin + oc tag openshift/inventory:latest openshift/coolstore-inventory:prod --as=system:admin + oc tag openshift/catalog:latest openshift/coolstore-catalog:prod --as=system:admin + oc tag openshift/coolstore-gw:latest openshift/coolstore-gateway:prod --as=system:admin + + oc create -f https://raw.githubusercontent.com/openshift-labs/devops-labs/ocp-3.5/lab-6/coolstore-template.yaml -n openshift --as=system:admin +} + +function set_project_permissions() { + oc policy remove-role-from-user admin developer -n lab-infra --as=system:admin + oc policy add-role-to-user view developer -n lab-infra --as=system:admin +} +######################## +# Prepare Labs Cluster # +######################## +START=`date +%s` + +create_project +deploy_nexus +deploy_gogs +sleep 5 +import_imagestreams +build_images +set_project_permissions + +END=`date +%s` +echo +echo "Lab cluster is ready! (completed in $(( ($END - $START)/60 )) min $(( ($END - $START)%60 )) sec)" diff --git a/solutions/support/lab-solve.sh b/solutions/support/lab-solve.sh new file mode 100755 index 0000000..ea998c9 --- /dev/null +++ b/solutions/support/lab-solve.sh @@ -0,0 +1,43 @@ + +# Set Vars +GOGS_ROUTE=$(oc get route gogs -o template --template='{{.spec.host}}' -n lab-infra) +CART_REPO=http://$GOGS_ROUTE/developer/cart-service.git +PIPELINES_REPO=http://$GOGS_ROUTE/developer/pipelines.git + +# Create Projects +oc new-project dev --display-name="Cart Dev" +oc new-project prod --display-name="Coolstore Prod" + +# Deploy Dev +oc process -f https://raw.githubusercontent.com/openshift-labs/devops-labs/ocp-3.5/lab-3/cart-template.yaml \ + --param=GIT_URI=$CART_REPO \ + --param=MAVEN_MIRROR_URL=http://nexus.lab-infra.svc.cluster.local:8081/content/groups/public/ \ + | oc create -f - -n dev + +# Deploy Prod +HOSTNAME=$(echo "$GOGS_ROUTE" | sed "s/gogs-lab-infra.//g") +oc process -f https://raw.githubusercontent.com/openshift-labs/devops-labs/ocp-3.5/lab-7/coolstore-bluegreen-template.yaml \ + --param=HOSTNAME_SUFFIX=prod.$HOSTNAME \ + | oc create -f - -n prod +sleep 5 + +# Save Resources +oc scale dc/inventory --replicas=0 -n prod +oc scale dc/inventory-postgresql --replicas=0 -n prod + +# Deploy Pipeline +rm -rf /tmp/pipelines && \ + git clone http://$GOGS_ROUTE/developer/pipelines.git /tmp/pipelines && \ + pushd /tmp/pipelines && \ + curl -sL https://raw.githubusercontent.com/openshift-labs/devops-labs/ocp-3.5/lab-8/Jenkinsfile | sed "s|git url: .*|git url: '$CART_REPO'|g" > Jenkinsfile && \ + git add Jenkinsfile && \ + git commit -m "pipeline added" && \ + git push -f http://developer:developer@$GOGS_ROUTE/developer/pipelines.git master && \ + popd && \ + rm -rf /tmp/pipelines + +curl -sL https://raw.githubusercontent.com/openshift-labs/devops-labs/ocp-3.5/lab-4/cart-pipeline-scm.yaml | sed "s|uri: .*|uri: $PIPELINES_REPO|g" | oc create -f - -n dev + +oc policy add-role-to-user edit system:serviceaccount:dev:jenkins -n prod + +echo "Done!" \ No newline at end of file