Skip to content

Commit

Permalink
Add testcontainer integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jonesbusy committed Dec 22, 2023
1 parent ccb73a9 commit 03f2534
Show file tree
Hide file tree
Showing 21 changed files with 228 additions and 338 deletions.
2 changes: 1 addition & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/
buildPlugin(
forkCount: '1C', // run this number of tests in parallel for faster feedback. If the number terminates with a 'C', the value will be multiplied by the number of available CPU cores
useContainerAgent: true, // Set to `false` if you need to use Docker for containerized tests
useContainerAgent: false, // Set to `false` if you need to use Docker for containerized tests
configurations: [
[platform: 'linux', jdk: 21],
[platform: 'windows', jdk: 17],
Expand Down
37 changes: 33 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
<gitHubRepo>jenkinsci/ansible-plugin</gitHubRepo>
<jenkins.version>2.426.2</jenkins.version>
<spotless.check.skip>false</spotless.check.skip>

<!-- Test dependencies version -->
<testcontainer.version>1.19.3</testcontainer.version>

</properties>
<dependencyManagement>
<dependencies>
Expand Down Expand Up @@ -66,12 +70,12 @@
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>ssh-credentials</artifactId>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-step-api</artifactId>
<optional>true</optional>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand All @@ -83,16 +87,15 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-basic-steps</artifactId>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>ssh-slaves</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-cps</artifactId>
<scope>test</scope>
</dependency>
<!-- Test plugins -->
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-job</artifactId>
Expand All @@ -108,6 +111,32 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${testcontainer.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>${testcontainer.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
</exclusion>
<exclusion>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<repositories>
<repository>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,9 @@ public void perform(
? CredentialsProvider.findCredentialById(vaultCredentialsId, StandardCredentials.class, run)
: null);
invocation.setVaultTmpPath(
StringUtils.isNotBlank(vaultTmpPath) ? new FilePath(new File(vaultTmpPath)) : null);
StringUtils.isNotBlank(vaultTmpPath)

Check warning on line 242 in src/main/java/org/jenkinsci/plugins/ansible/AnsibleAdHocCommandBuilder.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 242 is only partially covered, one branch is missing
? new FilePath(computer.getChannel(), new File(vaultTmpPath).getAbsolutePath())

Check warning on line 243 in src/main/java/org/jenkinsci/plugins/ansible/AnsibleAdHocCommandBuilder.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 243 is not covered by tests
: null);
invocation.setExtraVars(extraVars);
invocation.setAdditionalParameters(additionalParameters);
invocation.setDisableHostKeyCheck(disableHostKeyChecking);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ public void perform(
throws InterruptedException, IOException {
try {
CLIRunner runner = new CLIRunner(run, ws, launcher, listener);
Computer computer = node.toComputer();
String exe = AnsibleInstallation.getExecutable(
ansibleName, AnsibleCommand.ANSIBLE_PLAYBOOK, node, listener, envVars);
AnsiblePlaybookInvocation invocation = new AnsiblePlaybookInvocation(exe, run, ws, listener, envVars);
Expand Down Expand Up @@ -295,7 +296,9 @@ public void perform(
run)
: null);
invocation.setVaultTmpPath(
StringUtils.isNotBlank(vaultTmpPath) ? new FilePath(new File(vaultTmpPath)) : null);
StringUtils.isNotBlank(vaultTmpPath)
? new FilePath(computer.getChannel(), new File(vaultTmpPath).getAbsolutePath())
: null);
invocation.setExtraVars(extraVars);
invocation.setAdditionalParameters(additionalParameters);
invocation.setDisableHostKeyCheck(disableHostKeyChecking);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ public void perform(
throws InterruptedException, IOException {
try {
CLIRunner runner = new CLIRunner(run, ws, launcher, listener);
Computer computer = node.toComputer();
String exe = AnsibleInstallation.getExecutable(
ansibleName, AnsibleCommand.ANSIBLE_VAULT, node, listener, envVars);
AnsibleVaultInvocation invocation = new AnsibleVaultInvocation(exe, run, ws, listener, envVars);
Expand All @@ -144,7 +145,9 @@ public void perform(
run)
: null);
invocation.setVaultTmpPath(
StringUtils.isNotBlank(vaultTmpPath) ? new FilePath(new File(vaultTmpPath)) : null);
StringUtils.isNotBlank(vaultTmpPath)
? new FilePath(computer.getChannel(), new File(vaultTmpPath).getAbsolutePath())
: null);

Check warning on line 150 in src/main/java/org/jenkinsci/plugins/ansible/AnsibleVaultBuilder.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 128-150 are not covered by tests
invocation.setContent(content);
invocation.setInput(input);
invocation.setOutput(output);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,12 @@
import static org.hamcrest.Matchers.hasEntry;
import static org.mockito.Mockito.*;

import com.cloudbees.jenkins.plugins.sshcredentials.SSHUserPrivateKey;
import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
import hudson.EnvVars;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.TaskListener;
import hudson.util.ArgumentListBuilder;
import hudson.util.Secret;
import java.util.Map;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.ArgumentCaptor;

Expand Down Expand Up @@ -128,66 +124,6 @@ public void secure_by_default_SEC_630() throws Exception {
assertThat((Map<String, String>) argument.getValue(), hasEntry("ANSIBLE_FORCE_COLOR", "true"));
}

@Test
@Ignore("build.getWorkspace() cannot be mocked")
public void should_handle_private_key_credentials() throws Exception {
// Given
Inventory inventory = new InventoryPath("/tmp/hosts");
SSHUserPrivateKey pkey = mock(SSHUserPrivateKey.class);
when(pkey.getUsername()).thenReturn("mylogin");
BuildListener listener = mock(BuildListener.class);
CLIRunner runner = mock(CLIRunner.class);
AbstractBuild<?, ?> build = mock(AbstractBuild.class);
when(build.getEnvironment(any(TaskListener.class))).thenReturn(new EnvVars());
AnsibleAdHocCommandInvocation invocation =
new AnsibleAdHocCommandInvocation("/usr/local/bin/ansible", build, listener);
invocation.setHostPattern("localhost");
invocation.setInventory(inventory);
invocation.setModule("ping");
invocation.setCredentials(pkey);
invocation.setForks(5);
// When
invocation.execute(runner);
// Then
ArgumentCaptor<ArgumentListBuilder> argument = ArgumentCaptor.forClass(ArgumentListBuilder.class);
verify(runner).execute(argument.capture(), anyMap());

assertThat(
argument.getValue().toString(),
is("/usr/local/bin/ansible localhost -i /tmp/hosts -m ping -f 5 --private-key .+ -u mylogin"));
}

@Test
@Ignore("Secret can neither be instanced nor mocked")
public void should_handle_password_credentials() throws Exception {
// Given
Inventory inventory = new InventoryPath("/tmp/hosts");
StandardUsernamePasswordCredentials password = mock(StandardUsernamePasswordCredentials.class);
when(password.getUsername()).thenReturn("mylogin");
when(password.getPassword()).thenReturn(Secret.fromString("aStrongSecretPassword"));
BuildListener listener = mock(BuildListener.class);
CLIRunner runner = mock(CLIRunner.class);
AbstractBuild<?, ?> build = mock(AbstractBuild.class);
when(build.getEnvironment(any(TaskListener.class))).thenReturn(new EnvVars());
AnsibleAdHocCommandInvocation invocation =
new AnsibleAdHocCommandInvocation("/usr/local/bin/ansible", build, listener);
invocation.setHostPattern("localhost");
invocation.setInventory(inventory);
invocation.setModule("ping");
invocation.setCredentials(password);
invocation.setForks(5);
// When
invocation.execute(runner);
// Then
ArgumentCaptor<ArgumentListBuilder> argument = ArgumentCaptor.forClass(ArgumentListBuilder.class);
verify(runner).execute(argument.capture(), anyMap());

assertThat(
argument.getValue().toString(),
is("sshpass ****** /usr/local/bin/ansible localhost -i /tmp/hosts -m ping -f 5 " + "-u"
+ " mylogin -k"));
}

@Test
public void should_handle_variables() throws Exception {
// Given
Expand Down
Loading

0 comments on commit 03f2534

Please sign in to comment.