/** * Attempts to parse the string as JSON. returns true on success * * @param possiblyJson A string that may be JSON * @return true or false. True if string is valid JSON. */ private boolean isTaskJson(String possiblyJson) { try { JSONSerializer.toJSON(possiblyJson); return true; } catch (JSONException ex) { return false; } }
/** * Process HTTP request. * * @param act Action. * @param req Http request. * @param res Http response. */ private void processRequest(String act, HttpServletRequest req, HttpServletResponse res) { res.setContentType("application/json"); res.setCharacterEncoding("UTF-8"); GridRestCommand cmd = command(req); if (cmd == null) { res.setStatus(HttpServletResponse.SC_BAD_REQUEST); return; } if (!authChecker.apply(req.getHeader("X-Signature"))) { res.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return; } GridRestResponse cmdRes; Map<String, Object> params = parameters(req); try { GridRestRequest cmdReq = createRequest(cmd, params, req); if (log.isDebugEnabled()) log.debug("Initialized command request: " + cmdReq); cmdRes = hnd.handle(cmdReq); if (cmdRes == null) throw new IllegalStateException("Received null result from handler: " + hnd); byte[] sesTok = cmdRes.sessionTokenBytes(); if (sesTok != null) cmdRes.setSessionToken(U.byteArray2HexString(sesTok)); res.setStatus(HttpServletResponse.SC_OK); } catch (Exception e) { res.setStatus(HttpServletResponse.SC_OK); U.error(log, "Failed to process HTTP request [action=" + act + ", req=" + req + ']', e); cmdRes = new GridRestResponse(STATUS_FAILED, e.getMessage()); } catch (Throwable e) { U.error(log, "Failed to process HTTP request [action=" + act + ", req=" + req + ']', e); throw e; } JsonConfig cfg = new GridJettyJsonConfig(); // Workaround for not needed transformation of string into JSON object. if (cmdRes.getResponse() instanceof String) cfg.registerJsonValueProcessor(cmdRes.getClass(), "response", SKIP_STR_VAL_PROC); if (cmdRes.getResponse() instanceof GridClientTaskResultBean && ((GridClientTaskResultBean) cmdRes.getResponse()).getResult() instanceof String) cfg.registerJsonValueProcessor(cmdRes.getResponse().getClass(), "result", SKIP_STR_VAL_PROC); JSON json; try { json = JSONSerializer.toJSON(cmdRes, cfg); } catch (JSONException e) { U.error(log, "Failed to convert response to JSON: " + cmdRes, e); json = JSONSerializer.toJSON(new GridRestResponse(STATUS_FAILED, e.getMessage()), cfg); } try { if (log.isDebugEnabled()) log.debug("Parsed command response into JSON object: " + json.toString(2)); res.getWriter().write(json.toString()); if (log.isDebugEnabled()) log.debug( "Processed HTTP request [action=" + act + ", jsonRes=" + cmdRes + ", req=" + req + ']'); } catch (IOException e) { U.error(log, "Failed to send HTTP response: " + json.toString(2), e); } }
@Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) { // This method deserves a refactor and cleanup. boolean success = true; Log log = new Log(listener); if (Result.FAILURE.equals(build.getResult())) { log.info("Not deploying due to job being in FAILED state."); return success; } logStartHeader(log); // todo: getting from descriptor is ugly. refactor? getDescriptorImpl().setGlobalConfiguration(); OctopusApi api = getDescriptorImpl().api; VariableResolver resolver = build.getBuildVariableResolver(); EnvVars envVars; try { envVars = build.getEnvironment(listener); } catch (Exception ex) { log.fatal( String.format( "Failed to retrieve environment variables for this build - '%s'", ex.getMessage())); return false; } EnvironmentVariableValueInjector envInjector = new EnvironmentVariableValueInjector(resolver, envVars); // NOTE: hiding the member variables of the same name with their env-injected equivalents String project = envInjector.injectEnvironmentVariableValues(this.project); String releaseVersion = envInjector.injectEnvironmentVariableValues(this.releaseVersion); String environment = envInjector.injectEnvironmentVariableValues(this.environment); String variables = envInjector.injectEnvironmentVariableValues(this.variables); com.octopusdeploy.api.Project p = null; try { p = api.getProjectByName(project); } catch (Exception ex) { log.fatal( String.format( "Retrieving project name '%s' failed with message '%s'", project, ex.getMessage())); success = false; } com.octopusdeploy.api.Environment env = null; try { env = api.getEnvironmentByName(environment); } catch (Exception ex) { log.fatal( String.format( "Retrieving environment name '%s' failed with message '%s'", environment, ex.getMessage())); success = false; } if (p == null) { log.fatal("Project was not found."); success = false; } if (env == null) { log.fatal("Environment was not found."); success = false; } if (!success) // Early exit { return success; } Set<com.octopusdeploy.api.Release> releases = null; try { releases = api.getReleasesForProject(p.getId()); } catch (Exception ex) { log.fatal( String.format( "Retrieving releases for project '%s' failed with message '%s'", project, ex.getMessage())); success = false; } if (releases == null) { log.fatal("Releases was not found."); return false; } Release releaseToDeploy = null; for (Release r : releases) { if (releaseVersion.equals(r.getVersion())) { releaseToDeploy = r; break; } } if (releaseToDeploy == null) // early exit { log.fatal( String.format( "Unable to find release version %s for project %s", releaseVersion, project)); return false; } Properties properties = new Properties(); try { properties.load(new StringReader(variables)); } catch (Exception ex) { log.fatal( String.format( "Unable to load entry variables failed with message '%s'", ex.getMessage())); success = false; } // TODO: Can we tell if we need to call? For now I will always try and get variable and use if I // find them Set<com.octopusdeploy.api.Variable> variablesForDeploy = null; try { String releaseId = releaseToDeploy.getId(); String environmentId = env.getId(); variablesForDeploy = api.getVariablesByReleaseAndEnvironment(releaseId, environmentId, properties); } catch (Exception ex) { log.fatal( String.format( "Retrieving variables for release '%s' to environment '%s' failed with message '%s'", releaseToDeploy.getId(), env.getName(), ex.getMessage())); success = false; } try { String results = api.executeDeployment(releaseToDeploy.getId(), env.getId(), variablesForDeploy); if (isTaskJson(results)) { JSON resultJson = JSONSerializer.toJSON(results); String urlSuffix = ((JSONObject) resultJson).getJSONObject("Links").getString("Web"); String url = getDescriptorImpl().octopusHost; if (url.endsWith("/")) { url = url.substring(0, url.length() - 2); } log.info("Deployment executed: \n\t" + url + urlSuffix); build.addAction( new BuildInfoSummary( BuildInfoSummary.OctopusDeployEventType.Deployment, url + urlSuffix)); if (waitForDeployment) { log.info("Waiting for deployment to complete."); String resultState = waitForDeploymentCompletion(resultJson, api, log); if (resultState == null) { log.info("Marking build failed due to failure in waiting for deployment to complete."); success = false; } if ("Failed".equals(resultState)) { log.info("Marking build failed due to deployment task status."); success = false; } } } } catch (IOException ex) { log.fatal("Failed to deploy: " + ex.getMessage()); success = false; } return success; }