Skip to content

Commit

Permalink
Add option to remove secrets (#63)
Browse files Browse the repository at this point in the history
* Add option to remove secrets
  • Loading branch information
kdebisschop authored Nov 22, 2022
1 parent ae3664b commit 8f6622d
Show file tree
Hide file tree
Showing 14 changed files with 150 additions and 156 deletions.
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Configuration:

Note:

Note that Rancher uses container ID to to construct the URL used to make API requests.
Note that Rancher uses container ID to construct the URL used to make API requests.
When services are upgraded, new containers are created so the API urls used in the
node operations cannot work anymore. The container does not exist, so the URL will
fail. As long nodes are defined by containers, there is probably no way to avoid this.
Expand All @@ -54,7 +54,7 @@ in the same job context.

### Rancher Node Executor

Executes jobs on remote Docker containers managed by the Rancher host.
Execute jobs on remote Docker containers managed by the Rancher host.

Features:

Expand All @@ -63,7 +63,7 @@ Features:

### Rancher File Copier

Copies files to a node. Can be configured to use Rancher CLI if it is installed and
Copy files to a node. Can be configured to use Rancher CLI if it is installed and
available. Otherwise, assembles files from Base64-encoded parts transmitted via Rancher
API.

Expand Down Expand Up @@ -103,9 +103,12 @@ Adds a service to an existing stack. Required inputs:
Optional inputs:

- Data volumes
- OS environment
- OS environment variables
- Service labels
- Secrets
- OS environment variables to remove
- Service labels to remove
- Secrets to remove

### Manage Service

Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ apply plugin: 'eclipse'
apply plugin: 'idea'

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}

compileJava {
Expand Down Expand Up @@ -100,7 +100,7 @@ dependencies {
testImplementation (
'com.squareup.okhttp3:mockwebserver:3.11.0',
'junit:junit:4.12',
'org.mockito:mockito-core:3.6+',
'org.mockito:mockito-core:3.7+',
'org.slf4j:slf4j-simple:1.7.30+',
)
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/bioraft/rundeck/rancher/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ private Constants() {
public static final String NODE_ATT_ACTIONS = "actions";
public static final String NODE_ATT_SELF = "self";

// Splits services by whitespace, comma, or semicolon.
public static final String PERMISSIVE_WHITESPACE_REGEX = "[,; ]+";

public static final String NODE_LINK_SERVICES = "services";

public static final String STATE_ACTIVE = "active";
Expand Down Expand Up @@ -87,6 +90,7 @@ private Constants() {
public static final String OPT_IMAGE_UUID = "imageUuid";
public static final String OPT_LABELS = "labels";
public static final String OPT_SECRETS = "secrets";
public static final String OPT_REMOVE_SECRETS = "removeSecrets";
public static final String OPT_SERVICE_NAME = "serviceName";
public static final String OPT_STACK_NAME = "stackName";

Expand Down
5 changes: 2 additions & 3 deletions src/main/java/com/bioraft/rundeck/rancher/MessageReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
/**
* Reads a message from Rancher transmitting a portion of a Docker multiplexed
* stream.
*
* To use this class, instantiate with an InputStream, read nextMessage() until
* the stream is exhausted, then prepend nextHeader to the next message from
* Rancher.
Expand Down Expand Up @@ -94,7 +93,7 @@ public LogMessage nextMessage() throws IOException {
final int frameSize = header.getInt(FRAME_SIZE_OFFSET);

// If the Docker frame extends into the next Rancher message, the log
// message will consist of the rest of the buffer and we need to
// message will consist of the rest of the buffer, and we need to
// calculate how much of the Docker frame is in the next Rancher
// message. Otherwise, just send the frame (which moves the buffer
// pointer forward to prepare for the next call of nextMessage()).
Expand Down Expand Up @@ -144,7 +143,7 @@ public byte[] nextHeader() {
public void close() throws IOException {
// RancherWebSocketListener will close the stream and release the connection
// after we read all the data.
// We cannot call the stream's close method because it an instance of
// We cannot call the stream's close method because it is an instance of
// UncloseableInputStream, where close is a no-op.
copy(stream, nullOutputStream());
}
Expand Down
31 changes: 21 additions & 10 deletions src/main/java/com/bioraft/rundeck/rancher/RancherLaunchConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@
import java.util.Iterator;
import java.util.Map;

import static com.bioraft.rundeck.rancher.Constants.OPT_DATA_VOLUMES;
import static com.bioraft.rundeck.rancher.Constants.OPT_SECRETS;
import static com.bioraft.rundeck.rancher.Constants.*;
import static com.bioraft.rundeck.rancher.Errors.ErrorCause.*;

/**
Expand All @@ -54,6 +53,8 @@ public class RancherLaunchConfig {

private Map<String, String> secretMap;

private Map<String, String> removeSecretMap;

private final String nodeName;

private final PluginLogger logger;
Expand Down Expand Up @@ -107,15 +108,22 @@ public void removeLabels(String removeLabels) {
this.removeLabels = removeLabels;
}

public void setSecrets(String secrets) {
public void setSecrets(String secrets, String remove) {
this.secrets = secrets;
secretMap = new HashMap<>();
removeSecretMap = new HashMap<>();
if (secrets != null && secrets.trim().length() > 0) {
// Add in the new or replacement secrets specified in the step.
secretMap = new HashMap<>();
for (String secretId : secrets.split("[,; ]+")) {
for (String secretId : secrets.split(PERMISSIVE_WHITESPACE_REGEX)) {
secretMap.put(secretId, secretId);
}
}
if (remove != null && remove.trim().length() > 0) {
// Add in the new or replacement secrets specified in the step.
for (String secretId : remove.split(PERMISSIVE_WHITESPACE_REGEX)) {
removeSecretMap.put(secretId, secretId);
}
}
}

/**
Expand Down Expand Up @@ -207,17 +215,20 @@ private void addSecrets(ObjectNode launchConfig) {
}

// Add in the new or replacement secrets specified in the step.
for (String secretId : secrets.split("[,; ]+")) {
secretsArray.add((new Strings()).buildSecret(secretId));
logger.log(Constants.INFO_LEVEL, "Adding secret map to " + secretId);
for (String secretId : secrets.split(PERMISSIVE_WHITESPACE_REGEX)) {
if (!removeSecretMap.containsKey(secretId)) {
secretsArray.add((new Strings()).buildSecret(secretId));
logger.log(Constants.INFO_LEVEL, "Adding secret map to " + secretId);
}
}
}
}

private void copyOldSecrets(Iterator<JsonNode> elements, ArrayNode secretsArray) {
while (elements.hasNext()) {
JsonNode secretObject = elements.next();
if (!secretMap.containsKey(secretObject.path("secretId").asText())) {
String key = secretObject.path("secretId").asText();
if (!secretMap.containsKey(key) && !removeSecretMap.containsKey(key)) {
secretsArray.add(secretObject);
}
}
Expand All @@ -226,7 +237,7 @@ private void copyOldSecrets(Iterator<JsonNode> elements, ArrayNode secretsArray)
/**
* Add or replace secrets.
*
* @throws NodeStepException when secret JSON is malformed (passed up from {@see this.buildSecret()}.
* @throws NodeStepException when secret JSON is malformed (passed up from {@see this.buildSecret()}).
*/
private void setMountArray(String newData) throws NodeStepException {
if (newData != null && newData.length() > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public class RancherResourceModelSource implements ResourceModelSource {
// Track how many times each stack_service has been seen.
Map<String, Integer> seen;

// Map stack IDs to names once to reduce API calls.
// Map stack IDs to stack names once to reduce API calls.
HashMap<String, String> stackNames = new HashMap<>();

/**
Expand Down Expand Up @@ -426,7 +426,6 @@ private boolean isExclude(String property) {

/**
* Count the number of containers are in each service for each stack.
*
* By constructing a node filter of "seen:1" we can run on only one container in
* a service even when we are not limiting the project node set to the one
* container per service.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ public class RancherUpgradeService implements NodeStepPlugin {
@PluginProperty(title = "Secrets", description = "Keys for secrets separated by commas or spaces")
private String secrets;

@PluginProperty(title = "Secrets to Remove", description = "Keys for secrets separated by commas or spaces")
private String removeSecrets;

@PluginProperty(title = "Start before stopping", description = "Start new container(s) before stopping old", required = true, defaultValue = "true")
private Boolean startFirst;

Expand Down Expand Up @@ -162,14 +165,15 @@ public void executeNodeStep(PluginStepContext ctx, Map<String, Object> cfg, INod
dataVolumes = (String) cfg.getOrDefault("dataVolumes", defaultString(dataVolumes));
labels = (String) cfg.getOrDefault("labels", defaultString(labels));
secrets = (String) cfg.getOrDefault("secrets", defaultString(secrets));
removeSecrets = (String) cfg.getOrDefault("removeSecrets", defaultString(removeSecrets));
removeEnvironment = (String) cfg.getOrDefault("removeEnvironment", defaultString(removeEnvironment));
removeLabels = (String) cfg.getOrDefault("removeLabels", defaultString(removeLabels));

rancherLaunchConfig.setDockerImage(dockerImage);
rancherLaunchConfig.setEnvironment(environment);
rancherLaunchConfig.setDataVolumes(dataVolumes);
rancherLaunchConfig.setLabels(labels);
rancherLaunchConfig.setSecrets(secrets);
rancherLaunchConfig.setSecrets(secrets, removeSecrets);
rancherLaunchConfig.removeEnvironment(removeEnvironment);
rancherLaunchConfig.removeLabels(removeLabels);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ public void putFile(String url, String accessKey, String secretKey, File file, S

/**
* Runs a command and passes output back to an external listener.
*
* Exit status is read after completion from the job's PID file in /tmp.
*
* @param url The URL the listener should use to launch the job.
Expand All @@ -219,9 +218,9 @@ private void runJob(String url, String accessKey, String secretKey, ExecutionLis
this.listener = listener;
this.nextHeader = new byte[0];

// Even though we are passing data back to an external listener, we need to
// buffer
// the message stream so we can pick out lines that are part of STDERR.
// Even though we are passing data back to an external listener, we
// need to buffer the message stream so we can pick out lines that
// are part of STDERR.
output = new StringBuilder();

client.newWebSocket(this.buildRequest(true), this);
Expand All @@ -234,7 +233,6 @@ private void runJob(String url, String accessKey, String secretKey, ExecutionLis

/**
* Runs a command, capturing output in a StringBuffer injected on invocation.
*
* This is used to get the contents of the PID file when the job ends and
* determine the exit status.
*
Expand Down Expand Up @@ -266,8 +264,7 @@ private void run(String url, String accessKey, String secretKey, StringBuilder o

/**
* Put a file onto the server.
*
* Neither STDIN or STDOUT are attached. The file is sent as a payload with the
* Neither STDIN nor STDOUT are attached. The file is sent as a payload with the
* post command.
*
* @param url The URL the listener should use to launch the job.
Expand Down
Loading

0 comments on commit 8f6622d

Please sign in to comment.