Merge "[DockerImageScanner] Add custom namespace for DTR images"
diff --git a/src/com/mirantis/mcp/MCPArtifactory.groovy b/src/com/mirantis/mcp/MCPArtifactory.groovy
index fd01573..83b1975 100644
--- a/src/com/mirantis/mcp/MCPArtifactory.groovy
+++ b/src/com/mirantis/mcp/MCPArtifactory.groovy
@@ -151,14 +151,8 @@
  */
 def deleteItem (String artifactoryURL, String itemPath) {
     def url = "${artifactoryURL}/${itemPath}"
-    withCredentials([
-            [$class          : 'UsernamePasswordMultiBinding',
-             credentialsId   : 'artifactory',
-             passwordVariable: 'ARTIFACTORY_PASSWORD',
-             usernameVariable: 'ARTIFACTORY_LOGIN']
-    ]) {
-        sh "bash -c \"curl -X DELETE -u ${ARTIFACTORY_LOGIN}:${ARTIFACTORY_PASSWORD} \'${url}\'\""
-    }
+    def http = new com.mirantis.mk.Http()
+    return http.doDelete(url, 'artifactory')
 }
 
 /**
@@ -278,6 +272,48 @@
 }
 
 /**
+ * Convert Mirantis docker image url/path to Mirantis artifactory path ready for use in API calls
+ *
+ * For example:
+ * 'docker-dev-kaas-local.docker.mirantis.net/mirantis/kaas/si-test:master' -> 'docker-dev-kaas-local/mirantis/kaas/si-test/master'
+ *
+ */
+def dockerImageToArtifactoryPath(String image) {
+    List imageParts = image.tokenize('/')
+    String repoName = imageParts[0].tokenize('.')[0]
+    String namespace = imageParts[1..-2].join('/')
+    String imageName = imageParts[-1].tokenize(':')[0]
+    String imageTag = imageParts[-1].tokenize(':')[1]
+
+    return [repoName, namespace, imageName, imageTag].join('/')
+}
+
+/**
+ * Copy docker image from one url to another
+ *
+ * @param srcImage String, Mirantis URL/path for docker image to copy from
+ * @param dstImage String, Mirantis URL/path for docker image to copy to
+ */
+def copyDockerImage(String srcImage, String dstImage) {
+    def artifactoryServer = Artifactory.server(env.ARTIFACTORY_SERVER ?: 'mcp-ci')
+    String srcPath = dockerImageToArtifactoryPath(srcImage)
+    String dstPath = dockerImageToArtifactoryPath(dstImage)
+
+    return moveItem(artifactoryServer.getUrl(), srcPath, dstPath, true)
+}
+
+/**
+ * Delete docker image on Mirantis's artifactory
+ *
+ * @param image String, Mirantis URL/path for docker image to delete
+ */
+def deleteDockerImage(String image) {
+    def artifactoryServer = Artifactory.server(env.ARTIFACTORY_SERVER ?: 'mcp-ci')
+
+    return deleteItem(artifactoryServer.getUrl() + '/artifactory', dockerImageToArtifactoryPath(image))
+}
+
+/**
  * Upload docker image to Artifactory
  *
  * @param server ArtifactoryServer, the instance of Artifactory server
diff --git a/src/com/mirantis/mk/Ceph.groovy b/src/com/mirantis/mk/Ceph.groovy
index fe71d7d..79083bc 100644
--- a/src/com/mirantis/mk/Ceph.groovy
+++ b/src/com/mirantis/mk/Ceph.groovy
@@ -291,8 +291,8 @@
 
 def deleteKeyrings(master, target, extra_tgt='') {
     def host = getGrain(master, target, 'host')
-    def keys = cmdRun(master, "ceph auth list | grep $host", false).tokenize('\n')
-    if(keys.empty()) {
+    def keys = cmdRun(master, "ceph auth list 2>/dev/null | grep $host", false).tokenize('\n')
+    if(keys.isEmpty()) {
         new Common().warningMsg("Nothing to do. There is no keyring for $host")
     }
     for(key in keys) {
diff --git a/src/com/mirantis/mk/Helm.groovy b/src/com/mirantis/mk/Helm.groovy
index 61ff48a..ad262e0 100644
--- a/src/com/mirantis/mk/Helm.groovy
+++ b/src/com/mirantis/mk/Helm.groovy
@@ -18,17 +18,22 @@
 
 /**
  * Rebuild index file for helm chart repo
- * @param helmRepoUrl  repository with helm charts
- * @param md5Remote    md5 sum of index.yaml for check
+ * @param absHelmRepoUrl if set to true, URLs to charts will be absolute
+ * @param helmRepoUrl    repository with helm charts
+ * @param md5Remote      md5 sum of index.yaml for check
  */
 
-def helmMergeRepoIndex(helmRepoUrl, md5Remote='') {
+def helmMergeRepoIndex(helmRepoUrl, md5Remote='', absHelmRepoUrl=true) {
     def common      = new com.mirantis.mk.Common()
 
     def helmRepoDir    = '.'
-    def helmExtraParams = "--url ${helmRepoUrl}"
+    def helmExtraParams = ''
+    if (absHelmRepoUrl) {
+        helmExtraParams = "--url ${helmRepoUrl}"
+    }
 
     def indexRes = common.shCmdStatus("wget -O index-upstream.yaml ${helmRepoUrl}/index.yaml")
+
     if (indexRes['status']){
         if (indexRes['status'] == 8 && indexRes['stderr'].contains('ERROR 404') && !md5Remote) {
             common.warningMsg("Index.yaml not found in ${helmRepoUrl} and will be fully regenerated")
diff --git a/src/com/mirantis/mk/JenkinsUtils.groovy b/src/com/mirantis/mk/JenkinsUtils.groovy
index b760812..a9c5d0c 100644
--- a/src/com/mirantis/mk/JenkinsUtils.groovy
+++ b/src/com/mirantis/mk/JenkinsUtils.groovy
@@ -277,3 +277,30 @@
     }
     return [status: true, log: '', jobs: depList]
 }
+
+/**
+ *  Return jenkins infra metadata according to specified jenkins intstance
+
+ * @param jenkinsServerURL  (string) URL to jenkins server in form: env.JENKINS_URL
+ * @return                  (map)[
+ *                              jenkins_service_user: (string) name of jenkins user needed for gerrit ops
+ *                             ]
+ */
+def getJenkinsInfraMetadata(jenkinsServerURL) {
+    def meta = [
+        jenkins_service_user: '',
+    ]
+
+    switch (jenkinsServerURL) {
+        case 'https://ci.mcp.mirantis.net/':
+            meta['jenkins_service_user'] = 'mcp-jenkins'
+            break
+        case 'https://mcc-ci.infra.mirantis.net/':
+            meta['jenkins_service_user'] = 'mcc-ci-jenkins'
+            break
+        default:
+            error("Failed to detect jenkins service user, supported jenkins platforms: 'https://ci.mcp.mirantis.net/' 'https://mcc-ci.infra.mirantis.net/'")
+    }
+
+    return meta
+}
diff --git a/src/com/mirantis/mk/KaasUtils.groovy b/src/com/mirantis/mk/KaasUtils.groovy
index 5936ec8..6882315 100644
--- a/src/com/mirantis/mk/KaasUtils.groovy
+++ b/src/com/mirantis/mk/KaasUtils.groovy
@@ -65,6 +65,11 @@
         regionLocation: '',
     ]
 
+    // proxy customization
+    def proxyConfig = [
+        mgmtOffline: env.OFFLINE_MGMT_CLUSTER ? env.OFFLINE_MGMT_CLUSTER.toBoolean() : false, // TODO(vnaumov) add additonal vars for regional/child cluster ops
+    ]
+
     // optional demo deployment customization
     def awsOnDemandDemo = env.ALLOW_AWS_ON_DEMAND ? env.ALLOW_AWS_ON_DEMAND.toBoolean() : false
     def awsOnRhelDemo = false
@@ -74,6 +79,10 @@
     def enableBMDemo = true
 
     def commitMsg = env.GERRIT_CHANGE_COMMIT_MESSAGE ? new String(env.GERRIT_CHANGE_COMMIT_MESSAGE.decodeBase64()) : ''
+    if (commitMsg ==~ /(?s).*\[mgmt-proxy\].*/ || env.GERRIT_EVENT_COMMENT_TEXT ==~ /(?s).*mgmt-proxy.*/) {
+        proxyConfig['mgmtOffline'] = true
+        common.warningMsg('Forced running offline mgmt deployment, all provider CDN regions for mgmt deployment will be set to *public-ci* to verify proxy configuration')
+    }
     if (commitMsg ==~ /(?s).*\[seed-macos\].*/ || env.GERRIT_EVENT_COMMENT_TEXT ==~ /(?s).*seed-macos.*/) {
         seedMacOs = true
     }
@@ -177,10 +186,21 @@
             break
     }
 
+    // CDN configuration
+    def cdnConfig = [
+        mgmt: [
+            openstack:  (proxyConfig['mgmtOffline'] == true) ? 'public-ci' : 'internal-ci',
+            vsphere:  (proxyConfig['mgmtOffline'] == true) ? 'public-ci' : 'internal-ci',
+            aws: 'public-ci',
+        ], // TODO(vnaumov) add additonal vars for regional cluster cdn ops
+    ]
+
     // calculate weight of current demo run to manage lockable resources
     def demoWeight = (deployChild) ? 2 : 1 // management = 1, child = 1
 
     common.infoMsg("""
+        CDN deployment configuration: ${cdnConfig}
+        MCC offline deployment configuration: ${proxyConfig}
         Use MacOS node as seed: ${seedMacOs}
         Child cluster deployment scheduled: ${deployChild}
         Child cluster release upgrade scheduled: ${upgradeChild}
@@ -201,6 +221,8 @@
         Current weight of the demo run: ${demoWeight} (Used to manage lockable resources)
         Triggers: https://docs.google.com/document/d/1SSPD8ZdljbqmNl_FEAvTHUTow9Ki8NIMu82IcAVhzXw/""")
     return [
+        cdnConfig                  : cdnConfig,
+        proxyConfig                : proxyConfig,
         useMacOsSeedNode           : seedMacOs,
         deployChildEnabled         : deployChild,
         upgradeChildEnabled        : upgradeChild,
@@ -441,6 +463,7 @@
         string(name: 'SI_TESTS_DOCKER_IMAGE_TAG', value: siRefspec.siTestsDockerImageTag),
         string(name: 'SI_PIPELINES_REFSPEC', value: siRefspec.siPipelines),
         string(name: 'CUSTOM_RELEASE_PATCH_SPEC', value: patchSpec),
+        booleanParam(name: 'OFFLINE_MGMT_CLUSTER', value: triggers.proxyConfig['mgmtOffline']),
         booleanParam(name: 'SEED_MACOS', value: triggers.useMacOsSeedNode),
         booleanParam(name: 'UPGRADE_MGMT_CLUSTER', value: triggers.upgradeMgmtEnabled),
         booleanParam(name: 'RUN_UI_E2E', value: triggers.runUie2eEnabled),