apiVersion: v1
kind: Template
metadata:
  name: maven-pipeline
parameters:
- name: APP_NAME
  description: The name assigned to all of the application objects defined in this template.
  displayName: Application Name
  required: true
  value: openshift-jee-sample
- name: GIT_SOURCE_URL
  description: The source URL for the application
  displayName: Source URL
  required: true
  value: https://github.com/openshift/openshift-jee-sample.git
- name: GIT_SOURCE_REF
  description: The source Ref for the application
  displayName: Source Ref
  required: true
  value: master
- description: Github trigger secret.  A difficult to guess string encoded as part of the webhook URL.  Not encrypted.
  displayName: GitHub Webhook Secret
  from: '[a-zA-Z0-9]{40}'
  generate: expression
  name: GITHUB_WEBHOOK_SECRET
  required: true
- description: A secret string used to configure the Generic webhook.
  displayName: Generic Webhook Secret
  from: '[a-zA-Z0-9]{40}'
  generate: expression
  name: GENERIC_WEBHOOK_SECRET
  required: true
objects:
- apiVersion: v1
  kind: ImageStream
  metadata:
    labels:
      app: ${APP_NAME}
    name: ${APP_NAME}
  spec: {}
  status:
    dockerImageRepository: ""
- apiVersion: v1
  kind: ImageStream
  metadata:
    name: wildfly
  spec:
    tags:
    - annotations:
        supports: wildfly:10.1,jee,java
        tags: builder,wildfly,java
        version: "10.1"
      from:
        kind: DockerImage
        name: openshift/wildfly-101-centos7:latest
      name: "10.1"
    - annotations:
        supports: jee,java
        tags: builder,wildfly,java
      from:
        kind: ImageStreamTag
        name: "10.1"
      name: latest
- apiVersion: v1
  kind: BuildConfig
  metadata:
    annotations:
      pipeline.alpha.openshift.io/uses: '[{"name": "${NAME}", "namespace": "", "kind": "DeploymentConfig"}]'
    creationTimestamp: null
    labels:
      name: ${APP_NAME}
    name: ${APP_NAME}
  spec:
    strategy:
      jenkinsPipelineStrategy:
        jenkinsfile: |-
          try {
             timeout(time: 20, unit: 'MINUTES') {
                def appName="${APP_NAME}"
                def project=""

                node {
                  stage("Initialize") {
                    project = env.PROJECT_NAME
                  }
                }

                node("maven") {
                  stage("Checkout") {
                    git url: "${GIT_SOURCE_URL}", branch: "${GIT_SOURCE_REF}"
                  }
                  stage("Build WAR") {
                    sh "mvn clean package -Popenshift"
                    stash name:"war", includes:"target/ROOT.war"
                  }
                }

                node {
                  stage("Build Image") {
                    unstash name:"war"
                    def status = sh(returnStdout: true, script: "oc start-build ${appName}-docker --from-file=target/ROOT.war -n ${project}")

                    def result = status.split("\n").find{ it.matches("^build.*started") }
                    
                    if(!result) {
                      echo "ERROR: No started build found for ${appName}"
                      currentBuild.result = 'FAILURE'
                      return
                    }
                    
                    // result can be:
                    // - build "build-name" started
                    // - build build.build.openshift.io/build-name started
                    // - build "build.build.openshift.io/build-name" started
                    // Goal is to isolate "build-name"
                    def startedBuild = result.replaceAll("build [^0-9a-zA-Z]*", "").replaceAll("[^0-9a-zA-Z]* started", "").replaceFirst("^.*/", "")
                    echo "Build ${startedBuild} has started. Now watching it ..."
                    
                    timeout(time: 20, unit: 'MINUTES') {
                      openshift.withCluster() {
                        openshift.withProject() {
                          def build = openshift.selector('builds', "${startedBuild}")
                          build.untilEach {
                            def object = it.object()
                            if(object.status.phase == "Failed") {
                              error("Build ${startedBuild} failed")
                            }
                            return object.status.phase == "Complete"
                          }
                        }
                      }  
                    }
                  }
                  stage("Deploy") {
                    openshift.withCluster() {
                      openshift.withProject() {
                        def dc = openshift.selector('dc', "${appName}")
                        dc.rollout().status()
                      }
                    }
                  }
                }
             }
          } catch (err) {
             echo "in catch block"
             echo "Caught: ${err}"
             currentBuild.result = 'FAILURE'
             throw err
          }
      type: JenkinsPipeline
    triggers:
    - github:
        secret: "${GITHUB_WEBHOOK_SECRET}"
      type: GitHub
    - generic:
        secret: "${GENERIC_WEBHOOK_SECRET}"
      type: Generic
- apiVersion: v1
  kind: BuildConfig
  metadata:
    labels:
      app: ${APP_NAME}-docker
    name: ${APP_NAME}-docker
  spec:
    output:
      to:
        kind: ImageStreamTag
        name: ${APP_NAME}:latest
    postCommit: {}
    resources: {}
    runPolicy: Serial
    source:
      dockerfile: |-
        FROM wildfly
        COPY ROOT.war /wildfly/standalone/deployments/ROOT.war
        CMD $STI_SCRIPTS_PATH/run
      binary:
        asFile: ROOT.war
      type: Docker
    strategy:
      dockerStrategy:
        from:
          kind: ImageStreamTag
          name: wildfly:latest
      type: Docker
    triggers: []
- apiVersion: v1
  kind: DeploymentConfig
  metadata:
    labels:
      app: ${APP_NAME}
    name: ${APP_NAME}
  spec:
    replicas: 1
    selector:
      app: ${APP_NAME}
      deploymentconfig: ${APP_NAME}
    strategy:
      rollingParams:
        intervalSeconds: 1
        maxSurge: 25%
        maxUnavailable: 25%
        timeoutSeconds: 600
        updatePeriodSeconds: 1
      type: Rolling
    template:
      metadata:
        labels:
          app: ${APP_NAME}
          deploymentconfig: ${APP_NAME}
      spec:
        containers:
        - image: ${APP_NAME}:latest
          imagePullPolicy: Always
          name: ${APP_NAME}
          ports:
          - containerPort: 8080
            protocol: TCP
          resources: {}
          terminationMessagePath: /dev/termination-log
          livenessProbe:
            httpGet:
              path: /
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 10
            timeoutSeconds: 2
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          readinessProbe:
            httpGet:
              path: /
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 30
            timeoutSeconds: 2
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
        dnsPolicy: ClusterFirst
        restartPolicy: Always
        securityContext: {}
        terminationGracePeriodSeconds: 30
    test: false
    triggers:
    - type: ConfigChange
    - imageChangeParams:
        automatic: true
        containerNames:
        - ${APP_NAME}
        from:
          kind: ImageStreamTag
          name: ${APP_NAME}:latest
      type: ImageChange
  status: {}
- apiVersion: v1
  kind: Service
  metadata:
    annotations:
      openshift.io/generated-by: OpenShiftNewApp
    labels:
      app: ${APP_NAME}
    name: ${APP_NAME}
  spec:
    ports:
    - name: 8080-tcp
      port: 8080
      protocol: TCP
      targetPort: 8080
    selector:
      app: ${APP_NAME}
      deploymentconfig: ${APP_NAME}
    sessionAffinity: None
    type: ClusterIP
  status:
    loadBalancer: {}
- apiVersion: v1
  kind: Route
  metadata:
    name: ${APP_NAME}
    labels:
      app: ${APP_NAME}
  spec:
    to:
      kind: Service
      name: ${APP_NAME}
      weight: 100
    port:
      targetPort: 8080-tcp
    wildcardPolicy: None
