diff --git a/.github/buildResources/createStandalonePom.groovy b/.github/buildResources/createStandalonePom.groovy new file mode 100644 index 0000000..82ac240 --- /dev/null +++ b/.github/buildResources/createStandalonePom.groovy @@ -0,0 +1,16 @@ + +/** + * Creates a new pom-standalone.xml based on pom.xml but with new artifact (jirainstancemanager-standalone) name and + * additional build steps for shading based on shadingConf.xml + */ +String projectBasePath = project.basedir +File origPom = new File(projectBasePath + "/pom.xml") +File shadingConf = new File(projectBasePath + "/.github/buildResources/shadingConf.xml") + +String newPomBody = origPom.text.replace("", "\n" + shadingConf.text) + +newPomBody = newPomBody.replaceFirst("jirainstancemanager<\\/artifactId>", "jirainstancemanager-standalone<\\/artifactId>") + +File standalonePom = new File(projectBasePath + "/pom-standalone.xml") +standalonePom.createNewFile() +standalonePom.text = newPomBody \ No newline at end of file diff --git a/.github/buildResources/secret_licenses/decrypt_licenses.sh b/.github/buildResources/secret_licenses/decrypt_licenses.sh new file mode 100755 index 0000000..64f98f2 --- /dev/null +++ b/.github/buildResources/secret_licenses/decrypt_licenses.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +set -e + +DIR="$( cd "$( dirname "$0" )" && pwd )" + + +mkdir -p $HOME/.licenses/jira +# --batch to prevent interactive command +# --yes to assume "yes" for questions +gpg --quiet --batch --yes --decrypt --passphrase="$LICENSE_PASSWORD" \ +--output $HOME/.licenses/jira/jsm.license $DIR/jsm.license.gpg +gpg --quiet --batch --yes --decrypt --passphrase="$LICENSE_PASSWORD" \ +--output $HOME/.licenses/jira/sr.license $DIR/sr.license.gpg diff --git a/.github/buildResources/secret_licenses/jsm.license.gpg b/.github/buildResources/secret_licenses/jsm.license.gpg new file mode 100644 index 0000000..bfb49a5 Binary files /dev/null and b/.github/buildResources/secret_licenses/jsm.license.gpg differ diff --git a/.github/buildResources/secret_licenses/sr.license.gpg b/.github/buildResources/secret_licenses/sr.license.gpg new file mode 100644 index 0000000..ea885bf --- /dev/null +++ b/.github/buildResources/secret_licenses/sr.license.gpg @@ -0,0 +1,4 @@ +  ⻵yaE +b&*!wG9K͊IgW+'lh I;M1-s4M5_#5w@]b puW虸$ 4=oFsJ<˼7fR*L>ǀk5%/8wgEB|R5ܲ8C*kę}&wYΉrDᬪ +HT+?%'*HgCqki'^.{?[CFXz C4T=S@?+MĹ\ 8m|yT^jT9aetRbhe(R C=d AFiWDQ9KDo3WB٣d5]j9u_xRj̴3N_oxd`IdRX'uCXTd~BB٣nfrB2 qW;/ 0n| +bV5 n-S~~*rbְih\hO>B#R,;rHz1nʟxIU \ No newline at end of file diff --git a/.github/buildResources/shadingConf.xml b/.github/buildResources/shadingConf.xml new file mode 100644 index 0000000..832bdf2 --- /dev/null +++ b/.github/buildResources/shadingConf.xml @@ -0,0 +1,77 @@ + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.1 + + + package + + shade + + + + + the-aggregated-module + 1.0.0 + + + + false + + + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + org.junit.jupiter:* + org.codehaus.groovy:* + org.junit:* + junit:* + + + + + + unirest + com.eficode.shaded.unirest + + + kong + com.eficode.shaded.kong + + + org.apache.commons + com.eficode.shaded.org.apache.commons + + + + + true + + true + + + + + + \ No newline at end of file diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index a7ba6bf..f511278 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -36,19 +36,34 @@ jobs: restore-keys: | ${{ runner.os }}-maven- - - name: Compile and install locally + - name: decrypt licenses + run: .github/buildResources/secret_licenses/decrypt_licenses.sh + env: + LICENSE_PASSWORD: ${{secrets.LICENSE_PASSWORD}} + + + - name: Compile and install main version run: | mkdir -p repository/com/eficode/atlassian/jirainstancemanager/ + echo Building and installing "normal" version + mvn install -f pom.xml -DcreateChecksum=true + + - name: Compile and install standalone version + run: | - mvn help:effective-pom -P groovy-3 -Doutput=effective-pom.xml - mvn install -f effective-pom.xml -DcreateChecksum=true + mkdir -p repository/com/eficode/atlassian/jirainstancemanager-standalone/ + echo Creating pom for standalone version and installing + mvn gplus:execute@execute + echo Building and installing "standalone" version + mvn install -f pom-standalone.xml -DcreateChecksum=true - name: Copying JAR files run: | echo Copying the new JAR files to repository which will be added to git branch "packages" rsync -avh --checksum ~/.m2/repository/com/eficode/atlassian/jirainstancemanager/ repository/com/eficode/atlassian/jirainstancemanager/ + rsync -avh --checksum ~/.m2/repository/com/eficode/atlassian/jirainstancemanager-standalone/ repository/com/eficode/atlassian/jirainstancemanager-standalone/ - name: Committing and pushing JAR files run: | @@ -71,4 +86,9 @@ jobs: echo Committing changes git commit -m "Updated packages to $VERSION" echo Pushing changes - git push \ No newline at end of file + git push + + + # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive + - name: Update dependency graph + uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 \ No newline at end of file diff --git a/README.md b/README.md index 1dfb1c5..095a1b5 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,12 @@ Jira Instance Manager Rest (JR) is a Groovy library which can perform several ad ## Breaking Changes +* 2.1.0 + * Switching to Unirest 4 might break some things if you depend on JIM supplying v4 + * See https://github.com/Kong/unirest-java/blob/main/UPGRADE_GUIDE.md for Unirest breaking changes + * Due to problems with shading the standalone version is now released as a separate artifact "jirainstancemanager-standalone" + * The classifier standalone is no longer used + * 1.1.0: * Almost all static methods in JiraInstanceManagerRest have been removed in order to better facilitate working with multiple JIRA instances and in cooperation with other libraries using Unirest library. * Fixing the unfortunate spelling mistake "JiraInstanceManagrRest" in favor for "JiraInstanceManagerRest" diff --git a/pom.xml b/pom.xml index 24bec24..05890b3 100644 --- a/pom.xml +++ b/pom.xml @@ -6,68 +6,52 @@ com.eficode.atlassian jirainstancemanager - 2.0.9-SNAPSHOT + 2.1.0-SNAPSHOT A groovy library for interacting with Jira REST API. - - - groovy-3 - - true - - - 11 - 11 - 3.0 - 3.0.11 - 2.2-groovy-3.0 - - - - - groovy-3.0.14 - - 3.0.14 - - - - groovy-3.0.13 - - 3.0.13 - - - - groovy-3.0.12 - - 3.0.12 - - - - groovy-3.0.11 - - 3.0.11 - - - - + + 11 + 11 + 3.0 + 3.0.11 + 2.2-groovy-3.0 + + + + + + + + com.konghq + unirest-java-bom + 4.2.6 + pom + import + + + - - com.konghq - unirest-java - 3.14.2 - standalone - org.slf4j slf4j-simple 2.0.5 + + com.konghq + unirest-java-core + + + com.konghq + unirest-objectmapper-jackson + + + com.eficode devstack-standalone - 2.3.11-SNAPSHOT + 2.3.12-SNAPSHOT test @@ -120,12 +104,12 @@ 2.14.0 - + @@ -200,94 +184,24 @@ + - org.apache.maven.plugins - maven-shade-plugin - 3.5.1 - - - package - - shade - - - - - the-aggregated-module - 1.0.0 - - - - true - - - standalone - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - org.junit.jupiter:* - org.codehaus.groovy:* - org.junit:* - junit:* - - - - - - - - unirest - com.eficode.shaded.unirest - - - kong - com.eficode.shaded.kong - - - org.apache.http - com.eficode.shaded.org.apache.http - - - org.apache.commons - com.eficode.shaded.org.apache.commons - - - - - true - - - - + maven-surefire-plugin + 3.2.5 + + + com/eficode/atlassian/jiraInstanceManager/jiraLocalScripts/** + + + com/eficode/atlassian/jiraInstanceManager/* + + + + org.apache.maven.plugins maven-source-plugin @@ -306,58 +220,36 @@ org.codehaus.gmavenplus gmavenplus-plugin - 1.13.1 + 3.0.2 - - add-dynamic-properties - initialize - execute + addSources + addTestSources + compile + compileTests - - - - - - add-dynamic-properties-v2 - compile + execute execute - - - - - - - - - - addSources - addTestSources - compile - compileTests - - - + + + + + + diff --git a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/JiraInstanceManagerRest.groovy b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/JiraInstanceManagerRest.groovy index c0dc98f..c1cdbbc 100644 --- a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/JiraInstanceManagerRest.groovy +++ b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/JiraInstanceManagerRest.groovy @@ -15,24 +15,22 @@ import com.eficode.atlassian.jiraInstanceManager.beans.SrJob import groovy.ant.AntBuilder import groovy.io.FileType import groovy.json.JsonSlurper -import kong.unirest.Cookie -import kong.unirest.Cookies -import kong.unirest.Empty -import kong.unirest.GenericType -import kong.unirest.GetRequest -import kong.unirest.HttpResponse -import kong.unirest.JsonNode -import kong.unirest.Unirest -import kong.unirest.UnirestException -import kong.unirest.UnirestInstance +import kong.unirest.core.Cookie +import kong.unirest.core.Cookies +import kong.unirest.core.Empty +import kong.unirest.core.GenericType +import kong.unirest.core.GetRequest +import kong.unirest.core.HttpResponse +import kong.unirest.core.JsonNode +import kong.unirest.core.Unirest +import kong.unirest.core.UnirestException +import kong.unirest.core.UnirestInstance import org.apache.groovy.json.internal.LazyMap -import org.codehaus.groovy.runtime.ResourceGroovyMethods +//import org.codehaus.groovy.runtime.ResourceGroovyMethods +import java.nio.file.Paths import org.slf4j.Logger import org.slf4j.LoggerFactory -import unirest.shaded.com.google.gson.JsonObject -import unirest.shaded.org.apache.http.NoHttpResponseException -import unirest.shaded.org.apache.http.conn.ConnectTimeoutException -import unirest.shaded.org.apache.http.conn.HttpHostConnectException + import java.nio.file.StandardCopyOption @@ -99,14 +97,9 @@ final class JiraInstanceManagerRest { existingCookies = new Cookies() } - response.headers.all().findAll { it.name == "Set-Cookie" }.each { - - String name = it.value.split(";")[0].split("=")[0] - String value = it.value.split(";")[0].split("=")[1] - - existingCookies.removeAll { it.name == name } - existingCookies.add(new Cookie(name, value)) - + response.cookies.each {newCookie -> + existingCookies.removeAll{it.name == newCookie.name} + existingCookies.add(newCookie) } @@ -136,14 +129,13 @@ final class JiraInstanceManagerRest { .asJson() - unirestInstance.shutDown() + assert switchUserResponse.status == 200, "Error getting cookies for user " + userKey UnirestInstance verifyInstance = Unirest.spawnInstance() verifyInstance.config().defaultBaseUrl(baseUrl).verifySsl(verifySsl) Map verifyMap = verifyInstance.get("/rest/api/2/myself").cookie(cookies).asJson().getBody().object.toMap() - verifyInstance.shutDown() assert verifyMap.get("key") == userKey log.info("\tTransform of admin to user cookies appears successfull") @@ -159,6 +151,7 @@ final class JiraInstanceManagerRest { Cookies acquireWebSudoCookies() { Map cookies = useSamlNoSso ? getCookiesFromRedirect("/secure/admin/WebSudoAuthenticate") : getCookiesFromRedirect("/login.jsp?nosso") + Cookie xsrfCookie = cookies.cookies.find { it.name == "atlassian.xsrf.token" } assert xsrfCookie: "Could not get atlassian.xsrf.token-cookie needed for WebSudo" @@ -174,7 +167,7 @@ final class JiraInstanceManagerRest { .field("webSudoPassword", adminPassword).asEmpty() - unirestInstance.shutDown() + assert webSudoResponse.status == 302, "Error acquiring Web Sudo" Cookies sudoCookies = webSudoResponse.cookies return sudoCookies @@ -250,7 +243,7 @@ final class JiraInstanceManagerRest { } /** - * Unirest by default gets lost when several redirects return cookies, this method will retain them + * This method collects all cooikies supleid during a getRequest even if several 302 redirects are done * @param path * @return */ @@ -284,7 +277,6 @@ final class JiraInstanceManagerRest { } - unirestInstance.shutDown() return ["cookies": cookies, "lastResponse": getResponse] } @@ -809,7 +801,7 @@ final class JiraInstanceManagerRest { .cookie(cookies) .field("setupLicenseKey", jiraLicense.replaceAll("[\n\r]", "")) .field("atl_token", cookies.find { it.name == "atlassian.xsrf.token" }.value) - .socketTimeout(4 * 60000) + .connectTimeout(4 * 60000) .asJson() assert setupLicenceResponse.status == 302, "Error setting license" @@ -846,7 +838,7 @@ final class JiraInstanceManagerRest { assert setupEmailResponse.status == 302, "Error setting up email" log.info("\t\tSet email successfully") - localUnirest.shutDown() + return true } @@ -885,7 +877,6 @@ final class JiraInstanceManagerRest { } catch (UnirestException ex) { - assert ex.cause.class == NoHttpResponseException || ex.cause.class == ConnectTimeoutException || ex.cause.class == HttpHostConnectException || ex.cause.class == SocketException log.info("---- Jira not available yet ----") sleep(1000) } @@ -893,18 +884,18 @@ final class JiraInstanceManagerRest { if (System.currentTimeMillis() > startTime + 180000) { - localUnirest.shutDown() - throw new NoHttpResponseException("Timeout waiting for JIRA Setup dialog") + + throw new SocketTimeoutException("Timeout waiting for JIRA Setup dialog") } log.info("Setting up local H2 database, this will take a several minutes.") HttpResponse setupDbResponse = localUnirest.post("/secure/SetupDatabase.jspa") .field("databaseOption", "internal") .field("atl_token", xsrfCookie.value) - .socketTimeout((8 * 60000)) + .connectTimeout((8 * 60000)) .asEmpty() - localUnirest.shutDown() + assert setupDbResponse.status == 302 assert setupDbResponse.headers.getFirst("Location").endsWith("SetupApplicationProperties!default.jspa") @@ -1139,7 +1130,7 @@ final class JiraInstanceManagerRest { createProjectResponse = rest.post("/rest/jira-importers-plugin/1.0/demo/create") .cookie(getCookiesFromRedirect("/rest/project-templates/1.0/templates").cookies) .cookie(acquireWebSudoCookies()) - .socketTimeout(60000 * 8) + .connectTimeout(60000 * 8) .header("X-Atlassian-Token", "no-check") .field("name", name) .field("key", projectKey.toUpperCase()) @@ -1465,7 +1456,7 @@ final class JiraInstanceManagerRest { ) .contentType("application/json") .cookie(acquireWebSudoCookies()) - .socketTimeout(60000 * 8) + .connectTimeout(60000 * 8) .asObject(Map) assert spockResponse.status == 200: "Got unexpected HTTP Status when running Spock test" @@ -1516,7 +1507,7 @@ final class JiraInstanceManagerRest { .body(["FIELD_TEST": [testToRun], "FIELD_SCAN_PACKAGES": packageToRun]) .contentType("application/json") .cookie(acquireWebSudoCookies()) - .socketTimeout(60000 * 8) + .connectTimeout(60000 * 8) .asJson() @@ -1732,7 +1723,7 @@ final class JiraInstanceManagerRest { Map executeLocalScriptFile(String scriptContent) { - HttpResponse scriptResponse = rest.post("/rest/scriptrunner/latest/user/exec/").socketTimeout(4 * 60000).cookie(acquireWebSudoCookies()).contentType("application/json").body(["script": scriptContent]).asJson() + HttpResponse scriptResponse = rest.post("/rest/scriptrunner/latest/user/exec/").connectTimeout(4 * 60000).cookie(acquireWebSudoCookies()).contentType("application/json").body(["script": scriptContent]).asJson() Map scriptResponseJson = scriptResponse.body.getObject().toMap() ArrayList logRows = scriptResponseJson.snapshot?.log?.split("\n") @@ -1847,20 +1838,22 @@ final class JiraInstanceManagerRest { log.info("Getting ID for REST Endpoint:" + endpointName) Cookies cookies = acquireWebSudoCookies() - HttpResponse response = rest.get("/rest/scriptrunner/latest/custom/customadmin?").cookie(cookies).asJson() - List endpointsRaw = response.body.getArray().toList() + HttpResponse> response = rest.get("/rest/scriptrunner/latest/custom/customadmin?").cookie(cookies).asObject (new GenericType>(){}) + + - log.trace("\tRaw response:") - endpointName.eachLine { log.trace("\t\t" + it) } - Map correctEndpoint = endpointsRaw.find { it.get("endpoints").toList().any { it.name == endpointName } }?.toMap() + Map correctEndpoint = response.body.find { (it.get("endpoints") as ArrayList).any { it.name == endpointName } } return correctEndpoint?.id } + + + /** * Create a new SR Scripted Rest endpoint * Nothing will stop you from creating multiple endpoints with the same name, but the result will be unpredictable. @@ -1952,11 +1945,11 @@ final class JiraInstanceManagerRest { Cookies cookies = acquireWebSudoCookies() - HttpResponse response = rest.get("/rest/scriptrunner/latest/resources?").cookie(cookies).asJson() - List resourcesRaw = response.body.getArray().toList() + HttpResponse> response = rest.get("/rest/scriptrunner/latest/resources?").cookie(cookies).asObject(new GenericType>(){}) + - Map correctEndpoint = resourcesRaw.find { it.get("canned-script") == "com.onresolve.scriptrunner.canned.db.LocalDatabaseConnection" && it.get("poolName") == poolName }?.toMap() + Map correctEndpoint = response.body.find { it.get("canned-script") == "com.onresolve.scriptrunner.canned.db.LocalDatabaseConnection" && it.get("poolName") == poolName } return correctEndpoint?.id @@ -2046,7 +2039,9 @@ final class JiraInstanceManagerRest { Map filesToUpload = [:] sourceRoot.eachFileRecurse(FileType.FILES) { sourceFile -> - filesToUpload.put(sourceFile.absolutePath, ResourceGroovyMethods.relativePath(sourceRoot.parentFile, sourceFile)) + String relativePath = Paths.get(sourceRoot.parentFile.toURI()).relativize(Paths.get(sourceFile.toURI())) + + filesToUpload.put(sourceFile.absolutePath, relativePath) } log.info("\tGot ${filesToUpload.size()} files from JAR archive, uploading them now") @@ -2127,7 +2122,7 @@ final class JiraInstanceManagerRest { assert unzipDir.mkdirs(): "Error creating temporary unzip dir:" + unzipDir.canonicalPath HttpResponse downloadResponse = githubRest.get("$githubRepoUrl/archive/refs/heads/${branch}.zip").asFile((tempDir.canonicalPath.endsWith("/") ?: tempDir.canonicalPath + "/").toString() + "${branch}.zip") - githubRest.shutDown() + File zipFile = new File(tempDir.canonicalPath, branch + ".zip") assert zipFile.canRead(): "Error reading downloaded zip:" + zipFile.canonicalPath diff --git a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/AssetAutomationBean.groovy b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/AssetAutomationBean.groovy index b2fd0b3..497a9ab 100644 --- a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/AssetAutomationBean.groovy +++ b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/AssetAutomationBean.groovy @@ -1,7 +1,7 @@ package com.eficode.atlassian.jiraInstanceManager.beans -import com.fasterxml.jackson.databind.ObjectMapper -import unirest.shaded.com.google.gson.annotations.SerializedName +import com.fasterxml.jackson.annotation.JsonProperty + class AssetAutomationBean { @@ -63,9 +63,9 @@ class AssetAutomationBean { enum ActionType { - @SerializedName("com.riadalabs.jira.plugins.insight.services.automation.action.AutomationRuleGroovyScriptAction") + @JsonProperty("com.riadalabs.jira.plugins.insight.services.automation.action.AutomationRuleGroovyScriptAction") GroovyScript("Execute Groovy script", 'com.riadalabs.jira.plugins.insight.services.automation.action.AutomationRuleGroovyScriptAction'), - @SerializedName("com.riadalabs.jira.plugins.insight.services.automation.action.AutomationRuleHttpRequestAction") + @JsonProperty("com.riadalabs.jira.plugins.insight.services.automation.action.AutomationRuleHttpRequestAction") HttpRequest ("Http Request", "com.riadalabs.jira.plugins.insight.services.automation.action.AutomationRuleHttpRequestAction") diff --git a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/AssetFieldBean.groovy b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/AssetFieldBean.groovy index ba75a66..f85b500 100644 --- a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/AssetFieldBean.groovy +++ b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/AssetFieldBean.groovy @@ -1,6 +1,6 @@ package com.eficode.atlassian.jiraInstanceManager.beans -import kong.unirest.HttpResponse +import kong.unirest.core.HttpResponse class AssetFieldBean extends FieldBean { diff --git a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/CustomFieldBean.groovy b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/CustomFieldBean.groovy index c988e11..d4b797f 100644 --- a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/CustomFieldBean.groovy +++ b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/CustomFieldBean.groovy @@ -4,9 +4,8 @@ import com.eficode.atlassian.jiraInstanceManager.JiraInstanceManagerRest import com.fasterxml.jackson.annotation.* import com.fasterxml.jackson.core.type.TypeReference import com.fasterxml.jackson.databind.ObjectMapper -import kong.unirest.GenericType -import kong.unirest.HttpResponse -import kong.unirest.JsonNode +import kong.unirest.core.GenericType +import kong.unirest.core.HttpResponse import org.slf4j.Logger import org.slf4j.LoggerFactory diff --git a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/FieldBean.groovy b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/FieldBean.groovy index c279b18..9d54070 100644 --- a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/FieldBean.groovy +++ b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/FieldBean.groovy @@ -7,9 +7,9 @@ import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.ObjectMapper -import kong.unirest.GenericType -import kong.unirest.HttpResponse -import kong.unirest.UnirestInstance +import kong.unirest.core.GenericType +import kong.unirest.core.HttpResponse +import kong.unirest.core.UnirestInstance import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -357,7 +357,7 @@ class FieldBean { */ static ArrayList getFields(JiraInstanceManagerRest jim) { - UnirestInstance unirest = jim.getUnirest() + UnirestInstance unirest = jim.rest ArrayList fields try { @@ -395,7 +395,7 @@ class FieldBean { */ static FieldBean createCustomfield(JiraInstanceManagerRest jim, String name, String searcherKey, String typeKey, String description = "", ArrayList projectIds = [], ArrayList issueTypeIds = ["-1"]) { - UnirestInstance unirest = jim.getUnirest() + UnirestInstance unirest = jim.rest try { HttpResponse rawResponse = unirest.post("/rest/api/2/field") diff --git a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/IssueTypeBean.groovy b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/IssueTypeBean.groovy index 58db54c..8b54152 100644 --- a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/IssueTypeBean.groovy +++ b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/IssueTypeBean.groovy @@ -6,9 +6,7 @@ import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.ObjectMapper -import kong.unirest.GenericType -import kong.unirest.HttpResponse -import kong.unirest.UnirestInstance +import kong.unirest.core.UnirestInstance import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -54,8 +52,6 @@ class IssueTypeBean { static ArrayList getIssueTypes(JiraInstanceManagerRest jim) { - UnirestInstance unirest = jim.getUnirest() - ArrayList fields try { diff --git a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/MarketplaceApp.groovy b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/MarketplaceApp.groovy index 27669c8..ad69630 100644 --- a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/MarketplaceApp.groovy +++ b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/MarketplaceApp.groovy @@ -3,9 +3,9 @@ package com.eficode.atlassian.jiraInstanceManager.beans import com.eficode.atlassian.jiraInstanceManager.JiraInstanceManagerRest import com.fasterxml.jackson.core.type.TypeReference import com.fasterxml.jackson.databind.ObjectMapper -import kong.unirest.HttpResponse -import kong.unirest.Unirest -import kong.unirest.UnirestInstance +import kong.unirest.core.HttpResponse +import kong.unirest.core.Unirest +import kong.unirest.core.UnirestInstance import com.fasterxml.jackson.annotation.JsonAnyGetter @@ -15,7 +15,7 @@ import com.fasterxml.jackson.annotation.JsonInclude import com.fasterxml.jackson.annotation.JsonProperty import org.slf4j.Logger import org.slf4j.LoggerFactory -import unirest.shaded.com.google.gson.annotations.SerializedName + @JsonInclude(JsonInclude.Include.NON_NULL) @@ -66,7 +66,7 @@ class MarketplaceApp { appsRaw += response.body?.get("_embedded")?.get("addons") nextPageUrl = response?.body?.get("_links")?.get("next")?.find { it.type == "application/json" }?.href as String } - mrktUnirest.shutDown() + ArrayList marketplaceApps = appsRaw.collect { MarketplaceApp.fromMap(it) } return marketplaceApps @@ -178,13 +178,13 @@ class MarketplaceApp { enum Hosting { - @SerializedName("any") + @JsonProperty("any") Any, - @SerializedName("cloud") + @JsonProperty("cloud") Cloud, - @SerializedName("datacenter") + @JsonProperty("datacenter") Datacenter, - @SerializedName("server") + @JsonProperty("server") Server } diff --git a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/ProjectBean.groovy b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/ProjectBean.groovy index cc88896..298277d 100644 --- a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/ProjectBean.groovy +++ b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/ProjectBean.groovy @@ -6,7 +6,7 @@ import com.fasterxml.jackson.annotation.JsonAnyGetter import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.databind.ObjectMapper -import kong.unirest.HttpResponse +import kong.unirest.core.HttpResponse class ProjectBean { diff --git a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/ScriptFieldBean.groovy b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/ScriptFieldBean.groovy index 2a1a893..72c9476 100644 --- a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/ScriptFieldBean.groovy +++ b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/ScriptFieldBean.groovy @@ -10,9 +10,9 @@ import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonSetter import com.fasterxml.jackson.core.type.TypeReference import com.fasterxml.jackson.databind.ObjectMapper -import kong.unirest.Cookies -import kong.unirest.GenericType -import kong.unirest.HttpResponse +import kong.unirest.core.Cookies +import kong.unirest.core.GenericType +import kong.unirest.core.HttpResponse import org.slf4j.Logger import org.slf4j.LoggerFactory diff --git a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/SrJob.groovy b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/SrJob.groovy index d865ea7..db8d600 100644 --- a/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/SrJob.groovy +++ b/src/main/groovy/com/eficode/atlassian/jiraInstanceManager/beans/SrJob.groovy @@ -7,9 +7,9 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.ObjectMapper -import kong.unirest.GenericType -import kong.unirest.HttpResponse -import kong.unirest.UnirestInstance; +import kong.unirest.core.GenericType +import kong.unirest.core.HttpResponse +import kong.unirest.core.UnirestInstance; /** * Represents a ScriptRunenr scheduled job @@ -68,11 +68,10 @@ class SrJob { static boolean deleteJob(JiraInstanceManagerRest jim, String jobId) { - UnirestInstance unirestInstance = jim.getUnirest() + UnirestInstance unirestInstance = jim.rest HttpResponse response = unirestInstance.delete("/rest/scriptrunner/latest/scheduled-jobs/" + jobId).cookie(jim.acquireWebSudoCookies()).asEmpty() - unirestInstance.shutDown() return response.status == 204 @@ -80,7 +79,7 @@ class SrJob { static SrJob createJob(JiraInstanceManagerRest jim, String jobNote, String userKey, String cron, String scriptPath) { - UnirestInstance unirestInstance = jim.getUnirest() + UnirestInstance unirestInstance = jim.rest HttpResponse createResponse = unirestInstance @@ -100,12 +99,12 @@ class SrJob { .asEmpty() .ifFailure(Error.class, r -> { - unirestInstance.shutDown() + throw new InputMismatchException("Error creating SR Job \"$jobNote\": " + r.body.toString()) }) assert createResponse.status == 200: "Error creating SR Job \"$jobNote\"" - unirestInstance.shutDown() + ArrayList srJobs = getJobs(jim) @@ -119,7 +118,7 @@ class SrJob { static ArrayList getJobs(JiraInstanceManagerRest jim) { - UnirestInstance unirestInstance = jim.getUnirest() + UnirestInstance unirestInstance = jim.rest HttpResponse> response = unirestInstance.get("/rest/scriptrunner/latest/scheduled-jobs?").cookie(jim.acquireWebSudoCookies()).asObject(new GenericType>() { @@ -127,7 +126,6 @@ class SrJob { assert response.status == 200: "Error getting SR Jobs" - unirestInstance.shutDown() ArrayList jobs = response.body.collect { fromMap(it) } diff --git a/src/test/groovy/com/eficode/atlassian/jiraInstanceManager/CrossGroovyVersionSpec.groovy b/src/test/groovy/com/eficode/atlassian/jiraInstanceManager/CrossGroovyVersionSpec.groovy index 50d240d..5c332e2 100644 --- a/src/test/groovy/com/eficode/atlassian/jiraInstanceManager/CrossGroovyVersionSpec.groovy +++ b/src/test/groovy/com/eficode/atlassian/jiraInstanceManager/CrossGroovyVersionSpec.groovy @@ -1,9 +1,12 @@ package com.eficode.atlassian.jiraInstanceManager import com.eficode.devstack.container.impl.GroovyContainer +import spock.lang.Ignore import spock.lang.Shared import spock.lang.Specification + +@Ignore class CrossGroovyVersionSpec extends Specification{ diff --git a/src/test/groovy/com/eficode/atlassian/jiraInstanceManager/JiraInstanceManagerRestSpec.groovy b/src/test/groovy/com/eficode/atlassian/jiraInstanceManager/JiraInstanceManagerRestSpec.groovy index 9eb9a08..a37d8bf 100644 --- a/src/test/groovy/com/eficode/atlassian/jiraInstanceManager/JiraInstanceManagerRestSpec.groovy +++ b/src/test/groovy/com/eficode/atlassian/jiraInstanceManager/JiraInstanceManagerRestSpec.groovy @@ -12,10 +12,10 @@ import com.eficode.atlassian.jiraInstanceManager.beans.SrJob import com.eficode.devstack.deployment.impl.JsmH2Deployment import de.gesellix.docker.remote.api.ContainerState import groovy.io.FileType -import kong.unirest.Cookies -import kong.unirest.HttpResponse -import kong.unirest.Unirest -import kong.unirest.UnirestInstance +import kong.unirest.core.Cookies +import kong.unirest.core.HttpResponse +import kong.unirest.core.Unirest +import kong.unirest.core.UnirestInstance import org.apache.groovy.json.internal.LazyMap import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -59,6 +59,7 @@ class JiraInstanceManagerRestSpec extends Specification { Unirest.config().defaultBaseUrl(baseUrl).setDefaultBasicAuth(restAdmin, restPw) + jsmDep.setJiraLicense(jsmLicense) if (!(reuseContainer && jsmDep?.jsmContainer?.status() == ContainerState.Status.Running)) { @@ -68,7 +69,9 @@ class JiraInstanceManagerRestSpec extends Specification { //Start and wait for the deployment jsmDep.setupDeployment() - assert jiraInstanceManagerRest.installScriptRunner(srLicense, baseSrVersion) : "Error installing SR version:" + baseSrVersion + jsmDep.jiraRest.waitForJiraToBeResponsive() + + assert jiraInstanceManagerRest.installScriptRunner(srLicense, baseSrVersion): "Error installing SR version:" + baseSrVersion } @@ -77,11 +80,12 @@ class JiraInstanceManagerRestSpec extends Specification { } JiraInstanceManagerRest getJiraInstanceManagerRest() { - return new JiraInstanceManagerRest(restAdmin, restPw, baseUrl) + JiraInstanceManagerRest jim = new JiraInstanceManagerRest(restAdmin, restPw, baseUrl) + //jim.setProxy("localhost", 8090) + return jim } - def "Test scriptRunnerIsInstalled"() { setup: @@ -281,7 +285,7 @@ class JiraInstanceManagerRestSpec extends Specification { setup: log.info("Testing CRUD of SR jobs") JiraInstanceManagerRest jira = new JiraInstanceManagerRest(baseUrl) - + String jobFile = "com/eficode/atlassian/jiraInstanceManager/jiraLocalScripts/srJob.groovy" String jobNote = "SPOC Job" @@ -290,7 +294,7 @@ class JiraInstanceManagerRestSpec extends Specification { assert jira.updateScriptrunnerFile("log.warn(\"test\")", jobFile): "Error creating SR Job File" - assert jira.installScriptRunner(srLicense, srVersionNumber) : "Error installing SR version:" + srVersionNumber + assert jira.installScriptRunner(srLicense, srVersionNumber): "Error installing SR version:" + srVersionNumber log.info("\tUsing SR version:" + srVersionNumber) sleep(1500)//Wait for sr to detect file changes @@ -322,9 +326,7 @@ class JiraInstanceManagerRestSpec extends Specification { //Not sure why a new instance is needed here, deletion/cleanup fails otherwise JiraInstanceManagerRest jim = new JiraInstanceManagerRest(baseUrl) - jim.setProxy("localhost", 8081) - jim.setVerifySsl(false) - assert jim.installScriptRunner(srLicense, baseSrVersion) : "Error installing SR version:" + baseSrVersion + assert jim.installScriptRunner(srLicense, baseSrVersion): "Error installing SR version:" + baseSrVersion } @@ -332,13 +334,10 @@ class JiraInstanceManagerRestSpec extends Specification { srVersionNumber | last "latest" | false "7.13.0" | false - "7.6.0" | false "7.0.0" | false - "6.58.1" | false "6.55.0" | true - } def "Test runSpockTest"(String srVersionNumber, boolean last) { @@ -351,8 +350,7 @@ class JiraInstanceManagerRestSpec extends Specification { assert jiraLocalScriptRootDir.isDirectory() - - assert jira.installScriptRunner(srLicense, srVersionNumber) : "Error installing SR version:" + srVersionNumber + assert jira.installScriptRunner(srLicense, srVersionNumber): "Error installing SR version:" + srVersionNumber log.info("\tUsing SR version:" + srVersionNumber) @@ -424,7 +422,7 @@ class JiraInstanceManagerRestSpec extends Specification { cleanup: if (last) { - assert jira.installScriptRunner(srLicense, baseSrVersion) : "Error installing SR version:" + baseSrVersion + assert jira.installScriptRunner(srLicense, baseSrVersion): "Error installing SR version:" + baseSrVersion } @@ -432,10 +430,7 @@ class JiraInstanceManagerRestSpec extends Specification { srVersionNumber | last "latest" | false "7.13.0" | false - "7.6.0" | false - "7.0.0" | false "6.58.1" | false - "6.56.0" | false "6.55.0" | true } @@ -451,7 +446,7 @@ class JiraInstanceManagerRestSpec extends Specification { File jiraLocalScriptRootDir = new File("src/test/groovy") assert jiraLocalScriptRootDir.isDirectory() - assert jira.installScriptRunner(srLicense, srVersionNumber) : "Error installing SR version:" + srVersionNumber + assert jira.installScriptRunner(srLicense, srVersionNumber): "Error installing SR version:" + srVersionNumber log.info("\tUsing SR version:" + srVersionNumber) log.info("\tUsing test files found in local dir:" + jiraLocalScriptsDir.name) @@ -521,7 +516,7 @@ class JiraInstanceManagerRestSpec extends Specification { cleanup: if (last) { - assert jira.installScriptRunner(srLicense, baseSrVersion) : "Error installing SR version:" + baseSrVersion + assert jira.installScriptRunner(srLicense, baseSrVersion): "Error installing SR version:" + baseSrVersion } @@ -639,7 +634,6 @@ class JiraInstanceManagerRestSpec extends Specification { log.info("\tRest API indicates the cookie is functional") cleanup: - spocInstance.shutDown() Map deleteUserResult = jiraRest.executeLocalScriptFile(userCrudScript.replace(["CREATE_USER": "false", "DELETE_USER": "true", "SPOC_USER_KEY": spocUserKey])) assert deleteUserResult.success log.info("\tSpoc user was deleted") @@ -653,9 +647,14 @@ class JiraInstanceManagerRestSpec extends Specification { setup: JiraInstanceManagerRest jiraR = getJiraInstanceManagerRest() - when: "Instantiate JiraInstanceManager" + //Cleanup pre-existing pool + String preExistingPool = jiraR.getLocalDbResourceId("spoc-pool") + if (preExistingPool) { + jiraR.deleteLocalDbResourceId(preExistingPool) + } - JiraInstanceManagerRest jira = new JiraInstanceManagerRest(baseUrl) + + when: "Instantiate JiraInstanceManager" then: assert jiraR.createLocalDbResource("spoc-pool"): "Error creating Local DB Resource" @@ -886,11 +885,11 @@ class JiraInstanceManagerRestSpec extends Specification { jim.createJsmProjectWithSampleData("Asset Field Crud", "ASSFCRUD") } - ArrayList assetFieldTypes = jim.getFieldTypes().findAll {it.key.startsWith("com.riadalabs.jira.plugins.insight")} + ArrayList assetFieldTypes = jim.getFieldTypes().findAll { it.key.startsWith("com.riadalabs.jira.plugins.insight") } expect: - assetFieldTypes.each {assetFieldType -> + assetFieldTypes.each { assetFieldType -> String fieldPrefix = System.currentTimeMillis().toString()[-5..-1] @@ -898,11 +897,11 @@ class JiraInstanceManagerRestSpec extends Specification { FieldBean newField = jim.createCustomfield(fieldPrefix + "-" + assetFieldType.name, assetFieldType.searchers.first(), assetFieldType.key, "Field type: ${assetFieldType.name}") - assert newField.class == AssetFieldBean : "createCustomfield() did not return an AssetFieldBean when creating an asset field" + assert newField.class == AssetFieldBean: "createCustomfield() did not return an AssetFieldBean when creating an asset field" AssetFieldBean newAssetField = newField as AssetFieldBean - assert newAssetField.getConfigSchemeIds().size() == 1 : "getConfigSchemeIds() did not return the expected number of schema ids" + assert newAssetField.getConfigSchemeIds().size() == 1: "getConfigSchemeIds() did not return the expected number of schema ids" assert newAssetField.deleteCustomField() @@ -936,7 +935,7 @@ class JiraInstanceManagerRestSpec extends Specification { FieldBean.FieldType.getFieldTypes(jim).size() > 35 FieldBean.getFields(jim).id.sort() == jim.getFields().id.sort() assert jiraFieldBeans.find { it.name == "CAB" }.getFieldContexts().allProjects == [true]: "Expected CAB field to be applied to all projects" - assert jiraFieldBeans.find { it.name == "CAB" }.getFieldContexts().allIssueTypes == [true] : "Expected CAB field applied to all issue types" + assert jiraFieldBeans.find { it.name == "CAB" }.getFieldContexts().allIssueTypes == [true]: "Expected CAB field applied to all issue types" expect: "Creation of fields with global/specific issueType/project of all fieldTypes and searchers, to work." @@ -964,17 +963,17 @@ class JiraInstanceManagerRestSpec extends Specification { FieldBean newField = jim.createCustomfield(fieldPrefix + "-" + fieldType.name, searcherKey, fieldTypKey, "Field type: ${fieldType.name}, Project: $projectIds, IssueType: $issueTypeIds", projectIds, issueTypeIds) log.info("\t" * 3 + "Created field:" + newField.toString()) - ArrayListfieldConfigContexts = newField.getFieldContexts() - assert fieldConfigContexts.size() == 1 : "Expected new field to only have one config context" + ArrayList fieldConfigContexts = newField.getFieldContexts() + assert fieldConfigContexts.size() == 1: "Expected new field to only have one config context" FieldBean.FieldConfigurationContext fieldConfigContext = fieldConfigContexts.first() if (projectIds == [null]) { - assert fieldConfigContext.allProjects : "Field ${newField.id} was setup as project-global but field config context was not set to allProjects=true" - assert fieldConfigContext.projects.isEmpty() : "Field ${newField.id} was setup as project-global fieldConfigContext.projects was not empty" + assert fieldConfigContext.allProjects: "Field ${newField.id} was setup as project-global but field config context was not set to allProjects=true" + assert fieldConfigContext.projects.isEmpty(): "Field ${newField.id} was setup as project-global fieldConfigContext.projects was not empty" //assert newField.getFieldProjects(true).projectId == jim.getProjects().projectId: "Field ${newField.id} was setup as project-global but getFieldProjects(true) did not return all projects" } else { - assert projectIds.toString() == fieldConfigContext.projects.collect {it.projectId}.toString(): "Field ${newField.id} was setup for specific projects ($projectIds) but fieldConfigContext.projects did not return the expected projects" + assert projectIds.toString() == fieldConfigContext.projects.collect { it.projectId }.toString(): "Field ${newField.id} was setup for specific projects ($projectIds) but fieldConfigContext.projects did not return the expected projects" } @@ -986,7 +985,6 @@ class JiraInstanceManagerRestSpec extends Specification { } - assert newField.getFieldType(true).key == fieldType.key: "Field ${newField.id} was suposed to be type ${fieldType.key}, but API returned ${newField.getFieldType(true).key}" log.info("\t" * 3 + "Field was successfully created")