Initial commit
Add infrastructure jobs for sandbox

Related-PROD: RE-336

Change-Id: I2140d47e3fc360ab05f92175b29b31e69b2ec10b
diff --git a/common/pipelines/test-jenkins-jobs.groovy b/common/pipelines/test-jenkins-jobs.groovy
new file mode 100644
index 0000000..e04f644
--- /dev/null
+++ b/common/pipelines/test-jenkins-jobs.groovy
@@ -0,0 +1,218 @@
+#!groovy
+//import groovy.transform.Field
+
+String getJobs(getJobsCmd) {
+    String result
+    dir("${env.WORKSPACE}/output/${env.CI_NAME}") {
+        result = sh \
+            script: """\
+                   ${getJobsCmd} \
+                   | grep -v '\\/\$' \
+                   | grep -E '^(deleting|Files)' \
+                   | sed -r 's%^(deleting|Files)\\s%%g' \
+                   | sed -r 's%^old/%%' \
+                   | cut -d' ' -f1
+                """,
+            returnStdout: true
+    }
+    return result
+}
+
+def main() {
+    // Use gerrit parameters if set with fallback to job param
+    String gitUrl = "${env.GERRIT_SCHEME}://${env.GERRIT_HOST}:${env.GERRIT_PORT}/${env.GERRIT_PROJECT}"
+    String gitRef = env.GERRIT_REFSPEC
+
+    String pathSep = '/'
+
+    String getAddedJobsCmd = 'rsync --dry-run -av --delete old/ new/'
+    String getRemovedJobsCmd = 'rsync --dry-run -av --delete new/ old/'
+    String getDiffJobsCmd = 'diff -rq old/ new/'
+
+    // Set current build description
+    if (env.GERRIT_CHANGE_URL) {
+        currentBuild.description = """
+        <p>
+          Triggered by change: <a href="${env.GERRIT_CHANGE_URL}">${env.GERRIT_CHANGE_NUMBER},${env.GERRIT_PATCHSET_NUMBER}</a><br/>
+          Project: <b>${env.GERRIT_PROJECT}</b><br/>
+          Branch: <b>${env.GERRIT_BRANCH}</b><br/>
+          Subject: <b>${env.GERRIT_CHANGE_SUBJECT}</b><br/>
+        </p>
+        """
+    }
+
+    // Get & prepare source code
+    stage('SCM checkout') {
+        echo "Checking out git repository from ${gitUrl} @ ${gitRef}"
+
+        checkout \
+            $class: 'GitSCM',
+            branches: [
+                [name: 'FETCH_HEAD'],
+            ],
+            userRemoteConfigs: [
+                [url: gitUrl, refspec: gitRef, credentialsId: env.GIT_CREDENTIALS_ID],
+            ],
+            extensions: [
+                [$class: 'WipeWorkspace'],
+            ]
+    }
+
+    stage('Check for non-ascii characters') {
+        def asciiStatus = sh \
+            script: 'grep -q --perl-regexp -R "[^[:ascii:]]" --include \\*.sh --include \\*.yaml --include \\*.groovy *',
+            returnStatus: true
+
+        if (asciiStatus == 0) {
+            error 'Found non-ASCII symbols!!!'
+        }
+    }
+
+    stage('JJB verify') {
+        withEnv(['HOME=/tmp/']) {
+            // Generate current jobs from parent commit (will be used for diff)
+            sh 'tox -v -e compare-xml-new'
+        }
+    }
+
+    stage('JJB compare') {
+        withEnv(['HOME=/tmp/']) {
+            // Generate jobs from parent commit (will be used for diff)
+            sh '''
+                git reset --hard HEAD^
+                git checkout FETCH_HEAD -- tox.ini
+                tox -v -e compare-xml-old
+            '''
+        }
+
+        dir("output/${env.CI_NAME}") {
+            Integer diffStatus = sh \
+                script: 'diff -rq old/ new/',
+                returnStatus: true
+
+            if (diffStatus == 0) {
+                currentBuild.result = 'SUCCESS'
+                currentBuild.description += 'No job changes'
+                currentBuild.getRawBuild().getExecutor().interrupt(Result.SUCCESS)
+                sleep(1)   // Interrupt is not blocking and does not take effect immediately.
+            }
+        }
+
+        // Analyse output file and prepare array with results
+
+        String diffJobs = getJobs(getDiffJobsCmd)
+        String addedJobs = getJobs(getAddedJobsCmd)
+        String removedJobs = getJobs(getRemovedJobsCmd)
+
+        // Set job description
+
+        String description = ''
+        String _item, _itemPath
+
+        dir("output/${env.CI_NAME}") {
+            if (diffJobs.size() > 0) {
+                description += '<b>CHANGED</b><ul>'
+                diffJobs.split('\n').each { item ->
+                    _item = item.replace('/config.xml', '')
+                    try {
+                        _itemPath = item.tokenize(pathSep)[0..-2].join(pathSep)
+                    } catch (e) {
+                        _itemPath = ''
+                    }
+                    description += "<li><a href=\"${env.BUILD_URL}artifact/output/${env.CI_NAME}/diff/${item}/*view*/\">${_item}</a></li>"
+
+                    // Generate diff file
+                    sh """
+                        mkdir -p diff/${_itemPath}
+                        diff -U 50 \
+                            'old/${item}' \
+                            'new/${item}' \
+                            > 'diff/${item}' || :
+                    """
+                }
+                description += '</ul>'
+            }
+
+            if (addedJobs.size() > 0) {
+                description += '<b>ADDED</b><ul>'
+                addedJobs.split('\n').each { item ->
+                    _item = item.replace('/config.xml', '')
+                    try {
+                        _itemPath = item.tokenize(pathSep)[0..-2].join(pathSep)
+                    } catch (e) {
+                        _itemPath = ''
+                    }
+                    description += "<li><a href=\"${env.BUILD_URL}artifact/output/${env.CI_NAME}/diff/${item}/*view*/\">${_item}</a></li>"
+                    sh """
+                        mkdir -p diff/${_itemPath}
+                        cp new/${item} diff/${_itemPath}/
+                    """
+                }
+                description += '</ul>'
+            }
+
+            if (removedJobs.size() > 0) {
+                description += '<b>DELETED</b><ul>'
+                removedJobs.split('\n').each { item ->
+                    _item = item.replace('/config.xml', '')
+                    try {
+                        _itemPath = item.tokenize(pathSep)[0..-2].join(pathSep)
+                    } catch (e) {
+                        _itemPath = ''
+                    }
+                    description += "<li><a href=\"${env.BUILD_URL}artifact/output/${env.CI_NAME}/diff/${item}/*view*/\">${_item}</a></li>"
+                    sh """
+                        mkdir -p diff/${_itemPath}
+                        cp old/${item} diff/${_itemPath}/
+                    """
+                }
+                description += '</ul>'
+            }
+        }
+
+        currentBuild.description += description
+    }
+
+    // Save results
+    stage('Record test results') {
+        archiveArtifacts([
+            artifacts: "output/${env.CI_NAME}/diff/**",
+            allowEmptyArchive: true,
+        ])
+    }
+}
+
+String podTpl = """
+    apiVersion: "v1"
+    kind: "Pod"
+    spec:
+      securityContext:
+          runAsUser: 1000
+      containers:
+      - name: "tox"
+        image: "${env.DOCKER_IMAGE}"
+        command:
+        - "cat"
+        securityContext:
+          privileged: false
+        tty: true
+"""
+if (env.K8S_CLUSTER == 'unset') {
+    node(env.SLAVE_LABEL ?: 'docker') {
+        docker.image(env.DOCKER_IMAGE).inside('--entrypoint=""') {
+            main()
+        }
+    }
+} else {
+    podTemplate(
+            cloud: env.K8S_CLUSTER,
+            yaml: podTpl,
+            showRawYaml: false
+        ) {
+            node(POD_LABEL) {
+            container('tox') {
+                main()
+            }
+        }
+    }
+}