diff --git a/README.md b/README.md index a9d4609..80df91e 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ Optional inputs: - 0.6.6 Make File Copier binary-safe. - 0.7.0 Provide container upgrade node step, with ability to set labels and environment variables. - - 0.7.1 Provide ability to remove labels and environment variables via container upgrade. + - 0.7.x Provide ability to remove labels and environment variables via container upgrade. - 0.9.x Provide reasonable if not complete test coverage prior to 1.x ## Compatibility diff --git a/build.gradle b/build.gradle index 58c1796..0838c45 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,7 @@ ext.pluginName = 'Rancher Node Plugins' ext.pluginDescription = 'Interface with Rancher environments' scmVersion { - ignoreUncommittedChanges = false + ignoreUncommittedChanges = true tag { // Ignore tags that begin with , include all tags // if prefix is empty. diff --git a/src/main/java/com/bioraft/rundeck/rancher/RancherAddService.java b/src/main/java/com/bioraft/rundeck/rancher/RancherAddService.java index 70bd6c0..a29b5f1 100644 --- a/src/main/java/com/bioraft/rundeck/rancher/RancherAddService.java +++ b/src/main/java/com/bioraft/rundeck/rancher/RancherAddService.java @@ -16,11 +16,8 @@ package com.bioraft.rundeck.rancher; import com.dtolabs.rundeck.core.common.Framework; -import com.dtolabs.rundeck.core.execution.ExecutionContext; -import com.dtolabs.rundeck.core.execution.workflow.steps.FailureReason; import com.dtolabs.rundeck.core.execution.workflow.steps.StepException; import com.dtolabs.rundeck.core.plugins.Plugin; -import com.dtolabs.rundeck.core.storage.ResourceMeta; import com.dtolabs.rundeck.plugins.PluginLogger; import com.dtolabs.rundeck.plugins.ServiceNameConstants; import com.dtolabs.rundeck.plugins.descriptions.*; @@ -31,8 +28,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableMap; -import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import static com.bioraft.rundeck.rancher.RancherShared.*; @@ -110,21 +108,21 @@ public void executeStep(final PluginStepContext context, final Map mapBuilder = ImmutableMap.builder(); mapBuilder.put("type", "launchConfig"); @@ -167,13 +177,22 @@ public void executeStep(final PluginStepContext context, final Map 0) { + // Add in the new or replacement secrets specified in the step. + List secretsArray = new ArrayList<>(); + for (String secretId : secrets.split("/[,; ]+/")) { + secretsArray.add(secretJson(secretId)); + } + mapBuilder.put("secrets", "[" + String.join(",", secretsArray) + "]"); + } + JsonNode check; String stackCheck; String stackId; try { // First look for a stack with the designated ID. stackCheck = endpoint + "/projects/" + environmentId + "/stacks/" + stackName; - logger.log(INFO_LEVEL, "Looking for `" + stackCheck); + logger.log(INFO_LEVEL, "Looking for " + stackCheck); check = client.get(stackCheck); if (check.path("type").asText().equals("error")) { throw new IOException(); @@ -184,7 +203,7 @@ public void executeStep(final PluginStepContext context, final Mapbuilder().put("name", stackName).build()); - if (check.path("data").elements().hasNext()) { - return check.path("data").elements().next().path("id").asText(); + String stackCheck = endpoint + "/projects/" + environmentId + "/stacks?name=" + stackName; + logger.log(INFO_LEVEL, "Looking for " + stackCheck); + JsonNode check = client.get(stackCheck); + if (check.path("data").has(0)) { + return check.path("data").get(0).path("id").asText(); } else { logger.log(ERR_LEVEL, "FATAL: no stack `" + stackName + "` was found."); - throw new StepException("Stack does not exist", Cause.InvalidConfiguration); + throw new StepException("Stack does not exist", ErrorCause.InvalidConfiguration); } } catch (IOException ex) { logger.log(ERR_LEVEL, "FATAL: no stack `" + stackName + "` was found."); - throw new StepException("Stack does not exist", Cause.InvalidConfiguration); + throw new StepException("Stack does not exist", ErrorCause.InvalidConfiguration); } } @@ -230,34 +249,7 @@ private void addJsonData(String name, String data, ImmutableMap.Builderbuilder().put("name", stackName).build()); - if (check.path("data").elements().hasNext()) { + if (check.path("data").has(0)) { logger.log(ERR_LEVEL, "FATAL: A stack with the name " + stackName + " already exists."); throw new StepException("Stack already exists", RancherNewStackFailureReason.InvalidConfiguration); } @@ -121,26 +131,4 @@ public enum RancherNewStackFailureReason implements FailureReason { InvalidEnvironmentName, IOException } - - /** - * Get a (secret) value from password storage. - * - * @param context The current plugin execution context. - * @param passwordStoragePath The path to look up in storage. - * @return The requested secret or password. - * @throws StepException When there is an IO Exception writing to stream. - */ - private String loadStoragePathData(final ExecutionContext context, final String passwordStoragePath) throws StepException { - if (null == passwordStoragePath) { - return null; - } - ResourceMeta contents = context.getStorageTree().getResource(passwordStoragePath).getContents(); - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - try { - contents.writeContent(byteArrayOutputStream); - } catch (IOException e) { - throw new StepException("Could not get " + passwordStoragePath, e, RancherNewStackFailureReason.IOException); - } - return new String(byteArrayOutputStream.toByteArray()); - } } diff --git a/src/main/java/com/bioraft/rundeck/rancher/RancherShared.java b/src/main/java/com/bioraft/rundeck/rancher/RancherShared.java index 8dbb252..f2d8267 100644 --- a/src/main/java/com/bioraft/rundeck/rancher/RancherShared.java +++ b/src/main/java/com/bioraft/rundeck/rancher/RancherShared.java @@ -16,6 +16,18 @@ package com.bioraft.rundeck.rancher; +import com.dtolabs.rundeck.core.execution.ExecutionContext; +import com.dtolabs.rundeck.core.execution.workflow.steps.FailureReason; +import com.dtolabs.rundeck.core.execution.workflow.steps.StepException; +import com.dtolabs.rundeck.core.execution.workflow.steps.node.NodeStepException; +import com.dtolabs.rundeck.core.storage.ResourceMeta; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + import static com.dtolabs.rundeck.core.plugins.configuration.PropertyResolverFactory.PROJECT_PREFIX; import static com.dtolabs.rundeck.core.plugins.configuration.PropertyResolverFactory.FRAMEWORK_PREFIX; @@ -57,9 +69,15 @@ public class RancherShared { // Step Plugins public static final String PROJ_RANCHER_ENDPOINT = PROJECT_PREFIX + RANCHER_CONFIG_ENDPOINT; - public static final String PROJ_RANCHER_ENVIRONMENT_IDS = PROJECT_PREFIX + RANCHER_SERVICE_PROVIDER + "-" + CONFIG_ENVIRONMENT_IDS; + public static final String FMWK_RANCHER_ENDPOINT = FRAMEWORK_PREFIX + RANCHER_CONFIG_ENDPOINT; + public static final String PROJ_RANCHER_ACCESSKEY_PATH = PROJECT_PREFIX + RANCHER_SERVICE_PROVIDER + "-" + CONFIG_ACCESSKEY_PATH; + public static final String FMWK_RANCHER_ACCESSKEY_PATH = FRAMEWORK_PREFIX + RANCHER_SERVICE_PROVIDER + "-" + CONFIG_ACCESSKEY_PATH; + public static final String PROJ_RANCHER_SECRETKEY_PATH = PROJECT_PREFIX + RANCHER_SERVICE_PROVIDER + "-" + CONFIG_SECRETKEY_PATH; + public static final String FMWK_RANCHER_SECRETKEY_PATH = FRAMEWORK_PREFIX + RANCHER_SERVICE_PROVIDER + "-" + CONFIG_SECRETKEY_PATH; + + public static final String PROJ_RANCHER_ENVIRONMENT_IDS = PROJECT_PREFIX + RANCHER_SERVICE_PROVIDER + "-" + CONFIG_ENVIRONMENT_IDS; public static String ensureStringIsJsonObject(String string) { if (string == null) { @@ -76,4 +94,55 @@ public static String ensureStringIsJsonArray(String string) { String trimmed = string.replaceFirst("^\\s*\\[?", "[").replaceFirst("\\s*$", ""); return trimmed + (trimmed.endsWith("]") ? "" : "]"); } + + /** + * Get a (secret) value from password storage. + * + * @param context The current plugin execution context. + * @param passwordStoragePath The path to look up in storage. + * @return The requested secret or password. + * @throws IOException When there is an IO Exception writing to stream. + */ + public static String loadStoragePathData(final ExecutionContext context, final String passwordStoragePath) throws IOException { + if (null == passwordStoragePath) { + throw new IOException("Storage path is not defined."); + } + ResourceMeta contents = context.getStorageTree().getResource(passwordStoragePath).getContents(); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + contents.writeContent(byteArrayOutputStream); + return new String(byteArrayOutputStream.toByteArray()); + } + + /** + * Builds a JsonNode object for insertion into the secrets array. + * + * @param secretId A secret ID from Rancher (like "1se1") + * @return JSON expression for secret reference. + * @throws NodeStepException when JSON is not valid. + */ + public static JsonNode buildSecret(String secretId, String nodeName) throws NodeStepException { + try { + return (new ObjectMapper()).readTree(secretJson(secretId)); + } catch (JsonProcessingException e) { + throw new NodeStepException("Failed add secret", e, ErrorCause.InvalidJson, nodeName); + } + } + + public static String secretJson(String secretId) { + return "{ \"type\": \"secretReference\", \"gid\": \"0\", \"mode\": \"444\", \"name\": \"\", \"secretId\": \"" + + secretId + "\", \"uid\": \"0\"}"; + } + + public enum ErrorCause implements FailureReason { + InvalidConfiguration, + InvalidJson, + IOException, + NoKeyStorage, + NoServiceObject, + ServiceNotRunning, + MissingUpgradeURL, + NoUpgradeData, + UpgradeFailure, + Interrupted + } } \ No newline at end of file diff --git a/src/main/java/com/bioraft/rundeck/rancher/RancherUpgradeService.java b/src/main/java/com/bioraft/rundeck/rancher/RancherUpgradeService.java index b0ba84d..e71c3cd 100644 --- a/src/main/java/com/bioraft/rundeck/rancher/RancherUpgradeService.java +++ b/src/main/java/com/bioraft/rundeck/rancher/RancherUpgradeService.java @@ -23,7 +23,6 @@ import com.dtolabs.rundeck.core.Constants; import com.dtolabs.rundeck.core.common.INodeEntry; import com.dtolabs.rundeck.core.execution.ExecutionContext; -import com.dtolabs.rundeck.core.execution.workflow.steps.FailureReason; import com.dtolabs.rundeck.core.execution.workflow.steps.node.NodeStepException; import com.dtolabs.rundeck.core.plugins.Plugin; import com.dtolabs.rundeck.plugins.PluginLogger; @@ -48,6 +47,7 @@ import okhttp3.RequestBody; import okhttp3.Response; +import static com.bioraft.rundeck.rancher.RancherShared.*; import static com.dtolabs.rundeck.core.plugins.configuration.StringRenderingConstants.CODE_SYNTAX_MODE; import static com.dtolabs.rundeck.core.plugins.configuration.StringRenderingConstants.DISPLAY_TYPE_KEY; @@ -86,8 +86,6 @@ public class RancherUpgradeService implements NodeStepPlugin { private String nodeName; - private ExecutionContext executionContext; - private PluginLogger logger; OkHttpClient client; @@ -105,30 +103,35 @@ public void executeNodeStep(PluginStepContext ctx, Map cfg, INod throws NodeStepException { this.nodeName = node.getNodename(); - this.executionContext = ctx.getExecutionContext(); + ExecutionContext executionContext = ctx.getExecutionContext(); this.logger = ctx.getLogger(); Map attributes = node.getAttributes(); - String accessKey = this.loadStoragePathData(attributes.get(RancherShared.CONFIG_ACCESSKEY_PATH)); - String secretKey = this.loadStoragePathData(attributes.get(RancherShared.CONFIG_SECRETKEY_PATH)); + String accessKey; + String secretKey; + try { + accessKey = loadStoragePathData(executionContext, attributes.get(RancherShared.CONFIG_ACCESSKEY_PATH)); + secretKey = loadStoragePathData(executionContext, attributes.get(RancherShared.CONFIG_SECRETKEY_PATH)); + } catch (IOException e) { + throw new NodeStepException("Could not get secret storage path", e, ErrorCause.IOException, this.nodeName); + } JsonNode service = apiGet(accessKey, secretKey, attributes.get("services")).path("data").path(0); - String serviceState = service.path("state").asText(); if (!serviceState.equals("active")) { String message = "Service state must be running, was " + serviceState; - throw new NodeStepException(message, UpgradeFailureReason.ServiceNotRunning, node.getNodename()); + throw new NodeStepException(message, ErrorCause.ServiceNotRunning, node.getNodename()); } String upgradeUrl = service.path("actions").path("upgrade").asText(); if (upgradeUrl.length() == 0) { - throw new NodeStepException("No upgrade URL found", UpgradeFailureReason.MissingUpgradeURL, + throw new NodeStepException("No upgrade URL found", ErrorCause.MissingUpgradeURL, node.getNodename()); } JsonNode upgrade = service.path("upgrade"); if (upgrade.isMissingNode()) { - throw new NodeStepException("No upgrade data found", UpgradeFailureReason.NoUpgradeData, + throw new NodeStepException("No upgrade data found", ErrorCause.NoUpgradeData, node.getNodename()); } @@ -172,13 +175,22 @@ public void executeNodeStep(PluginStepContext ctx, Map cfg, INod * * @param upgrade JsonNode representing the target upgraded configuration. */ - private void setEnvVars(JsonNode upgrade) { + private void setEnvVars(JsonNode upgrade) throws NodeStepException { if (environment != null && environment.length() > 0) { ObjectNode envObject = (ObjectNode) upgrade.get("inServiceStrategy").get("launchConfig").get("environment"); - for (String keyValue : environment.split(";")) { - String[] values = keyValue.split(":"); - envObject.put(values[0], values[1]); - logger.log(Constants.INFO_LEVEL, "Setting environment variable " + values[0] + " to " + values[1]); + ObjectMapper objectMapper = new ObjectMapper(); + try { + JsonNode map = objectMapper.readTree(ensureStringIsJsonObject(environment)); + Iterator> iterator = map.fields(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + String key = entry.getKey(); + String value = entry.getValue().asText(); + envObject.put(key, value); + logger.log(Constants.INFO_LEVEL, "Setting environment variable " + key + " to " + value); + } + } catch (JsonProcessingException e) { + throw new NodeStepException("Invalid Labels JSON", ErrorCause.InvalidJson, this.nodeName); } } } @@ -188,13 +200,22 @@ private void setEnvVars(JsonNode upgrade) { * * @param upgrade JsonNode representing the target upgraded configuration. */ - private void setLabels(JsonNode upgrade) { + private void setLabels(JsonNode upgrade) throws NodeStepException { if (labels != null && labels.length() > 0) { ObjectNode labelObject = (ObjectNode) upgrade.get("inServiceStrategy").get("launchConfig").get("labels"); - for (String keyValue : labels.split(";")) { - String[] values = keyValue.split(":"); - labelObject.put(values[0], values[1]); - logger.log(Constants.INFO_LEVEL, "Setting label " + values[0] + " to " + values[1]); + ObjectMapper objectMapper = new ObjectMapper(); + try { + JsonNode map = objectMapper.readTree(ensureStringIsJsonObject(labels)); + Iterator> iterator = map.fields(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + String key = entry.getKey(); + String value = entry.getValue().asText(); + labelObject.put(key, value); + logger.log(Constants.INFO_LEVEL, "Setting environment variable " + key + " to " + value); + } + } catch (JsonProcessingException e) { + throw new NodeStepException("Invalid Labels JSON", ErrorCause.InvalidJson, this.nodeName); } } } @@ -216,6 +237,7 @@ private void addSecrets(JsonNode upgrade) throws NodeStepException { Iterator elements = launchConfig.get("secrets").elements(); while (elements.hasNext()) { JsonNode secretObject = elements.next(); + // @todo this only works for a single secret added. if (!secretObject.get("secretId").asText().equals(secrets)) { secretsArray.add(secretObject); } @@ -224,29 +246,12 @@ private void addSecrets(JsonNode upgrade) throws NodeStepException { // Add in the new or replacement secrets specified in the step. for (String secretId : secrets.split("/[,; ]+/")) { - secretsArray.add(this.buildSecret(secretId)); + secretsArray.add(buildSecret(secretId, this.nodeName)); logger.log(Constants.INFO_LEVEL, "Adding secret map to " + secretId); } } } - /** - * Builds a JsonNode object for insertion into the secrets array. - * - * @param secretId A secret ID from Rancher (like "1se1") - * @return JSON expression for secret reference. - * @throws NodeStepException when JSON is not valid. - */ - private JsonNode buildSecret(String secretId) throws NodeStepException { - String json = "{ \"type\": \"secretReference\", \"gid\": \"0\", \"mode\": \"444\", \"name\": \"\", \"secretId\": \"" - + secretId + "\", \"uid\": \"0\"}"; - try { - return (new ObjectMapper()).readTree(json); - } catch (JsonProcessingException e) { - throw new NodeStepException("Failed add secret", e, UpgradeFailureReason.InvalidJson, this.nodeName); - } - } - /** * Performs the actual upgrade. * @@ -268,7 +273,7 @@ private void doUpgrade(String accessKey, String secretKey, String upgradeUrl, St try { Thread.sleep(5000); } catch (InterruptedException e) { - throw new NodeStepException(e, UpgradeFailureReason.Interrupted, nodeName); + throw new NodeStepException(e, ErrorCause.Interrupted, nodeName); } service = apiGet(accessKey, secretKey, link); state = service.get("state").asText(); @@ -289,7 +294,7 @@ private void doUpgrade(String accessKey, String secretKey, String upgradeUrl, St try { Thread.sleep(5000); } catch (InterruptedException e) { - throw new NodeStepException(e, UpgradeFailureReason.Interrupted, nodeName); + throw new NodeStepException(e, ErrorCause.Interrupted, nodeName); } } } @@ -317,7 +322,7 @@ private JsonNode apiGet(String accessKey, String secretKey, String url) throws N assert response.body() != null; return mapper.readTree(response.body().string()); } catch (IOException e) { - throw new NodeStepException(e.getMessage(), e, UpgradeFailureReason.NoServiceObject, nodeName); + throw new NodeStepException(e.getMessage(), e, ErrorCause.NoServiceObject, nodeName); } } @@ -345,47 +350,7 @@ private JsonNode apiPost(String accessKey, String secretKey, String url, String assert response.body() != null; return mapper.readTree(response.body().string()); } catch (IOException e) { - throw new NodeStepException(e.getMessage(), e, UpgradeFailureReason.UpgradeFailure, nodeName); + throw new NodeStepException(e.getMessage(), e, ErrorCause.UpgradeFailure, nodeName); } } - - /** - * Get a (secret) value from password storage. - * - * @param path Storage path for secure data. - * @return Secure data from Rundeck storage. - * @throws NodeStepException when content cannot be written to output stream - */ - private String loadStoragePathData(final String path) throws NodeStepException { - if (null == path) { - return null; - } - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - try { - executionContext.getStorageTree().getResource(path).getContents().writeContent(stream); - } catch (Exception e) { - throw new NodeStepException(e, UpgradeFailureReason.NoKeyStorage, nodeName); - } - return new String(stream.toByteArray()); - } - - private enum UpgradeFailureReason implements FailureReason { - // Could not read Access Key and/or Storage Key - NoKeyStorage, - // Service specified in node did not exist - NoServiceObject, - // Service specified in node was not running - ServiceNotRunning, - // Upgrade URL not specified in service JSON - MissingUpgradeURL, - // Upgrade data is missing - NoUpgradeData, - // Upgrade failed - UpgradeFailure, - // Upgrade was interrupted - Interrupted, - // A JSON string could not be read into a JsonNode object - InvalidJson - } - } diff --git a/src/test/java/com/bioraft/rundeck/rancher/PluginStepTest.java b/src/test/java/com/bioraft/rundeck/rancher/PluginStepTest.java index 7af747c..537c435 100644 --- a/src/test/java/com/bioraft/rundeck/rancher/PluginStepTest.java +++ b/src/test/java/com/bioraft/rundeck/rancher/PluginStepTest.java @@ -23,13 +23,7 @@ import com.dtolabs.rundeck.plugins.step.PluginStepContext; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import okhttp3.Call; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; import org.rundeck.storage.api.Resource; import java.io.BufferedReader; @@ -37,11 +31,10 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; import static com.bioraft.rundeck.rancher.RancherShared.*; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.when; /** * Tests for Nexus3OptionProvider. @@ -59,9 +52,6 @@ public class PluginStepTest { @Mock HttpClient client; - @Mock - Call call; - @Mock PluginStepContext ctx; @@ -86,16 +76,10 @@ public class PluginStepTest { @Mock Map cfg; - RancherNewStack upgrade; - - public void setUp() throws IOException { - Map map = Stream - .of(new String[][]{{"services", endpoint}, - {RancherShared.CONFIG_ACCESSKEY_PATH, "keys/rancher/access.key"}, - {RancherShared.CONFIG_SECRETKEY_PATH, "keys/rancher/secret.key"},}) - .collect(Collectors.toMap(data -> data[0], data -> data[1])); + public void setUp() { when(ctx.getLogger()).thenReturn(logger); when(ctx.getFramework()).thenReturn(framework); + when(ctx.getFrameworkProject()).thenReturn(project); when(ctx.getExecutionContext()).thenReturn(executionContext); when(framework.getProjectProperty(project, PROJ_RANCHER_ENDPOINT)).thenReturn(endpoint); @@ -108,15 +92,14 @@ public void setUp() throws IOException { when(cfg.get("stack")).thenReturn("testStack"); } - - private InputStream getResourceStream(String resource) { + protected InputStream getResourceStream(String resource) { ClassLoader classLoader = getClass().getClassLoader(); InputStream stream = classLoader.getResourceAsStream(resource); if (stream == null) throw new AssertionError(); return stream; } - private JsonNode readFromInputStream(InputStream inputStream) throws IOException { + protected JsonNode readFromInputStream(InputStream inputStream) throws IOException { StringBuilder resultStringBuilder = new StringBuilder(); InputStreamReader reader = new InputStreamReader(inputStream); try (BufferedReader br = new BufferedReader(reader)) { @@ -126,6 +109,6 @@ private JsonNode readFromInputStream(InputStream inputStream) throws IOException } } ObjectMapper mapper = new ObjectMapper(); - return (ObjectNode) mapper.readTree(resultStringBuilder.toString()); + return mapper.readTree(resultStringBuilder.toString()); } } \ No newline at end of file diff --git a/src/test/java/com/bioraft/rundeck/rancher/RancherAddServiceTest.java b/src/test/java/com/bioraft/rundeck/rancher/RancherAddServiceTest.java index f95e115..788035a 100644 --- a/src/test/java/com/bioraft/rundeck/rancher/RancherAddServiceTest.java +++ b/src/test/java/com/bioraft/rundeck/rancher/RancherAddServiceTest.java @@ -17,16 +17,12 @@ import com.dtolabs.rundeck.core.execution.workflow.steps.StepException; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.runners.MockitoJUnitRunner; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import static org.mockito.Mockito.*; @@ -42,7 +38,7 @@ public class RancherAddServiceTest extends PluginStepTest { RancherAddService upgrade; @Before - public void implSetUp() throws IOException { + public void implSetUp() { setUp(); } @@ -75,9 +71,9 @@ public void whenStackNameIsGiven() throws StepException, IOException { when(cfg.get("imageUuid")).thenReturn("repo/image:tag"); JsonNode notFound = readFromInputStream(getResourceStream("not-found.json")); - when(client.get(anyString())).thenReturn(notFound); - JsonNode stacks = readFromInputStream(getResourceStream("stacks.json")); + when(client.get(anyString())).thenReturn(notFound, stacks); + when(client.get(anyString(), anyMapOf(String.class, String.class))).thenReturn(stacks); JsonNode service = readFromInputStream(getResourceStream("service.json")); @@ -86,8 +82,8 @@ public void whenStackNameIsGiven() throws StepException, IOException { upgrade = new RancherAddService(client); upgrade.executeStep(ctx, cfg); - verify(client, times(1)).get(anyString()); - verify(client, times(1)).get(anyString(), anyMapOf(String.class, String.class)); + verify(client, times(2)).get(anyString()); + verify(client, times(0)).get(anyString(), anyMapOf(String.class, String.class)); verify(client, times(1)).post(anyString(), anyMapOf(String.class, Object.class)); } @@ -111,24 +107,4 @@ public void whenStackDoesNotExist() throws StepException, IOException { verify(client, times(1)).get(anyString(), anyMapOf(String.class, String.class)); verify(client, times(0)).post(anyString(), anyMapOf(String.class, Object.class)); } - - private InputStream getResourceStream(String resource) { - ClassLoader classLoader = getClass().getClassLoader(); - InputStream stream = classLoader.getResourceAsStream(resource); - if (stream == null) throw new AssertionError(); - return stream; - } - - private JsonNode readFromInputStream(InputStream inputStream) throws IOException { - StringBuilder resultStringBuilder = new StringBuilder(); - InputStreamReader reader = new InputStreamReader(inputStream); - try (BufferedReader br = new BufferedReader(reader)) { - String line; - while ((line = br.readLine()) != null) { - resultStringBuilder.append(line).append("\n"); - } - } - ObjectMapper mapper = new ObjectMapper(); - return mapper.readTree(resultStringBuilder.toString()); - } } \ No newline at end of file diff --git a/src/test/java/com/bioraft/rundeck/rancher/RancherNewStackTest.java b/src/test/java/com/bioraft/rundeck/rancher/RancherNewStackTest.java index cf08e0b..75aab32 100644 --- a/src/test/java/com/bioraft/rundeck/rancher/RancherNewStackTest.java +++ b/src/test/java/com/bioraft/rundeck/rancher/RancherNewStackTest.java @@ -17,16 +17,12 @@ import com.dtolabs.rundeck.core.execution.workflow.steps.StepException; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.runners.MockitoJUnitRunner; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import static org.mockito.Mockito.*; @@ -42,7 +38,7 @@ public class RancherNewStackTest extends PluginStepTest { RancherNewStack upgrade; @Before - public void implSetUp() throws IOException { + public void implSetUp() { setUp(); } @@ -78,24 +74,4 @@ public void whenStackExists() throws StepException, IOException { verify(client, times(1)).get(anyString(), anyMapOf(String.class, String.class)); verify(client, times(0)).post(anyString(), anyMapOf(String.class, Object.class)); } - - private InputStream getResourceStream(String resource) { - ClassLoader classLoader = getClass().getClassLoader(); - InputStream stream = classLoader.getResourceAsStream(resource); - if (stream == null) throw new AssertionError(); - return stream; - } - - private JsonNode readFromInputStream(InputStream inputStream) throws IOException { - StringBuilder resultStringBuilder = new StringBuilder(); - InputStreamReader reader = new InputStreamReader(inputStream); - try (BufferedReader br = new BufferedReader(reader)) { - String line; - while ((line = br.readLine()) != null) { - resultStringBuilder.append(line).append("\n"); - } - } - ObjectMapper mapper = new ObjectMapper(); - return mapper.readTree(resultStringBuilder.toString()); - } } \ No newline at end of file