Skip to content

Commit

Permalink
Merge pull request #55 from gigantor/sfdc
Browse files Browse the repository at this point in the history
Make salt api endpoint scheme configurable
  • Loading branch information
jlisfdc committed Jul 30, 2014
2 parents 5d0c631 + 3e0eea9 commit 2958e07
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 24 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version = 0.2
version = 0.3
rundeckPluginVersion = 1.1

mavenCentralUrl = http://repo1.maven.org/maven2
18 changes: 12 additions & 6 deletions src/main/java/org/rundeck/plugin/salt/SaltApiNodeStepPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,6 @@ public enum SaltApiNodeStepFailureReason implements FailureReason {

protected static final String SECURE_OPTION_VALUE = "****";

protected static final String[] VALID_SALT_API_END_POINT_SCHEMES = { "http", "https" };

protected static final String LOGIN_RESOURCE = "/login";
protected static final String MINION_RESOURCE = "/minions";
protected static final String JOBS_RESOURCE = "/jobs";
Expand Down Expand Up @@ -191,13 +189,21 @@ public enum SaltApiNodeStepFailureReason implements FailureReason {
@Value("${saltApi.http.numRetries}")
protected int numRetries;

// Supported API protocols
protected String[] endPointSchemes;

@Autowired
protected ExponentialBackoffTimer.Factory timerFactory;

public SaltApiNodeStepPlugin() {
new DependencyInjectionUtil().inject(this);
}

@Autowired
public void setEndPointSchemes(@Value("${saltApi.endPointSchemes}") String epSchemes) throws IllegalArgumentException {
endPointSchemes = epSchemes.split(",");
}

@Override
public void executeNodeStep(PluginStepContext context, Map<String, Object> configuration, INodeEntry entry)
throws NodeStepException {
Expand Down Expand Up @@ -353,7 +359,7 @@ protected void validate(String user, String password, INodeEntry entry) throws S
checkNotEmpty(SALT_USER_OPTION_NAME, user, SaltApiNodeStepFailureReason.ARGUMENTS_MISSING, entry);
checkNotEmpty(SALT_PASSWORD_OPTION_NAME, password, SaltApiNodeStepFailureReason.ARGUMENTS_MISSING, entry);

UrlValidator urlValidator = new UrlValidator(VALID_SALT_API_END_POINT_SCHEMES, UrlValidator.ALLOW_LOCAL_URLS);
UrlValidator urlValidator = new UrlValidator(endPointSchemes, UrlValidator.ALLOW_LOCAL_URLS);
if (!urlValidator.isValid(saltEndpoint)) {
throw new SaltStepValidationException(SALT_API_END_POINT_OPTION_NAME, String.format(
"%s is not a valid endpoint.", saltEndpoint), SaltApiNodeStepFailureReason.ARGUMENTS_INVALID,
Expand All @@ -364,12 +370,13 @@ protected void validate(String user, String password, INodeEntry entry) throws S
protected String waitForJidResponse(HttpClient client, String authToken, String jid, String minionId)
throws IOException, InterruptedException, SaltApiException {
ExponentialBackoffTimer timer = timerFactory.newTimer(delayStep, maximumRetryDelay);
String jidResource = String.format("%s%s/%s", saltEndpoint, JOBS_RESOURCE, jid);
logWrapper.info("Polling for job status with salt-api endpoint: [%s]", jidResource);
do {
String response = extractOutputForJid(client, authToken, jid, minionId);
if (response != null) {
return response;
}
logWrapper.debug("No response received, waiting...");
timer.waitForNext();
} while (true);
}
Expand All @@ -390,14 +397,12 @@ protected String extractOutputForJid(HttpClient client, String authToken, String
get.setHeader(SALT_AUTH_TOKEN_HEADER, authToken);
get.setHeader(REQUEST_ACCEPT_HEADER_NAME, JSON_RESPONSE_ACCEPT_TYPE);

logWrapper.info("Polling for job status with salt-api endpoint: [%s]", get.getURI());
HttpResponse response = retryExecutor.execute(logWrapper, client, get, numRetries);

try {
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entity = response.getEntity();
String entityResponse = extractBodyFromEntity(entity);
logWrapper.debug("Received response for jobs/%s = %s", jid, response);
Gson gson = new Gson();
Map<String, List<Map<String, Object>>> result = gson.fromJson(entityResponse, JOB_RESPONSE_TYPE);
List<Map<String, Object>> responses = result.get(SALT_OUTPUT_RETURN_KEY);
Expand All @@ -406,6 +411,7 @@ protected String extractOutputForJid(HttpClient client, String authToken, String
} else if (responses.size() == 1) {
Map<String, Object> minionResponse = responses.get(0);
if (minionResponse.containsKey(minionId)) {
logWrapper.debug("Received response for jobs/%s = %s", jid, response);
Object responseObj = minionResponse.get(minionId);
return gson.toJson(responseObj);
}
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/defaultReturners.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ alwaysSuccessful: &alwaysSuccessful !!org.rundeck.plugin.salt.output.DefaultSalt

handlerMappings:
cmd.run_all: *defaultCommandParser
file.touch: *alwaysSuccessful
file.append: *alwaysSuccessful
file.remove: *alwaysSuccessful
3 changes: 2 additions & 1 deletion src/main/resources/salt-api-plugin.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ retryingHttpClientExecutor.maximumRetryDelay=15000
retryingHttpClientExecutor.delayStep=500
saltJobPolling.maximumRetryDelay=15000
saltJobPolling.delayStep=500
saltApi.http.numRetries=5
saltApi.http.numRetries=5
saltApi.endPointSchemes=https
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@

package org.rundeck.plugin.salt;

import java.net.URI;
import java.net.URLEncoder;
import java.util.Map;

import com.dtolabs.rundeck.core.common.INodeEntry;
import com.dtolabs.rundeck.plugins.PluginLogger;
import com.dtolabs.rundeck.plugins.step.PluginStepContext;
import com.google.common.base.Predicate;
import com.google.common.collect.Maps;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
Expand All @@ -54,15 +55,13 @@
import org.rundeck.plugin.salt.util.RetryingHttpClientExecutor;
import org.rundeck.plugin.salt.version.SaltApiCapability;

import com.dtolabs.rundeck.core.common.INodeEntry;
import com.dtolabs.rundeck.plugins.PluginLogger;
import com.dtolabs.rundeck.plugins.step.PluginStepContext;
import com.google.common.base.Predicate;
import com.google.common.collect.Maps;
import java.net.URI;
import java.net.URLEncoder;
import java.util.Map;

public abstract class AbstractSaltApiNodeStepPluginTest {

protected static final String PARAM_ENDPOINT = "http://localhost";
protected static final String PARAM_ENDPOINT = "https://localhost";
protected static final String PARAM_EAUTH = "pam";
protected static final String PARAM_MINION_NAME = "minion";
protected static final String PARAM_FUNCTION = "some.function";
Expand Down Expand Up @@ -107,6 +106,7 @@ public void setUp() {
plugin.saltEndpoint = PARAM_ENDPOINT;
plugin.eAuth = PARAM_EAUTH;
plugin.function = PARAM_FUNCTION;
plugin.setEndPointSchemes("https");
latestCapability = plugin.capabilityRegistry.getLatest();
client = Mockito.mock(HttpClient.class);
post = Mockito.mock(HttpPost.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@

package org.rundeck.plugin.salt;

import java.util.Set;

import com.dtolabs.rundeck.core.execution.workflow.steps.node.NodeStepException;
import com.google.common.collect.ImmutableSet;
import org.apache.http.HttpException;
import org.apache.http.client.HttpClient;
import org.junit.Assert;
Expand All @@ -39,10 +39,8 @@
import org.rundeck.plugin.salt.output.SaltReturnResponse;
import org.rundeck.plugin.salt.output.SaltReturnResponseParseException;
import org.rundeck.plugin.salt.validation.SaltStepValidationException;
import org.rundeck.plugin.salt.version.SaltApiCapability;

import com.dtolabs.rundeck.core.execution.workflow.steps.node.NodeStepException;
import com.google.common.collect.ImmutableSet;
import java.util.Set;

public class SaltApiNodeStepPlugin_ExecuteTest extends AbstractSaltApiNodeStepPluginTest {

Expand All @@ -54,6 +52,9 @@ public void setup() throws Exception {
@Test
public void testExecuteWithAuthenticationFailure() {
setupAuthenticate(null);
setupDoReturnJidWhenSubmitJob();
setupDoReturnHostResponseWhenWaitForResponse();
setupDoReturnSaltResponseWhenExtractResponse(0, new String[0], new String[0]);

try {
plugin.executeNodeStep(pluginContext, configuration, node);
Expand Down Expand Up @@ -81,6 +82,10 @@ public void testExecuteWithValidationFailure() throws Exception {

@Test
public void testExecuteWithDataContextMissing() {
setupAuthenticate();
setupDoReturnJidWhenSubmitJob();
setupDoReturnHostResponseWhenWaitForResponse();
setupDoReturnSaltResponseWhenExtractResponse(0, new String[0], new String[0]);
dataContext.clear();
try {
plugin.executeNodeStep(pluginContext, configuration, node);
Expand Down Expand Up @@ -273,6 +278,24 @@ public void testExecuteWithHttpException() {
}
}

@Test
public void testExecuteWithUnsupportedEndPointScheme() {
setupAuthenticate();
setupDoReturnJidWhenSubmitJob();
setupDoReturnHostResponseWhenWaitForResponse();
setupDoReturnSaltResponseWhenExtractResponse(0, new String[0], new String[0]);

plugin.setEndPointSchemes("http");

try {
plugin.executeNodeStep(pluginContext, configuration, node);
Assert.fail("Expected node step failure.");
} catch (NodeStepException e) {
Assert.assertEquals("Expected failure reason to be set based on exception type",
SaltApiNodeStepFailureReason.ARGUMENTS_INVALID, e.getFailureReason());
}
}

@Test
public void testExecuteWithInterruptedException() throws Exception {
setupAuthenticate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public void testValidateThrowsIfValidatorThrows() throws SaltStepValidationExcep

@Test
public void testValidateChecksValidEndpointHttpUrl() throws NodeStepException {
plugin.saltEndpoint = "http://some.machine.com";
plugin.saltEndpoint = "https://some.machine.com";
plugin.validate(PARAM_USER, PARAM_PASSWORD, node);
}

Expand Down

0 comments on commit 2958e07

Please sign in to comment.