Add harborUtils module
Provides main methods for work with helm charts/repos/projects
Change-Id: I07dee30e327d2480c63d1afa5553e2afa438aa53
Related-Prod: https://mirantis.jira.com/browse/PROD-30728
diff --git a/src/com/mirantis/mk/HarborUtils.groovy b/src/com/mirantis/mk/HarborUtils.groovy
new file mode 100644
index 0000000..0473f29
--- /dev/null
+++ b/src/com/mirantis/mk/HarborUtils.groovy
@@ -0,0 +1,151 @@
+package com.mirantis.mk
+
+/**
+ *
+ * Functions to work with Harbor Api
+ *
+ */
+
+ /**
+ * Returns a list of Harbor projects (hash maps) containing common pattern in name
+ * @param harborApi HashMap contains 'url' and 'auth' fields. Url field is a string
+ * containing Harbor api url - e.g. http://[harbor_api_host]/api,
+ * Auth field should provide string with base64 encoded presentation
+ * of string 'username:password' for connection to Harbor Api
+ * @param projectPattern String contains full name or part of project name
+ * @return list
+ */
+def getHarborProjectsByPattern(harborApi, projectPattern){
+ def http = new com.mirantis.mk.Http()
+ def common = new com.mirantis.mk.Common()
+ def auth = harborApi['auth']
+ def headers = ['Authorization': "Basic ${auth}"]
+ def res = http.restGet(harborApi, "/projects?name=${projectPattern}", null, headers)
+ if (!(res instanceof List)){
+ common.warningMsg("No projects found for the pattern ${projectPattern}, The result is ${res}")
+ return []
+ }
+ return res
+}
+
+ /**
+ * Returns an id of a project
+ * @param harborApi HashMap contains 'url' and 'auth' fields. Url field is a string
+ * containing Harbor api url - e.g. http://[harbor_api_host]/api,
+ * Auth field should provide string with base64 encoded presentation
+ * of string 'username:password' for connection to Harbor Api
+ * @param projectName String project name to search for
+ * @return string
+ */
+def getHarborProjectByName(harborApi, projectName){
+ def plist = getHarborProjectsByPattern(harborApi, projectName)
+ def id = null
+ for (i in plist){
+ if (i.get('name') == projectName){
+ id = i['project_id']
+ }
+ }
+ return id
+}
+
+ /**
+ * Creates a project in Harbor, returns string
+ * @param harborApi HashMap contains 'url' and 'auth' fields. Url field is a string
+ * containing Harbor api url - e.g. http://[harbor_api_host]/api,
+ * Auth field should provide string with base64 encoded presentation
+ * of string 'username:password' for connection to Harbor Api
+ * @param projectName String project name to create
+ * @param isPublic Bool whether to create public project
+ * @return string
+ */
+def createHarborProject(harborApi, projectName, isPublic = true){
+ def http = new com.mirantis.mk.Http()
+ def data = ['project_name': projectName, 'metadata': ['public': isPublic.toString()]]
+ def auth = harborApi['auth']
+ def headers = ['Authorization': "Basic ${auth}"]
+ return http.restPost(harborApi, '/projects/', data, headers)
+}
+
+ /**
+ * Deletes a project in Harbor returns string
+ * @param harborApi HashMap contains 'url' and 'auth' fields. Url field is a string
+ * containing Harbor api url - e.g. http://[harbor_api_host]/api,
+ * Auth field should provide string with base64 encoded presentation
+ * of string 'username:password' for connection to Harbor Api
+ * @param projectId String project id to delete
+ * @return string
+ */
+def deleteHarborProject(harborApi, projectId){
+ def http = new com.mirantis.mk.Http()
+ def auth = harborApi['auth']
+ def headers = ['Authorization': "Basic ${auth}"]
+ return http.restDelete(harborApi, "/projects/${projectId}", null, headers)
+}
+
+ /**
+ * Returns a list of Helm charts (hash maps) from repo
+ * @param harborApi HashMap contains 'url' and 'auth' fields. Url field is a string
+ * containing Harbor api url - e.g. http://[harbor_api_host]/api,
+ * Auth field should provide string with base64 encoded presentation
+ * of string 'username:password' for connection to Harbor Api
+ * @param repoName String name of Helm charts repo
+ * @return list
+ */
+def getHarborHelmCharts(harborApi, repoName){
+ def http = new com.mirantis.mk.Http()
+ def auth = harborApi['auth']
+ def headers = ['Authorization': "Basic ${auth}"]
+ return http.restGet(harborApi, "/chartrepo/${repoName}/charts", null, headers)
+}
+
+ /**
+ * Deletes a Helm chart from repo, returns string
+ * @param harborApi HashMap contains 'url' and 'auth' fields. Url field is a string
+ * containing Harbor api url - e.g. http://[harbor_api_host]/api,
+ * Auth field should provide string with base64 encoded presentation
+ * of string 'username:password' for connection to Harbor Api
+ * @param repoName String name of Helm charts repo
+ * @param chartName String name of chart to remove
+ * @return string
+ */
+ def deleteHarborHelmChart(harborApi, repoName, chartName){
+ def http = new com.mirantis.mk.Http()
+ def auth = harborApi['auth']
+ def headers = ['Authorization': "Basic ${auth}"]
+ return http.restDelete(harborApi, "/chartrepo/${repoName}/charts/${chartName}", null, headers)
+}
+
+ /**
+ * Publishes a Helm chart to Harbor repo. TODO(mkarpin): currently http.restCall doesn't support
+ * multipart/form-data content type for POST request, when this support is added, this method
+ * should be switched to restCall.
+ * @param harborApi HashMap contains 'url' and 'auth' fields. Url field is a string
+ * containing Harbor api url - e.g. http://[harbor_api_host]/api,
+ * Auth field should provide string with base64 encoded presentation
+ * of string 'username:password' for connection to Harbor Api
+ * @param repoName String name of Helm charts repo
+ * @param chartFile String name of file with Helm chart
+ * @param chartFile String name of file with signature of Helm chart
+ * @return string
+ */
+def publishHarborHelmChart(harborApi, repoName, chartFile, provFile = null){
+ def http = new com.mirantis.mk.Http()
+ def common = new com.mirantis.mk.Common()
+ def data = "-F 'chart=@${chartFile}'"
+ def res = [:]
+ if (provFile){
+ data += ' '
+ data += "-F 'prov=@${provFile}'"
+ }
+ def auth = harborApi['auth']
+ def headers = "-H 'Authorization: Basic ${auth}'"
+ def repo_url = "${harborApi['url']}/chartrepo/${repoName}/charts"
+
+ common.infoMsg("Publishing chart ${chartFile} to ${repo_url}")
+ res = common.shCmdStatus("set +x; curl --fail ${headers} ${data} ${repo_url}")
+ if (res['status'] == 0){
+ return res['stdout']
+ } else {
+ error "Chart publishing failed with error ${res['stderr']}"
+ }
+}
\ No newline at end of file