From 40e3f0bdb9ab119f1bacebe8ac428b0b7cc4ffb5 Mon Sep 17 00:00:00 2001 From: Leelavathi D H Date: Mon, 22 Aug 2022 17:47:06 +0530 Subject: [PATCH 1/8] HCL Accelerate Multiple Instance Support in jenkins --- .../devops/connect/CRPipeline/CheckGate.java | 130 ++++--- .../ContinuousReleaseProperties.java | 2 +- .../CRPipeline/UploadASoCTestResult.java | 156 +++++--- .../connect/CRPipeline/UploadBuild.java | 162 +++++--- .../connect/CRPipeline/UploadDeployment.java | 179 ++++++--- .../CRPipeline/UploadJUnitTestResult.java | 45 ++- .../connect/CRPipeline/UploadMetricsFile.java | 202 +++++++--- .../connect/CloudBuildStepListener.java | 35 +- .../com/hcl/devops/connect/CloudCause.java | 11 +- .../devops/connect/CloudGraphListener.java | 19 +- .../hcl/devops/connect/CloudItemListener.java | 49 +-- .../hcl/devops/connect/CloudPublisher.java | 260 ++++++++----- .../hcl/devops/connect/CloudRunListener.java | 64 ++-- .../devops/connect/CloudSocketComponent.java | 250 +++++++------ .../hcl/devops/connect/CloudWorkListener.java | 93 ++--- .../devops/connect/CloudWorkListener2.java | 106 +++--- .../connect/ConnectComputerListener.java | 48 +-- .../connect/DevOpsGlobalConfiguration.java | 125 ++----- .../connect/Endpoints/EndpointManager.java | 42 ++- .../Endpoints/EndpointsAccelerate.java | 56 +-- .../devops/connect/Endpoints/IEndpoints.java | 22 +- .../java/com/hcl/devops/connect/Entry.java | 213 +++++++++++ .../devops/connect/JenkinsIntegrationId.java | 12 +- .../com/hcl/devops/connect/JenkinsJob.java | 25 +- .../com/hcl/devops/connect/JenkinsServer.java | 347 +++++++++--------- .../hcl/devops/connect/ReconnectExecutor.java | 21 +- .../SecuredActions/AbstractSecuredAction.java | 27 +- .../connect/SecuredActions/TriggerJob.java | 5 +- .../connect/Status/AbstractJenkinsStatus.java | 65 ++-- .../hcl/devops/connect/Status/CrAction.java | 12 +- .../hcl/devops/connect/Status/DRAData.java | 18 +- .../connect/Status/JenkinsJobStatus.java | 13 +- .../connect/Status/JenkinsPipelineStatus.java | 27 +- .../hcl/devops/connect/Status/SourceData.java | 10 +- .../UploadASoCTestResult/config.jelly | 3 + .../help-instanceBaseUrl.html | 17 + .../CRPipeline/UploadBuild/config.jelly | 3 + .../UploadBuild/help-instanceBaseUrl.html | 17 + .../CRPipeline/UploadDeployment/config.jelly | 3 + .../help-instanceBaseUrl.html | 17 + .../CRPipeline/UploadMetricsFile/config.jelly | 3 + .../help-instanceBaseUrl.html | 17 + .../DevOpsGlobalConfiguration/config.jelly | 29 +- .../com/hcl/devops/connect/Entry/config.jelly | 36 ++ .../help-apiToken.html | 0 .../connect/Entry/help-checkDuplicate.html | 17 + .../help-rabbitMQHost.html | 0 .../help-rabbitMQPort.html | 0 .../help-syncId.html | 0 .../help-syncToken.html | 0 50 files changed, 1878 insertions(+), 1135 deletions(-) create mode 100644 src/main/java/com/hcl/devops/connect/Entry.java create mode 100644 src/main/resources/com/hcl/devops/connect/CRPipeline/UploadASoCTestResult/help-instanceBaseUrl.html create mode 100644 src/main/resources/com/hcl/devops/connect/CRPipeline/UploadBuild/help-instanceBaseUrl.html create mode 100644 src/main/resources/com/hcl/devops/connect/CRPipeline/UploadDeployment/help-instanceBaseUrl.html create mode 100644 src/main/resources/com/hcl/devops/connect/CRPipeline/UploadMetricsFile/help-instanceBaseUrl.html create mode 100644 src/main/resources/com/hcl/devops/connect/Entry/config.jelly rename src/main/resources/com/hcl/devops/connect/{DevOpsGlobalConfiguration => Entry}/help-apiToken.html (100%) create mode 100644 src/main/resources/com/hcl/devops/connect/Entry/help-checkDuplicate.html rename src/main/resources/com/hcl/devops/connect/{DevOpsGlobalConfiguration => Entry}/help-rabbitMQHost.html (100%) rename src/main/resources/com/hcl/devops/connect/{DevOpsGlobalConfiguration => Entry}/help-rabbitMQPort.html (100%) rename src/main/resources/com/hcl/devops/connect/{DevOpsGlobalConfiguration => Entry}/help-syncId.html (100%) rename src/main/resources/com/hcl/devops/connect/{DevOpsGlobalConfiguration => Entry}/help-syncToken.html (100%) diff --git a/src/main/java/com/hcl/devops/connect/CRPipeline/CheckGate.java b/src/main/java/com/hcl/devops/connect/CRPipeline/CheckGate.java index c45a58d..23ca2e8 100644 --- a/src/main/java/com/hcl/devops/connect/CRPipeline/CheckGate.java +++ b/src/main/java/com/hcl/devops/connect/CRPipeline/CheckGate.java @@ -27,6 +27,9 @@ import com.hcl.devops.connect.CloudPublisher; import com.hcl.devops.connect.DevOpsGlobalConfiguration; import com.hcl.devops.connect.Endpoints.EndpointManager; +import com.hcl.devops.connect.Entry; +import java.util.List; +import org.apache.commons.lang.StringUtils; import net.sf.json.JSONObject; @@ -45,32 +48,34 @@ public CheckGate( String pipelineId, String stageName, String versionId, - String fatal - ) { + String fatal) { this.pipelineId = pipelineId; this.stageName = stageName; this.versionId = versionId; this.fatal = fatal; } - public String getPipelineId() { return this.pipelineId; } - public String getStageName() { return this.stageName; } - public String getVersionId() { return this.versionId; } - public String getFatal() { return this.fatal; } + public String getPipelineId() { + return this.pipelineId; + } + public String getStageName() { + return this.stageName; + } + public String getVersionId() { + return this.versionId; + } + public String getFatal() { + return this.fatal; + } - private static String getPipelinesUrl() { + private static String getPipelinesUrl(Entry entry) { EndpointManager em = new EndpointManager(); - return em.getPipelinesEndpoint(); + return em.getPipelinesEndpoint(entry); } @Override public void perform(final Run build, FilePath workspace, Launcher launcher, final TaskListener listener) - throws AbortException, InterruptedException, IOException, RuntimeException { - if (!Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { - listener.getLogger().println("Could not check Accelerate gates as there is no configuration specified."); - return; - } - + throws AbortException, InterruptedException, IOException, RuntimeException { EnvVars envVars = build.getEnvironment(listener); String pipelineId = envVars.expand(this.pipelineId); @@ -78,47 +83,70 @@ public void perform(final Run build, FilePath workspace, Launcher launcher String versionId = envVars.expand(this.versionId); String fatal = envVars.expand(this.fatal); - listener.getLogger().println("Check gates on pipeline: " + CheckGate.getPipelinesUrl() + pipelineId); - listener.getLogger().println("Checking gate on stage \"" + stageName + "\" for version \"" + versionId + "\" in HCL Accelerate..."); - Boolean throwException = false; - try { - String result = CloudPublisher.checkGate(pipelineId, stageName, versionId); - JSONObject resultObj = JSONObject.fromObject(result); - if (resultObj.has("errors")) { - throw new RuntimeException(resultObj.get("errors").toString()); - } - Iterator keys = resultObj.keys(); - Boolean anyGateFailed = false; - while(keys.hasNext()) { - String key = keys.next().toString(); - String value = resultObj.get(key).toString(); - if (value.equals("true")) { - listener.getLogger().println("Gate \"" + key + "\" passed"); - } else if (value.equals("false")) { - listener.getLogger().println("Gate \"" + key + "\" failed"); - anyGateFailed = true; + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getEntries(); + Entry finalEntry = null; + for (Entry entry : entries) { + try { + if (CloudPublisher.isPipeline(entry, pipelineId)) { + finalEntry = entry; + break; } - } - if (anyGateFailed) { - if (fatal != null && fatal.equals("true")) { - throwException = true; + } catch (Exception e) { + listener.getLogger().println("Entry: " + entry); + listener.error("Error checking validity of pipelineId: " + e.getClass() + " - " + e.getMessage()); + throw new RuntimeException("Not able to validate pipelineId"); + } + } + if (finalEntry != null) { + listener.getLogger() + .println("Check gates on pipeline: " + CheckGate.getPipelinesUrl(finalEntry) + pipelineId); + listener.getLogger().println("Checking gate on stage \"" + stageName + "\" for version \"" + versionId + + "\" in HCL Accelerate (" + finalEntry.getBaseUrl() + ")."); + Boolean throwException = false; + String logString = finalEntry.getBaseUrl(); + try { + String result = CloudPublisher.checkGate(finalEntry, pipelineId, stageName, versionId); + JSONObject resultObj = JSONObject.fromObject(result); + if (resultObj.has("errors")) { + throw new RuntimeException(resultObj.get("errors").toString()); + } + Iterator keys = resultObj.keys(); + Boolean anyGateFailed = false; + while (keys.hasNext()) { + String key = keys.next().toString(); + String value = resultObj.get(key).toString(); + if (value.equals("true")) { + listener.getLogger().println("Gate \"" + key + "\" passed (" + logString + ")."); + } else if (value.equals("false")) { + listener.getLogger().println("Gate \"" + key + "\" failed (" + logString + ")."); + anyGateFailed = true; + } + } + if (anyGateFailed) { + if (fatal != null && fatal.equals("true")) { + throwException = true; + } + build.setResult(Result.FAILURE); + } else { + listener.getLogger().println("No gate failures, gates pass (" + logString + ")."); + } + } catch (Exception ex) { + listener.error("Error checking gate (" + logString + "): " + ex.getClass() + " - " + ex.getMessage()); + listener.error("Stack trace (" + logString + "): "); + StackTraceElement[] elements = ex.getStackTrace(); + for (int i = 0; i < elements.length; i++) { + StackTraceElement s = elements[i]; + listener.error("\tat " + s.getClassName() + "." + s.getMethodName() + "(" + s.getFileName() + ":" + + s.getLineNumber() + ")"); } build.setResult(Result.FAILURE); - } else { - listener.getLogger().println("No gate failures, gates pass."); - } - } catch (Exception ex) { - listener.error("Error checking gate: " + ex.getClass() + " - " + ex.getMessage()); - listener.error("Stack trace:"); - StackTraceElement[] elements = ex.getStackTrace(); - for (int i = 0; i < elements.length; i++) { - StackTraceElement s = elements[i]; - listener.error("\tat " + s.getClassName() + "." + s.getMethodName() + "(" + s.getFileName() + ":" + s.getLineNumber() + ")"); } - build.setResult(Result.FAILURE); - } - if (throwException) { - throw new RuntimeException("Gate failure and fatal set to \"true\", exception thrown to stop build."); + if (throwException) { + throw new RuntimeException( + "Gate failure and fatal set to \"true\", exception thrown to stop build (" + logString + ")."); + } + } else { + throw new RuntimeException("Invalid pipelineId"); } } diff --git a/src/main/java/com/hcl/devops/connect/CRPipeline/ContinuousReleaseProperties.java b/src/main/java/com/hcl/devops/connect/CRPipeline/ContinuousReleaseProperties.java index d3c6d6c..36f1e87 100644 --- a/src/main/java/com/hcl/devops/connect/CRPipeline/ContinuousReleaseProperties.java +++ b/src/main/java/com/hcl/devops/connect/CRPipeline/ContinuousReleaseProperties.java @@ -61,7 +61,7 @@ public void perform(final Run build, FilePath workspace, Launcher launcher throws AbortException, InterruptedException, IOException { CrAction action = build.getAction(CrAction.class); - if(action == null) { + if (action == null) { action = new CrAction(); build.addAction(action); } diff --git a/src/main/java/com/hcl/devops/connect/CRPipeline/UploadASoCTestResult.java b/src/main/java/com/hcl/devops/connect/CRPipeline/UploadASoCTestResult.java index 37dc291..b5eb433 100644 --- a/src/main/java/com/hcl/devops/connect/CRPipeline/UploadASoCTestResult.java +++ b/src/main/java/com/hcl/devops/connect/CRPipeline/UploadASoCTestResult.java @@ -28,6 +28,12 @@ import com.hcl.devops.connect.CloudPublisher; import com.hcl.devops.connect.DevOpsGlobalConfiguration; +import com.hcl.devops.connect.Entry; +import java.util.List; +import org.apache.commons.lang.StringUtils; +import hudson.util.ListBoxModel; +import org.kohsuke.stapler.QueryParameter; +import java.util.ArrayList; import java.lang.reflect.InvocationTargetException; @@ -49,6 +55,7 @@ public class UploadASoCTestResult extends Notifier { private String metricDefinition; private String recordName; private String commitId; + private String instanceBaseUrl; @DataBoundConstructor public UploadASoCTestResult( @@ -60,8 +67,8 @@ public UploadASoCTestResult( String buildUrl, String metricDefinition, String recordName, - String commitId - ) { + String commitId, + String instanceBaseUrl) { this.tenantId = tenantId; this.environment = environment; this.appId = appId; @@ -71,17 +78,39 @@ public UploadASoCTestResult( this.metricDefinition = metricDefinition; this.recordName = recordName; this.commitId = commitId; + this.instanceBaseUrl = instanceBaseUrl; } - public String getTenantId() { return tenantId; } - public String getEnvironment() { return environment; } - public String getAppId() { return appId; } - public String getAppExtId() { return appExtId; } - public String getAppName() { return appName; } - public String getBuildUrl() { return buildUrl; } - public String getMetricDefinition() { return metricDefinition; } - public String getRecordName() { return recordName; } - public String getCommitId() { return commitId; } + public String getTenantId() { + return tenantId; + } + public String getEnvironment() { + return environment; + } + public String getAppId() { + return appId; + } + public String getAppExtId() { + return appExtId; + } + public String getAppName() { + return appName; + } + public String getBuildUrl() { + return buildUrl; + } + public String getMetricDefinition() { + return metricDefinition; + } + public String getRecordName() { + return recordName; + } + public String getCommitId() { + return commitId; + } + public String getInstanceBaseUrl() { + return this.instanceBaseUrl; + } @Override public BuildStepMonitor getRequiredMonitorService() { @@ -94,11 +123,6 @@ public BuildStepMonitor getRequiredMonitorService() { public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws AbortException, InterruptedException, IOException { - if (!Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { - listener.getLogger().println("Could not upload ASoC results to Accelerate as there is no configuration specified."); - return false; - } - EnvVars envVars = build.getEnvironment(listener); // Resolving all passed ${VARIABLES} String tenantIdValue = envVars.expand(this.tenantId); @@ -109,29 +133,37 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen String buildUrlValue = envVars.expand(this.buildUrl); String metricDefinitionValue = envVars.expand(this.metricDefinition); String recordNameValue = envVars.expand(this.recordName); + String instanceBaseUrl = envVars.expand(this.instanceBaseUrl == null ? "" : this.instanceBaseUrl.toString()); + + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getEntries(); + List finalEntriesList = CloudPublisher.getFinalEntriesList("Upload ASoC Test Result", instanceBaseUrl, + entries); - Job parentJob = (Job)build.getParent(); + Job parentJob = (Job) build.getParent(); Run thisBuild = parentJob.getBuildByNumber(build.getNumber()); List actions = thisBuild.getActions(); Class scanResultClass = null; Action actualAction = null; - for(Action action : actions) { + for (Action action : actions) { listener.getLogger().println(action.getClass().getName()); - if(action.getClass().getName().equals("com.ibm.appscan.jenkins.plugin.actions.ResultsRetriever")) { + if (action.getClass().getName().equals("com.ibm.appscan.jenkins.plugin.actions.ResultsRetriever")) { Class retrieverClass = action.getClass(); Action retrieverAction = action; - try { + try { listener.getLogger().println("[HCL Accelerate] Triggering loading of ASoC Results"); Method checkResults = retrieverClass.getDeclaredMethod("checkResults", Run.class); checkResults.invoke(retrieverAction, build); } catch (NoSuchMethodException e1) { - listener.getLogger().println("Could not find method on the ScanResult Object. Is this running the proper version of AppScan on Cloud plugin?"); + listener.getLogger().println( + "Could not find method on the ScanResult Object. Is this running the proper version of AppScan on Cloud plugin?"); } catch (IllegalAccessException e2) { - listener.getLogger().println("Could not acces the method on the ScanResult Object. Is this running the proper version of AppScan on Cloud plugin?"); + listener.getLogger().println( + "Could not acces the method on the ScanResult Object. Is this running the proper version of AppScan on Cloud plugin?"); } catch (InvocationTargetException e3) { - listener.getLogger().println("Could not invoke the target on the ScanResult Object. Is this running the proper version of AppScan on Cloud plugin?"); + listener.getLogger().println( + "Could not invoke the target on the ScanResult Object. Is this running the proper version of AppScan on Cloud plugin?"); } } } @@ -140,15 +172,17 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen List actualBuildActions = build.getActions(); // actualAction = actualBuild.getAction(Class.forName("com.ibm.appscan.jenkins.plugin.actions.ScanResults").asSubclass(Actionable.class)); - for(Action act : actualBuildActions) { + for (Action act : actualBuildActions) { + // actualAction = + // actualBuild.getAction(Class.forName("com.ibm.appscan.jenkins.plugin.actions.ScanResults").asSubclass(Actionable.class)); listener.getLogger().println("---->" + act.getClass().getName()); - if(act.getClass().getName().equals("com.ibm.appscan.jenkins.plugin.actions.ScanResults")) { + if (act.getClass().getName().equals("com.ibm.appscan.jenkins.plugin.actions.ScanResults")) { scanResultClass = act.getClass(); actualAction = act; } } - if(actualAction != null) { + if (actualAction != null) { listener.getLogger().println("We have found the Scan Results from AppScan"); try { @@ -159,16 +193,18 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen Method getMediumCountMethod = scanResultClass.getDeclaredMethod("getMediumCount"); Method getHighCountMethod = scanResultClass.getDeclaredMethod("getHighCount"); - int totalFindings = (int)getTotalFindingsMethod.invoke(actualAction); - int lowFindings = (int)getLowCountMethod.invoke(actualAction); - int mediumFindings = (int)getMediumCountMethod.invoke(actualAction); - int highFindings = (int)getHighCountMethod.invoke(actualAction); - int infoFindings = (int)getInfoCountMethod.invoke(actualAction); - - // The ASoC plugin has a bug where the info count is 0. That is not accurate, so we adjust - if(infoFindings == 0 && totalFindings != (lowFindings + mediumFindings + highFindings + infoFindings)) { - infoFindings = totalFindings - (lowFindings + mediumFindings + highFindings); - } + int totalFindings = (int) getTotalFindingsMethod.invoke(actualAction); + int lowFindings = (int) getLowCountMethod.invoke(actualAction); + int mediumFindings = (int) getMediumCountMethod.invoke(actualAction); + int highFindings = (int) getHighCountMethod.invoke(actualAction); + int infoFindings = (int) getInfoCountMethod.invoke(actualAction); + + // The ASoC plugin has a bug where the info count is 0. That is not accurate, so + // we adjust + if (infoFindings == 0 + && totalFindings != (lowFindings + mediumFindings + highFindings + infoFindings)) { + infoFindings = totalFindings - (lowFindings + mediumFindings + highFindings); + } listener.getLogger().println("Total ----> " + totalFindings); listener.getLogger().println("info ----> " + infoFindings); @@ -207,21 +243,33 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen payload.put("build", buildObj); listener.getLogger().println("Payload Doc To Upload: " + payload.toString()); - listener.getLogger().println("Uploading Payload Doc"); - try { - CloudPublisher.uploadQualityDataRaw(payload.toString()); - listener.getLogger().println("Upload Complete"); - } catch (Exception ex) { - listener.error("Error uploading ASoC data: " + ex.getClass() + " - " + ex.getMessage()); - build.setResult(Result.FAILURE); + for (Entry entry : finalEntriesList) { + String logString = entry.getBaseUrl(); + listener.getLogger().println("Uploading Payload Doc (" + logString + ")."); + try { + if (!entry.isConfigured()) { + listener.getLogger().println( + "Could not upload builds to Accelerate as there is no configuration specified."); + return false; + } + CloudPublisher.uploadQualityDataRaw(entry, payload.toString()); + listener.getLogger().println("Upload Complete (" + logString + ")."); + } catch (Exception ex) { + listener.error("Error uploading ASoC data (" + logString + "): " + ex.getClass() + " - " + + ex.getMessage()); + build.setResult(Result.FAILURE); + } } } catch (NoSuchMethodException e1) { - listener.getLogger().println("Could not find method on the ScanResult Object. Is this running the proper version of AppScan on Cloud plugin?"); + listener.getLogger().println( + "Could not find method on the ScanResult Object. Is this running the proper version of AppScan on Cloud plugin?"); } catch (IllegalAccessException e2) { - listener.getLogger().println("Could not acces the method on the ScanResult Object. Is this running the proper version of AppScan on Cloud plugin?"); + listener.getLogger().println( + "Could not acces the method on the ScanResult Object. Is this running the proper version of AppScan on Cloud plugin?"); } catch (InvocationTargetException e3) { - listener.getLogger().println("Could not invoke the target on the ScanResult Object. Is this running the proper version of AppScan on Cloud plugin?"); + listener.getLogger().println( + "Could not invoke the target on the ScanResult Object. Is this running the proper version of AppScan on Cloud plugin?"); } } return true; @@ -256,5 +304,21 @@ public boolean isApplicable(Class jobType) { // This is not meant for public use in its current form. return false; } + + @SuppressWarnings("unused") + public ListBoxModel doFillInstanceBaseUrlItems(@QueryParameter String currentInstanceBaseUrl) { + // Create ListBoxModel from all projects for this AWS Device Farm account. + List baseUrls = new ArrayList(); + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class) + .getEntries(); + String all = "Upload ASoC Test Result to All HCL Accelerate Instances"; + baseUrls.add(new ListBoxModel.Option(all, all, all.equals(currentInstanceBaseUrl))); + for (Entry entry : entries) { + // We don't ignore case because these *should* be unique. + baseUrls.add(new ListBoxModel.Option(entry.getBaseUrl(), entry.getBaseUrl(), + entry.getBaseUrl().equals(currentInstanceBaseUrl))); + } + return new ListBoxModel(baseUrls); + } } } diff --git a/src/main/java/com/hcl/devops/connect/CRPipeline/UploadBuild.java b/src/main/java/com/hcl/devops/connect/CRPipeline/UploadBuild.java index af3bc4d..f4039f7 100644 --- a/src/main/java/com/hcl/devops/connect/CRPipeline/UploadBuild.java +++ b/src/main/java/com/hcl/devops/connect/CRPipeline/UploadBuild.java @@ -29,6 +29,12 @@ import com.hcl.devops.connect.CloudPublisher; import com.hcl.devops.connect.DevOpsGlobalConfiguration; +import com.hcl.devops.connect.Entry; +import java.util.List; +import org.apache.commons.lang.StringUtils; +import hudson.util.ListBoxModel; +import org.kohsuke.stapler.QueryParameter; +import java.util.ArrayList; import net.sf.json.JSONObject; @@ -51,6 +57,7 @@ public class UploadBuild extends Builder implements SimpleBuildStep { private String appExtId; private Boolean debug; private Boolean fatal; + private String instanceBaseUrl; @DataBoundConstructor public UploadBuild( @@ -67,8 +74,8 @@ public UploadBuild( String appId, String appExtId, Boolean debug, - Boolean fatal - ) { + Boolean fatal, + String instanceBaseUrl) { this.tenantId = tenantId; this.id = id; this.name = name; @@ -83,30 +90,58 @@ public UploadBuild( this.appExtId = appExtId; this.debug = debug; this.fatal = fatal; + this.instanceBaseUrl = instanceBaseUrl; } - public String getId() { return this.id; } - public String getName() {return this.name; } - public String getVersionName() {return this.versionName; } - public String getTenantId() { return this.tenantId; } - public String getRevision() { return this.revision; } - public String getRequestor() { return this.requestor; } - public String getStatus() { return this.status; } - public String getStartTime() { return this.startTime; } - public String getEndTime() { return this.endTime; } - public String getAppName() { return this.appName; } - public String getAppId() { return this.appId; } - public String getAppExtId() { return this.appExtId; } - public Boolean getDebug() { return this.debug; } - public Boolean getFatal() { return this.fatal; } + public String getId() { + return this.id; + } + public String getName() { + return this.name; + } + public String getVersionName() { + return this.versionName; + } + public String getTenantId() { + return this.tenantId; + } + public String getRevision() { + return this.revision; + } + public String getRequestor() { + return this.requestor; + } + public String getStatus() { + return this.status; + } + public String getStartTime() { + return this.startTime; + } + public String getEndTime() { + return this.endTime; + } + public String getAppName() { + return this.appName; + } + public String getAppId() { + return this.appId; + } + public String getAppExtId() { + return this.appExtId; + } + public Boolean getDebug() { + return this.debug; + } + public Boolean getFatal() { + return this.fatal; + } + public String getInstanceBaseUrl() { + return this.instanceBaseUrl; + } @Override public void perform(final Run build, FilePath workspace, Launcher launcher, final TaskListener listener) throws AbortException, InterruptedException, IOException { - if (!Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { - listener.getLogger().println("Could not upload builds to Accelerate as there is no configuration specified."); - return; - } EnvVars envVars = build.getEnvironment(listener); @@ -124,6 +159,10 @@ public void perform(final Run build, FilePath workspace, Launcher launcher String appExtId = envVars.expand(this.appExtId); String debug = envVars.expand(this.debug == null ? "" : this.debug.toString()); String fatal = envVars.expand(this.fatal == null ? "" : this.fatal.toString()); + String instanceBaseUrl = envVars.expand(this.instanceBaseUrl == null ? "" : this.instanceBaseUrl.toString()); + + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getEntries(); + List finalEntriesList = CloudPublisher.getFinalEntriesList("Upload Build", instanceBaseUrl, entries); JSONObject payload = new JSONObject(); @@ -151,13 +190,14 @@ public void perform(final Run build, FilePath workspace, Launcher launcher } else { for (Cause cause : build.getCauses()) { if (cause instanceof UserIdCause) { - UserIdCause userCause = (UserIdCause)cause; + UserIdCause userCause = (UserIdCause) cause; payload.put("requestor", userCause.getUserName()); } else if (cause instanceof UpstreamCause) { - UpstreamCause upstreamCause = (UpstreamCause)cause; - payload.put("requestor", "Upstream job \"" + upstreamCause.getUpstreamProject() + "\", build \"" + upstreamCause.getUpstreamBuild() + "\""); + UpstreamCause upstreamCause = (UpstreamCause) cause; + payload.put("requestor", "Upstream job \"" + upstreamCause.getUpstreamProject() + "\", build \"" + + upstreamCause.getUpstreamBuild() + "\""); } else if (cause instanceof RemoteCause) { - RemoteCause remoteCause = (RemoteCause)cause; + RemoteCause remoteCause = (RemoteCause) cause; payload.put("requestor", remoteCause.getAddr()); } else { payload.put("requestor", cause.getShortDescription()); @@ -165,7 +205,7 @@ public void perform(final Run build, FilePath workspace, Launcher launcher } } if (status != null && !status.equals("")) { - payload.put("status", status); + payload.put("status", status); } else { String computedStatus = "failure"; Result buildResult = build.getResult(); @@ -206,34 +246,47 @@ public void perform(final Run build, FilePath workspace, Launcher launcher if (debug.equals("true")) { listener.getLogger().println("payload: " + payload.toString()); } - - listener.getLogger().println("Uploading build \"" + payload.get("id") + "\" to HCL Accelerate..."); - try { - String response = CloudPublisher.uploadBuild(payload.toString()); - JSONObject json = JSONObject.fromObject(response); - if (json.isEmpty() || !json.has("_id") || json.get("_id").equals("")) { - throw new RuntimeException("Did not receive successful response: " + response); - } - listener.getLogger().println("Successfully uploaded build to HCL Accelerate."); - } catch (Exception ex) { - listener.error("Error uploading build data: " + ex.getClass() + " - " + ex.getMessage()); - if (fatal.equals("true")) { - if (debug.equals("true")) { - listener.getLogger().println("Failing build due to fatal=true."); + for (Entry entry : finalEntriesList) { + String logString = entry.getBaseUrl(); + listener.getLogger().println( + "Uploading build \"" + payload.get("id") + "\" to HCL Accelerate (" + logString + ")."); + try { + if (!entry.isConfigured()) { + listener.getLogger() + .println("Could not upload builds to Accelerate as there is no configuration specified."); + return; } - build.setResult(Result.FAILURE); - } else if (fatal.equals("false")) { - if (debug.equals("true")) { - listener.getLogger().println("Not changing build result due to fatal=false."); + String response = CloudPublisher.uploadBuild(payload.toString(), entry); + JSONObject json = JSONObject.fromObject(response); + if (json.isEmpty() || !json.has("_id") || json.get("_id").equals("")) { + throw new RuntimeException("Did not receive successful response (" + logString + "): " + response); } - } else { - if (debug.equals("true")) { - listener.getLogger().println("Marking build as unstable due to fatal flag not set."); + listener.getLogger().println("Successfully uploaded build to HCL Accelerate (" + logString + ")."); + } catch (Exception ex) { + listener.error( + "Error uploading build data (" + logString + "): " + ex.getClass() + " - " + ex.getMessage()); + if (fatal.equals("true")) { + if (debug.equals("true")) { + listener.getLogger().println("Failing build due to fatal=true (" + logString + ")."); + } + build.setResult(Result.FAILURE); + } else if (fatal.equals("false")) { + if (debug.equals("true")) { + listener.getLogger() + .println("Not changing build result due to fatal=false (" + logString + ")."); + } + } else { + if (debug.equals("true")) { + listener.getLogger() + .println("Marking build as unstable due to fatal flag not set (" + logString + ")."); + } + build.setResult(Result.UNSTABLE); } - build.setResult(Result.UNSTABLE); } } } + + @Extension public static class UploadBuildDescriptor extends BuildStepDescriptor { @@ -263,5 +316,20 @@ public String getDisplayName() { public boolean isApplicable(Class jobType) { return true; } + + public ListBoxModel doFillInstanceBaseUrlItems(@QueryParameter String currentInstanceBaseUrl) { + // Create ListBoxModel from all projects for this AWS Device Farm account. + List baseUrls = new ArrayList(); + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class) + .getEntries(); + String all = "Upload Build to All HCL Accelerate Instances"; + baseUrls.add(new ListBoxModel.Option(all, all, all.equals(currentInstanceBaseUrl))); + for (Entry entry : entries) { + // We don't ignore case because these *should* be unique. + baseUrls.add(new ListBoxModel.Option(entry.getBaseUrl(), entry.getBaseUrl(), + entry.getBaseUrl().equals(currentInstanceBaseUrl))); + } + return new ListBoxModel(baseUrls); + } } } diff --git a/src/main/java/com/hcl/devops/connect/CRPipeline/UploadDeployment.java b/src/main/java/com/hcl/devops/connect/CRPipeline/UploadDeployment.java index 2e63eaa..f55db14 100644 --- a/src/main/java/com/hcl/devops/connect/CRPipeline/UploadDeployment.java +++ b/src/main/java/com/hcl/devops/connect/CRPipeline/UploadDeployment.java @@ -29,6 +29,12 @@ import com.hcl.devops.connect.CloudPublisher; import com.hcl.devops.connect.DevOpsGlobalConfiguration; +import com.hcl.devops.connect.Entry; +import java.util.List; +import org.apache.commons.lang.StringUtils; +import hudson.util.ListBoxModel; +import org.kohsuke.stapler.QueryParameter; +import java.util.ArrayList; import net.sf.json.JSONObject; @@ -55,6 +61,7 @@ public class UploadDeployment extends Builder implements SimpleBuildStep { private String appExtId; private Boolean debug; private Boolean fatal; + private String instanceBaseUrl; @DataBoundConstructor public UploadDeployment( @@ -75,8 +82,8 @@ public UploadDeployment( String appId, String appExtId, Boolean debug, - Boolean fatal - ) { + Boolean fatal, + String instanceBaseUrl) { this.id = id; this.tenantId = tenantId; this.name = name; @@ -95,34 +102,70 @@ public UploadDeployment( this.appExtId = appExtId; this.debug = debug; this.fatal = fatal; + this.instanceBaseUrl = instanceBaseUrl; } - public String getId() { return this.id; } - public String getTenantId() { return this.tenantId; } - public String getName() { return this.name; } - public String getResult() { return this.result; } - public String getInitiator() { return this.initiator; } - public String getVersionName() { return this.versionName; } - public String getVersionExtId() { return this.versionExtId; } - public String getType() { return this.type; } - public String getEnvironmentId() { return this.environmentId; } - public String getEnvironmentName() { return this.environmentName; } - public String getDescription() { return this.description; } - public String getStartTime() { return this.startTime; } - public String getEndTime() { return this.endTime; } - public String getAppName() { return this.appName; } - public String getAppId() { return this.appId; } - public String getAppExtId() { return this.appExtId; } - public Boolean getDebug() { return this.debug; } - public Boolean getFatal() { return this.fatal; } + public String getId() { + return this.id; + } + public String getTenantId() { + return this.tenantId; + } + public String getName() { + return this.name; + } + public String getResult() { + return this.result; + } + public String getInitiator() { + return this.initiator; + } + public String getVersionName() { + return this.versionName; + } + public String getVersionExtId() { + return this.versionExtId; + } + public String getType() { + return this.type; + } + public String getEnvironmentId() { + return this.environmentId; + } + public String getEnvironmentName() { + return this.environmentName; + } + public String getDescription() { + return this.description; + } + public String getStartTime() { + return this.startTime; + } + public String getEndTime() { + return this.endTime; + } + public String getAppName() { + return this.appName; + } + public String getAppId() { + return this.appId; + } + public String getAppExtId() { + return this.appExtId; + } + public Boolean getDebug() { + return this.debug; + } + public Boolean getFatal() { + return this.fatal; + } + public String getInstanceBaseUrl() { + return this.instanceBaseUrl; + } @Override public void perform(final Run build, FilePath workspace, Launcher launcher, final TaskListener listener) throws AbortException, InterruptedException, IOException { - if (!Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { - listener.getLogger().println("Could not upload deployments to Accelerate as there is no configuration specified."); - return; - } EnvVars envVars = build.getEnvironment(listener); @@ -144,6 +187,12 @@ public void perform(final Run build, FilePath workspace, Launcher launcher String endTime = envVars.expand(this.endTime); String debug = envVars.expand(this.debug == null ? "" : this.debug.toString()); String fatal = envVars.expand(this.fatal == null ? "" : this.fatal.toString()); + String instanceBaseUrl = envVars.expand(this.instanceBaseUrl == null ? "" : this.instanceBaseUrl.toString()); + + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getEntries(); + List finalEntriesList = CloudPublisher.getFinalEntriesList("Upload Deployment", instanceBaseUrl, + entries); + JSONObject payload = new JSONObject(); @@ -192,13 +241,14 @@ public void perform(final Run build, FilePath workspace, Launcher launcher } else { for (Cause cause : build.getCauses()) { if (cause instanceof UserIdCause) { - UserIdCause userCause = (UserIdCause)cause; + UserIdCause userCause = (UserIdCause) cause; payload.put("by_user", userCause.getUserName()); } else if (cause instanceof UpstreamCause) { - UpstreamCause upstreamCause = (UpstreamCause)cause; - payload.put("by_user", "Upstream job \"" + upstreamCause.getUpstreamProject() + "\", build \"" + upstreamCause.getUpstreamBuild() + "\""); + UpstreamCause upstreamCause = (UpstreamCause) cause; + payload.put("by_user", "Upstream job \"" + upstreamCause.getUpstreamProject() + "\", build \"" + + upstreamCause.getUpstreamBuild() + "\""); } else if (cause instanceof RemoteCause) { - RemoteCause remoteCause = (RemoteCause)cause; + RemoteCause remoteCause = (RemoteCause) cause; payload.put("requestor", remoteCause.getAddr()); } else { payload.put("requestor", cause.getShortDescription()); @@ -235,31 +285,44 @@ public void perform(final Run build, FilePath workspace, Launcher launcher listener.getLogger().println("payload: " + payload.toString()); } - listener.getLogger().println("Uploading deployment \"" + payload.get("version_name") + "\" of \"" + payload.get("name") + "\" to HCL Accelerate..."); - try { - String response = CloudPublisher.uploadDeployment(payload.toString()); - System.out.println("TEST response: " + response); - JSONObject json = JSONObject.fromObject(response); - if (json.isEmpty() || !json.has("_id") || json.get("_id").equals("")) { - throw new RuntimeException("Did not receive successful response: " + response); - } - listener.getLogger().println("Successfully uploaded deployment to HCL Accelerate."); - } catch (Exception ex) { - listener.error("Error uploading deployment data: " + ex.getClass() + " - " + ex.getMessage()); - if (fatal.equals("true")) { - if (debug.equals("true")) { - listener.getLogger().println("Failing build due to fatal=true."); + for (Entry entry : finalEntriesList) { + String logString = entry.getBaseUrl(); + listener.getLogger().println("Uploading deployment \"" + payload.get("version_name") + "\" of \"" + + payload.get("name") + "\" to HCL Accelerate (" + entry.getBaseUrl() + ")."); + try { + if (!entry.isConfigured()) { + listener.getLogger().println( + "Could not upload deployments to Accelerate as there is no configuration specified."); + return; } - build.setResult(Result.FAILURE); - } else if (fatal.equals("false")) { - if (debug.equals("true")) { - listener.getLogger().println("Not changing build result due to fatal=false."); + String response = CloudPublisher.uploadDeployment(payload.toString(), entry); + System.out.println("TEST response: " + response); + JSONObject json = JSONObject.fromObject(response); + if (json.isEmpty() || !json.has("_id") || json.get("_id").equals("")) { + throw new RuntimeException("Did not receive successful response (" + logString + "): " + response); } - } else { - if (debug.equals("true")) { - listener.getLogger().println("Marking build as unstable due to fatal flag not set."); + listener.getLogger() + .println("Successfully uploaded deployment to HCL Accelerate (" + logString + ")."); + } catch (Exception ex) { + listener.error("Error uploading deployment data (" + logString + "): " + ex.getClass() + " - " + + ex.getMessage()); + if (fatal.equals("true")) { + if (debug.equals("true")) { + listener.getLogger().println("Failing build due to fatal=true (" + logString + ")."); + } + build.setResult(Result.FAILURE); + } else if (fatal.equals("false")) { + if (debug.equals("true")) { + listener.getLogger() + .println("Not changing build result due to fatal=false (" + logString + ")."); + } + } else { + if (debug.equals("true")) { + listener.getLogger() + .println("Marking build as unstable due to fatal flag not set (" + logString + ")."); + } + build.setResult(Result.UNSTABLE); } - build.setResult(Result.UNSTABLE); } } } @@ -292,5 +355,21 @@ public String getDisplayName() { public boolean isApplicable(Class jobType) { return true; } + + @SuppressWarnings("unused") + public ListBoxModel doFillInstanceBaseUrlItems(@QueryParameter String currentInstanceBaseUrl) { + // Create ListBoxModel from all projects for this AWS Device Farm account. + List baseUrls = new ArrayList(); + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class) + .getEntries(); + String all = "Upload Deployment to All HCL Accelerate Instances"; + baseUrls.add(new ListBoxModel.Option(all, all, all.equals(currentInstanceBaseUrl))); + for (Entry entry : entries) { + // We don't ignore case because these *should* be unique. + baseUrls.add(new ListBoxModel.Option(entry.getBaseUrl(), entry.getBaseUrl(), + entry.getBaseUrl().equals(currentInstanceBaseUrl))); + } + return new ListBoxModel(baseUrls); + } } } diff --git a/src/main/java/com/hcl/devops/connect/CRPipeline/UploadJUnitTestResult.java b/src/main/java/com/hcl/devops/connect/CRPipeline/UploadJUnitTestResult.java index a0bb1f8..f9b3955 100644 --- a/src/main/java/com/hcl/devops/connect/CRPipeline/UploadJUnitTestResult.java +++ b/src/main/java/com/hcl/devops/connect/CRPipeline/UploadJUnitTestResult.java @@ -35,6 +35,8 @@ import com.hcl.devops.connect.CloudPublisher; import com.hcl.devops.connect.DevOpsGlobalConfiguration; +import com.hcl.devops.connect.Entry; +import java.util.List; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.HttpEntity; @@ -56,21 +58,24 @@ public Map getProperties() { @Override public void perform(final Run build, FilePath workspace, Launcher launcher, final TaskListener listener) throws AbortException, InterruptedException, IOException { - if (!Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { - listener.getLogger().println("Could not upload junit tests to Accelerate as there is no configuration specified."); - return; - } - + Object fatalFailure = this.properties.get("fatal"); String buildUrl = Jenkins.getInstance().getRootUrl() + build.getUrl(); - String userAccessKey = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getApiToken(); - - boolean success = workspace.act(new FileUploader(this.properties, listener, buildUrl, CloudPublisher.getQualityDataUrl(), userAccessKey)); - if (!success) { - if (fatalFailure != null && fatalFailure.toString().equals("true")) { - build.setResult(Result.FAILURE); - } else { - build.setResult(Result.UNSTABLE); + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getEntries(); + for (Entry entry : entries) { + if (!entry.isConfigured()) { + listener.getLogger() + .println("Could not upload junit tests to Accelerate as there is no configuration specified."); + return; + } + boolean success = workspace.act(new FileUploader(this.properties, listener, buildUrl, + CloudPublisher.getQualityDataUrl(entry), entry.getApiToken(), entry.getBaseUrl())); + if (!success) { + if (fatalFailure != null && fatalFailure.toString().equals("true")) { + build.setResult(Result.FAILURE); + } else { + build.setResult(Result.UNSTABLE); + } } } } @@ -111,16 +116,20 @@ private static final class FileUploader implements FileCallable { private String buildUrl; private String postUrl; private String userAccessKey; + private String baseUrl; - public FileUploader(Map properties, TaskListener listener, String buildUrl, String postUrl, String userAccessKey) { + public FileUploader(Map properties, TaskListener listener, String buildUrl, String postUrl, + String userAccessKey, String baseUrl) { this.properties = properties; this.listener = listener; this.buildUrl = buildUrl; this.postUrl = postUrl; this.userAccessKey = userAccessKey; + this.baseUrl = baseUrl; } - @Override public Boolean invoke(File f, VirtualChannel channel) { + @Override + public Boolean invoke(File f, VirtualChannel channel) { listener.getLogger().println("Uploading JUnit File"); String filePath = properties.get("filePath"); @@ -173,14 +182,16 @@ public FileUploader(Map properties, TaskListener listener, Strin HttpEntity entity = MultipartEntityBuilder .create() .addTextBody("payload", payload.toString()) - .addBinaryBody("file", new File(f, filePath), ContentType.create("application/octet-stream"), "filename") + .addBinaryBody("file", new File(f, filePath), ContentType.create("application/octet-stream"), + "filename") .build(); + boolean success = false; try { success = CloudPublisher.uploadQualityData(entity, postUrl, userAccessKey); } catch (Exception ex) { - listener.error("Error uploading quality data: " + ex.getClass() + " - " + ex.getMessage()); + listener.error("Error uploading quality data (" + baseUrl + "): " + ex.getClass() + " - " + ex.getMessage()); } return success; } diff --git a/src/main/java/com/hcl/devops/connect/CRPipeline/UploadMetricsFile.java b/src/main/java/com/hcl/devops/connect/CRPipeline/UploadMetricsFile.java index db6f355..6783146 100644 --- a/src/main/java/com/hcl/devops/connect/CRPipeline/UploadMetricsFile.java +++ b/src/main/java/com/hcl/devops/connect/CRPipeline/UploadMetricsFile.java @@ -29,6 +29,11 @@ import com.hcl.devops.connect.CloudPublisher; import com.hcl.devops.connect.DevOpsGlobalConfiguration; +import com.hcl.devops.connect.Entry; +import java.util.List; +import hudson.util.ListBoxModel; +import org.kohsuke.stapler.QueryParameter; +import java.util.ArrayList; import net.sf.json.JSONObject; @@ -62,6 +67,7 @@ public class UploadMetricsFile extends Builder implements SimpleBuildStep { private String appId; private String appName; private String appExtId; + private String instanceBaseUrl; @DataBoundConstructor public UploadMetricsFile( @@ -84,8 +90,8 @@ public UploadMetricsFile( String buildUrl, String appId, String appName, - String appExtId - ) { + String appExtId, + String instanceBaseUrl) { this.tenantId = tenantId; this.name = name; this.filePath = filePath; @@ -106,37 +112,76 @@ public UploadMetricsFile( this.appId = appId; this.appName = appName; this.appExtId = appExtId; + this.instanceBaseUrl = instanceBaseUrl; } - public String getTenantId() { return this.tenantId; } - public String getName() { return this.name; } - public String getFilePath() { return this.filePath; } - public String getTestSetName() { return this.testSetName; } - public String getEnvironment() { return this.environment; } - public Boolean getCombineTestSuites() { return this.combineTestSuites; } - public Boolean getFatal() { return this.fatal; } - public Boolean getDebug() { return this.debug; } - public String getPluginType() { return this.pluginType; } - public String getDataFormat() { return this.dataFormat; } - public String getRecordName() { return this.recordName; } - public String getMetricDefinitionId() { return this.metricDefinitionId; } - public String getMetricsRecordUrl() { return this.metricsRecordUrl; } - public String getDescription() { return this.description; } - public String getExecutionDate() { return this.executionDate; } - public String getBuildId() { return this.buildId; } - public String getBuildUrl() { return this.buildUrl; } - public String getAppId() { return this.appId; } - public String getAppName() { return this.appName; } - public String getAppExtId() { return this.appExtId; } + public String getTenantId() { + return this.tenantId; + } + public String getName() { + return this.name; + } + public String getFilePath() { + return this.filePath; + } + public String getTestSetName() { + return this.testSetName; + } + public String getEnvironment() { + return this.environment; + } + public Boolean getCombineTestSuites() { + return this.combineTestSuites; + } + public Boolean getFatal() { + return this.fatal; + } + public Boolean getDebug() { + return this.debug; + } + public String getPluginType() { + return this.pluginType; + } + public String getDataFormat() { + return this.dataFormat; + } + public String getRecordName() { + return this.recordName; + } + public String getMetricDefinitionId() { + return this.metricDefinitionId; + } + public String getMetricsRecordUrl() { + return this.metricsRecordUrl; + } + public String getDescription() { + return this.description; + } + public String getExecutionDate() { + return this.executionDate; + } + public String getBuildId() { + return this.buildId; + } + public String getBuildUrl() { + return this.buildUrl; + } + public String getAppId() { + return this.appId; + } + public String getAppName() { + return this.appName; + } + public String getAppExtId() { + return this.appExtId; + } + public String getInstanceBaseUrl() { + return this.instanceBaseUrl; + } @Override public void perform(final Run build, FilePath workspace, Launcher launcher, final TaskListener listener) throws AbortException, InterruptedException, IOException { - if (!Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { - listener.getLogger().println("Could not metrics file to Accelerate as there is no configuration specified."); - return; - } - EnvVars envVars = build.getEnvironment(listener); String testSetName = envVars.expand(this.testSetName); @@ -152,12 +197,18 @@ public void perform(final Run build, FilePath workspace, Launcher launcher String metricDefinitionId = envVars.expand(this.metricDefinitionId); String metricsRecordUrl = envVars.expand(this.metricsRecordUrl); String description = envVars.expand(this.description); - String combineTestSuites = envVars.expand(this.combineTestSuites == null ? "" : this.combineTestSuites.toString()); + String combineTestSuites = envVars + .expand(this.combineTestSuites == null ? "" : this.combineTestSuites.toString()); String fatal = envVars.expand(this.fatal == null ? "" : this.fatal.toString()); String debug = envVars.expand(this.debug == null ? "" : this.debug.toString()); String executionDate = envVars.expand(this.executionDate); String buildId = envVars.expand(this.buildId); String buildUrl = envVars.expand(this.buildUrl); + String instanceBaseUrl = envVars.expand(this.instanceBaseUrl == null ? "" : this.instanceBaseUrl.toString()); + + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getEntries(); + List finalEntriesList = CloudPublisher.getFinalEntriesList("Upload Metric File", instanceBaseUrl, + entries); JSONObject payload = new JSONObject(); @@ -203,7 +254,8 @@ public void perform(final Run build, FilePath workspace, Launcher launcher payload.put("record", record); JSONObject options = new JSONObject(); - options.put("combineTestSuites", combineTestSuites != null && !combineTestSuites.equals("") ? combineTestSuites.toString() : "true"); + options.put("combineTestSuites", + combineTestSuites != null && !combineTestSuites.equals("") ? combineTestSuites.toString() : "true"); payload.put("options", options); JSONObject buildObj = new JSONObject(); @@ -221,33 +273,44 @@ public void perform(final Run build, FilePath workspace, Launcher launcher listener.getLogger().println("payload: " + payload.toString()); } System.out.println("TEST payload: " + payload.toString(2)); - - listener.getLogger().println("Uploading metric \"" + name + "\" to HCL Accelerate..."); - - String userAccessKey = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getApiToken(); - - boolean success = workspace.act(new FileUploader(filePath, payload.toString(), listener, CloudPublisher.getQualityDataUrl(), userAccessKey)); - if (!success) { - listener.getLogger().println("Problem uploading metrics file to HCL Accelerate."); - if (fatal.equals("true")) { - if (debug.equals("true")) { - listener.getLogger().println("Failing build due to fatal=true."); - } - build.setResult(Result.FAILURE); - } else if (fatal.equals("false")) { - if (debug.equals("true")) { - listener.getLogger().println("Not changing build result due to fatal=false."); + for (Entry entry : finalEntriesList) { + String logString = entry.getBaseUrl(); + listener.getLogger() + .println("Uploading metric \"" + name + "\" to HCL Accelerate (" + logString + ")."); + if (!entry.isConfigured()) { + listener.getLogger() + .println("Could not upload metric file to Accelerate as there is no configuration specified."); + return; + } + boolean success = workspace.act(new FileUploader(filePath, payload.toString(), listener, + CloudPublisher.getQualityDataUrl(entry), entry.getApiToken())); + if (!success) { + listener.getLogger() + .println("Problem uploading metrics file to HCL Accelerate (" + logString + ")."); + if (fatal.equals("true")) { + if (debug.equals("true")) { + listener.getLogger().println("Failing build due to fatal=true (" + logString + ")."); + } + build.setResult(Result.FAILURE); + } else if (fatal.equals("false")) { + if (debug.equals("true")) { + listener.getLogger() + .println("Not changing build result due to fatal=false (" + logString + ")."); + } + } else { + if (debug.equals("true")) { + listener.getLogger() + .println("Marking build as unstable due to fatal flag not set (" + logString + ")."); + } + build.setResult(Result.UNSTABLE); } } else { - if (debug.equals("true")) { - listener.getLogger().println("Marking build as unstable due to fatal flag not set."); - } - build.setResult(Result.UNSTABLE); + listener.getLogger() + .println("Successfully uploaded metric file to HCL Accelerate (" + logString + ")."); } - } else { - listener.getLogger().println("Successfully uploaded metric file to HCL Accelerate."); } } + @Extension public static class UploadMetricsFileDescriptor extends BuildStepDescriptor { @@ -277,6 +340,21 @@ public String getDisplayName() { public boolean isApplicable(Class jobType) { return true; } + + public ListBoxModel doFillInstanceBaseUrlItems(@QueryParameter String currentInstanceBaseUrl) { + // Create ListBoxModel from all projects for this AWS Device Farm account. + List baseUrls = new ArrayList(); + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class) + .getEntries(); + String all = "Upload Metric File to All HCL Accelerate Instances"; + baseUrls.add(new ListBoxModel.Option(all, all, all.equals(currentInstanceBaseUrl))); + for (Entry entry : entries) { + // We don't ignore case because these *should* be unique. + baseUrls.add(new ListBoxModel.Option(entry.getBaseUrl(), entry.getBaseUrl(), + entry.getBaseUrl().equals(currentInstanceBaseUrl))); + } + return new ListBoxModel(baseUrls); + } } private static final class FileUploader implements FileCallable { @@ -287,7 +365,8 @@ private static final class FileUploader implements FileCallable { private String userAccessKey; private TaskListener listener; - public FileUploader(String filePath, String payload, TaskListener listener, String postUrl, String userAccessKey) { + public FileUploader(String filePath, String payload, TaskListener listener, String postUrl, + String userAccessKey) { this.filePath = filePath; this.payload = payload; this.listener = listener; @@ -295,7 +374,8 @@ public FileUploader(String filePath, String payload, TaskListener listener, Stri this.userAccessKey = userAccessKey; } - @Override public Boolean invoke(File f, VirtualChannel channel) throws IOException, InterruptedException { + @Override + public Boolean invoke(File f, VirtualChannel channel) throws IOException, InterruptedException { File file = new File(this.filePath); if (!file.isAbsolute()) { @@ -306,25 +386,27 @@ public FileUploader(String filePath, String payload, TaskListener listener, Stri } HttpEntity entity = MultipartEntityBuilder - .create() - .addTextBody("payload", this.payload) - .addBinaryBody("file", file, ContentType.create("application/octet-stream"), "filename") - .build(); + .create() + .addTextBody("payload", this.payload) + .addBinaryBody("file", file, ContentType.create("application/octet-stream"), "filename") + .build(); boolean success = false; try { success = CloudPublisher.uploadQualityData(entity, postUrl, userAccessKey); } catch (Exception ex) { - listener.error("Error uploading metric file: " + ex.getClass() + " - " + ex.getMessage()); - listener.error("Stack trace:"); + listener.error("Error uploading metric file : " + ex.getClass() + " - " + ex.getMessage()); + listener.error("Stack trace :"); StackTraceElement[] elements = ex.getStackTrace(); for (int i = 0; i < elements.length; i++) { StackTraceElement s = elements[i]; - listener.error("\tat " + s.getClassName() + "." + s.getMethodName() + "(" + s.getFileName() + ":" + s.getLineNumber() + ")"); + listener.error("\tat " + s.getClassName() + "." + s.getMethodName() + "(" + s.getFileName() + ":" + + s.getLineNumber() + ")"); } } return success; } + /** * Check the role of the executing node to follow jenkins new file access rules */ diff --git a/src/main/java/com/hcl/devops/connect/CloudBuildStepListener.java b/src/main/java/com/hcl/devops/connect/CloudBuildStepListener.java index 7699dc5..c125f8b 100644 --- a/src/main/java/com/hcl/devops/connect/CloudBuildStepListener.java +++ b/src/main/java/com/hcl/devops/connect/CloudBuildStepListener.java @@ -30,34 +30,41 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of import org.slf4j.LoggerFactory; import net.sf.json.JSONObject; +import java.util.List; @Extension public class CloudBuildStepListener extends BuildStepListener { public static final Logger log = LoggerFactory.getLogger(CloudBuildStepListener.class); + public static final List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class) + .getEntries(); public void finished(AbstractBuild build, BuildStep bs, BuildListener listener, boolean canContinue) { - if (Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { - CloudCause cloudCause = getCloudCause(build); - if (cloudCause == null) { - cloudCause = new CloudCause(); + CloudCause cloudCause = getCloudCause(build); + if (cloudCause == null) { + cloudCause = new CloudCause(); + } + JenkinsJobStatus status = new JenkinsJobStatus(build, cloudCause, bs, listener, false, !canContinue); + for (Entry entry : entries) { + if (entry.isConfigured()) { + JSONObject statusUpdate = status.generate(false, entry); + CloudPublisher.uploadJobStatus(statusUpdate, entry); } - JenkinsJobStatus status = new JenkinsJobStatus(build, cloudCause, bs, listener, false, !canContinue); - JSONObject statusUpdate = status.generate(false); - CloudPublisher.uploadJobStatus(statusUpdate); } } public void started(AbstractBuild build, BuildStep bs, BuildListener listener) { // We listen to jobs that are started by HCL Accelerate only - if(Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured() && this.shouldListen(build)) { - JenkinsJobStatus status = new JenkinsJobStatus(build, getCloudCause(build), bs, listener, true, false); - JSONObject statusUpdate = status.generate(false); - CloudPublisher.uploadJobStatus(statusUpdate); + JenkinsJobStatus status = new JenkinsJobStatus(build, getCloudCause(build), bs, listener, true, false); + for (Entry entry : entries) { + if (entry.isConfigured() && this.shouldListen(build)) { + JSONObject statusUpdate = status.generate(false, entry); + CloudPublisher.uploadJobStatus(statusUpdate, entry); + } } } private boolean shouldListen(AbstractBuild build) { - if(getCloudCause(build) == null) { + if (getCloudCause(build) == null) { return false; } else { return true; @@ -67,9 +74,9 @@ private boolean shouldListen(AbstractBuild build) { private CloudCause getCloudCause(AbstractBuild build) { List causes = build.getCauses(); - for(Cause cause : causes) { + for (Cause cause : causes) { if (cause instanceof CloudCause ) { - return (CloudCause)cause; + return (CloudCause) cause; } } diff --git a/src/main/java/com/hcl/devops/connect/CloudCause.java b/src/main/java/com/hcl/devops/connect/CloudCause.java index e6cdc8c..ed76b73 100644 --- a/src/main/java/com/hcl/devops/connect/CloudCause.java +++ b/src/main/java/com/hcl/devops/connect/CloudCause.java @@ -14,8 +14,9 @@ import net.sf.json.JSONArray; /** -* This is the cause object that is attached to a build if it is started by HCL Accelerate. -*/ +* This is the cause object that is attached to a build if it is started by + * HCL Accelerate. + */ public class CloudCause extends Cause { public enum JobStatus { @@ -74,7 +75,7 @@ public DRAData getDRAData() { } public JSONObject getSourceDataJson() { - if(this.sourceData == null) { + if (this.sourceData == null) { return new JSONObject(); } else { return sourceData.toJson(); @@ -82,7 +83,7 @@ public JSONObject getSourceDataJson() { } public JSONObject getDRADataJson() { - if(this.draData == null) { + if (this.draData == null) { return new JSONObject(); } else { return draData.toJson(); @@ -94,7 +95,7 @@ public void updateLastStep(String name, String status, String message, boolean i addStep(name, status, message, isFatal); } else { JSONObject obj = JSONObject.fromObject(steps.get(steps.size() - 1)); - if(name != null) { + if (name != null) { obj.put("name", name); } obj.put("status", status); diff --git a/src/main/java/com/hcl/devops/connect/CloudGraphListener.java b/src/main/java/com/hcl/devops/connect/CloudGraphListener.java index acd5f58..4f49d35 100644 --- a/src/main/java/com/hcl/devops/connect/CloudGraphListener.java +++ b/src/main/java/com/hcl/devops/connect/CloudGraphListener.java @@ -36,6 +36,7 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of import org.jenkinsci.plugins.workflow.support.actions.PauseAction; import java.io.IOException; +import java.util.List; @Extension public class CloudGraphListener implements GraphListener { @@ -49,7 +50,7 @@ public void onNewHead(FlowNode node) { try { if (execution.getOwner().getExecutable() instanceof WorkflowRun) { - workflowRun = (WorkflowRun)(execution.getOwner().getExecutable()); + workflowRun = (WorkflowRun) (execution.getOwner().getExecutable()); listener = execution.getOwner().getListener(); } } catch (IOException e) { @@ -66,10 +67,14 @@ public void onNewHead(FlowNode node) { boolean isEndNode = node.getClass().getName().equals("org.jenkinsci.plugins.workflow.cps.nodes.StepEndNode"); boolean isPauseNode = PauseAction.isPaused(node); - if ((isStartNode || isEndNode || isPauseNode) && Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { - JenkinsPipelineStatus status = new JenkinsPipelineStatus(workflowRun, cloudCause, node, listener, isStartNode, isPauseNode); - JSONObject statusUpdate = status.generate(false); - CloudPublisher.uploadJobStatus(statusUpdate); + JenkinsPipelineStatus status = new JenkinsPipelineStatus(workflowRun, cloudCause, node, listener, isStartNode, + isPauseNode); + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getEntries(); + for (Entry entry : entries) { + if ((isStartNode || isEndNode || isPauseNode) && entry.isConfigured()) { + JSONObject statusUpdate = status.generate(false, entry); + CloudPublisher.uploadJobStatus(statusUpdate, entry); + } } } @@ -77,9 +82,9 @@ private CloudCause getCloudCause(WorkflowRun workflowRun) { if (workflowRun != null) { List causes = workflowRun.getCauses(); - for(Cause cause : causes) { + for (Cause cause : causes) { if (cause instanceof CloudCause ) { - return (CloudCause)cause; + return (CloudCause) cause; } } } diff --git a/src/main/java/com/hcl/devops/connect/CloudItemListener.java b/src/main/java/com/hcl/devops/connect/CloudItemListener.java index c16ee49..5edee49 100644 --- a/src/main/java/com/hcl/devops/connect/CloudItemListener.java +++ b/src/main/java/com/hcl/devops/connect/CloudItemListener.java @@ -34,13 +34,17 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of @Extension public class CloudItemListener extends ItemListener { public static final Logger log = LoggerFactory.getLogger(CloudItemListener.class); - private String logPrefix= "[HCL Accelerate] CloudItemListener#"; - - public CloudItemListener(){ - logPrefix= logPrefix + "CloudItemListener "; - if (Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { - log.info(logPrefix + "CloudItemListener started..."); - } + public static final List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class) + .getEntries(); + private String logPrefix = "[HCL Accelerate] CloudItemListener#"; + + public CloudItemListener() { + logPrefix = logPrefix + "CloudItemListener "; + // if + // (Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) + // { + log.info(logPrefix + "CloudItemListener started..."); + // } } @Override @@ -59,27 +63,30 @@ public void onUpdated(Item item) { } private void handleEvent(Item item, String phase) { - if (Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { - if( !(item instanceof Folder) ) { - JenkinsJob jenkinsJob= new JenkinsJob(item); - log.info(ToStringBuilder.reflectionToString(jenkinsJob.toJson()) + " was " + phase); - CloudPublisher.uploadJobInfo(jenkinsJob.toJson()); + if (!(item instanceof Folder)) { + JenkinsJob jenkinsJob = new JenkinsJob(item); + log.info(ToStringBuilder.reflectionToString(jenkinsJob.toJson()) + " was " + phase); + for (Entry entry : entries) { + if (entry.isConfigured()) { + CloudPublisher.uploadJobInfo(jenkinsJob.toJson(), entry); + } } } } public List buildJobsList() { - List allProjects= JenkinsServer.getAllItems(); + List allProjects = JenkinsServer.getAllItems(); List allJobs = new ArrayList(); - if (Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { - log.info(logPrefix + "\n\n\tBuilding the list of Jenkins jobs...\n\n"); - for (Item anItem : allProjects) { - if( !(anItem instanceof Folder) ) { - JenkinsJob jenkinsJob= new JenkinsJob(anItem); - allJobs.add(jenkinsJob.toJson()); - - CloudPublisher.uploadJobInfo(jenkinsJob.toJson()); + log.info(logPrefix + "\n\n\tBuilding the list of Jenkins jobs...\n\n"); + for (Item anItem : allProjects) { + if (!(anItem instanceof Folder)) { + JenkinsJob jenkinsJob = new JenkinsJob(anItem); + allJobs.add(jenkinsJob.toJson()); + for (Entry entry : entries) { + if (entry.isConfigured()) { + CloudPublisher.uploadJobInfo(jenkinsJob.toJson(), entry); + } } } } diff --git a/src/main/java/com/hcl/devops/connect/CloudPublisher.java b/src/main/java/com/hcl/devops/connect/CloudPublisher.java index 1344b3f..0edf088 100644 --- a/src/main/java/com/hcl/devops/connect/CloudPublisher.java +++ b/src/main/java/com/hcl/devops/connect/CloudPublisher.java @@ -47,7 +47,8 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of import org.apache.http.StatusLine; import org.apache.http.ssl.SSLContexts; import org.apache.http.ssl.TrustStrategy; - +import org.apache.commons.lang.StringUtils; +import java.util.List; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; @@ -58,10 +59,10 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of import javax.net.ssl.SSLContext; import org.apache.http.HttpEntity; +import java.util.*; public class CloudPublisher { public static final Logger log = LoggerFactory.getLogger(CloudPublisher.class); - private static String logPrefix= "[HCL Accelerate] CloudPublisher#"; private final static String JENKINS_JOB_ENDPOINT_URL = "api/v1/jenkins/jobs"; private final static String JENKINS_JOB_STATUS_ENDPOINT_URL = "api/v1/jenkins/jobStatus"; @@ -81,12 +82,14 @@ public static void ensureHttpClientInitialized() { try { SSLContextBuilder builder = new SSLContextBuilder(); builder.loadTrustMaterial(null, new TrustSelfSignedStrategy()); - SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(), new AllowAllHostnameVerifier()); + SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(), + new AllowAllHostnameVerifier()); RequestConfig config = RequestConfig.custom() - .setConnectTimeout(requestTimeoutSeconds * 1000) - .setConnectionRequestTimeout(requestTimeoutSeconds * 1000) - .setSocketTimeout(requestTimeoutSeconds * 1000).build(); - httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultRequestConfig(config).build(); + .setConnectTimeout(requestTimeoutSeconds * 1000) + .setConnectionRequestTimeout(requestTimeoutSeconds * 1000) + .setSocketTimeout(requestTimeoutSeconds * 1000).build(); + httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultRequestConfig(config) + .build(); } catch (NoSuchAlgorithmException nsae) { nsae.printStackTrace(); } catch (KeyManagementException kme) { @@ -104,11 +107,12 @@ public static void ensureAsyncHttpClientInitialized() { if (acceptAllCerts) { try { TrustStrategy acceptingTrustStrategy = new TrustStrategy() { - public boolean isTrusted(X509Certificate[] certificate, String authType) { + public boolean isTrusted(X509Certificate[] certificate, String authType) { return true; } }; - SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build(); + SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy) + .build(); asyncHttpClient = HttpAsyncClients.custom() .setSSLHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER) @@ -127,9 +131,9 @@ public boolean isTrusted(X509Certificate[] certificate, String authType) { } } - private static String getSyncApiUrl() { + private static String getSyncApiUrl(Entry entry) { EndpointManager em = new EndpointManager(); - return em.getSyncApiEndpoint(); + return em.getSyncApiEndpoint(entry); } private static String getSyncApiUrl(String baseUrl) { @@ -137,36 +141,41 @@ private static String getSyncApiUrl(String baseUrl) { return em.getSyncApiEndpoint(baseUrl); } - public static String getQualityDataUrl() { + public static String getQualityDataUrl(Entry entry) { + EndpointManager em = new EndpointManager(); + return em.getQualityDataEndpoint(entry); + } + + private static String getQualityDataRawUrl(Entry entry) { EndpointManager em = new EndpointManager(); - return em.getQualityDataEndpoint(); + return em.getQualityDataRawEndpoint(entry); } - private static String getQualityDataRawUrl() { + private static String getBuildUploadUrl(Entry entry) { EndpointManager em = new EndpointManager(); - return em.getQualityDataRawEndpoint(); + return em.getReleaseEvensApiEndpoint(entry) + BUILD_UPLOAD_URL; } - private static String getBuildUploadUrl() { + private static String getDeploymentUploadUrl(Entry entry) { EndpointManager em = new EndpointManager(); - return em.getReleaseEvensApiEndpoint() + BUILD_UPLOAD_URL; + return em.getReleaseEvensApiEndpoint(entry) + DEPLOYMENT_UPLOAD_URL; } - private static String getDeploymentUploadUrl() { + private static String getDotsUrl(Entry entry) { EndpointManager em = new EndpointManager(); - return em.getReleaseEvensApiEndpoint() + DEPLOYMENT_UPLOAD_URL; + return em.getDotsEndpoint(entry); } - private static String getDotsUrl() { + private static String getGraphqlUrl(Entry entry) { EndpointManager em = new EndpointManager(); - return em.getDotsEndpoint(); + return em.getGraphqlApiEndpoint(entry); } /** * Upload the build information to Sync API - API V1. */ - public static void uploadJobInfo(JSONObject jobJson) { - String url = CloudPublisher.getSyncApiUrl() + JENKINS_JOB_ENDPOINT_URL; + public static void uploadJobInfo(JSONObject jobJson, Entry entry) { + String url = CloudPublisher.getSyncApiUrl(entry) + JENKINS_JOB_ENDPOINT_URL; JSONArray payload = new JSONArray(); payload.add(jobJson); @@ -175,87 +184,110 @@ public static void uploadJobInfo(JSONObject jobJson) { System.out.println(url); System.out.println(jobJson.toString()); - CloudPublisher.postToSyncAPI(url, payload.toString()); + CloudPublisher.postToSyncAPI(url, payload.toString(), entry); } - public static void uploadJobStatus(JSONObject jobStatus) { - String url = CloudPublisher.getSyncApiUrl() + JENKINS_JOB_STATUS_ENDPOINT_URL; - CloudPublisher.postToSyncAPI(url, jobStatus.toString()); + public static void uploadJobStatus(JSONObject jobStatus, Entry entry) { + String url = CloudPublisher.getSyncApiUrl(entry) + JENKINS_JOB_STATUS_ENDPOINT_URL; + CloudPublisher.postToSyncAPI(url, jobStatus.toString(), entry); } - public static String uploadBuild(String payload) throws Exception { + public static String uploadBuild(String payload, Entry entry) throws Exception { CloudPublisher.ensureHttpClientInitialized(); - String localLogPrefix= logPrefix + "uploadBuild "; String resStr = ""; - String url = CloudPublisher.getBuildUploadUrl(); + String url = CloudPublisher.getBuildUploadUrl(entry); CloseableHttpResponse response = null; + String logPrefix = "[HCL Accelerate " + entry.getBaseUrl() + "] CloudPublisher#uploadBuild"; try { HttpPost postMethod = new HttpPost(url); - attachHeaders(postMethod); + attachHeaders(postMethod, entry); postMethod.setHeader("Content-Type", "application/json"); - postMethod.setHeader("Authorization", "UserAccessKey " + Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getApiToken()); + postMethod.setHeader("Authorization", "UserAccessKey " + entry.getApiToken()); postMethod.setEntity(new StringEntity(payload)); response = httpClient.execute(postMethod); resStr = EntityUtils.toString(response.getEntity()); if (response.getStatusLine().toString().contains("200")) { - log.info(localLogPrefix + "Uploaded Build successfully"); + log.info(logPrefix + " Uploaded Build successfully"); } else { - throw new Exception("Bad response code when uploading Build: " + response.getStatusLine() + " - " + resStr); + throw new Exception(logPrefix + "Bad response code when uploading Build: " + response.getStatusLine() + + " - " + resStr); } } finally { if (response != null) { try { response.close(); } catch (Exception e) { - log.error("Could not close uploadBuild response"); + log.error(logPrefix + " Could not close uploadBuild response"); } } } return resStr; } - public static String uploadDeployment(String payload) throws Exception { + public static String uploadDeployment(String payload, Entry entry) throws Exception { CloudPublisher.ensureHttpClientInitialized(); - String localLogPrefix= logPrefix + "uploadDeployment "; String resStr = ""; - String url = CloudPublisher.getDeploymentUploadUrl(); + String url = CloudPublisher.getDeploymentUploadUrl(entry); CloseableHttpResponse response = null; + String logPrefix = "[HCL Accelerate " + entry.getBaseUrl() + "] CloudPublisher#uploadDeployment"; try { HttpPost postMethod = new HttpPost(url); - attachHeaders(postMethod); + attachHeaders(postMethod, entry); postMethod.setHeader("Content-Type", "application/json"); - postMethod.setHeader("Authorization", "UserAccessKey " + Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getApiToken()); + postMethod.setHeader("Authorization", "UserAccessKey " + entry.getApiToken()); postMethod.setEntity(new StringEntity(payload)); response = httpClient.execute(postMethod); resStr = EntityUtils.toString(response.getEntity()); if (response.getStatusLine().toString().contains("200")) { - log.info(localLogPrefix + "Uploaded Deployment successfully"); + log.info(logPrefix + " Uploaded Deployment successfully"); } else { - throw new Exception("Bad response code when uploading Deployment: " + response.getStatusLine() + " - " + resStr); + throw new Exception(logPrefix + "Bad response code when uploading Deployment: " + + response.getStatusLine() + " - " + resStr); } } finally { if (response != null) { try { response.close(); } catch (Exception e) { - log.error("Could not close uploadDeployment response"); + log.error(logPrefix + " Could not close uploadDeployment response"); } } } return resStr; } - public static String checkGate(String pipelineId, String stageName, String versionId) throws Exception { + public static List getFinalEntriesList(String jobString, String instanceBaseUrl, List entries) { + List finalEntriesList = new ArrayList<>(); + if (StringUtils.isNotEmpty(instanceBaseUrl)) { + for (Entry entry : entries) { + if (removeTrailingSlash(instanceBaseUrl).equals(removeTrailingSlash(entry.getBaseUrl()))) { + finalEntriesList.add(entry); + break; + } + } + if (finalEntriesList.size() == 0) { + log.info("Using default: " + jobString + "to All HCL Accelerate Instances."); + return entries; + } + } else { + log.info("HCL Accelerate Instance BaseUrl is not provided for " + jobString + ". Using default: " + jobString + + "to All HCL Accelerate Instances."); + return entries; + } + return finalEntriesList; + } + + public static String checkGate(Entry entry, String pipelineId, String stageName, String versionId) + throws Exception { CloudPublisher.ensureHttpClientInitialized(); - String localLogPrefix= logPrefix + "checkGate "; String resStr = ""; - String url = CloudPublisher.getDotsUrl(); + String url = CloudPublisher.getDotsUrl(entry); CloseableHttpResponse response = null; - + String logPrefix = "[HCL Accelerate " + entry.getBaseUrl() + "] CloudPublisher#checkGate"; try { URIBuilder builder = new URIBuilder(url); builder.setParameter("pipelineId", pipelineId); @@ -264,36 +296,72 @@ public static String checkGate(String pipelineId, String stageName, String versi URI uri = builder.build(); System.out.println("TEST gates url: " + uri.toString()); HttpGet getMethod = new HttpGet(uri); - attachHeaders(getMethod); + attachHeaders(getMethod, entry); getMethod.setHeader("Accept", "application/json"); - getMethod.setHeader("Authorization", "UserAccessKey " + Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getApiToken()); + getMethod.setHeader("Authorization", "UserAccessKey " + entry.getApiToken()); response = httpClient.execute(getMethod); resStr = EntityUtils.toString(response.getEntity()); if (response.getStatusLine().toString().contains("200")) { - log.info(localLogPrefix + "Gates Checked Successfully"); + log.info(logPrefix + " Gates Checked Successfully"); } else { - throw new Exception("Bad response code when uploading Deployment: " + response.getStatusLine() + " - " + resStr); + throw new Exception(logPrefix + "Bad response code when uploading Deployment: " + + response.getStatusLine() + " - " + resStr); } } finally { if (response != null) { try { response.close(); } catch (Exception e) { - log.error("Could not close uploadDeployment response"); + log.error(logPrefix + " Could not close uploadDeployment response"); } } } return resStr; } + public static Boolean isPipeline(Entry entry, String pipelineId) throws Exception { + CloudPublisher.ensureHttpClientInitialized(); + String resStr = ""; + String url = CloudPublisher.getGraphqlUrl(entry); + CloseableHttpResponse response = null; + try { + URIBuilder builder = new URIBuilder(url); + builder.setParameter("query", "{pipelineById(pipelineId: \"" + pipelineId + "\"){_id}}"); + URI uri = builder.build(); + System.out.println("TEST gates url: " + uri.toString()); + HttpGet getMethod = new HttpGet(uri); + attachHeaders(getMethod, entry); + getMethod.setHeader("Accept", "application/json"); + getMethod.setHeader("Authorization", "UserAccessKey " + entry.getApiToken()); + + response = httpClient.execute(getMethod); + resStr = EntityUtils.toString(response.getEntity()); + log.info(resStr); + if (resStr.contains(pipelineId)) { + return true; + } else { + return false; + } + } finally { + if (response != null) { + try { + response.close(); + } catch (Exception e) { + log.error("[HCL Accelerate " + entry.getBaseUrl() + + "] CloudPublisher#isPipeline Could not close isPipeline response"); + } + } + } + } + + public static boolean uploadQualityData(HttpEntity entity, String url, String userAccessKey) throws Exception { CloudPublisher.ensureHttpClientInitialized(); - String localLogPrefix= logPrefix + "uploadQualityData "; String resStr = ""; CloseableHttpResponse response = null; boolean success = false; - + String logPrefix = "[HCL Accelerate] CloudPublisher#uploadQualityData"; try { HttpPost postMethod = new HttpPost(url); postMethod.setHeader("Authorization", "UserAccessKey " + userAccessKey); @@ -302,7 +370,7 @@ public static boolean uploadQualityData(HttpEntity entity, String url, String us response = httpClient.execute(postMethod); resStr = EntityUtils.toString(response.getEntity()); if (response.getStatusLine().toString().contains("200")) { - log.info(localLogPrefix + "Upload Quality Data successfully"); + log.info(logPrefix + " Upload Quality Data successfully"); success = true; } return success; @@ -313,69 +381,70 @@ public static boolean uploadQualityData(HttpEntity entity, String url, String us try { response.close(); } catch (Exception e) { - log.error("Could not close uploadQualityData response"); + log.error(logPrefix + " Could not close uploadQualityData response"); } } if (!success) { - throw new Exception("Bad response code when uploading Quality Data: " + status + " - " + resStr); + throw new Exception(logPrefix + "Bad response code when uploading Quality Data: " + status + " - " + resStr); } } } - public static void uploadQualityDataRaw(String payload) throws Exception { + public static void uploadQualityDataRaw(Entry entry, String payload) throws Exception { CloudPublisher.ensureHttpClientInitialized(); - String localLogPrefix= logPrefix + "uploadMetricDataRaw "; String resStr = ""; - String url = CloudPublisher.getQualityDataRawUrl(); + String url = CloudPublisher.getQualityDataRawUrl(entry); CloseableHttpResponse response = null; - + String logPrefix = "[HCL Accelerate " + entry.getBaseUrl() + "] CloudPublisher#uploadMetricDataRaw"; try { HttpPost postMethod = new HttpPost(url); - attachHeaders(postMethod); + attachHeaders(postMethod, entry); postMethod.setHeader("Content-Type", "application/json"); - postMethod.setHeader("Authorization", "UserAccessKey " + Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getApiToken()); + postMethod.setHeader("Authorization", "UserAccessKey " + entry.getApiToken()); postMethod.setEntity(new StringEntity(payload)); response = httpClient.execute(postMethod); resStr = EntityUtils.toString(response.getEntity()); if (response.getStatusLine().toString().contains("200")) { - log.info(localLogPrefix + "Uploaded Metric (raw) successfully"); + log.info(logPrefix + " Uploaded Metric (raw) successfully"); } else { - throw new Exception("Bad response code when uploading Metric (raw): " + response.getStatusLine() + " - " + resStr); + throw new Exception(logPrefix + " Bad response code when uploading Metric (raw): " + response.getStatusLine() + " - " + resStr); } } finally { if (response != null) { try { response.close(); } catch (Exception e) { - log.error("Could not close uploadQualityDataRaw response"); + log.error(logPrefix + " Could not close uploadQualityDataRaw response"); } } } } - private static void attachHeaders(AbstractHttpMessage message) { - String syncId = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getSyncId(); - message.setHeader("sync_token", Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getSyncToken()); + private static void attachHeaders(AbstractHttpMessage message, Entry entry) { + String syncId = entry.getSyncId(); + message.setHeader("sync_token", entry.getSyncToken()); message.setHeader("sync_id", syncId); message.setHeader("instance_type", "JENKINS"); message.setHeader("instance_id", syncId); message.setHeader("integration_id", syncId); - // Must include both _ and - headers because NGINX services don't pass _ headers by default and the original version of the Accelerate services expected the _ headers - message.setHeader("sync-token", Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getSyncToken()); + // Must include both _ and - headers because NGINX services don't pass _ headers + // by default and the original version of the Accelerate services expected the _ + // headers + message.setHeader("sync-token", entry.getSyncToken()); message.setHeader("sync-id", syncId); message.setHeader("instance-type", "JENKINS"); message.setHeader("instance-id", syncId); message.setHeader("integration-id", syncId); } - private static void postToSyncAPI(String url, String payload) { + private static void postToSyncAPI(String url, String payload, Entry entry) { CloudPublisher.ensureAsyncHttpClientInitialized(); - String localLogPrefix= logPrefix + "uploadJobInfo "; + String logPrefix = "[HCL Accelerate " + entry.getBaseUrl() + "] CloudPublisher#uploadJobInfo"; try { HttpPost postMethod = new HttpPost(url); - attachHeaders(postMethod); + attachHeaders(postMethod, entry); postMethod.setHeader("Content-Type", "application/json"); StringEntity data = new StringEntity(payload); postMethod.setEntity(data); @@ -383,36 +452,43 @@ private static void postToSyncAPI(String url, String payload) { asyncHttpClient.execute(postMethod, new FutureCallback() { public void completed(final HttpResponse response2) { if (response2.getStatusLine().toString().contains("200")) { - log.info(localLogPrefix + "Upload Job Information successfully"); + log.info(logPrefix + " Upload Job Information successfully"); } else { - log.error(localLogPrefix + "Error: Upload Job has bad status code, response status " + response2.getStatusLine()); + log.error(logPrefix + " Error: Upload Job has bad status code, response status " + response2.getStatusLine()); } try { EntityUtils.toString(response2.getEntity()); } catch (JsonSyntaxException e) { - log.error(localLogPrefix + "Invalid Json response, response: " + response2.getEntity()); + log.error(logPrefix + "Invalid Json response, response: " + response2.getEntity()); } catch (IOException e) { - log.error(localLogPrefix + "Input/Output error, response: " + response2.getEntity()); + log.error(logPrefix + "Input/Output error, response: " + response2.getEntity()); } } public void failed(final Exception ex) { - log.error(localLogPrefix + "Error: Failed to upload Job, response status " + ex.getMessage()); + log.error(logPrefix + "Error: Failed to upload Job, response status " + ex.getMessage()); ex.printStackTrace(); if (ex instanceof IllegalStateException) { - log.error(localLogPrefix + "Please check if you have the access to the configured tenant."); + log.error(logPrefix + "Please check if you have the access to the configured tenant."); } } public void cancelled() { - log.error(localLogPrefix + "Error: Upload Job cancelled."); + log.error(logPrefix + "Error: Upload Job cancelled."); } }); } catch (UnsupportedEncodingException e) { - log.error("UnsupportedEncodingException trying to post job data", e); + log.error(logPrefix + "UnsupportedEncodingException trying to post job data", e); } catch (Exception e) { - log.error("Error trying to post job data", e); + log.error(logPrefix + "Error trying to post job data", e); + } + } + + public static String removeTrailingSlash(String url) { + if (url.endsWith("/")) { + url = url.substring(0, url.length() - 1); } + return url; } public static boolean testConnection(String syncId, String syncToken, String baseUrl) { @@ -428,7 +504,9 @@ public static boolean testConnection(String syncId, String syncToken, String bas getMethod.setHeader("instance_id", syncId); getMethod.setHeader("integration_id", syncId); - // Must include both _ and - headers because NGINX services don't pass _ headers by default and the original version of the Accelerate services expected the _ headers + // Must include both _ and - headers because NGINX services don't pass _ headers + // by default and the original version of the Accelerate services expected the _ + // headers getMethod.setHeader("sync-token", syncToken); getMethod.setHeader("sync-id", syncId); getMethod.setHeader("instance-type", "JENKINS"); @@ -439,30 +517,30 @@ public static boolean testConnection(String syncId, String syncToken, String bas if (response.getStatusLine().toString().contains("200")) { // get 200 response - log.info("Connected to Accelerate service successfully."); + log.info("Connected to Accelerate service successfully for : " + baseUrl); return true; } else { - log.warn("Could not authenticate to Accelerate Services:"); + log.warn("Could not authenticate to Accelerate Services for :" + baseUrl); log.warn(response.toString()); } } catch (IllegalStateException e) { - log.error("Could not connect to Accelerate:"); + log.error("Could not connect to Accelerate for : " + baseUrl); log.error(e.getMessage()); } catch (UnsupportedEncodingException e) { - log.error("Could not connect to Accelerate:"); + log.error("Could not connect to Accelerate for : " + baseUrl); log.error(e.getMessage()); } catch (ClientProtocolException e) { - log.error("Could not connect to Accelerate:"); + log.error("Could not connect to Accelerate for : " + baseUrl); log.error(e.getMessage()); } catch (IOException e) { - log.error("Could not connect to Accelerate:"); + log.error("Could not connect to Accelerate for : " + baseUrl); log.error(e.getMessage()); } finally { if (response != null) { try { response.close(); } catch (Exception e) { - log.error("Could not close testconnection response"); + log.error("Could not close testconnection response for : " + baseUrl); } } } diff --git a/src/main/java/com/hcl/devops/connect/CloudRunListener.java b/src/main/java/com/hcl/devops/connect/CloudRunListener.java index 8248c8b..971b6a1 100644 --- a/src/main/java/com/hcl/devops/connect/CloudRunListener.java +++ b/src/main/java/com/hcl/devops/connect/CloudRunListener.java @@ -42,53 +42,57 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of @Extension public class CloudRunListener extends RunListener { public static final Logger log = LoggerFactory.getLogger(CloudRunListener.class); - + public static final List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class) + .getEntries(); @Override public void onStarted(Run run, TaskListener listener) { - if (Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { - CloudCause cloudCause = getCloudCause(run); - if (cloudCause == null) { - cloudCause = new CloudCause(); - } + CloudCause cloudCause = getCloudCause(run); + if (cloudCause == null) { + cloudCause = new CloudCause(); + } - AbstractJenkinsStatus status = null; - if (run instanceof WorkflowRun) { - status = new JenkinsPipelineStatus((WorkflowRun)run, cloudCause, null, listener, true, false); - } else { - status = new JenkinsJobStatus(run, cloudCause, null, listener, true, false); + AbstractJenkinsStatus status = null; + if (run instanceof WorkflowRun) { + status = new JenkinsPipelineStatus((WorkflowRun) run, cloudCause, null, listener, true, false); + } else { + status = new JenkinsJobStatus(run, cloudCause, null, listener, true, false); + } + status.setRunStatus(true); + for (Entry entry : entries) { + if (entry.isConfigured()) { + JSONObject statusUpdate = status.generate(false, entry); + CloudPublisher.uploadJobStatus(statusUpdate, entry); } - status.setRunStatus(true); - JSONObject statusUpdate = status.generate(false); - CloudPublisher.uploadJobStatus(statusUpdate); } } @Override public void onCompleted(Run run, TaskListener listener) { - if (Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { - CloudCause cloudCause = getCloudCause(run); - if (cloudCause == null) { - cloudCause = new CloudCause(); - } - - AbstractJenkinsStatus status = null; - if (run instanceof WorkflowRun) { - status = new JenkinsPipelineStatus((WorkflowRun)run, cloudCause, null, listener, false, false); - } else { - status = new JenkinsJobStatus(run, cloudCause, null, listener, false, false); + CloudCause cloudCause = getCloudCause(run); + if (cloudCause == null) { + cloudCause = new CloudCause(); + } + AbstractJenkinsStatus status = null; + if (run instanceof WorkflowRun) { + status = new JenkinsPipelineStatus((WorkflowRun) run, cloudCause, null, listener, false, false); + } else { + status = new JenkinsJobStatus(run, cloudCause, null, listener, false, false); + } + status.setRunStatus(true); + for (Entry entry : entries) { + if (entry.isConfigured()) { + JSONObject statusUpdate = status.generate(true, entry); + CloudPublisher.uploadJobStatus(statusUpdate, entry); } - status.setRunStatus(true); - JSONObject statusUpdate = status.generate(true); - CloudPublisher.uploadJobStatus(statusUpdate); } } private CloudCause getCloudCause(Run run) { List causes = run.getCauses(); - for(Cause cause : causes) { + for (Cause cause : causes) { if (cause instanceof CloudCause ) { - return (CloudCause)cause; + return (CloudCause) cause; } } diff --git a/src/main/java/com/hcl/devops/connect/CloudSocketComponent.java b/src/main/java/com/hcl/devops/connect/CloudSocketComponent.java index afda9a0..2e55223 100644 --- a/src/main/java/com/hcl/devops/connect/CloudSocketComponent.java +++ b/src/main/java/com/hcl/devops/connect/CloudSocketComponent.java @@ -37,21 +37,24 @@ import java.util.Base64; import java.nio.charset.StandardCharsets; import org.apache.http.client.utils.URIBuilder; +import java.util.List; public class CloudSocketComponent { public static final Logger log = LoggerFactory.getLogger(CloudSocketComponent.class); - private String logPrefix= "[HCL Accelerate] CloudSocketComponent#"; final private IWorkListener workListener; final private String cloudUrl; - private static Connection conn; + private static Connection conn[] = new Connection[5]; private static boolean queueIsAvailable = false; private static boolean otherIntegrationExists = false; + // private static void setOtherIntegrationsExists(boolean exists) { + // otherIntegrationExists = exists; + // } private static void setOtherIntegrationsExists(boolean exists) { otherIntegrationExists = exists; } @@ -61,25 +64,11 @@ public CloudSocketComponent(IWorkListener workListener, String cloudUrl) { this.cloudUrl = cloudUrl; } - public boolean isRegistered() { - return StringUtils.isNotBlank(getSyncToken()); - } - - public String getSyncId() { - return Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getSyncId(); - } - - public String getSyncToken() { - return Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getSyncToken(); - } - - public void connectToCloudServices() throws Exception { - if (Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { - logPrefix= logPrefix + "connectToCloudServices "; - - connectToAMQP(); - - log.info(logPrefix + "Assembling list of Jenkins Jobs..."); + public void connectToCloudServices(Entry entry) throws Exception { + if (entry.isConfigured()) { + connectToAMQP(entry); + log.info("[HCL Accelerate " + entry.getBaseUrl() + "] CloudSocketComponent#connectToCloudServices " + + "Assembling list of Jenkins Jobs..."); BuildJobsList buildJobList = new BuildJobsList(); BuildJobListParamObj paramObj = buildJobList.new BuildJobListParamObj(); @@ -87,18 +76,33 @@ public void connectToCloudServices() throws Exception { } } - public static boolean isAMQPConnected() { - if (conn == null || queueIsAvailable == false) { + public static int getInstanceNum(Entry entry) { + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getEntries(); + int i = 0; + int instanceNum = -1; + for (Entry entry2 : entries) { + if (entry.equals(entry2)) { + instanceNum = i; + break; + } + i++; + } + return instanceNum; + } + + public static boolean isAMQPConnected(Entry entry) { + int instanceNum = getInstanceNum(entry); + if (conn[instanceNum] == null || queueIsAvailable == false) { return false; } - return conn.isOpen(); + return conn[instanceNum].isOpen(); } private static byte[] toByte(String hexString) { - int len = hexString.length()/2; + int len = hexString.length() / 2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) { - result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); + result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue(); } return result; } @@ -114,16 +118,16 @@ private static String decrypt(String seed, String encrypted) throws Exception { return new String(clearbyte, "UTF-8"); } - private static String getEncodedString(String credentials){ - return Base64.getEncoder().encodeToString(credentials.getBytes(StandardCharsets.UTF_8)); + private static String getEncodedString(String credentials) { + return Base64.getEncoder().encodeToString(credentials.getBytes(StandardCharsets.UTF_8)); } - public void connectToAMQP() throws Exception { - if (!Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { + public void connectToAMQP(Entry entry) throws Exception { + if (!entry.isConfigured()) { return; } - - String syncId = getSyncId(); + String logPrefix = "[HCL Accelerate " + entry.getBaseUrl() + "] "; + String syncId = entry.getSyncId(); ConnectionFactory factory = new ConnectionFactory(); factory.setAutomaticRecoveryEnabled(false); @@ -134,8 +138,8 @@ public void connectToAMQP() throws Exception { factory.setUsername("jenkins"); factory.setPassword("jenkins"); - String host = em.getAccelerateHostname(); - String rabbitHost = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getRabbitMQHost(); + String host = em.getAccelerateHostname(entry); + String rabbitHost = entry.getRabbitMQHost(); if (rabbitHost != null && !rabbitHost.equals("")) { try { if (rabbitHost.endsWith("/")) { @@ -144,19 +148,19 @@ public void connectToAMQP() throws Exception { URL urlObj = new URL(rabbitHost); host = urlObj.getHost(); } catch (MalformedURLException e) { - log.warn("Provided Rabbit MQ Host is not a valid hostname. Using default : " + host, e); + log.warn(logPrefix + "Provided Rabbit MQ Host is not a valid hostname. Using default : " + host, e); } } factory.setHost(host); int port = 5672; - String rabbitPort = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getRabbitMQPort(); + String rabbitPort = entry.getRabbitMQPort(); if (rabbitPort != null && !rabbitPort.equals("")) { try { port = Integer.parseInt(rabbitPort); } catch (NumberFormatException nfe) { - log.warn("Provided Rabbit MQ port is not an integer. Using default 5672"); + log.warn(logPrefix + "Provided Rabbit MQ port is not an integer. Using default 5672"); } } factory.setPort(port); @@ -164,15 +168,15 @@ public void connectToAMQP() throws Exception { // Synchronized to protect manipulation of static variable synchronized (this) { - if(this.conn != null && this.conn.isOpen()) { - this.conn.abort(); + if(this.conn[getInstanceNum(entry)] != null && this.conn[getInstanceNum(entry)].isOpen()) { + this.conn[getInstanceNum(entry)].abort(); } - conn = factory.newConnection(); + conn[getInstanceNum(entry)] = factory.newConnection(); - Channel channel = conn.createChannel(); + Channel channel = conn[getInstanceNum(entry)].createChannel(); - log.info("Connecting to RabbitMQ"); + log.info(logPrefix + "Connecting to RabbitMQ"); String EXCHANGE_NAME = "jenkins"; String queueName = "jenkins.client." + syncId; @@ -180,76 +184,69 @@ public void connectToAMQP() throws Exception { Consumer consumer = new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, - AMQP.BasicProperties properties, byte[] body) throws IOException { + AMQP.BasicProperties properties, byte[] body) throws IOException { if (envelope.getRoutingKey().contains(".heartbeat")) { - String syncId = getSyncId(); - String syncToken = getSyncToken(); - - String url = removeTrailingSlash(Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getBaseUrl()); - CloudPublisher.testConnection(syncId, syncToken, url); + String syncId = entry.getSyncId(); + String syncToken = entry.getSyncToken(); + String url = CloudPublisher.removeTrailingSlash(entry.getBaseUrl()); + boolean connected = CloudPublisher.testConnection(syncId, syncToken, url); } else { String message = new String(body, "UTF-8"); - String payload = null; - String syncToken = getSyncToken(); - try { - payload = decrypt(syncToken, message.toString()); - log.info("payload: " + payload); - } catch (Exception e) { - System.out.println("Unable to decrypt"); - } - JSONArray incomingJobs = JSONArray.fromObject("[" + payload + "]"); - JSONObject incomingJob = incomingJobs.getJSONObject(0); - String workId = incomingJob.getString("id"); - String jobName = incomingJob.getString("fullName"); - StandardUsernamePasswordCredentials credentials = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getCredentialsObj(); - String plainCredentials = credentials.getUsername() + ":" + credentials.getPassword().getPlainText(); - String encodedString = getEncodedString(plainCredentials); - String authorizationHeader = "Basic " + encodedString; - String rootUrl = Jenkins.getInstance().getRootUrl(); - log.info("Root Url: " + rootUrl); - String path = "job/"+jobName.replaceAll("/", "/job/")+"/api/json"; - log.info("Path: " + path); - String finalUrl = null; - String buildDetails = null; - try { - URIBuilder builder = new URIBuilder(rootUrl); - builder.setPath(builder.getPath()+path); - builder.setParameter("fetchAllbuildDetails", "True"); - finalUrl = builder.toString(); - log.info("Final Url: " + finalUrl); - } catch (Exception e) { - log.warn("Caught error while building url to get details of previous builds: ", e); - } - try { - HttpResponse response = Unirest.get(finalUrl) - .header("Authorization", authorizationHeader) - .asString(); - buildDetails = response.getBody().toString(); - log.info("buildDetails Response: " + buildDetails); - } catch (UnirestException e) { - log.warn("UnirestException: Failed to get details of previous Builds. Skipping duplicate check."); - System.out.println(" [x] Received '" + message + "'"); - CloudWorkListener2 cloudWorkListener = new CloudWorkListener2(); - cloudWorkListener.call("startJob", message); - } - if (buildDetails != null) { + if (entry.getCheckDuplicate() == true) { + log.info("Checking for duplicate jobs enabled..."); + String payload = null; + String syncToken = entry.getSyncToken(); + try { + payload = decrypt(syncToken, message.toString()); + } catch (Exception e) { + System.out.println("Unable to decrypt"); + } + JSONArray incomingJobs = JSONArray.fromObject("[" + payload + "]"); + JSONObject incomingJob = incomingJobs.getJSONObject(0); + String workId = incomingJob.getString("id"); + String jobName = incomingJob.getString("fullName"); + StandardUsernamePasswordCredentials credentials = Jenkins.getInstance() + .getDescriptorByType(DevOpsGlobalConfiguration.class).getCredentialsObj(); + String plainCredentials = credentials.getUsername() + ":" + + credentials.getPassword().getPlainText(); + String encodedString = getEncodedString(plainCredentials); + String authorizationHeader = "Basic " + encodedString; + String rootUrl = Jenkins.getInstance().getRootUrl(); + String path = "job/" + jobName.replaceAll("/", "/job/") + "/api/json"; + String finalUrl = null; + String buildDetails = null; + try { + URIBuilder builder = new URIBuilder(rootUrl); + builder.setPath(builder.getPath() + path); + builder.setQuery("fetchAllbuildDetails=True"); + finalUrl = builder.toString(); + } catch (Exception e) { + log.error("Caught error while building url to get details of previous builds: ", e); + } + try { + HttpResponse response = Unirest.get(finalUrl) + .header("Authorization", authorizationHeader) + .asString(); + buildDetails = response.getBody().toString(); + } catch (UnirestException e) { + log.error("UnirestException: Failed to get details of previous Builds", e); + } JSONArray buildDetailsArray = JSONArray.fromObject("[" + buildDetails + "]"); JSONObject buildDetailsObject = buildDetailsArray.getJSONObject(0); - if(buildDetailsObject.has("builds")){ + if (buildDetailsObject.has("builds")) { JSONArray builds = JSONArray.fromObject(buildDetailsObject.getString("builds")); int buildsCount = 0; - if(builds.size()<50){ - buildsCount=builds.size(); - } - else{ - buildsCount=50; + if (builds.size() < 50) { + buildsCount = builds.size(); + } else { + buildsCount = 50; } StringBuilder str = new StringBuilder(); - for(int i=0;i buildResponse = Unirest.get(finalBuildUrl) - .header("Authorization", authorizationHeader) - .asString(); + .header("Authorization", authorizationHeader) + .asString(); String buildConsole = buildResponse.getBody().toString(); str.append(buildConsole); } catch (UnirestException e) { @@ -269,46 +266,45 @@ public void handleDelivery(String consumerTag, Envelope envelope, } } String allConsoleLogs = str.toString(); - boolean isFound = allConsoleLogs.contains("Started due to a request from UrbanCode Velocity. Work Id: "+workId); - if(isFound==true){ - log.info(" =========================== Found duplicate Jenkins Job and stopped it =========================== "); - } - else{ - System.out.println(" [x] Received '" + message + "'"); + boolean isFound = allConsoleLogs + .contains("Started due to a request from HCL Accelerate. Work Id: " + workId); + if (isFound == true) { + log.info( + " =========================== Found duplicate Jenkins Job and stopped it =========================== "); + } else { + System.out.println(logPrefix + "[x] Received '" + message + "'"); CloudWorkListener2 cloudWorkListener = new CloudWorkListener2(); - cloudWorkListener.call("startJob", message); + cloudWorkListener.call("startJob", message, entry); } } - } - } + } else { + System.out.println(logPrefix + "[x] Received '" + message + "'"); + CloudWorkListener2 cloudWorkListener = new CloudWorkListener2(); + cloudWorkListener.call("startJob", message, entry); + } } - }; + } + }; - if (checkQueueAvailability(channel, queueName)) { + if (checkQueueAvailability(channel, queueName, entry)) { channel.basicConsume(queueName, true, consumer); - }else{ - log.info("Queue is not yet available, will attempt to reconect shortly..."); + } else { + log.info(logPrefix + "Queue is not yet available, will attempt to reconect shortly..."); queueIsAvailable = false; } } } - public static boolean checkQueueAvailability(Channel channel, String queueName) throws IOException { + public static boolean checkQueueAvailability(Channel channel, String queueName, Entry entry) throws IOException { try { - channel.queueDeclarePassive(queueName); - queueIsAvailable = true; - return true; + channel.queueDeclarePassive(queueName); + queueIsAvailable = true; + return true; } catch (IOException e) { log.error("Checking Queue availability threw exception: ", e); + log.error("[HCL Accelerate " + entry.getBaseUrl() + "] Checking Queue availability threw exception: ",e); } return false; - } - - private String removeTrailingSlash(String url) { - if (url.endsWith("/")) { - url = url.substring(0, url.length() - 1); - } - return url; } public String getCauseOfFailure() { diff --git a/src/main/java/com/hcl/devops/connect/CloudWorkListener.java b/src/main/java/com/hcl/devops/connect/CloudWorkListener.java index a784f37..d4e4f7f 100644 --- a/src/main/java/com/hcl/devops/connect/CloudWorkListener.java +++ b/src/main/java/com/hcl/devops/connect/CloudWorkListener.java @@ -68,7 +68,7 @@ */ public class CloudWorkListener implements IWorkListener { public static final Logger log = LoggerFactory.getLogger(CloudWorkListener.class); - private String logPrefix= "[HCL Accelerate] CloudWorkListener#"; + private String logPrefix = "[HCL Accelerate] CloudWorkListener#"; public CloudWorkListener() { @@ -78,8 +78,11 @@ public enum WorkStatus { success, failed, started } - /* (non-Javadoc) - * @see com.ibm.cloud.urbancode.sync.IWorkListener#call(com.ibm.cloud.urbancode.connect.client.ConnectSocket, java.lang.String, java.lang.Object) + /* + * (non-Javadoc) + * + * @see com.ibm.cloud.urbancode.sync.IWorkListener#call(com.ibm.cloud.urbancode. + * connect.client.ConnectSocket, java.lang.String, java.lang.Object) */ @Override public void call(ConnectSocket socket, String event, Object... args) { @@ -93,8 +96,9 @@ public void callSecured(ConnectSocket socket, String event, Object... args) { log.info(logPrefix + " Received event from Connect Socket"); JSONArray incomingJobs = JSONArray.fromObject(args[0].toString()); + Entry entry = (Entry) args[1]; - for(int i=0; i < incomingJobs.size(); i++) { + for (int i = 0; i < incomingJobs.size(); i++) { WorkStatus workStatus = WorkStatus.started; @@ -102,9 +106,9 @@ public void callSecured(ConnectSocket socket, String event, Object... args) { // sample job creation request from a toolchain if (incomingJob.has("jobType") && "new".equalsIgnoreCase(incomingJob.get("jobType").toString())) { log.info(logPrefix + "Job creation request received."); - // delegating job creation to the Jenkins server - JenkinsServer.createJob(incomingJob); - } + // delegating job creation to the Jenkins server + JenkinsServer.createJob(incomingJob, entry); + } if (incomingJob.has("fullName")) { @@ -118,13 +122,13 @@ public void callSecured(ConnectSocket socket, String event, Object... args) { log.info("Item Found (1): " + item); // If item is not retrieved, get by full name - if(item == null) { + if (item == null) { item = myJenkins.getItemByFullName(fullName); log.info("Item Found (2): " + item); } // If item is not retrieved, get by full name with escaped characters - if(item == null) { + if (item == null) { item = myJenkins.getItemByFullName(escapeItemName(fullName)); log.info("Item Found (3): " + item); } @@ -132,7 +136,7 @@ public void callSecured(ConnectSocket socket, String event, Object... args) { List parametersList = generateParamList(incomingJob, getParameterTypeMap(item)); JSONObject returnProps = new JSONObject(); - if(incomingJob.has("returnProps")) { + if (incomingJob.has("returnProps")) { returnProps = incomingJob.getJSONObject("returnProps"); } @@ -140,7 +144,7 @@ public void callSecured(ConnectSocket socket, String event, Object... args) { Queue.Item queuedItem = null; String errorMessage = null; - if(item instanceof AbstractProject) { + if (item instanceof AbstractProject) { AbstractProject abstractProject = (AbstractProject)item; queuedItem = ParameterizedJobMixIn.scheduleBuild2(abstractProject, 0, new ParametersAction(parametersList), new CauseAction(cloudCause)); @@ -149,7 +153,7 @@ public void callSecured(ConnectSocket socket, String event, Object... args) { errorMessage = "Could not start parameterized build."; } } else if (item instanceof WorkflowJob) { - WorkflowJob workflowJob = (WorkflowJob)item; + WorkflowJob workflowJob = (WorkflowJob) item; QueueTaskFuture queuedTask = workflowJob.scheduleBuild2(0, new ParametersAction(parametersList), new CauseAction(cloudCause)); @@ -164,10 +168,10 @@ public void callSecured(ConnectSocket socket, String event, Object... args) { log.warn(errorMessage); } - if( errorMessage != null ) { + if (errorMessage != null) { JenkinsJobStatus erroredJobStatus = new JenkinsJobStatus(null, cloudCause, null, null, true, true); - JSONObject statusUpdate = erroredJobStatus.generateErrorStatus(errorMessage); - CloudPublisher.uploadJobStatus(statusUpdate); + JSONObject statusUpdate = erroredJobStatus.generateErrorStatus(errorMessage, entry); + CloudPublisher.uploadJobStatus(statusUpdate, entry); workStatus = WorkStatus.failed; } @@ -185,21 +189,20 @@ private void sendResult(ConnectSocket socket, String id, WorkStatus status, Stri json.put("id", id); json.put("status", status.name()); json.put("description", comment); - } - catch (JSONException e) { + } catch (JSONException e) { throw new RuntimeException("Error constructing work result JSON", e); } socket.emit("set_work_status", json.toString()); } - private List generateParamList (JSONObject incomingJob, Map typeMap) { + private List generateParamList(JSONObject incomingJob, Map typeMap) { ArrayList result = new ArrayList(); - if(incomingJob.has("props")) { + if (incomingJob.has("props")) { JSONObject props = incomingJob.getJSONObject("props"); Iterator keys = props.keys(); - while( keys.hasNext() ) { - String key = (String)keys.next(); + while(keys.hasNext()) { + String key = (String) keys.next(); Object value = props.get(key); String type = typeMap.get(key); @@ -209,18 +212,18 @@ private List generateParamList (JSONObject incomingJob, Map\t\t" + value); System.out.println("->\t\t" + type); - if(type == null) { + if (type == null) { - } else if(type.equalsIgnoreCase("BooleanParameterDefinition")) { - if(props.get(key).getClass().equals(String.class)) { - Boolean p = Boolean.parseBoolean((String)props.get(key)); + } else if (type.equalsIgnoreCase("BooleanParameterDefinition")) { + if (props.get(key).getClass().equals(String.class)) { + Boolean p = Boolean.parseBoolean((String) props.get(key)); result.add(new BooleanParameterValue(key, p)); } else { - result.add(new BooleanParameterValue(key, (boolean)props.get(key))); + result.add(new BooleanParameterValue(key, (boolean) props.get(key))); } - } else if(type.equalsIgnoreCase("PasswordParameterDefinition")) { + } else if (type.equalsIgnoreCase("PasswordParameterDefinition")) { result.add(new PasswordParameterValue(key, props.get(key).toString())); - } else if(type.equalsIgnoreCase("TextParameterDefinition")) { + } else if (type.equalsIgnoreCase("TextParameterDefinition")) { result.add(new TextParameterValue(key, props.get(key).toString())); } else { result.add(new StringParameterValue(key, props.get(key).toString())); @@ -234,24 +237,26 @@ private List generateParamList (JSONObject incomingJob, Map getParameterTypeMap(Item item) { Map result = new HashMap(); - if(item instanceof WorkflowJob) { - List> properties = ((WorkflowJob)item).getAllProperties(); + if (item instanceof WorkflowJob) { + List> properties = ((WorkflowJob) item).getAllProperties(); - for(JobProperty property : properties) { - if (property instanceof ParametersDefinitionProperty) { - List paraDefs = ((ParametersDefinitionProperty)property).getParameterDefinitions(); - for (ParameterDefinition paramDef : paraDefs) { + for (JobProperty property : properties) { + if (property instanceof ParametersDefinitionProperty) { + List paraDefs = ((ParametersDefinitionProperty) property) + .getParameterDefinitions(); + for (ParameterDefinition paramDef : paraDefs) { result.put(paramDef.getName(), paramDef.getType()); - } - } - } - } else if(item instanceof AbstractItem) { - List actions = ((AbstractItem)item).getActions(); - - for(Action action : actions) { - if (action instanceof ParametersDefinitionProperty) { - List paraDefs = ((ParametersDefinitionProperty)action).getParameterDefinitions(); - for (ParameterDefinition paramDef : paraDefs) { + } + } + } + } else if (item instanceof AbstractItem) { + List actions = ((AbstractItem) item).getActions(); + + for (Action action : actions) { + if (action instanceof ParametersDefinitionProperty) { + List paraDefs = ((ParametersDefinitionProperty) action) + .getParameterDefinitions(); + for (ParameterDefinition paramDef : paraDefs) { result.put(paramDef.getName(), paramDef.getType()); } } diff --git a/src/main/java/com/hcl/devops/connect/CloudWorkListener2.java b/src/main/java/com/hcl/devops/connect/CloudWorkListener2.java index 469cfdf..9a41ece 100644 --- a/src/main/java/com/hcl/devops/connect/CloudWorkListener2.java +++ b/src/main/java/com/hcl/devops/connect/CloudWorkListener2.java @@ -8,20 +8,20 @@ *******************************************************************************/ package com.hcl.devops.connect; -import java.util.concurrent.TimeUnit; +// import java.util.concurrent.TimeUnit; // import org.json.JSONArray; // import org.json.JSONException; // import org.json.JSONObject; -import org.apache.commons.lang.builder.ToStringBuilder; +// import org.apache.commons.lang.builder.ToStringBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.hcl.devops.connect.CloudCause.JobStatus; +// import com.google.common.cache.Cache; +// import com.google.common.cache.CacheBuilder; +// import com.hcl.devops.connect.CloudCause.JobStatus; import com.hcl.devops.connect.SecuredActions.AbstractSecuredAction; import com.hcl.devops.connect.SecuredActions.TriggerJob; import com.hcl.devops.connect.SecuredActions.TriggerJob.TriggerJobParamObj; @@ -54,9 +54,9 @@ import java.util.Map; import java.util.HashMap; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.lang.InterruptedException; +// import java.util.concurrent.CancellationException; +// import java.util.concurrent.ExecutionException; +// import java.lang.InterruptedException; import org.jenkinsci.plugins.workflow.job.WorkflowJob; @@ -66,7 +66,7 @@ import javax.crypto.spec.SecretKeySpec; import javax.crypto.Cipher; -import org.acegisecurity.userdetails.UsernameNotFoundException; +// import org.acegisecurity.userdetails.UsernameNotFoundException; /* * When Spring is applying the @Transactional annotation, it creates a proxy class which wraps your class. @@ -76,7 +76,6 @@ */ public class CloudWorkListener2 { public static final Logger log = LoggerFactory.getLogger(CloudWorkListener2.class); - private String logPrefix= "[HCL Accelerate] CloudWorkListener2#"; public CloudWorkListener2() { @@ -86,8 +85,11 @@ public enum WorkStatus { success, failed, started } - /* (non-Javadoc) - * @see com.ibm.cloud.urbancode.sync.IWorkListener#call(com.ibm.cloud.urbancode.connect.client.ConnectSocket, java.lang.String, java.lang.Object) + /* + * (non-Javadoc) + * + * @see com.ibm.cloud.urbancode.sync.IWorkListener#call(com.ibm.cloud.urbancode. + * connect.client.ConnectSocket, java.lang.String, java.lang.Object) */ public void call(String event, Object... args) { TriggerJob triggerJob = new TriggerJob(); @@ -96,10 +98,10 @@ public void call(String event, Object... args) { triggerJob.runAsJenkinsUser(paramObj); } private static byte[] toByte(String hexString) { - int len = hexString.length()/2; + int len = hexString.length() / 2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) { - result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); + result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue(); } return result; } @@ -117,28 +119,30 @@ private static String decrypt(String seed, String encrypted) throws Exception { } public void callSecured(ConnectSocket socket, String event, String securityError, Object... args) { - log.info(logPrefix + " Received event from Connect Socket"); String payload = args[0].toString(); - String token = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getSyncToken(); + Entry entry = (Entry) args[1]; + String logPrefix = "[HCL Accelerate " + entry.getBaseUrl() + "] CloudWorkListener2#callSecured - "; + log.info(logPrefix + "Received event from Connect Socket"); + String token = entry.getSyncToken(); try { payload = decrypt(token, payload); } catch (Exception e) { - //TODO handle decryption error + // TODO handle decryption error System.out.println("Unable to decrypt"); } - //TODO Don't make this an array in the silly way that I have. I just want this to work + // TODO Don't make this an array in the silly way that I have. I just want this to work JSONArray incomingJobs = JSONArray.fromObject("[" + payload + "]"); - for(int i=0; i < incomingJobs.size(); i++) { + for (int i = 0; i < incomingJobs.size(); i++) { JSONObject incomingJob = incomingJobs.getJSONObject(i); // sample job creation request from a toolchain if (incomingJob.has("jobType") && "new".equalsIgnoreCase(incomingJob.get("jobType").toString())) { log.info(logPrefix + "Job creation request received."); // delegating job creation to the Jenkins server - JenkinsServer.createJob(incomingJob); + JenkinsServer.createJob(incomingJob, entry); } if (incomingJob.has("fullName")) { @@ -149,24 +153,24 @@ public void callSecured(ConnectSocket socket, String event, String securityError // Get item by name Item item = myJenkins.getItem(fullName); - log.info("Item Found (1): " + item); + log.info(logPrefix + "Item Found (1): " + item); // If item is not retrieved, get by full name - if(item == null) { + if (item == null) { item = myJenkins.getItemByFullName(fullName); - log.info("Item Found (2): " + item); + log.info(logPrefix + "Item Found (2): " + item); } // If item is not retrieved, get by full name with escaped characters - if(item == null) { + if (item == null) { item = myJenkins.getItemByFullName(escapeItemName(fullName)); - log.info("Item Found (3): " + item); + log.info(logPrefix + "Item Found (3): " + item); } List parametersList = generateParamList(incomingJob, getParameterTypeMap(item)); JSONObject returnProps = new JSONObject(); - if(incomingJob.has("returnProps")) { + if (incomingJob.has("returnProps")) { returnProps = incomingJob.getJSONObject("returnProps"); } @@ -174,8 +178,8 @@ public void callSecured(ConnectSocket socket, String event, String securityError Queue.Item queuedItem = null; String errorMessage = null; - if(item instanceof AbstractProject) { - AbstractProject abstractProject = (AbstractProject)item; + if (item instanceof AbstractProject) { + AbstractProject abstractProject = (AbstractProject) item; queuedItem = ParameterizedJobMixIn.scheduleBuild2(abstractProject, 0, new ParametersAction(parametersList), new CauseAction(cloudCause)); @@ -183,7 +187,7 @@ public void callSecured(ConnectSocket socket, String event, String securityError errorMessage = "Could not start parameterized build."; } } else if (item instanceof WorkflowJob) { - WorkflowJob workflowJob = (WorkflowJob)item; + WorkflowJob workflowJob = (WorkflowJob) item; QueueTaskFuture queuedTask = workflowJob.scheduleBuild2(0, new ParametersAction(parametersList), new CauseAction(cloudCause)); @@ -191,8 +195,8 @@ public void callSecured(ConnectSocket socket, String event, String securityError errorMessage = "Could not start pipeline build."; } } else if (item == null) { - if(securityError != null) { - if(securityError.equals(AbstractSecuredAction.NO_CREDENTIALS_PROVIDED)) { + if (securityError != null) { + if (securityError.equals(AbstractSecuredAction.NO_CREDENTIALS_PROVIDED)) { errorMessage = "No Item Found. No Jenkins credentials were provided in Accelerate config on Jenkins 'Configure System' page. Credentials may be required."; } else { errorMessage = securityError; @@ -200,16 +204,16 @@ public void callSecured(ConnectSocket socket, String event, String securityError } else { errorMessage = "No Item Found"; } - log.warn(errorMessage); + log.warn(logPrefix + errorMessage); } else { errorMessage = "Unhandled job type found: " + item.getClass(); - log.warn(errorMessage); + log.warn(logPrefix + errorMessage); } - if( errorMessage != null ) { + if (errorMessage != null) { JenkinsJobStatus erroredJobStatus = new JenkinsJobStatus(null, cloudCause, null, null, true, true); - JSONObject statusUpdate = erroredJobStatus.generateErrorStatus(errorMessage); - CloudPublisher.uploadJobStatus(statusUpdate); + JSONObject statusUpdate = erroredJobStatus.generateErrorStatus(errorMessage, entry); + CloudPublisher.uploadJobStatus(statusUpdate, entry); } } @@ -219,14 +223,14 @@ public void callSecured(ConnectSocket socket, String event, String securityError } - private List generateParamList (JSONObject incomingJob, Map typeMap) { + private List generateParamList(JSONObject incomingJob, Map typeMap) { ArrayList result = new ArrayList(); - if(incomingJob.has("props")) { + if (incomingJob.has("props")) { JSONObject props = incomingJob.getJSONObject("props"); Iterator keys = props.keys(); - while( keys.hasNext() ) { - String key = (String)keys.next(); + while(keys.hasNext()) { + String key = (String) keys.next(); Object value = props.get(key); String type = typeMap.get(key); @@ -236,18 +240,18 @@ private List generateParamList (JSONObject incomingJob, Map\t\t" + value); System.out.println("->\t\t" + type); - if(type == null) { + if (type == null) { - } else if(type.equalsIgnoreCase("BooleanParameterDefinition")) { - if(props.get(key).getClass().equals(String.class)) { - Boolean p = Boolean.parseBoolean((String)props.get(key)); + } else if (type.equalsIgnoreCase("BooleanParameterDefinition")) { + if (props.get(key).getClass().equals(String.class)) { + Boolean p = Boolean.parseBoolean((String) props.get(key)); result.add(new BooleanParameterValue(key, p)); } else { - result.add(new BooleanParameterValue(key, (boolean)props.get(key))); + result.add(new BooleanParameterValue(key, (boolean) props.get(key))); } - } else if(type.equalsIgnoreCase("PasswordParameterDefinition")) { + } else if (type.equalsIgnoreCase("PasswordParameterDefinition")) { result.add(new PasswordParameterValue(key, props.get(key).toString())); - } else if(type.equalsIgnoreCase("TextParameterDefinition")) { + } else if (type.equalsIgnoreCase("TextParameterDefinition")) { result.add(new TextParameterValue(key, props.get(key).toString())); } else { result.add(new StringParameterValue(key, props.get(key).toString())); @@ -261,10 +265,10 @@ private List generateParamList (JSONObject incomingJob, Map getParameterTypeMap(Item item) { Map result = new HashMap(); - if(item instanceof WorkflowJob) { + if (item instanceof WorkflowJob) { List> properties = ((WorkflowJob)item).getAllProperties(); - for(JobProperty property : properties) { + for (JobProperty property : properties) { if (property instanceof ParametersDefinitionProperty) { List paraDefs = ((ParametersDefinitionProperty)property).getParameterDefinitions(); for (ParameterDefinition paramDef : paraDefs) { @@ -272,10 +276,10 @@ private Map getParameterTypeMap(Item item) { } } } - } else if(item instanceof AbstractItem) { + } else if (item instanceof AbstractItem) { List actions = ((AbstractItem)item).getActions(); - for(Action action : actions) { + for (Action action : actions) { if (action instanceof ParametersDefinitionProperty) { List paraDefs = ((ParametersDefinitionProperty)action).getParameterDefinitions(); for (ParameterDefinition paramDef : paraDefs) { diff --git a/src/main/java/com/hcl/devops/connect/ConnectComputerListener.java b/src/main/java/com/hcl/devops/connect/ConnectComputerListener.java index aea95ca..8a513b9 100644 --- a/src/main/java/com/hcl/devops/connect/ConnectComputerListener.java +++ b/src/main/java/com/hcl/devops/connect/ConnectComputerListener.java @@ -18,50 +18,56 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; - +import java.util.List; @Extension public class ConnectComputerListener extends ComputerListener { public static final Logger log = LoggerFactory.getLogger(ConnectComputerListener.class); - private String logPrefix= "[HCL Accelerate] ConnectComputerListener#"; private static CloudSocketComponent cloudSocketInstance; private static ReconnectExecutor reconnectExecutor; - private static void setCloudSocketComponent( CloudSocketComponent comp ) { + public static boolean isRabbitConnected(Entry entry) { + return cloudSocketInstance.isAMQPConnected(entry); + } + + private static void setCloudSocketComponent(CloudSocketComponent comp) { cloudSocketInstance = comp; } @Override public void onOnline(Computer c) { - if ( c instanceof jenkins.model.Jenkins.MasterComputer && Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { - logPrefix= logPrefix + "onOnline "; - String url = getConnectUrl(); - - CloudWorkListener listener = new CloudWorkListener(); + + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getEntries(); + for (Entry entry : entries) { + if (c instanceof jenkins.model.Jenkins.MasterComputer && entry.isConfigured()) { + String url = getConnectUrl(entry); + String logPrefix = "[HCL Accelerate " + entry.getBaseUrl() + + "] ConnectComputerListener#onOnline - "; + CloudWorkListener listener = new CloudWorkListener(); + ConnectComputerListener.setCloudSocketComponent(new CloudSocketComponent(listener, url)); - ConnectComputerListener.setCloudSocketComponent(new CloudSocketComponent(listener, url)); - - try { - log.info(logPrefix + "Connecting to Cloud Services..."); - getCloudSocketInstance().connectToCloudServices(); - } catch (Exception e) { - log.error(logPrefix + "Exception caught while connecting to Cloud Services: " + e); - e.printStackTrace(); - } + try { + log.info(logPrefix + "Connecting to Cloud Services..."); + getCloudSocketInstance().connectToCloudServices(entry); + } catch (Exception e) { + log.error(logPrefix + "Exception caught while connecting to Cloud Services: " + e); + e.printStackTrace(); + } // Synchronized to protect lazy initalization of static variable - synchronized(this) { - if(reconnectExecutor == null) { + synchronized (this) { + if (reconnectExecutor == null) { reconnectExecutor = new ReconnectExecutor(cloudSocketInstance); reconnectExecutor.startReconnectExecutor(); } + } } } } - private String getConnectUrl() { + private String getConnectUrl(Entry entry) { EndpointManager em = new EndpointManager(); - return em.getConnectEndpoint(); + return em.getConnectEndpoint(entry); } public CloudSocketComponent getCloudSocketInstance() { diff --git a/src/main/java/com/hcl/devops/connect/DevOpsGlobalConfiguration.java b/src/main/java/com/hcl/devops/connect/DevOpsGlobalConfiguration.java index 640afb9..091ffd3 100644 --- a/src/main/java/com/hcl/devops/connect/DevOpsGlobalConfiguration.java +++ b/src/main/java/com/hcl/devops/connect/DevOpsGlobalConfiguration.java @@ -15,6 +15,8 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of package com.hcl.devops.connect; import java.util.List; +import java.util.ArrayList; +import java.util.Collections; import hudson.CopyOnWrite; import hudson.Extension; @@ -42,51 +44,26 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of public class DevOpsGlobalConfiguration extends GlobalConfiguration { @CopyOnWrite - private volatile String syncId; - private volatile String syncToken; - private volatile String baseUrl; private String credentialsId; - private String rabbitMQPort; - private String rabbitMQHost; - private String apiToken; + private List entries = new ArrayList<>(); public DevOpsGlobalConfiguration() { load(); } - public String getSyncId() { - return syncId; + public List getEntries() { + return entries; } - public void setSyncId(String syncId) { - this.syncId = syncId; - save(); - } - - public String getSyncToken() { - return syncToken; - } - - public void setSyncToken(String syncToken) { - this.syncToken = syncToken; - save(); - } - - public String getApiToken() { - return apiToken; - } - - public void setApiToken(String apiToken) { - this.apiToken = apiToken; - save(); - } - - public String getBaseUrl() { - return baseUrl; - } - - public void setBaseUrl(String baseUrl) { - this.baseUrl = baseUrl; + public void setEntries(List entries) { + List entriesFinal = new ArrayList<>(); + for (Entry entry : entries) { + if (StringUtils.isNotEmpty(entry.getSyncId()) && StringUtils.isNotEmpty(entry.getBaseUrl()) + && StringUtils.isNotEmpty(entry.getApiToken()) && StringUtils.isNotEmpty(entry.getSyncToken())) { + entriesFinal.add(entry); + } + } + this.entries = entriesFinal; save(); } @@ -99,40 +76,17 @@ public void setCredentialsId(String credentialsId) { save(); } - public String getRabbitMQPort() { - return rabbitMQPort; - } - - public String getRabbitMQHost() { - return rabbitMQHost; - } - - public void setRabbitMQPort(String rabbitMQPort) { - this.rabbitMQPort = rabbitMQPort; - save(); - } - - public void setRabbitMQHost(String rabbitMQHost) { - this.rabbitMQHost = rabbitMQHost; - save(); - } - @Override public boolean configure(StaplerRequest req, JSONObject formData) throws FormException { // To persist global configuration information, // set that to properties and call save(). - syncId = formData.getString("syncId"); - syncToken = formData.getString("syncToken"); - baseUrl = formData.getString("baseUrl"); - credentialsId = formData.getString("credentialsId"); - rabbitMQPort = formData.getString("rabbitMQPort"); - rabbitMQHost = formData.getString("rabbitMQHost"); - apiToken = formData.getString("apiToken"); + setEntries(Collections.emptyList()); + req.bindJSON(this, formData); save(); reconnectCloudSocket(); - return super.configure(req,formData); + return super.configure(req, formData); } // for the future multi-region use @@ -141,29 +95,6 @@ public ListBoxModel doFillRegionItems() { return items; } - public FormValidation doTestConnection(@QueryParameter("syncId") final String syncId, - @QueryParameter("syncToken") final String syncToken, - @QueryParameter("baseUrl") final String baseUrl) - throws FormException { - try { - boolean connected = CloudPublisher.testConnection(syncId, syncToken, baseUrl); - if (connected) { - boolean amqpConnected = CloudSocketComponent.isAMQPConnected(); - - String rabbitMessage = "Not connected to RabbitMQ. Unable to run Jenkins jobs from HCL Accelerate."; - if(amqpConnected) { - rabbitMessage = "Connected to RabbitMQ successfully. Ready to run Jenkins jobs from HCL Accelerate."; - } - - return FormValidation.ok("Successful connection to Accelerate Services.\n" + rabbitMessage); - } else { - return FormValidation.error("Could not connect to Accelerate. Please check your URL and credentials provided."); - } - } catch (Exception e) { - return FormValidation.error("Could not connect to Accelerate : " + e.getMessage()); - } - } - /** * This method is called to populate the credentials list on the Jenkins config page. */ @@ -175,20 +106,18 @@ public ListBoxModel doFillCredentialsIdItems(@QueryParameter("target") final Str StandardUsernameCredentials.class, Jenkins.getInstance(), ACL.SYSTEM, - URIRequirementBuilder.fromUri(target).build() - ) - ); + URIRequirementBuilder.fromUri(target).build())); return result; } public StandardUsernamePasswordCredentials getCredentialsObj() { List standardCredentials = CredentialsProvider.lookupCredentials( - StandardUsernamePasswordCredentials.class, - Jenkins.getInstance(), - ACL.SYSTEM); + StandardUsernamePasswordCredentials.class, + Jenkins.getInstance(), + ACL.SYSTEM); - StandardUsernamePasswordCredentials credentials = - CredentialsMatchers.firstOrNull(standardCredentials, CredentialsMatchers.withId(this.credentialsId)); + StandardUsernamePasswordCredentials credentials = CredentialsMatchers.firstOrNull(standardCredentials, + CredentialsMatchers.withId(this.credentialsId)); return credentials; } @@ -199,11 +128,7 @@ private void reconnectCloudSocket() { connectComputerListener.onOnline(Jenkins.getInstance().toComputer()); } - public boolean isConfigured() { - return StringUtils.isNotEmpty(this.syncId) && - StringUtils.isNotEmpty(this.syncToken) && - StringUtils.isNotEmpty(this.baseUrl) && - StringUtils.isNotEmpty(this.credentialsId) && - StringUtils.isNotEmpty(this.apiToken); + public FormValidation doCheckCredentialsId(@QueryParameter("credentialsId") String credentialsId) { + return FormValidation.validateRequired(credentialsId); } } diff --git a/src/main/java/com/hcl/devops/connect/Endpoints/EndpointManager.java b/src/main/java/com/hcl/devops/connect/Endpoints/EndpointManager.java index 3daa6d2..0bb6787 100644 --- a/src/main/java/com/hcl/devops/connect/Endpoints/EndpointManager.java +++ b/src/main/java/com/hcl/devops/connect/Endpoints/EndpointManager.java @@ -1,5 +1,5 @@ package com.hcl.devops.connect.Endpoints; - +import com.hcl.devops.connect.Entry; public class EndpointManager { // TODO: Make configurable at build time or otherwise @@ -12,43 +12,47 @@ public EndpointManager() { endpointProvider = new EndpointsAccelerate(); } - public String getSyncApiEndpoint() { - return endpointProvider.getSyncApiEndpoint(); + public String getSyncApiEndpoint(Entry entry) { + return endpointProvider.getSyncApiEndpoint(entry); + } + + public String getGraphqlApiEndpoint(Entry entry) { + return endpointProvider.getGraphqlApiEndpoint(entry); } - public String getPipelinesEndpoint() { - return endpointProvider.getPipelinesEndpoint(); + public String getPipelinesEndpoint(Entry entry) { + return endpointProvider.getPipelinesEndpoint(entry); } - public String getQualityDataEndpoint() { - return endpointProvider.getQualityDataEndpoint(); + public String getQualityDataEndpoint(Entry entry) { + return endpointProvider.getQualityDataEndpoint(entry); } - public String getQualityDataRawEndpoint() { - return endpointProvider.getQualityDataRawEndpoint(); + public String getQualityDataRawEndpoint(Entry entry) { + return endpointProvider.getQualityDataRawEndpoint(entry); } public String getSyncApiEndpoint(String baseUrl) { return endpointProvider.getSyncApiEndpoint(baseUrl); } - public String getReleaseEvensApiEndpoint() { - return endpointProvider.getReleaseEvensApiEndpoint(); + public String getReleaseEvensApiEndpoint(Entry entry) { + return endpointProvider.getReleaseEvensApiEndpoint(entry); } - public String getDotsEndpoint() { - return endpointProvider.getDotsEndpoint(); + public String getDotsEndpoint(Entry entry) { + return endpointProvider.getDotsEndpoint(entry); } - public String getSyncStoreEndpoint() { - return endpointProvider.getSyncStoreEndpoint(); + public String getSyncStoreEndpoint(Entry entry) { + return endpointProvider.getSyncStoreEndpoint(entry); } - public String getConnectEndpoint() { - return endpointProvider.getConnectEndpoint(); + public String getConnectEndpoint(Entry entry) { + return endpointProvider.getConnectEndpoint(entry); } - public String getAccelerateHostname() { - return endpointProvider.getAccelerateHostname(); + public String getAccelerateHostname(Entry entry) { + return endpointProvider.getAccelerateHostname(entry); } } diff --git a/src/main/java/com/hcl/devops/connect/Endpoints/EndpointsAccelerate.java b/src/main/java/com/hcl/devops/connect/Endpoints/EndpointsAccelerate.java index 889ea94..2879892 100644 --- a/src/main/java/com/hcl/devops/connect/Endpoints/EndpointsAccelerate.java +++ b/src/main/java/com/hcl/devops/connect/Endpoints/EndpointsAccelerate.java @@ -3,9 +3,10 @@ import jenkins.model.Jenkins; import java.net.URL; - +import com.hcl.devops.connect.CloudPublisher; import com.hcl.devops.connect.DevOpsGlobalConfiguration; - +import com.hcl.devops.connect.Entry; +import java.util.List; import java.net.MalformedURLException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,47 +23,52 @@ public class EndpointsAccelerate implements IEndpoints { private static final String RELEASE_EVENTS_API_PATH = "/release-events-api/"; private static final String DOTS_PATH = "/api/v1/dots"; private static final String PIPELINES_PATH = "/pipelines/"; + private static final String GRAPHQL_PATH = "/release-events-api/graphql/"; + + public String getReleaseEvensApiEndpoint(Entry entry) { + return getBaseUrl(entry) + RELEASE_EVENTS_API_PATH; + } - public String getReleaseEvensApiEndpoint() { - return getBaseUrl() + RELEASE_EVENTS_API_PATH; + public String getGraphqlApiEndpoint(Entry entry) { + return getBaseUrl(entry) + GRAPHQL_PATH; } - public String getSyncApiEndpoint() { - return getBaseUrl() + REPORTING_SYNC_PATH; + public String getSyncApiEndpoint(Entry entry) { + return getBaseUrl(entry) + REPORTING_SYNC_PATH; } - public String getDotsEndpoint() { - return getBaseUrl() + DOTS_PATH; + public String getDotsEndpoint(Entry entry) { + return getBaseUrl(entry) + DOTS_PATH; } public String getSyncApiEndpoint(String baseUrl) { - baseUrl = removeTrailingSlash(baseUrl); + baseUrl = CloudPublisher.removeTrailingSlash(baseUrl); return baseUrl + REPORTING_SYNC_PATH; } - public String getPipelinesEndpoint() { - return getBaseUrl() + PIPELINES_PATH; + public String getPipelinesEndpoint(Entry entry) { + return getBaseUrl(entry) + PIPELINES_PATH; } - public String getQualityDataEndpoint() { - return getBaseUrl() + QUALITY_DATA_PATH; + public String getQualityDataEndpoint(Entry entry) { + return getBaseUrl(entry) + QUALITY_DATA_PATH; } - public String getQualityDataRawEndpoint() { - return getBaseUrl() + QUALITY_DATA_RAW_PATH; + public String getQualityDataRawEndpoint(Entry entry) { + return getBaseUrl(entry) + QUALITY_DATA_RAW_PATH; } - public String getSyncStoreEndpoint() { + public String getSyncStoreEndpoint(Entry entry) { return SYNC_STORE_ENPOINT; } - public String getConnectEndpoint() { + public String getConnectEndpoint(Entry entry) { return CONNECT_ENPOINT; } - public String getAccelerateHostname() { + public String getAccelerateHostname(Entry entry) { try { - String url = getBaseUrl(); + String url = getBaseUrl(entry); URL urlObj = new URL(url); return urlObj.getHost(); } catch (MalformedURLException e) { @@ -71,14 +77,8 @@ public String getAccelerateHostname() { return ""; } - private String getBaseUrl() { - return removeTrailingSlash(Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getBaseUrl()); - } - - private String removeTrailingSlash(String url) { - if (url.endsWith("/")) { - url = url.substring(0, url.length() - 1); - } - return url; + private String getBaseUrl(Entry entry) { + return CloudPublisher.removeTrailingSlash(entry.getBaseUrl()); } + } \ No newline at end of file diff --git a/src/main/java/com/hcl/devops/connect/Endpoints/IEndpoints.java b/src/main/java/com/hcl/devops/connect/Endpoints/IEndpoints.java index 34c4224..a8701a4 100644 --- a/src/main/java/com/hcl/devops/connect/Endpoints/IEndpoints.java +++ b/src/main/java/com/hcl/devops/connect/Endpoints/IEndpoints.java @@ -1,24 +1,28 @@ package com.hcl.devops.connect.Endpoints; +import com.hcl.devops.connect.Entry; + public interface IEndpoints { - public String getSyncApiEndpoint(); + public String getSyncApiEndpoint(Entry entry); + + public String getGraphqlApiEndpoint(Entry entry); - public String getPipelinesEndpoint(); + public String getPipelinesEndpoint(Entry entry); public String getSyncApiEndpoint(String baseUrl); - public String getSyncStoreEndpoint(); + public String getSyncStoreEndpoint(Entry entry); - public String getConnectEndpoint(); + public String getConnectEndpoint(Entry entry); - public String getQualityDataEndpoint(); + public String getQualityDataEndpoint(Entry entry); - public String getQualityDataRawEndpoint(); + public String getQualityDataRawEndpoint(Entry entry); - public String getAccelerateHostname(); + public String getAccelerateHostname(Entry entry); - public String getReleaseEvensApiEndpoint(); + public String getReleaseEvensApiEndpoint(Entry entry); - public String getDotsEndpoint(); + public String getDotsEndpoint(Entry entry); } \ No newline at end of file diff --git a/src/main/java/com/hcl/devops/connect/Entry.java b/src/main/java/com/hcl/devops/connect/Entry.java new file mode 100644 index 0000000..81f9771 --- /dev/null +++ b/src/main/java/com/hcl/devops/connect/Entry.java @@ -0,0 +1,213 @@ +package com.hcl.devops.connect; + +import hudson.Extension; +import hudson.model.Describable; +import hudson.model.Descriptor; +import hudson.util.ListBoxModel; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.QueryParameter; +import hudson.util.FormValidation; +import org.kohsuke.stapler.interceptor.RequirePOST; + +import java.util.List; +import jenkins.model.Jenkins; +import org.apache.commons.lang.StringUtils; + +public final class Entry implements Describable { + + /** + * Destination bucket for the copy. Can contain macros. + */ + private String syncId; + private String syncToken; + private String baseUrl; + private String rabbitMQPort; + private String rabbitMQHost; + private String apiToken; + private Boolean checkDuplicate; + + @DataBoundConstructor + public Entry(String syncId, String syncToken, String baseUrl, String rabbitMQPort, String rabbitMQHost, + String apiToken, Boolean checkDuplicate) { + this.syncId = syncId; + this.syncToken = syncToken; + this.baseUrl = baseUrl; + this.rabbitMQPort = rabbitMQPort; + this.rabbitMQHost = rabbitMQHost; + this.apiToken = apiToken; + this.checkDuplicate = checkDuplicate; + } + + public Entry(Object object) { + } + + public String getSyncId() { + return syncId; + } + + public String getSyncToken() { + return syncToken; + } + + public String getBaseUrl() { + return baseUrl; + } + + public String getRabbitMQPort() { + return rabbitMQPort; + } + + public String getRabbitMQHost() { + return rabbitMQHost; + } + + public String getApiToken() { + return apiToken; + } + + public Boolean getCheckDuplicate() { + return checkDuplicate; + } + + public boolean isConfigured() { + return StringUtils.isNotEmpty(this.syncId) && + StringUtils.isNotEmpty(this.syncToken) && + StringUtils.isNotEmpty(this.baseUrl) && + StringUtils.isNotEmpty(this.apiToken); + } + + @Override + public Descriptor getDescriptor() { + return DESCRIPOR; + } + + @Extension + public static final DescriptorImpl DESCRIPOR = new DescriptorImpl(); + + public static class DescriptorImpl extends Descriptor { + @Override + public String getDisplayName() { + return "Connect to HCL Accelerate Instance"; + } + + @SuppressWarnings("unused") + @RequirePOST + public FormValidation doTestConnections(@QueryParameter("syncId") String syncId, + @QueryParameter("syncToken") String syncToken, + @QueryParameter("baseUrl") String baseUrl) { + try { + boolean connected = CloudPublisher.testConnection(syncId, syncToken, baseUrl); + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class) + .getEntries(); + Entry finalEntry = null; + for (Entry entry : entries) { + if (baseUrl.equals(entry.getBaseUrl()) && syncId.equals(entry.getSyncId())) { + finalEntry = entry; + } + } + if (connected) { + boolean amqpConnected = ConnectComputerListener.isRabbitConnected(finalEntry); + + String rabbitMessage = "Not connected to RabbitMQ. Unable to run Jenkins jobs from " + + finalEntry.getBaseUrl(); + if (amqpConnected) { + if (StringUtils.isNotEmpty(finalEntry.getRabbitMQHost())) { + rabbitMessage = "Connected to RabbitMQ ( " + finalEntry.getRabbitMQHost() + + " ) successfully. Ready to run Jenkins jobs from " + finalEntry.getBaseUrl(); + } else { + rabbitMessage = "Connected to RabbitMQ successfully. Using default 'localhost' for RabbitMQ host. Ready to run Jenkins jobs from " + + finalEntry.getBaseUrl(); + } + } + + return FormValidation.ok("Successful connection to Accelerate Services.\n" + rabbitMessage); + } else { + return FormValidation.error("Could not connect to " + finalEntry.getBaseUrl() + + ". Please check your URL and credentials provided."); + } + } catch (Exception e) { + if (e.getMessage().contains("Index") && e.getMessage().contains("out of bounds for length")) { + return FormValidation.error("Could not connect to Accelerate : " + e.getMessage() + + "\nPlease try to Apply/Save Configration and Restart Jenkins"); + } else { + return FormValidation.error("Could not connect to Accelerate : " + e.getMessage()); + } + } + } + + public FormValidation doCheckSyncId(@QueryParameter("syncId") String syncId) { + int count = 0; + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class) + .getEntries(); + for (Entry entry : entries) { + if (entry.getSyncId().equals(syncId)) { + count = count + 1; + } + } + if (count > 1) { + return FormValidation.error("Duplicates not Allowed."); + } + return FormValidation.validateRequired(syncId); + } + + public FormValidation doCheckSyncToken(@QueryParameter("syncToken") String syncToken) { + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class) + .getEntries(); + int count = 0; + for (Entry entry : entries) { + if (entry.getSyncToken().equals(syncToken)) { + count = count + 1; + } + } + if (count > 1) { + return FormValidation.error("Duplicates not Allowed."); + } + return FormValidation.validateRequired(syncToken); + } + + public FormValidation doCheckBaseUrl(@QueryParameter("baseUrl") String baseUrl) { + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class) + .getEntries(); + int count = 0; + for (Entry entry : entries) { + if (entry.getBaseUrl().equals(baseUrl)) { + count = count + 1; + } + } + if (count > 1) { + return FormValidation.error("Duplicates not Allowed."); + } + return FormValidation.validateRequired(baseUrl); + } + + public FormValidation doCheckApiToken(@QueryParameter("apiToken") String apiToken) { + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class) + .getEntries(); + int count = 0; + for (Entry entry : entries) { + if (entry.getApiToken().equals(apiToken)) { + count = count + 1; + } + } + if (count > 1) { + return FormValidation.error("Duplicates not Allowed."); + } + return FormValidation.validateRequired(apiToken); + } + + public FormValidation doCheckRabbitMQHost(@QueryParameter("rabbitMQHost") String rabbitMQHost) { + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class) + .getEntries(); + int count = 0; + for (Entry entry : entries) { + if (entry.getRabbitMQHost().equals(rabbitMQHost)) { + count = count + 1; + } + } + if (count > 1) { + return FormValidation.error("Duplicates not Allowed."); + } + return FormValidation.ok(); + } + } +} diff --git a/src/main/java/com/hcl/devops/connect/JenkinsIntegrationId.java b/src/main/java/com/hcl/devops/connect/JenkinsIntegrationId.java index ee10e73..4f07a68 100644 --- a/src/main/java/com/hcl/devops/connect/JenkinsIntegrationId.java +++ b/src/main/java/com/hcl/devops/connect/JenkinsIntegrationId.java @@ -5,14 +5,15 @@ import org.jenkinsci.plugins.uniqueid.IdStore; import jenkins.model.Jenkins; +import java.util.List; public class JenkinsIntegrationId { - public JenkinsIntegrationId () { + public JenkinsIntegrationId() { } - public String getIntegrationId() { - String result = getSyncId() + "_" + getJenkinsId(); + public String getIntegrationId(int instanceNum) { + String result = getSyncId(instanceNum) + "_" + getJenkinsId(); return result; } @@ -28,7 +29,8 @@ private String getJenkinsId() { return jenkinsId; } - private String getSyncId() { - return Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getSyncId(); + private String getSyncId(int instanceNum) { + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getEntries(); + return entries.get(instanceNum).getSyncId(); } } \ No newline at end of file diff --git a/src/main/java/com/hcl/devops/connect/JenkinsJob.java b/src/main/java/com/hcl/devops/connect/JenkinsJob.java index a29ffb6..c1a5a8f 100644 --- a/src/main/java/com/hcl/devops/connect/JenkinsJob.java +++ b/src/main/java/com/hcl/devops/connect/JenkinsJob.java @@ -47,9 +47,10 @@ public class JenkinsJob { final private Item item; public static final Logger log = LoggerFactory.getLogger(JenkinsJob.class); - public JenkinsJob (Item item) { - this.item= item; + public JenkinsJob(Item item) { + this.item = item; } + // TODO: see what this guy can do for us: // - start: start a job // - getStatus: get the status of a job @@ -58,10 +59,10 @@ public JenkinsJob (Item item) { // - other stuff? public JSONObject toJson() { - String displayName= this.item.getDisplayName(); - String name= this.item.getName(); - String fullName= this.item.getFullName(); - String jobUrl= this.item.getUrl(); + String displayName = this.item.getDisplayName(); + String name = this.item.getName(); + String fullName = this.item.getFullName(); + String jobUrl = this.item.getUrl(); JSONObject jobToJson = new JSONObject(); jobToJson.put("displayName", displayName); @@ -72,7 +73,7 @@ public JSONObject toJson() { String jobId; - if(IdStore.getId(this.item) != null) { + if (IdStore.getId(this.item) != null) { jobId = IdStore.getId(this.item); } else { IdStore.makeId(this.item); @@ -82,7 +83,7 @@ public JSONObject toJson() { jobToJson.put("id", jobId); jobToJson.put("instanceType", "JENKINS"); - if(this.item instanceof WorkflowJob) { + if (this.item instanceof WorkflowJob) { jobToJson.put("isPipeline", true); // TODO: Find a way to get Stage definitions } else { @@ -106,9 +107,9 @@ private JSONArray getJobParams() { } } } else if (this.item instanceof AbstractProject) { - List actions = ((AbstractProject)this.item).getActions(); + List actions = ((AbstractProject) this.item).getActions(); - for(Action action : actions) { + for (Action action : actions) { if (action instanceof ParametersDefinitionProperty) { List paraDefs = ((ParametersDefinitionProperty)action).getParameterDefinitions(); for (ParameterDefinition paramDef : paraDefs) { @@ -132,8 +133,8 @@ private JSONObject convertJobParameter(ParameterDefinition paramDef) { result.put("defaultValue", pValue.getValue()); } - if(paramDef instanceof ChoiceParameterDefinition) { - List options = ((ChoiceParameterDefinition)paramDef).getChoices(); + if (paramDef instanceof ChoiceParameterDefinition) { + List options = ((ChoiceParameterDefinition) paramDef).getChoices(); result.put("options", options); } diff --git a/src/main/java/com/hcl/devops/connect/JenkinsServer.java b/src/main/java/com/hcl/devops/connect/JenkinsServer.java index e67517b..940cee7 100644 --- a/src/main/java/com/hcl/devops/connect/JenkinsServer.java +++ b/src/main/java/com/hcl/devops/connect/JenkinsServer.java @@ -44,177 +44,192 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.charset.Charset; + /** * Jenkins server */ public class JenkinsServer { public static final Logger log = LoggerFactory.getLogger(JenkinsServer.class); - private static String logPrefix= "[HCL Accelerate] JenkinsServer#"; - - // creds - private static String BLX_CREDS= "IBM_CLOUD_DEVOPS_CREDS_API"; - private static String BLX_CREDS_DESC= "IBM DevOps Bluemix credentials"; - // folder and job - private static String FOLDER_SPEC= "Folder created by the IBM Devops plugin"; - private static String jobSrc= "\r\n\r\n \r\n false\r\n \r\n \r\n \r\n \r\n * * * * *\r\n false\r\n \r\n \r\n \r\n \r\n \r\n \r\n 2\r\n \r\n \r\n https://github.com/ejodet/discovery-nodejs\r\n \r\n \r\n \r\n \r\n */mastertoto\r\n \r\n \r\n false\r\n \r\n \r\n \r\n Jenkinsfile\r\n true\r\n \r\n \r\n"; - - public static Collection getJobNames() { - log.debug(logPrefix + "getJobNames - get the list of job names"); - Collection allJobNames= Jenkins.getInstance().getJobNames(); - log.debug(logPrefix + "getJobNames - retrieved " + allJobNames.size() + " JobNames"); - for (Iterator iterator = allJobNames.iterator(); iterator.hasNext();) { - - String aJobName = (String) iterator.next(); - log.debug(logPrefix + "job: " + aJobName); - } - return Jenkins.getInstance().getJobNames(); - } - - public static List getAllItems() { - log.debug(logPrefix + "getAllItems - get the list of all items"); - List allItems= Jenkins.getInstance().getAllItems(); - if (allItems.size() == 0) { // ensure we're able to list all items - AuthorizationStrategy authorizationStrategy= Jenkins.getInstance().getAuthorizationStrategy(); - if (authorizationStrategy instanceof FullControlOnceLoggedInAuthorizationStrategy) { - // allow anoymous read in order to get all items - FullControlOnceLoggedInAuthorizationStrategy strat= (FullControlOnceLoggedInAuthorizationStrategy) authorizationStrategy; - // remember previous settings - boolean isAllowAnonymousRead= strat.isAllowAnonymousRead(); - strat.setAllowAnonymousRead(true); - allItems= Jenkins.getInstance().getAllItems(); - strat.setAllowAnonymousRead(isAllowAnonymousRead); - Jenkins.getInstance().setAuthorizationStrategy(strat); - } - } - log.debug(logPrefix + "getAllItems - Retrieved " + allItems.size() + " projects"); - return allItems; - } - - public static Item getItemByName(String itemName) { - log.info(logPrefix + "Retrieving project " + itemName); - List allProjects= JenkinsServer.getAllItems(); - - for (Item anItem : allProjects) { - String aName = anItem.getFullName(); - log.info(logPrefix + "project " + aName); - if (itemName.equals(aName)) { - log.info(logPrefix + "Project " + itemName + " retrieved!"); - return anItem; - } + + private static String logPrefix = "[HCL Accelerate] JenkinsServer#"; + + // creds + private static String BLX_CREDS = "IBM_CLOUD_DEVOPS_CREDS_API"; + private static String BLX_CREDS_DESC = "IBM DevOps Bluemix credentials"; + // folder and job + private static String FOLDER_SPEC = "Folder created by the IBM Devops plugin"; + private static String jobSrc = "\r\n\r\n \r\n false\r\n \r\n \r\n \r\n \r\n * * * * *\r\n false\r\n \r\n \r\n \r\n \r\n \r\n \r\n 2\r\n \r\n \r\n https://github.com/ejodet/discovery-nodejs\r\n \r\n \r\n \r\n \r\n */mastertoto\r\n \r\n \r\n false\r\n \r\n \r\n \r\n Jenkinsfile\r\n true\r\n \r\n \r\n"; + + public static Collection getJobNames(Entry entry) { + String logPrefix = "[HCL Accelerate " + entry.getBaseUrl() + "] JenkinsServer#getJobNames - "; + log.debug(logPrefix + "get the list of job names"); + Collection allJobNames = Jenkins.getInstance().getJobNames(); + log.debug(logPrefix + "retrieved " + allJobNames.size() + " JobNames"); + for (Iterator iterator = allJobNames.iterator(); iterator.hasNext();) { + String aJobName = (String) iterator.next(); + log.debug(logPrefix + "job: " + aJobName); + } + return Jenkins.getInstance().getJobNames(); + } + + public static List getAllItems() { + log.debug(logPrefix + "getAllItems - get the list of all items"); + List allItems = Jenkins.getInstance().getAllItems(); + if (allItems.size() == 0) { // ensure we're able to list all items + AuthorizationStrategy authorizationStrategy = Jenkins.getInstance().getAuthorizationStrategy(); + if (authorizationStrategy instanceof FullControlOnceLoggedInAuthorizationStrategy) { + // allow anoymous read in order to get all items + FullControlOnceLoggedInAuthorizationStrategy strat = (FullControlOnceLoggedInAuthorizationStrategy) authorizationStrategy; + // remember previous settings + boolean isAllowAnonymousRead = strat.isAllowAnonymousRead(); + strat.setAllowAnonymousRead(true); + allItems = Jenkins.getInstance().getAllItems(); + strat.setAllowAnonymousRead(isAllowAnonymousRead); + Jenkins.getInstance().setAuthorizationStrategy(strat); + } + } + log.debug(logPrefix + "getAllItems - Retrieved " + allItems.size() + " projects"); + return allItems; + } + + public static Item getItemByName(String itemName) { + log.info(logPrefix + "Retrieving project " + itemName); + List allProjects = JenkinsServer.getAllItems(); + + for (Item anItem : allProjects) { + String aName = anItem.getFullName(); + log.info(logPrefix + "project " + aName); + if (itemName.equals(aName)) { + log.info(logPrefix + "Project " + itemName + " retrieved!"); + return anItem; + } + } + log.info(logPrefix + "Project " + itemName + " not found!"); + return null; + } + + public static void createJob(JSONObject newJob, Entry entry) { + String logPrefix = "[HCL Accelerate " + entry.getBaseUrl() + "] JenkinsServer#createJob - "; + log.debug(logPrefix + "Creating a new job."); + if (validCreationRequest(newJob, entry)) { + // get current security settings + SecurityRealm securityRealm = Jenkins.getInstance().getSecurityRealm(); + AuthorizationStrategy authorizationStrategy = Jenkins.getInstance().getAuthorizationStrategy(); + + // temporarily disable security as we are not allowed to create jobs as + // anonymous + disableSecurity(entry); + try { + // create creds if necessary + createCredentials(newJob, entry); + JSONObject props = newJob.getJSONObject("props"); + // create folder + String folderName = props.get("folderName").toString(); + createFolder(folderName, entry); + // verify folder was created + Folder targetFolder = getFolder(folderName); + if (targetFolder == null) { + log.debug(logPrefix + "target folder not retrieved. Exiting creation process"); + } else { + log.debug(logPrefix + "target folder retrieved !!!!!"); + // create job in target folder + String jobSrc = props.get("source").toString(); + String jobName = props.get("jobName").toString(); + Collection existingJobs = getJobNames(entry); + if (existingJobs.contains(jobName)) { + // do not create + log.debug(logPrefix + "Job " + jobName + " already exists."); + } else { + createJobInFolder(targetFolder, jobName, jobSrc, entry); + } + } + } catch (Exception e) { + log.error(logPrefix + "An unexpected error occurred while creating job."); + e.printStackTrace(); + } finally { + // be sure to re-enable security + Jenkins.getInstance().setSecurityRealm(securityRealm); + Jenkins.getInstance().setAuthorizationStrategy(authorizationStrategy); + } + } + } + + private static void createCredentials(JSONObject newJob, Entry entry) { + String logPrefix = "[HCL Accelerate " + entry.getBaseUrl() + "] JenkinsServer#createCredentials - "; + if (newJob.has("props")) { + JSONObject props = newJob.getJSONObject("props"); + if (props.has("userName") && props.has("password")) { // not all jobs require creds creation + try { + log.debug(logPrefix + "creating " + BLX_CREDS + " credentials."); + Credentials creds = (Credentials) new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, + BLX_CREDS, BLX_CREDS_DESC, props.get("userName").toString(), + props.get("password").toString()); + SystemCredentialsProvider.getInstance().getCredentials().add(creds); + SystemCredentialsProvider.getInstance().save(); + log.debug(logPrefix + BLX_CREDS + " successfully created."); + } catch (Exception e) { + log.error(logPrefix + "unable to create " + BLX_CREDS + " credentials."); + e.printStackTrace(); + } + } else { + log.debug(logPrefix + "credentials creation not required."); + } + } - log.info(logPrefix + "Project " + itemName + " not found!"); - return null; - } - - public static void createJob(JSONObject newJob) { - log.debug(logPrefix + "createJob - Creating a new job."); - if(validCreationRequest(newJob)) { - // get current security settings - SecurityRealm securityRealm= Jenkins.getInstance().getSecurityRealm(); - AuthorizationStrategy authorizationStrategy= Jenkins.getInstance().getAuthorizationStrategy(); - - // temporarily disable security as we are not allowed to create jobs as anonymous - disableSecurity(); - try { - // create creds if necessary - createCredentials(newJob) ; - JSONObject props = newJob.getJSONObject("props"); - // create folder - String folderName= props.get("folderName").toString(); - createFolder(folderName); - // verify folder was created - Folder targetFolder= getFolder(folderName); - if (targetFolder == null) { - log.debug(logPrefix + "createJob - target folder not retrieved. Exiting creation process"); - } else { - log.debug(logPrefix + "createJob - target folder retrieved !!!!!"); - // create job in target folder - String jobSrc= props.get("source").toString(); - String jobName= props.get("jobName").toString(); - Collection existingJobs= getJobNames(); - if (existingJobs.contains(jobName)) { - // do not create - log.debug(logPrefix + "Job " + jobName + " already exists."); - } else { - createJobInFolder(targetFolder, jobName, jobSrc); - } - } - } catch (Exception e) { - log.error(logPrefix + "An unexpected error occurred while creating job."); - e.printStackTrace(); - } finally { - // be sure to re-enable security - Jenkins.getInstance().setSecurityRealm(securityRealm); - Jenkins.getInstance().setAuthorizationStrategy(authorizationStrategy); - } - } - } - - private static void createCredentials(JSONObject newJob) { - if(newJob.has("props")) { - JSONObject props = newJob.getJSONObject("props"); - if (props.has("userName") && props.has("password")) { // not all jobs require creds creation - try { - log.debug(logPrefix + "createCredentials - creating " + BLX_CREDS + " credentials."); - Credentials creds = (Credentials) new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, BLX_CREDS, BLX_CREDS_DESC, props.get("userName").toString(), props.get("password").toString()); - SystemCredentialsProvider.getInstance().getCredentials().add(creds); - SystemCredentialsProvider.getInstance().save(); - log.debug(logPrefix + "createCredentials " + BLX_CREDS + " successfully created."); - } catch (Exception e) { - log.error(logPrefix + "createCredentials - unable to create " + BLX_CREDS + " credentials."); - e.printStackTrace(); - } - } else { - log.debug(logPrefix + "createCredentials - credentials creation not required."); - } - } - } - - private static boolean validCreationRequest(JSONObject newJob) { - log.debug(logPrefix + "validCreationRequest - Validating creation payload."); - boolean valid= false; - if(newJob.has("props")) { - JSONObject props = newJob.getJSONObject("props"); - if (props.has("folderName") && props.has("jobName") && props.has("source")) { - log.debug(logPrefix + "validCreationRequest - Payload is valid."); - valid= true; - } else { - log.error(logPrefix + "validCreationRequest - Payload is not valid!"); - } - } - return valid; - } - - private static void createFolder(String folderName) { - log.debug(logPrefix + "createFolder - Creating folder " + folderName); - try { - Jenkins.getInstance().createProjectFromXML(folderName, new ByteArrayInputStream(FOLDER_SPEC.getBytes(Charset.forName("UTF-8")))); - log.debug(logPrefix + folderName + " was created successfully!"); - } catch (Exception e) { - // folder might be existing - log.debug(logPrefix + folderName + " was not created."); - // e.printStackTrace(); - } - } - - private static void createJobInFolder(Folder targetFolder, String jobName, String source) { - log.debug(logPrefix + "createItem - Creating job " + jobName); - try { - targetFolder.createProjectFromXML(jobName, new ByteArrayInputStream(source.getBytes(Charset.forName("UTF-8")))); - log.debug(logPrefix + jobName + " was created successfully!"); - } catch (Exception e) { - log.error(logPrefix + jobName + " was not created."); - e.printStackTrace(); - } - } - - private static void disableSecurity() { - log.debug(logPrefix + "disableSecurity()"); - Jenkins.getInstance().disableSecurity(); - } - - private static Folder getFolder(String folderName) { - return (Folder) Jenkins.getInstance().getItem(folderName); - } + + } + + private static boolean validCreationRequest(JSONObject newJob, Entry entry) { + String logPrefix = "[HCL Accelerate " + entry.getBaseUrl() + "] JenkinsServer#validCreationRequest - "; + log.debug(logPrefix + "Validating creation payload."); + boolean valid = false; + if (newJob.has("props")) { + JSONObject props = newJob.getJSONObject("props"); + if (props.has("folderName") && props.has("jobName") && props.has("source")) { + log.debug(logPrefix + "Payload is valid."); + valid = true; + } else { + log.error(logPrefix + "Payload is not valid!"); + } + } + return valid; + } + + private static void createFolder(String folderName, Entry entry) { + String logPrefix = "[HCL Accelerate " + entry.getBaseUrl() + "] JenkinsServer#createFolder - "; + log.debug(logPrefix + "Creating folder " + folderName); + try { + Jenkins.getInstance().createProjectFromXML(folderName, + new ByteArrayInputStream(FOLDER_SPEC.getBytes(Charset.forName("UTF-8")))); + log.debug(logPrefix + folderName + " was created successfully!"); + } catch (Exception e) { + // folder might be existing + log.debug(logPrefix + folderName + " was not created."); + // e.printStackTrace(); + } + } + + private static void createJobInFolder(Folder targetFolder, String jobName, String source, Entry entry) { + String logPrefix = "[HCL Accelerate " + entry.getBaseUrl() + "] JenkinsServer#createItem - "; + log.debug(logPrefix + "Creating job " + jobName); + try { + targetFolder.createProjectFromXML(jobName, + new ByteArrayInputStream(source.getBytes(Charset.forName("UTF-8")))); + log.debug(logPrefix + jobName + " was created successfully!"); + } catch (Exception e) { + log.error(logPrefix + jobName + " was not created."); + e.printStackTrace(); + } + } + + private static void disableSecurity(Entry entry) { + log.debug("[HCL Accelerate " + entry.getBaseUrl() + "] JenkinsServer#disableSecurity()"); + Jenkins.getInstance().disableSecurity(); + } + + private static Folder getFolder(String folderName) { + return (Folder) Jenkins.getInstance().getItem(folderName); + } + } \ No newline at end of file diff --git a/src/main/java/com/hcl/devops/connect/ReconnectExecutor.java b/src/main/java/com/hcl/devops/connect/ReconnectExecutor.java index 4015f1b..b24b7ab 100644 --- a/src/main/java/com/hcl/devops/connect/ReconnectExecutor.java +++ b/src/main/java/com/hcl/devops/connect/ReconnectExecutor.java @@ -17,13 +17,13 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.lang.Runnable; - +import java.util.List; public class ReconnectExecutor { public static final Logger log = LoggerFactory.getLogger(ReconnectExecutor.class); private CloudSocketComponent cloudSocketInstance; - public ReconnectExecutor (CloudSocketComponent cloudSocketInstance) { + public ReconnectExecutor(CloudSocketComponent cloudSocketInstance) { this.cloudSocketInstance = cloudSocketInstance; } @@ -37,13 +37,16 @@ public void startReconnectExecutor() { private class ReconnectRunner implements Runnable { @Override - public void run() - { - if (!cloudSocketInstance.isAMQPConnected() && Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).isConfigured()) { - try { - cloudSocketInstance.connectToAMQP(); - } catch (Exception e) { - log.error("Unable to Reconnect to HCL Accelerate AMQP", e); + public void run() { + List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class) + .getEntries(); + for (Entry entry : entries) { + if (!cloudSocketInstance.isAMQPConnected(entry) && entry.isConfigured()) { + try { + cloudSocketInstance.connectToAMQP(entry); + } catch (Exception e) { + log.error("[HCL Accelerate " + entry.getBaseUrl() + "] Unable to Reconnect to HCL AMQP", e); + } } } } diff --git a/src/main/java/com/hcl/devops/connect/SecuredActions/AbstractSecuredAction.java b/src/main/java/com/hcl/devops/connect/SecuredActions/AbstractSecuredAction.java index fef17fd..d1b6483 100644 --- a/src/main/java/com/hcl/devops/connect/SecuredActions/AbstractSecuredAction.java +++ b/src/main/java/com/hcl/devops/connect/SecuredActions/AbstractSecuredAction.java @@ -34,7 +34,7 @@ public String getJenkinsAuthenticationError() { } public Boolean isJenkinsAuthenticationError() { - if(this.jenkinsAuthenticationError != null) { + if (this.jenkinsAuthenticationError != null) { return true; } else { return false; @@ -44,7 +44,8 @@ public Boolean isJenkinsAuthenticationError() { public void runAsJenkinsUser(ParamObj paramObj) { - StandardUsernamePasswordCredentials providedCredentials = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getCredentialsObj(); + StandardUsernamePasswordCredentials providedCredentials = Jenkins.getInstance() + .getDescriptorByType(DevOpsGlobalConfiguration.class).getCredentialsObj(); Authentication originalAuth = null; @@ -54,12 +55,16 @@ public void runAsJenkinsUser(ParamObj paramObj) { Authentication authenticatedAuth = authenticateCredentials(providedCredentials); SecurityContextHolder.getContext().setAuthentication(authenticatedAuth); } catch (UsernameNotFoundException e) { - paramObj.setJenkinsAuthenticationError("Bad Jenkins Credentials: Accelerate configuration in Jenkins references Jenkins Credentials for a user that doesn't exist."); - System.out.println("Bad Jenkins Credentials: Wrong username provided in Accelerate configuration in Jenkins."); + paramObj.setJenkinsAuthenticationError( + "Bad Jenkins Credentials: Accelerate configuration in Jenkins references Jenkins Credentials for a user that doesn't exist."); + System.out.println( + "Bad Jenkins Credentials: Wrong username provided in Accelerate configuration in Jenkins."); } catch (AuthenticationException e) { if ( e instanceof BadCredentialsException ) { - paramObj.setJenkinsAuthenticationError("Bad Jenkins Credentials: Wrong username or password provided in Accelerate configuration in Jenkins."); - System.out.println("Bad Jenkins Credentials: Wrong username or password provided in Accelerate configuration in Jenkins."); + paramObj.setJenkinsAuthenticationError( + "Bad Jenkins Credentials: Wrong username or password provided in Accelerate configuration in Jenkins."); + System.out.println( + "Bad Jenkins Credentials: Wrong username or password provided in Accelerate configuration in Jenkins."); } else { paramObj.setJenkinsAuthenticationError("Bad Jenkins Credentials"); System.out.println("Something else went wrong"); @@ -69,7 +74,7 @@ public void runAsJenkinsUser(ParamObj paramObj) { paramObj.setJenkinsAuthenticationError(NO_CREDENTIALS_PROVIDED); } - try{ + try { run(paramObj); } finally { if (originalAuth != null) { @@ -79,14 +84,15 @@ public void runAsJenkinsUser(ParamObj paramObj) { } - private Authentication authenticateCredentials(StandardUsernamePasswordCredentials providedCredentials) throws AuthenticationException { + private Authentication authenticateCredentials(StandardUsernamePasswordCredentials providedCredentials) + throws AuthenticationException { SecurityRealm realm = Jenkins.getInstance().getSecurityRealm(); SecurityRealm.SecurityComponents securityComponents = realm.createSecurityComponents(); Authentication auth = getAuth(providedCredentials, realm); Authentication result = null; - if(auth != null) { + if (auth != null) { result = securityComponents.manager.authenticate(auth); } @@ -98,7 +104,8 @@ private Authentication getAuth(StandardUsernamePasswordCredentials providedCrede userDetails.getAuthorities(); - Authentication auth = new UsernamePasswordAuthenticationToken(providedCredentials.getUsername(), providedCredentials.getPassword().getPlainText(), userDetails.getAuthorities()); + Authentication auth = new UsernamePasswordAuthenticationToken(providedCredentials.getUsername(), + providedCredentials.getPassword().getPlainText(), userDetails.getAuthorities()); return auth; } diff --git a/src/main/java/com/hcl/devops/connect/SecuredActions/TriggerJob.java b/src/main/java/com/hcl/devops/connect/SecuredActions/TriggerJob.java index 7d5c614..20617f2 100644 --- a/src/main/java/com/hcl/devops/connect/SecuredActions/TriggerJob.java +++ b/src/main/java/com/hcl/devops/connect/SecuredActions/TriggerJob.java @@ -11,10 +11,11 @@ public class TriggerJob extends AbstractSecuredAction { protected void run(AbstractSecuredAction.ParamObj paramObj) { - TriggerJobParamObj triggerJobParamObj = (TriggerJobParamObj)paramObj; + TriggerJobParamObj triggerJobParamObj = (TriggerJobParamObj) paramObj; CloudWorkListener2 cwl = new CloudWorkListener2(); - cwl.callSecured(triggerJobParamObj.socket, triggerJobParamObj.event, triggerJobParamObj.getJenkinsAuthenticationError(), triggerJobParamObj.args); + cwl.callSecured(triggerJobParamObj.socket, triggerJobParamObj.event, + triggerJobParamObj.getJenkinsAuthenticationError(), triggerJobParamObj.args); } public class TriggerJobParamObj extends AbstractSecuredAction.ParamObj { diff --git a/src/main/java/com/hcl/devops/connect/Status/AbstractJenkinsStatus.java b/src/main/java/com/hcl/devops/connect/Status/AbstractJenkinsStatus.java index beae1bf..a2f61f7 100644 --- a/src/main/java/com/hcl/devops/connect/Status/AbstractJenkinsStatus.java +++ b/src/main/java/com/hcl/devops/connect/Status/AbstractJenkinsStatus.java @@ -49,6 +49,8 @@ import java.util.Base64; import java.nio.charset.StandardCharsets; import org.apache.http.client.utils.URIBuilder; +import com.hcl.devops.connect.Entry; +import java.util.List; public abstract class AbstractJenkinsStatus { public static final Logger log = LoggerFactory.getLogger(AbstractJenkinsStatus.class); @@ -74,11 +76,11 @@ public abstract class AbstractJenkinsStatus { protected void getOrCreateCrAction() { - if ( run != null) { + if (run != null) { List actions = run.getActions(); - for(Action action : actions) { + for (Action action : actions) { if (action instanceof CrAction) { - crAction = (CrAction)action; + crAction = (CrAction) action; } } @@ -92,7 +94,7 @@ protected void getOrCreateCrAction() { protected void getEnvVars() { try { - if( run != null && taskListener != null) { + if (run != null && taskListener != null) { this.envVars = run.getEnvironment(taskListener); Set keys = this.envVars.keySet(); List keysToRemove = new ArrayList(); @@ -114,18 +116,18 @@ protected void getEnvVars() { } } - public JSONObject generateErrorStatus(String errorMessage) { + public JSONObject generateErrorStatus(String errorMessage, Entry entry) { JSONObject result = new JSONObject(); cloudCause.addStep("Error: " + errorMessage, JobStatus.failure.toString(), "Failed due to error", true); result.put("status", JobStatus.failure.toString()); result.put("timestamp", System.currentTimeMillis()); - result.put("syncId", Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getSyncId()); + result.put("syncId", entry.getSyncId()); result.put("steps", cloudCause.getStepsArray()); result.put("returnProps", cloudCause.getReturnProps()); - if(run != null) { + if (run != null) { result.put("url", Jenkins.getInstance().getRootUrl() + run.getUrl()); result.put("jobExternalId", getJobUniqueIdFromBuild()); result.put("name", run.getDisplayName()); @@ -163,16 +165,17 @@ protected void evaluateSourceData() { } if (envVars != null) { - for(Action action : actions) { + for (Action action : actions) { // If using Hudson Git Plugin if (action instanceof BuildData) { - Map branchMap = ((BuildData)action).getBuildsByBranchName(); + Map branchMap = ((BuildData) action).getBuildsByBranchName(); - for(Map.Entry branchEntry : branchMap.entrySet()) { + for (Map.Entry branchEntry : branchMap.entrySet()) { Build gitBuild = branchEntry.getValue(); if (gitBuild.getBuildNumber() == run.getNumber()) { - SourceData sourceData = new SourceData(branchEntry.getKey(), gitBuild.getSHA1().getName(), "GIT"); + SourceData sourceData = new SourceData(branchEntry.getKey(), gitBuild.getSHA1().getName(), + "GIT"); sourceData.populateCommitMessage(taskListener, envVars, getWorkspaceFilePath(), gitBuild); cloudCause.setSourceData(sourceData); @@ -202,7 +205,7 @@ protected void evaluateDRAData() { //This block if for non-pipeline jobs to set additional data that we have access to if (this.buildStep != null && this.buildStep instanceof EvaluateGate) { - EvaluateGate egs = (EvaluateGate)buildStep; + EvaluateGate egs = (EvaluateGate) buildStep; String environment = egs.getEnvName(); String applicationName = egs.getApplicationName(); @@ -215,9 +218,9 @@ protected void evaluateDRAData() { data.setEnvironment(environment); } - for(Action action : actions) { + for (Action action : actions) { if (action instanceof GatePublisherAction) { - GatePublisherAction gpa = (GatePublisherAction)action; + GatePublisherAction gpa = (GatePublisherAction) action; String gateText = gpa.getText(); String riskDashboardLink = gpa.getRiskDashboardLink(); @@ -238,19 +241,19 @@ protected void evaluateDRAData() { } private void evaluateEnvironment() { - if( envVars != null ) { + if (envVars != null) { crAction.updateEnvProperties(envVars); } } - public JSONObject generate(boolean completed) { + public JSONObject generate(boolean completed, Entry entry) { JSONObject result = new JSONObject(); evaluateSourceData(); evaluateDRAData(); evaluateEnvironment(); - if(isPipeline) { + if (isPipeline) { evaluatePipelineStep(); } else { evaluateBuildStep(); @@ -268,7 +271,7 @@ public JSONObject generate(boolean completed) { result.put("status", status); result.put("timestamp", System.currentTimeMillis()); result.put("startTime", run.getStartTimeInMillis()); - result.put("syncId", Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getSyncId()); + result.put("syncId", entry.getSyncId()); result.put("name", run.getDisplayName()); result.put("steps", cloudCause.getStepsArray()); result.put("url", Jenkins.getInstance().getRootUrl() + run.getUrl()); @@ -282,7 +285,8 @@ public JSONObject generate(boolean completed) { result.put("draData", cloudCause.getDRADataJson()); result.put("crProperties", crAction.getCrProperties()); result.put("envProperties", crAction.getEnvProperties()); - StandardUsernamePasswordCredentials credentials = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class).getCredentialsObj(); + StandardUsernamePasswordCredentials credentials = Jenkins.getInstance() + .getDescriptorByType(DevOpsGlobalConfiguration.class).getCredentialsObj(); String plainCredentials = credentials.getUsername() + ":" + credentials.getPassword().getPlainText(); String encodedString = getEncodedString(plainCredentials); String authorizationHeader = "Basic " + encodedString; @@ -293,29 +297,29 @@ public JSONObject generate(boolean completed) { String requestor = null; try { URIBuilder builder = new URIBuilder(baseUrl); - builder.setPath(builder.getPath()+path); + builder.setPath(builder.getPath() + path); finalUrl = builder.toString(); } catch (Exception e) { log.error("Caught error while building url to get requestor name: ", e); } try { HttpResponse response = Unirest.get(finalUrl) - .header("Authorization", authorizationHeader) - .asString(); + .header("Authorization", authorizationHeader) + .asString(); apiResponse = response.getBody().toString(); JSONArray apiResponseArray = JSONArray.fromObject("[" + apiResponse + "]"); JSONObject apiResponseObject = apiResponseArray.getJSONObject(0); - if(apiResponseObject.has("actions")){ + if (apiResponseObject.has("actions")){ JSONArray actionsArray = JSONArray.fromObject(apiResponseObject.getString("actions")); - for(int i=0;i properties) { + public void updateCrProperties(Map properties) { this.crProperties.putAll(properties); } - public Map getCrProperties () { + public Map getCrProperties() { return crProperties; } - public void updateEnvProperties (Map properties) { + public void updateEnvProperties(Map properties) { this.envProperties.putAll(properties); } - public Map getEnvProperties () { + public Map getEnvProperties() { return envProperties; } diff --git a/src/main/java/com/hcl/devops/connect/Status/DRAData.java b/src/main/java/com/hcl/devops/connect/Status/DRAData.java index dae9037..b1675f2 100644 --- a/src/main/java/com/hcl/devops/connect/Status/DRAData.java +++ b/src/main/java/com/hcl/devops/connect/Status/DRAData.java @@ -18,15 +18,15 @@ public class DRAData { public DRAData() { } - public void setApplicationName (String applicationName) { + public void setApplicationName(String applicationName) { this.applicationName = applicationName; } - public void setOrgName (String orgName) { + public void setOrgName(String orgName) { this.orgName = orgName; } - public String getOrgName () { + public String getOrgName() { return orgName; } @@ -34,27 +34,27 @@ public void setToolchainName(String toolchainName) { this.toolchainName = toolchainName; } - public void setEnvironment (String environment) { + public void setEnvironment(String environment) { this.environment = environment; } - public void setBuildNumber (String buildNumber) { + public void setBuildNumber(String buildNumber) { this.buildNumber = buildNumber; } - public void setPolicy (String policy) { + public void setPolicy(String policy) { this.policy = policy; } - public void setGateText (String gateText) { + public void setGateText(String gateText) { this.gateText = gateText; } - public void setDecision (String decision) { + public void setDecision(String decision) { this.decision = decision; } - public void setRiskDahboardLink (String riskDahboardLink) { + public void setRiskDahboardLink(String riskDahboardLink) { this.riskDahboardLink = riskDahboardLink; } diff --git a/src/main/java/com/hcl/devops/connect/Status/JenkinsJobStatus.java b/src/main/java/com/hcl/devops/connect/Status/JenkinsJobStatus.java index c4820a7..25d7409 100644 --- a/src/main/java/com/hcl/devops/connect/Status/JenkinsJobStatus.java +++ b/src/main/java/com/hcl/devops/connect/Status/JenkinsJobStatus.java @@ -39,7 +39,8 @@ public class JenkinsJobStatus extends AbstractJenkinsStatus { public static final Logger log = LoggerFactory.getLogger(JenkinsJobStatus.class); - public JenkinsJobStatus(Run run, CloudCause cloudCause, BuildStep buildStep, TaskListener taskListener, Boolean newStep, Boolean isFatal) { + public JenkinsJobStatus(Run run, CloudCause cloudCause, BuildStep buildStep, TaskListener taskListener, + Boolean newStep, Boolean isFatal) { this.run = run; this.cloudCause = cloudCause; this.buildStep = buildStep; @@ -56,16 +57,17 @@ public JenkinsJobStatus(Run run, CloudCause cloudCause, BuildStep buildStep, Tas protected FilePath getWorkspaceFilePath() { // run.getBuild if (run instanceof AbstractBuild) { - return ((AbstractBuild)run).getWorkspace(); + return ((AbstractBuild) run).getWorkspace(); } return null; } protected void evaluateBuildStep() { - if(!(buildStep instanceof hudson.model.ParametersDefinitionProperty)) { + if (!(buildStep instanceof hudson.model.ParametersDefinitionProperty)) { if (newStep && buildStep != null) { - cloudCause.addStep(((Describable)buildStep).getDescriptor().getDisplayName(), JobStatus.started.toString(), "Started a build step", false); + cloudCause.addStep(((Describable)buildStep).getDescriptor().getDisplayName(), + JobStatus.started.toString(), "Started a build step", false); } else if (buildStep != null) { String newStatus; String message; @@ -78,7 +80,8 @@ protected void evaluateBuildStep() { } if (cloudCause.isCreatedByCR()) { - cloudCause.updateLastStep(((Describable)buildStep).getDescriptor().getDisplayName(), newStatus, message, isFatal); + cloudCause.updateLastStep(((Describable) buildStep).getDescriptor().getDisplayName(), newStatus, + message, isFatal); } } } diff --git a/src/main/java/com/hcl/devops/connect/Status/JenkinsPipelineStatus.java b/src/main/java/com/hcl/devops/connect/Status/JenkinsPipelineStatus.java index 14ed0d6..db1f2e7 100644 --- a/src/main/java/com/hcl/devops/connect/Status/JenkinsPipelineStatus.java +++ b/src/main/java/com/hcl/devops/connect/Status/JenkinsPipelineStatus.java @@ -43,7 +43,8 @@ public class JenkinsPipelineStatus extends AbstractJenkinsStatus { public static final Logger log = LoggerFactory.getLogger(JenkinsPipelineStatus.class); - public JenkinsPipelineStatus(WorkflowRun workflowRun, CloudCause cloudCause, FlowNode node, TaskListener listener, boolean newStep, boolean isPaused) { + public JenkinsPipelineStatus(WorkflowRun workflowRun, CloudCause cloudCause, FlowNode node, TaskListener listener, + boolean newStep, boolean isPaused) { this.run = workflowRun; this.cloudCause = cloudCause; this.node = node; @@ -61,15 +62,15 @@ public JenkinsPipelineStatus(WorkflowRun workflowRun, CloudCause cloudCause, Flo } protected FilePath getWorkspaceFilePath() { - FlowExecution exec = ((WorkflowRun)run).getExecution(); - if(exec == null) + FlowExecution exec = ((WorkflowRun) run).getExecution(); + if (exec == null) return null; FlowGraphWalker w = new FlowGraphWalker(exec); for (FlowNode n : w) { if (n.getClass().getName().equals("org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode")) { WorkspaceAction action = n.getAction(WorkspaceAction.class); - if(action != null) { + if (action != null) { String workspace = action.getPath().toString(); FilePath result = new FilePath(new File(workspace)); @@ -82,16 +83,18 @@ protected FilePath getWorkspaceFilePath() { } protected void evaluatePipelineStep() { - if(newStep && node == null) { - cloudCause.addStep("Starting Jenkins Pipeline", JobStatus.success.toString(), "Successfully started pipeline...", false); - } else if(newStep && node != null) { + if (newStep && node == null) { + cloudCause.addStep("Starting Jenkins Pipeline", JobStatus.success.toString(), + "Successfully started pipeline...", false); + } else if (newStep && node != null) { cloudCause.addStep(node.getDisplayName(), JobStatus.started.toString(), "Started stage", false); } else if (isPaused && node != null) { - cloudCause.addStep(node.getDisplayName(), JobStatus.started.toString(), "Please acknowledge the Jenkins Pipeline input", false); - } else if(!newStep && node != null) { + cloudCause.addStep(node.getDisplayName(), JobStatus.started.toString(), + "Please acknowledge the Jenkins Pipeline input", false); + } else if (!newStep && node != null) { - if(node.getError() == null) { - if(cloudCause.isCreatedByCR()) { + if (node.getError() == null) { + if (cloudCause.isCreatedByCR()) { cloudCause.updateLastStep(null, JobStatus.success.toString(), "Stage is successful", false); } else { cloudCause.addStep(null, JobStatus.success.toString(), "Stage is successful", false); @@ -100,7 +103,7 @@ protected void evaluatePipelineStep() { ErrorAction errorObj = node.getError(); String displayText = "Unknown Error"; - if( errorObj != null ) { + if (errorObj != null) { displayText = errorObj.getDisplayName(); } cloudCause.updateLastStep(null, JobStatus.failure.toString(), displayText, false); diff --git a/src/main/java/com/hcl/devops/connect/Status/SourceData.java b/src/main/java/com/hcl/devops/connect/Status/SourceData.java index 6b90a9e..fc4824d 100644 --- a/src/main/java/com/hcl/devops/connect/Status/SourceData.java +++ b/src/main/java/com/hcl/devops/connect/Status/SourceData.java @@ -36,11 +36,11 @@ public SourceData(String branch, String revision, String type) { this.type = type; } - public void setBranch (String branch) { + public void setBranch(String branch) { this.branch = branch; } - public void setRevision (String revision) { + public void setRevision(String revision) { this.revision = revision; } @@ -48,11 +48,11 @@ public void setScmName(String scmName) { this.scmName = scmName; } - public void setType (String type) { + public void setType(String type) { this.type = type; } - public void setRemoteUrls (Set remoteUrls) { + public void setRemoteUrls(Set remoteUrls) { this.remoteUrls = remoteUrls; } @@ -66,7 +66,7 @@ public JSONObject toJson() { result.put("fullMessage", fullMessage); result.put("shortMessage", shortMessage); result.put("type", type); - if(remoteUrls != null) { + if (remoteUrls != null) { result.put("remoteUrls", remoteUrls.toArray()); } diff --git a/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadASoCTestResult/config.jelly b/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadASoCTestResult/config.jelly index 27152be..411e57d 100644 --- a/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadASoCTestResult/config.jelly +++ b/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadASoCTestResult/config.jelly @@ -1,5 +1,8 @@ + + + diff --git a/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadASoCTestResult/help-instanceBaseUrl.html b/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadASoCTestResult/help-instanceBaseUrl.html new file mode 100644 index 0000000..cd82c29 --- /dev/null +++ b/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadASoCTestResult/help-instanceBaseUrl.html @@ -0,0 +1,17 @@ + + +
+ Select HCL Accelerate BaseUrl where you want to Upload ASoC Test Result (By default set to: Upload ASoC Test Result to All HCL Accelerate Instances). +
\ No newline at end of file diff --git a/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadBuild/config.jelly b/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadBuild/config.jelly index e958242..c9f5c6f 100644 --- a/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadBuild/config.jelly +++ b/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadBuild/config.jelly @@ -1,5 +1,8 @@ + + + diff --git a/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadBuild/help-instanceBaseUrl.html b/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadBuild/help-instanceBaseUrl.html new file mode 100644 index 0000000..99fd5a0 --- /dev/null +++ b/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadBuild/help-instanceBaseUrl.html @@ -0,0 +1,17 @@ + + +
+ Select HCL Accelerate BaseUrl where you want to Upload Build (By default set to: Upload Build to All HCL Accelerate Instances). +
\ No newline at end of file diff --git a/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadDeployment/config.jelly b/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadDeployment/config.jelly index 6874a19..79a0471 100644 --- a/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadDeployment/config.jelly +++ b/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadDeployment/config.jelly @@ -1,5 +1,8 @@ + + + diff --git a/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadDeployment/help-instanceBaseUrl.html b/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadDeployment/help-instanceBaseUrl.html new file mode 100644 index 0000000..f39ffd8 --- /dev/null +++ b/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadDeployment/help-instanceBaseUrl.html @@ -0,0 +1,17 @@ + + +
+ Select HCL Accelerate BaseUrl where you want to Upload Deployment (By default set to: Upload Deployment to All HCL Accelerate Instances). +
\ No newline at end of file diff --git a/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadMetricsFile/config.jelly b/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadMetricsFile/config.jelly index 51377a7..848ea1f 100644 --- a/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadMetricsFile/config.jelly +++ b/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadMetricsFile/config.jelly @@ -1,5 +1,8 @@ + + + diff --git a/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadMetricsFile/help-instanceBaseUrl.html b/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadMetricsFile/help-instanceBaseUrl.html new file mode 100644 index 0000000..a8aabb4 --- /dev/null +++ b/src/main/resources/com/hcl/devops/connect/CRPipeline/UploadMetricsFile/help-instanceBaseUrl.html @@ -0,0 +1,17 @@ + + +
+ Select HCL Accelerate BaseUrl where you want to Upload Metric File (By default set to: Upload Mertic File to All HCL Accelerate Instances). +
\ No newline at end of file diff --git a/src/main/resources/com/hcl/devops/connect/DevOpsGlobalConfiguration/config.jelly b/src/main/resources/com/hcl/devops/connect/DevOpsGlobalConfiguration/config.jelly index 78287d7..9c3472a 100644 --- a/src/main/resources/com/hcl/devops/connect/DevOpsGlobalConfiguration/config.jelly +++ b/src/main/resources/com/hcl/devops/connect/DevOpsGlobalConfiguration/config.jelly @@ -27,36 +27,15 @@ so it should be straightforward to find them. --> - - - - - - - - - - - - - - - - - - - - - + -
- +
+
+ diff --git a/src/main/resources/com/hcl/devops/connect/Entry/config.jelly b/src/main/resources/com/hcl/devops/connect/Entry/config.jelly new file mode 100644 index 0000000..a512257 --- /dev/null +++ b/src/main/resources/com/hcl/devops/connect/Entry/config.jelly @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ +
diff --git a/src/main/resources/com/hcl/devops/connect/DevOpsGlobalConfiguration/help-apiToken.html b/src/main/resources/com/hcl/devops/connect/Entry/help-apiToken.html similarity index 100% rename from src/main/resources/com/hcl/devops/connect/DevOpsGlobalConfiguration/help-apiToken.html rename to src/main/resources/com/hcl/devops/connect/Entry/help-apiToken.html diff --git a/src/main/resources/com/hcl/devops/connect/Entry/help-checkDuplicate.html b/src/main/resources/com/hcl/devops/connect/Entry/help-checkDuplicate.html new file mode 100644 index 0000000..6af911b --- /dev/null +++ b/src/main/resources/com/hcl/devops/connect/Entry/help-checkDuplicate.html @@ -0,0 +1,17 @@ + + +
+ Use this checkbox to enable dubplicate job checking and prevention. Note: Enabling this might casuse some delay in triggering jobs from HCL Accelerate, so use it only if duplicate jobs are getting triggered form HCL Accelerate Server. +
\ No newline at end of file diff --git a/src/main/resources/com/hcl/devops/connect/DevOpsGlobalConfiguration/help-rabbitMQHost.html b/src/main/resources/com/hcl/devops/connect/Entry/help-rabbitMQHost.html similarity index 100% rename from src/main/resources/com/hcl/devops/connect/DevOpsGlobalConfiguration/help-rabbitMQHost.html rename to src/main/resources/com/hcl/devops/connect/Entry/help-rabbitMQHost.html diff --git a/src/main/resources/com/hcl/devops/connect/DevOpsGlobalConfiguration/help-rabbitMQPort.html b/src/main/resources/com/hcl/devops/connect/Entry/help-rabbitMQPort.html similarity index 100% rename from src/main/resources/com/hcl/devops/connect/DevOpsGlobalConfiguration/help-rabbitMQPort.html rename to src/main/resources/com/hcl/devops/connect/Entry/help-rabbitMQPort.html diff --git a/src/main/resources/com/hcl/devops/connect/DevOpsGlobalConfiguration/help-syncId.html b/src/main/resources/com/hcl/devops/connect/Entry/help-syncId.html similarity index 100% rename from src/main/resources/com/hcl/devops/connect/DevOpsGlobalConfiguration/help-syncId.html rename to src/main/resources/com/hcl/devops/connect/Entry/help-syncId.html diff --git a/src/main/resources/com/hcl/devops/connect/DevOpsGlobalConfiguration/help-syncToken.html b/src/main/resources/com/hcl/devops/connect/Entry/help-syncToken.html similarity index 100% rename from src/main/resources/com/hcl/devops/connect/DevOpsGlobalConfiguration/help-syncToken.html rename to src/main/resources/com/hcl/devops/connect/Entry/help-syncToken.html From 1fd4c9f36f3b209af0b9eae8c7d026f92a2290e5 Mon Sep 17 00:00:00 2001 From: Leelavathi D H Date: Wed, 18 Jan 2023 14:55:11 +0530 Subject: [PATCH 2/8] Bump up version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 172221f..f94df54 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 4.0.0 com.hcl.devops hcl-accelerate - 2.1.5 + 3.0.1 hpi HCL Accelerate Plugin This plugin can run Jenkins jobs as a part of a deployment plan in HCL Accelerate. From 53cad78e6b2a4a3523adb5637c1f1a76e7760941 Mon Sep 17 00:00:00 2001 From: Leelavathi D H Date: Wed, 18 Jan 2023 14:58:31 +0530 Subject: [PATCH 3/8] Validation of provided jenkins credentials, performing connection test. --- .../hcl/devops/connect/CloudPublisher.java | 129 ++++++++++-------- .../devops/connect/CloudSocketComponent.java | 11 +- .../java/com/hcl/devops/connect/Entry.java | 14 +- .../com/hcl/devops/connect/Entry/config.jelly | 2 +- 4 files changed, 90 insertions(+), 66 deletions(-) diff --git a/src/main/java/com/hcl/devops/connect/CloudPublisher.java b/src/main/java/com/hcl/devops/connect/CloudPublisher.java index 0edf088..586465b 100644 --- a/src/main/java/com/hcl/devops/connect/CloudPublisher.java +++ b/src/main/java/com/hcl/devops/connect/CloudPublisher.java @@ -52,6 +52,7 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; +import java.net.URISyntaxException; import java.security.cert.X509Certificate; import java.security.NoSuchAlgorithmException; import java.security.KeyManagementException; @@ -66,7 +67,6 @@ public class CloudPublisher { private final static String JENKINS_JOB_ENDPOINT_URL = "api/v1/jenkins/jobs"; private final static String JENKINS_JOB_STATUS_ENDPOINT_URL = "api/v1/jenkins/jobStatus"; - private final static String JENKINS_TEST_CONNECTION_URL = "api/v1/jenkins/testConnection"; private final static String BUILD_UPLOAD_URL = "api/v1/builds"; private final static String DEPLOYMENT_UPLOAD_URL = "api/v1/deployments"; @@ -136,11 +136,6 @@ private static String getSyncApiUrl(Entry entry) { return em.getSyncApiEndpoint(entry); } - private static String getSyncApiUrl(String baseUrl) { - EndpointManager em = new EndpointManager(); - return em.getSyncApiEndpoint(baseUrl); - } - public static String getQualityDataUrl(Entry entry) { EndpointManager em = new EndpointManager(); return em.getQualityDataEndpoint(entry); @@ -180,9 +175,9 @@ public static void uploadJobInfo(JSONObject jobJson, Entry entry) { JSONArray payload = new JSONArray(); payload.add(jobJson); - System.out.println("SENDING JOBS TO: "); - System.out.println(url); - System.out.println(jobJson.toString()); + log.info("SENDING JOBS TO: "); + log.info(url); + log.info(jobJson.toString()); CloudPublisher.postToSyncAPI(url, payload.toString(), entry); } @@ -454,7 +449,7 @@ public void completed(final HttpResponse response2) { if (response2.getStatusLine().toString().contains("200")) { log.info(logPrefix + " Upload Job Information successfully"); } else { - log.error(logPrefix + " Error: Upload Job has bad status code, response status " + response2.getStatusLine()); + log.error(logPrefix + " Error: Upload Job has bad status code,(if 401 check configuration properties) response status " + response2.getStatusLine()); } try { EntityUtils.toString(response2.getEntity()); @@ -466,10 +461,10 @@ public void completed(final HttpResponse response2) { } public void failed(final Exception ex) { - log.error(logPrefix + "Error: Failed to upload Job, response status " + ex.getMessage()); + log.error(logPrefix + "Error: Failed to upload Job,(check connection between jenkins and Accelerate) response status " + ex.getMessage()); ex.printStackTrace(); if (ex instanceof IllegalStateException) { - log.error(logPrefix + "Please check if you have the access to the configured tenant."); + log.error(logPrefix + "Please check if you have the access to the configured tenant.also check connection between jenkins and Accelerate"); } } @@ -491,61 +486,83 @@ public static String removeTrailingSlash(String url) { return url; } - public static boolean testConnection(String syncId, String syncToken, String baseUrl) { + public static String testConnection(String syncId, String syncToken, String baseUrl, String apiToken) throws URISyntaxException { CloudPublisher.ensureHttpClientInitialized(); - String url = getSyncApiUrl(baseUrl) + JENKINS_TEST_CONNECTION_URL; CloseableHttpResponse response = null; - try { - HttpGet getMethod = new HttpGet(url); - // postMethod = addProxyInformation(postMethod); - getMethod.setHeader("sync_token", syncToken); - getMethod.setHeader("sync_id", syncId); - getMethod.setHeader("instance_type", "JENKINS"); - getMethod.setHeader("instance_id", syncId); - getMethod.setHeader("integration_id", syncId); - - // Must include both _ and - headers because NGINX services don't pass _ headers - // by default and the original version of the Accelerate services expected the _ - // headers - getMethod.setHeader("sync-token", syncToken); - getMethod.setHeader("sync-id", syncId); - getMethod.setHeader("instance-type", "JENKINS"); - getMethod.setHeader("instance-id", syncId); - getMethod.setHeader("integration-id", syncId); + String resStr = ""; + String result = ""; + String baseApiUrl = CloudPublisher.removeTrailingSlash(baseUrl); + String url = baseApiUrl + "/release-events-api/graphql/"; + try { + URIBuilder builder = new URIBuilder(url); + builder.setParameter("query", "query{integrationById(id: \"" + syncId + "\"){token,_id,userAccessKey}}"); + URI uri = builder.build(); + HttpGet getMethod = new HttpGet(uri); + getMethod.setHeader("Accept", "application/json"); + getMethod.setHeader("Authorization", "UserAccessKey " + apiToken); response = httpClient.execute(getMethod); + log.info("response status message" + response.toString()); + resStr = EntityUtils.toString(response.getEntity()); + log.info("Response body = " + resStr); + JSONObject jsonresStr = JSONObject.fromObject(resStr); + log.info("Response body object = " + jsonresStr); + if (response.getStatusLine().toString().contains("200")) { - // get 200 response - log.info("Connected to Accelerate service successfully for : " + baseUrl); - return true; + if (jsonresStr.has("data")) { + JSONObject dataObject = jsonresStr.getJSONObject("data"); + if (dataObject.has("integrationById")) { + JSONObject integrationByIdObj = dataObject.getJSONObject("integrationById"); + if (integrationByIdObj.isNullObject()) { + log.info("please provide correct integrationId"); + result = "please provide correct integrationId"; + return result; + } else if (!(integrationByIdObj.getString("token").equals(syncToken))) { + log.info("Please provide correct Integration Token value"); + result = "Please provide correct Integration Token value"; + return result; + } else { + log.info("successfull connection"); + result = "successfull connection"; + } + } + } + return result; + + } else if(response.getStatusLine().toString().contains("401")){ + log.error("Wrong userAccessKey, Please provide right one."); + return "Wrong userAccessKey, Please provide right one."; } else { - log.warn("Could not authenticate to Accelerate Services for :" + baseUrl); - log.warn(response.toString()); + log.error("could not able to connect to Accelerate"); + return "could not able to connect to Accelerate"; } } catch (IllegalStateException e) { - log.error("Could not connect to Accelerate for : " + baseUrl); - log.error(e.getMessage()); - } catch (UnsupportedEncodingException e) { - log.error("Could not connect to Accelerate for : " + baseUrl); - log.error(e.getMessage()); - } catch (ClientProtocolException e) { - log.error("Could not connect to Accelerate for : " + baseUrl); - log.error(e.getMessage()); - } catch (IOException e) { - log.error("Could not connect to Accelerate for : " + baseUrl); - log.error(e.getMessage()); - } finally { - if (response != null) { - try { - response.close(); - } catch (Exception e) { - log.error("Could not close testconnection response for : " + baseUrl); + log.error("From IllegalStateException"); + log.error("Could not connect to Accelerate:" + e.getMessage()); + return "Could not connect to Accelerate:" + e.getMessage(); + } catch (UnsupportedEncodingException e) { + log.error("From UnsupportedEncodingException"); + log.error("Could not connect to Accelerate:" + e.getMessage()); + return "Could not connect to Accelerate:" + e.getMessage(); + } catch (ClientProtocolException e) { + log.error("From ClientProtocolException"); + log.error("Could not connect to Accelerate:" + e.getMessage()); + return "Could not connect to Accelerate:" + e.getMessage(); + } catch (IOException e) { + log.error("From IOException"); + log.error("Could not connect to Accelerate:" + e.getMessage()); + return "Could not connect to Accelerate from IO:" + e.getMessage(); + } finally { + if (response != null) { + try { + response.close(); + } catch (Exception e) { + log.error("Could not close testconnection response"); + return "Could not close testconnection response"; + } } } - } - - return false; } } diff --git a/src/main/java/com/hcl/devops/connect/CloudSocketComponent.java b/src/main/java/com/hcl/devops/connect/CloudSocketComponent.java index 2e55223..fdb1c00 100644 --- a/src/main/java/com/hcl/devops/connect/CloudSocketComponent.java +++ b/src/main/java/com/hcl/devops/connect/CloudSocketComponent.java @@ -9,6 +9,7 @@ package com.hcl.devops.connect; import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.net.URL; import jenkins.model.Jenkins; @@ -189,8 +190,14 @@ public void handleDelivery(String consumerTag, Envelope envelope, if (envelope.getRoutingKey().contains(".heartbeat")) { String syncId = entry.getSyncId(); String syncToken = entry.getSyncToken(); + String apiToken = entry.getApiToken(); String url = CloudPublisher.removeTrailingSlash(entry.getBaseUrl()); - boolean connected = CloudPublisher.testConnection(syncId, syncToken, url); + try { + String connected = CloudPublisher.testConnection(syncId, syncToken, url, apiToken); + } catch (URISyntaxException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } else { String message = new String(body, "UTF-8"); if (entry.getCheckDuplicate() == true) { @@ -289,7 +296,7 @@ public void handleDelivery(String consumerTag, Envelope envelope, if (checkQueueAvailability(channel, queueName, entry)) { channel.basicConsume(queueName, true, consumer); } else { - log.info(logPrefix + "Queue is not yet available, will attempt to reconect shortly..."); + log.info(logPrefix + "Queue is not yet available, will attempt to reconnect shortly..."); queueIsAvailable = false; } } diff --git a/src/main/java/com/hcl/devops/connect/Entry.java b/src/main/java/com/hcl/devops/connect/Entry.java index 81f9771..b4529b1 100644 --- a/src/main/java/com/hcl/devops/connect/Entry.java +++ b/src/main/java/com/hcl/devops/connect/Entry.java @@ -94,9 +94,10 @@ public String getDisplayName() { @RequirePOST public FormValidation doTestConnections(@QueryParameter("syncId") String syncId, @QueryParameter("syncToken") String syncToken, - @QueryParameter("baseUrl") String baseUrl) { + @QueryParameter("baseUrl") String baseUrl, + @QueryParameter("apiToken") String apiToken) { try { - boolean connected = CloudPublisher.testConnection(syncId, syncToken, baseUrl); + String connected = CloudPublisher.testConnection(syncId, syncToken, baseUrl, apiToken); List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class) .getEntries(); Entry finalEntry = null; @@ -105,12 +106,12 @@ public FormValidation doTestConnections(@QueryParameter("syncId") String syncId, finalEntry = entry; } } - if (connected) { + if (connected.equals("successfull connection")) { boolean amqpConnected = ConnectComputerListener.isRabbitConnected(finalEntry); - String rabbitMessage = "Not connected to RabbitMQ. Unable to run Jenkins jobs from " + String rabbitMessage = "Not connected to RabbitMQ. Unable to run Jenkins jobs from Accelerate.\n WARNING:Check the port number correctly.\n If you use Kubernetes, the default port that is exposed is 31672." + finalEntry.getBaseUrl(); - if (amqpConnected) { + if (amqpConnected && connected.equals("successfull connection")) { if (StringUtils.isNotEmpty(finalEntry.getRabbitMQHost())) { rabbitMessage = "Connected to RabbitMQ ( " + finalEntry.getRabbitMQHost() + " ) successfully. Ready to run Jenkins jobs from " + finalEntry.getBaseUrl(); @@ -122,8 +123,7 @@ public FormValidation doTestConnections(@QueryParameter("syncId") String syncId, return FormValidation.ok("Successful connection to Accelerate Services.\n" + rabbitMessage); } else { - return FormValidation.error("Could not connect to " + finalEntry.getBaseUrl() - + ". Please check your URL and credentials provided."); + return FormValidation.error(connected); } } catch (Exception e) { if (e.getMessage().contains("Index") && e.getMessage().contains("out of bounds for length")) { diff --git a/src/main/resources/com/hcl/devops/connect/Entry/config.jelly b/src/main/resources/com/hcl/devops/connect/Entry/config.jelly index a512257..e03c5cf 100644 --- a/src/main/resources/com/hcl/devops/connect/Entry/config.jelly +++ b/src/main/resources/com/hcl/devops/connect/Entry/config.jelly @@ -28,7 +28,7 @@
+ method="testConnections" with="syncId,syncToken,baseUrl,apiToken"/>
From 09567491496542e3c399055be07442274a8567a0 Mon Sep 17 00:00:00 2001 From: Leelavathi D H Date: Wed, 18 Jan 2023 14:59:01 +0530 Subject: [PATCH 4/8] Checking user authorization --- .../hcl/devops/connect/Status/AbstractJenkinsStatus.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/hcl/devops/connect/Status/AbstractJenkinsStatus.java b/src/main/java/com/hcl/devops/connect/Status/AbstractJenkinsStatus.java index a2f61f7..c80bf19 100644 --- a/src/main/java/com/hcl/devops/connect/Status/AbstractJenkinsStatus.java +++ b/src/main/java/com/hcl/devops/connect/Status/AbstractJenkinsStatus.java @@ -307,7 +307,12 @@ public JSONObject generate(boolean completed, Entry entry) { .header("Authorization", authorizationHeader) .asString(); apiResponse = response.getBody().toString(); - JSONArray apiResponseArray = JSONArray.fromObject("[" + apiResponse + "]"); + JSONArray apiResponseArray = JSONArray.fromObject("[ ]"); + try{ + apiResponseArray = JSONArray.fromObject("[" + apiResponse + "]"); + } catch (Exception e) { + log.error(" Authorization failed, Check User and User privilages ", e); + } JSONObject apiResponseObject = apiResponseArray.getJSONObject(0); if (apiResponseObject.has("actions")){ JSONArray actionsArray = JSONArray.fromObject(apiResponseObject.getString("actions")); From 24f395ee67a04e28e934ede0effdb9acd6a73c14 Mon Sep 17 00:00:00 2001 From: Leelavathi D H Date: Thu, 19 Jan 2023 15:23:46 +0530 Subject: [PATCH 5/8] Revert "Bump up version" This reverts commit 1fd4c9f36f3b209af0b9eae8c7d026f92a2290e5. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f94df54..172221f 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 4.0.0 com.hcl.devops hcl-accelerate - 3.0.1 + 2.1.5 hpi HCL Accelerate Plugin This plugin can run Jenkins jobs as a part of a deployment plan in HCL Accelerate. From dd857ef5ed5748c687824f366fd3b0948ed60f2d Mon Sep 17 00:00:00 2001 From: Leelavathi D H Date: Thu, 19 Jan 2023 15:23:55 +0530 Subject: [PATCH 6/8] Revert "Validation of provided jenkins credentials, performing connection test." This reverts commit 53cad78e6b2a4a3523adb5637c1f1a76e7760941. --- .../hcl/devops/connect/CloudPublisher.java | 129 ++++++++---------- .../devops/connect/CloudSocketComponent.java | 11 +- .../java/com/hcl/devops/connect/Entry.java | 14 +- .../com/hcl/devops/connect/Entry/config.jelly | 2 +- 4 files changed, 66 insertions(+), 90 deletions(-) diff --git a/src/main/java/com/hcl/devops/connect/CloudPublisher.java b/src/main/java/com/hcl/devops/connect/CloudPublisher.java index 586465b..0edf088 100644 --- a/src/main/java/com/hcl/devops/connect/CloudPublisher.java +++ b/src/main/java/com/hcl/devops/connect/CloudPublisher.java @@ -52,7 +52,6 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; -import java.net.URISyntaxException; import java.security.cert.X509Certificate; import java.security.NoSuchAlgorithmException; import java.security.KeyManagementException; @@ -67,6 +66,7 @@ public class CloudPublisher { private final static String JENKINS_JOB_ENDPOINT_URL = "api/v1/jenkins/jobs"; private final static String JENKINS_JOB_STATUS_ENDPOINT_URL = "api/v1/jenkins/jobStatus"; + private final static String JENKINS_TEST_CONNECTION_URL = "api/v1/jenkins/testConnection"; private final static String BUILD_UPLOAD_URL = "api/v1/builds"; private final static String DEPLOYMENT_UPLOAD_URL = "api/v1/deployments"; @@ -136,6 +136,11 @@ private static String getSyncApiUrl(Entry entry) { return em.getSyncApiEndpoint(entry); } + private static String getSyncApiUrl(String baseUrl) { + EndpointManager em = new EndpointManager(); + return em.getSyncApiEndpoint(baseUrl); + } + public static String getQualityDataUrl(Entry entry) { EndpointManager em = new EndpointManager(); return em.getQualityDataEndpoint(entry); @@ -175,9 +180,9 @@ public static void uploadJobInfo(JSONObject jobJson, Entry entry) { JSONArray payload = new JSONArray(); payload.add(jobJson); - log.info("SENDING JOBS TO: "); - log.info(url); - log.info(jobJson.toString()); + System.out.println("SENDING JOBS TO: "); + System.out.println(url); + System.out.println(jobJson.toString()); CloudPublisher.postToSyncAPI(url, payload.toString(), entry); } @@ -449,7 +454,7 @@ public void completed(final HttpResponse response2) { if (response2.getStatusLine().toString().contains("200")) { log.info(logPrefix + " Upload Job Information successfully"); } else { - log.error(logPrefix + " Error: Upload Job has bad status code,(if 401 check configuration properties) response status " + response2.getStatusLine()); + log.error(logPrefix + " Error: Upload Job has bad status code, response status " + response2.getStatusLine()); } try { EntityUtils.toString(response2.getEntity()); @@ -461,10 +466,10 @@ public void completed(final HttpResponse response2) { } public void failed(final Exception ex) { - log.error(logPrefix + "Error: Failed to upload Job,(check connection between jenkins and Accelerate) response status " + ex.getMessage()); + log.error(logPrefix + "Error: Failed to upload Job, response status " + ex.getMessage()); ex.printStackTrace(); if (ex instanceof IllegalStateException) { - log.error(logPrefix + "Please check if you have the access to the configured tenant.also check connection between jenkins and Accelerate"); + log.error(logPrefix + "Please check if you have the access to the configured tenant."); } } @@ -486,83 +491,61 @@ public static String removeTrailingSlash(String url) { return url; } - public static String testConnection(String syncId, String syncToken, String baseUrl, String apiToken) throws URISyntaxException { + public static boolean testConnection(String syncId, String syncToken, String baseUrl) { CloudPublisher.ensureHttpClientInitialized(); + String url = getSyncApiUrl(baseUrl) + JENKINS_TEST_CONNECTION_URL; CloseableHttpResponse response = null; - String resStr = ""; - String result = ""; - String baseApiUrl = CloudPublisher.removeTrailingSlash(baseUrl); - String url = baseApiUrl + "/release-events-api/graphql/"; - try { - URIBuilder builder = new URIBuilder(url); - builder.setParameter("query", "query{integrationById(id: \"" + syncId + "\"){token,_id,userAccessKey}}"); - URI uri = builder.build(); - HttpGet getMethod = new HttpGet(uri); - getMethod.setHeader("Accept", "application/json"); - getMethod.setHeader("Authorization", "UserAccessKey " + apiToken); + try { + HttpGet getMethod = new HttpGet(url); + // postMethod = addProxyInformation(postMethod); + getMethod.setHeader("sync_token", syncToken); + getMethod.setHeader("sync_id", syncId); + getMethod.setHeader("instance_type", "JENKINS"); + getMethod.setHeader("instance_id", syncId); + getMethod.setHeader("integration_id", syncId); + + // Must include both _ and - headers because NGINX services don't pass _ headers + // by default and the original version of the Accelerate services expected the _ + // headers + getMethod.setHeader("sync-token", syncToken); + getMethod.setHeader("sync-id", syncId); + getMethod.setHeader("instance-type", "JENKINS"); + getMethod.setHeader("instance-id", syncId); + getMethod.setHeader("integration-id", syncId); response = httpClient.execute(getMethod); - log.info("response status message" + response.toString()); - resStr = EntityUtils.toString(response.getEntity()); - log.info("Response body = " + resStr); - JSONObject jsonresStr = JSONObject.fromObject(resStr); - log.info("Response body object = " + jsonresStr); - if (response.getStatusLine().toString().contains("200")) { - if (jsonresStr.has("data")) { - JSONObject dataObject = jsonresStr.getJSONObject("data"); - if (dataObject.has("integrationById")) { - JSONObject integrationByIdObj = dataObject.getJSONObject("integrationById"); - if (integrationByIdObj.isNullObject()) { - log.info("please provide correct integrationId"); - result = "please provide correct integrationId"; - return result; - } else if (!(integrationByIdObj.getString("token").equals(syncToken))) { - log.info("Please provide correct Integration Token value"); - result = "Please provide correct Integration Token value"; - return result; - } else { - log.info("successfull connection"); - result = "successfull connection"; - } - } - } - return result; - - } else if(response.getStatusLine().toString().contains("401")){ - log.error("Wrong userAccessKey, Please provide right one."); - return "Wrong userAccessKey, Please provide right one."; + // get 200 response + log.info("Connected to Accelerate service successfully for : " + baseUrl); + return true; } else { - log.error("could not able to connect to Accelerate"); - return "could not able to connect to Accelerate"; + log.warn("Could not authenticate to Accelerate Services for :" + baseUrl); + log.warn(response.toString()); } } catch (IllegalStateException e) { - log.error("From IllegalStateException"); - log.error("Could not connect to Accelerate:" + e.getMessage()); - return "Could not connect to Accelerate:" + e.getMessage(); - } catch (UnsupportedEncodingException e) { - log.error("From UnsupportedEncodingException"); - log.error("Could not connect to Accelerate:" + e.getMessage()); - return "Could not connect to Accelerate:" + e.getMessage(); - } catch (ClientProtocolException e) { - log.error("From ClientProtocolException"); - log.error("Could not connect to Accelerate:" + e.getMessage()); - return "Could not connect to Accelerate:" + e.getMessage(); - } catch (IOException e) { - log.error("From IOException"); - log.error("Could not connect to Accelerate:" + e.getMessage()); - return "Could not connect to Accelerate from IO:" + e.getMessage(); - } finally { - if (response != null) { - try { - response.close(); - } catch (Exception e) { - log.error("Could not close testconnection response"); - return "Could not close testconnection response"; - } + log.error("Could not connect to Accelerate for : " + baseUrl); + log.error(e.getMessage()); + } catch (UnsupportedEncodingException e) { + log.error("Could not connect to Accelerate for : " + baseUrl); + log.error(e.getMessage()); + } catch (ClientProtocolException e) { + log.error("Could not connect to Accelerate for : " + baseUrl); + log.error(e.getMessage()); + } catch (IOException e) { + log.error("Could not connect to Accelerate for : " + baseUrl); + log.error(e.getMessage()); + } finally { + if (response != null) { + try { + response.close(); + } catch (Exception e) { + log.error("Could not close testconnection response for : " + baseUrl); } } + } + + return false; } } diff --git a/src/main/java/com/hcl/devops/connect/CloudSocketComponent.java b/src/main/java/com/hcl/devops/connect/CloudSocketComponent.java index fdb1c00..2e55223 100644 --- a/src/main/java/com/hcl/devops/connect/CloudSocketComponent.java +++ b/src/main/java/com/hcl/devops/connect/CloudSocketComponent.java @@ -9,7 +9,6 @@ package com.hcl.devops.connect; import java.net.MalformedURLException; -import java.net.URISyntaxException; import java.net.URL; import jenkins.model.Jenkins; @@ -190,14 +189,8 @@ public void handleDelivery(String consumerTag, Envelope envelope, if (envelope.getRoutingKey().contains(".heartbeat")) { String syncId = entry.getSyncId(); String syncToken = entry.getSyncToken(); - String apiToken = entry.getApiToken(); String url = CloudPublisher.removeTrailingSlash(entry.getBaseUrl()); - try { - String connected = CloudPublisher.testConnection(syncId, syncToken, url, apiToken); - } catch (URISyntaxException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + boolean connected = CloudPublisher.testConnection(syncId, syncToken, url); } else { String message = new String(body, "UTF-8"); if (entry.getCheckDuplicate() == true) { @@ -296,7 +289,7 @@ public void handleDelivery(String consumerTag, Envelope envelope, if (checkQueueAvailability(channel, queueName, entry)) { channel.basicConsume(queueName, true, consumer); } else { - log.info(logPrefix + "Queue is not yet available, will attempt to reconnect shortly..."); + log.info(logPrefix + "Queue is not yet available, will attempt to reconect shortly..."); queueIsAvailable = false; } } diff --git a/src/main/java/com/hcl/devops/connect/Entry.java b/src/main/java/com/hcl/devops/connect/Entry.java index b4529b1..81f9771 100644 --- a/src/main/java/com/hcl/devops/connect/Entry.java +++ b/src/main/java/com/hcl/devops/connect/Entry.java @@ -94,10 +94,9 @@ public String getDisplayName() { @RequirePOST public FormValidation doTestConnections(@QueryParameter("syncId") String syncId, @QueryParameter("syncToken") String syncToken, - @QueryParameter("baseUrl") String baseUrl, - @QueryParameter("apiToken") String apiToken) { + @QueryParameter("baseUrl") String baseUrl) { try { - String connected = CloudPublisher.testConnection(syncId, syncToken, baseUrl, apiToken); + boolean connected = CloudPublisher.testConnection(syncId, syncToken, baseUrl); List entries = Jenkins.getInstance().getDescriptorByType(DevOpsGlobalConfiguration.class) .getEntries(); Entry finalEntry = null; @@ -106,12 +105,12 @@ public FormValidation doTestConnections(@QueryParameter("syncId") String syncId, finalEntry = entry; } } - if (connected.equals("successfull connection")) { + if (connected) { boolean amqpConnected = ConnectComputerListener.isRabbitConnected(finalEntry); - String rabbitMessage = "Not connected to RabbitMQ. Unable to run Jenkins jobs from Accelerate.\n WARNING:Check the port number correctly.\n If you use Kubernetes, the default port that is exposed is 31672." + String rabbitMessage = "Not connected to RabbitMQ. Unable to run Jenkins jobs from " + finalEntry.getBaseUrl(); - if (amqpConnected && connected.equals("successfull connection")) { + if (amqpConnected) { if (StringUtils.isNotEmpty(finalEntry.getRabbitMQHost())) { rabbitMessage = "Connected to RabbitMQ ( " + finalEntry.getRabbitMQHost() + " ) successfully. Ready to run Jenkins jobs from " + finalEntry.getBaseUrl(); @@ -123,7 +122,8 @@ public FormValidation doTestConnections(@QueryParameter("syncId") String syncId, return FormValidation.ok("Successful connection to Accelerate Services.\n" + rabbitMessage); } else { - return FormValidation.error(connected); + return FormValidation.error("Could not connect to " + finalEntry.getBaseUrl() + + ". Please check your URL and credentials provided."); } } catch (Exception e) { if (e.getMessage().contains("Index") && e.getMessage().contains("out of bounds for length")) { diff --git a/src/main/resources/com/hcl/devops/connect/Entry/config.jelly b/src/main/resources/com/hcl/devops/connect/Entry/config.jelly index e03c5cf..a512257 100644 --- a/src/main/resources/com/hcl/devops/connect/Entry/config.jelly +++ b/src/main/resources/com/hcl/devops/connect/Entry/config.jelly @@ -28,7 +28,7 @@
+ method="testConnections" with="syncId,syncToken,baseUrl"/>
From f148fec340b565adb6d87f0568d941799988cbb8 Mon Sep 17 00:00:00 2001 From: Leelavathi D H Date: Thu, 19 Jan 2023 15:24:58 +0530 Subject: [PATCH 7/8] Revert "Checking user authorization" This reverts commit 09567491496542e3c399055be07442274a8567a0. --- .../hcl/devops/connect/Status/AbstractJenkinsStatus.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/com/hcl/devops/connect/Status/AbstractJenkinsStatus.java b/src/main/java/com/hcl/devops/connect/Status/AbstractJenkinsStatus.java index c80bf19..a2f61f7 100644 --- a/src/main/java/com/hcl/devops/connect/Status/AbstractJenkinsStatus.java +++ b/src/main/java/com/hcl/devops/connect/Status/AbstractJenkinsStatus.java @@ -307,12 +307,7 @@ public JSONObject generate(boolean completed, Entry entry) { .header("Authorization", authorizationHeader) .asString(); apiResponse = response.getBody().toString(); - JSONArray apiResponseArray = JSONArray.fromObject("[ ]"); - try{ - apiResponseArray = JSONArray.fromObject("[" + apiResponse + "]"); - } catch (Exception e) { - log.error(" Authorization failed, Check User and User privilages ", e); - } + JSONArray apiResponseArray = JSONArray.fromObject("[" + apiResponse + "]"); JSONObject apiResponseObject = apiResponseArray.getJSONObject(0); if (apiResponseObject.has("actions")){ JSONArray actionsArray = JSONArray.fromObject(apiResponseObject.getString("actions")); From f88ff232e1fe191fc2ff390c636038c9be4ef626 Mon Sep 17 00:00:00 2001 From: Leelavathi D H Date: Thu, 19 Jan 2023 15:26:06 +0530 Subject: [PATCH 8/8] Bump up version to 3.0.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 172221f..1ee1d0c 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 4.0.0 com.hcl.devops hcl-accelerate - 2.1.5 + 3.0.0 hpi HCL Accelerate Plugin This plugin can run Jenkins jobs as a part of a deployment plan in HCL Accelerate.