diff --git a/Jenkinsfile b/Jenkinsfile index 09032da..29481c7 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -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], diff --git a/README.md b/README.md index fe2947a..306b779 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ Jenkins jobs. 3. Repeat for any additional desired installations +There is no automatic ansible installation possible using Global Tools. + ### OS User PATH Ansible can also be added to the PATH user used by the Jenkins executor @@ -40,6 +42,18 @@ guide. ------------------------------------------------------------------------ +## Supported versions + +The plugin is tested against supported ansible-core versions (https://endoflife.date/ansible-core). It might work with older versions, but this is not guaranteed. + +See `PipelineTest.java` + +```java +private static Stream ansibleVersions() { + return Stream.of("2.14.13", "2.15.8", "2.16.2"); +} +``` + ## Adhoc [Adhoc commands](http://docs.ansible.com/ansible/latest/intro_adhoc.html) allow @@ -289,122 +303,9 @@ a "Secret text" or a "Secret file". ------------------------------------------------------------------------ -## Open Issues - -[View issues in Jira](https://issues.jenkins.io/secure/IssueNavigator.jspa?reset=true&jqlQuery=component%20=%20ansible-plugin%20AND%20status%20in%20%28Open,%20%22In%20Progress%22,%20Reopened%29&tempMax=1000&src=confmacro) - ------------------------------------------------------------------------- - ## Changelog -#### Version 1.0 (26 March 2018) - -* [Fix security issue](https://jenkins.io/security/advisory/2018-03-26/#SECURITY-630): - Do not disable host key verification by default. **This may - break existing configurations as host key verification will - be enabled everywhere by default.** - -#### Version 0.8.0 (16 Jan 2018) - -* Add support for Ansible Vault - [JENKINS-48499](https://issues.jenkins.io/browse/JENKINS-48499) -* Add hostKeyChecking option to pipeline [JENKINS-42445](https://issues.jenkins.io/browse/JENKINS-42445) - -#### Version 0.6.2 (3 Jan 2017) - -* Fix blocker bug when launched from a pipeline - [JENKINS-40780](https://issues.jenkins.io/browse/JENKINS-40780) - -#### Version 0.6.1 (1 Jan 2017) - -* Use latest parent project definition in order to deploy - plugin (thanks - to [alecharp](https://github.com/alecharp) for the help and - the PR) - -#### Version 0.6 (31 Dec 2016) - -**WARN: 0.6.x version will be the last one to support Jenkins 1.xxx and -Ansible 1.x - The 0.7.x and next releases will require Jenkins 2.32.1 -(or higher) and Ansible 2.2 (or higher)** - -* Add a "do not specify" option for - inventory [JENKINS-34627](https://issues.jenkins.io/browse/JENKINS-34627) -* Support inventoryContent in pipeline (thanks - to [leewin12](https://github.com/leewin12) for the PR) -* Add support of extra variables in jobdsl (thanks - to [pawbur](https://github.com/pawbur) for the PR) -* Support empty forks (number of parallel processes) - parameter [JENKINS-39438](https://issues.jenkins.io/browse/JENKINS-39438) -* Escape '%' character in private key path (thanks - to [ewollesen](https://github.com/ewollesen) for the PR) -* Omit ansible option when expanded environment variable is - empty (thanks to [vjestin](https://github.com/vjestin) for - the PR) -* Add the --forks parameter configurable in pipeline step - (thanks to - [anguswilliams](https://github.com/anguswilliams) for the - PR) -* Fix usage of environment variable in ansiblePlaybook - pipeline step (thanks to - [thomasKalmar](https://github.com/thomasKalmar) - and [barthorre](https://github.com/barthorre) for the - PR) [JENKINS-38289](https://issues.jenkins.io/browse/JENKINS-38289) - -#### Version 0.5 (5 May 2016) - -* Add support for ansible extra variables - [JENKINS-29863](https://issues.jenkins.io/browse/JENKINS-29863) -* Improve Pipeline plugin - integration [JENKINS-32911](https://issues.jenkins.io/browse/JENKINS-32911) -* Add the possibility to use the default inventory file - (thanks to Johann Schmitz for the PR) -* Add colorized output in pipeline jobs (thanks to - Kirill Merkushev for the PR) -* Make Jenkins build variables available as environment - variables for ansible (thanks to Kevin Mooney for the - PR) [JENKINS-29284](https://issues.jenkins.io/browse/JENKINS-29284) - -#### Version 0.4 (25 December 2015) - -* Support for password protected SSH - keys [JENKINS-30656](https://issues.jenkins.io/browse/JENKINS-30656) -* Initial support for the workflow - plugin [JENKINS-30398](https://issues.jenkins.io/browse/JENKINS-30398) -* Add support for Job DSL plugin (thanks to Kirill Merkushev - for the - PR) [JENKINS-31790](https://issues.jenkins.io/browse/JENKINS-31790) - -#### Version 0.3.1 (15 July 2015) - -* Fix execution on slave - nodes [JENKINS-29294](https://issues.jenkins.io/browse/JENKINS-29294) - -#### Version 0.3 (20 June 2015) - -* Add support for password based SSH authentication (with - sshpass) -* Environment variables can be used in Module and Module - arguments text field in Ad-hoc command builder -* Environment variables can be used in inline inventory text - box - [JENKINS-28547](https://issues.jenkins.io/browse/JENKINS-28547) - -#### Version 0.2 (11 May 2015) - -* Fix NullPointerException when no credentials are selected -* Fix --skippedTags parameter configuration which was ignored -* Fix NullPointerException and print an error message in the - build console when the inventory is not set in the job - configuration - -#### Version 0.1 (01 May 2015) - -* Initial version - -This plugin gives the possibility to run [Ansible](http://www.ansible.com/) ad-hoc command or playbooks as a build step. - -[![Build Status](https://ci.jenkins.io/buildStatus/icon?job=Plugins/ansible-plugin/master)](https://ci.jenkins.io/job/Plugins/job/ansible-plugin/job/master/) +Changelog is now published on GitHub release. ## Using Jenkins Build and Environment Variables diff --git a/pom.xml b/pom.xml index e81a7f6..1ec7812 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,10 @@ jenkinsci/ansible-plugin 2.426.2 false + + + 1.19.3 + @@ -66,12 +70,12 @@ org.jenkins-ci.plugins ssh-credentials + org.jenkins-ci.plugins.workflow workflow-step-api true - junit junit @@ -83,8 +87,8 @@ test - org.jenkins-ci.plugins.workflow - workflow-basic-steps + org.jenkins-ci.plugins + ssh-slaves test @@ -92,7 +96,6 @@ workflow-cps test - org.jenkins-ci.plugins.workflow workflow-job @@ -108,6 +111,32 @@ mockito-core test + + org.testcontainers + junit-jupiter + ${testcontainer.version} + test + + + org.testcontainers + testcontainers + ${testcontainer.version} + test + + + org.apache.commons + commons-compress + + + org.jetbrains + annotations + + + org.slf4j + slf4j-api + + + diff --git a/src/main/java/org/jenkinsci/plugins/ansible/AnsibleAdHocCommandBuilder.java b/src/main/java/org/jenkinsci/plugins/ansible/AnsibleAdHocCommandBuilder.java index 630b2ee..46dfba8 100644 --- a/src/main/java/org/jenkinsci/plugins/ansible/AnsibleAdHocCommandBuilder.java +++ b/src/main/java/org/jenkinsci/plugins/ansible/AnsibleAdHocCommandBuilder.java @@ -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) + ? new FilePath(computer.getChannel(), new File(vaultTmpPath).getAbsolutePath()) + : null); invocation.setExtraVars(extraVars); invocation.setAdditionalParameters(additionalParameters); invocation.setDisableHostKeyCheck(disableHostKeyChecking); diff --git a/src/main/java/org/jenkinsci/plugins/ansible/AnsiblePlaybookBuilder.java b/src/main/java/org/jenkinsci/plugins/ansible/AnsiblePlaybookBuilder.java index 915f83f..595345d 100644 --- a/src/main/java/org/jenkinsci/plugins/ansible/AnsiblePlaybookBuilder.java +++ b/src/main/java/org/jenkinsci/plugins/ansible/AnsiblePlaybookBuilder.java @@ -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); @@ -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); diff --git a/src/main/java/org/jenkinsci/plugins/ansible/AnsibleVaultBuilder.java b/src/main/java/org/jenkinsci/plugins/ansible/AnsibleVaultBuilder.java index 3c7c2c4..35626fd 100644 --- a/src/main/java/org/jenkinsci/plugins/ansible/AnsibleVaultBuilder.java +++ b/src/main/java/org/jenkinsci/plugins/ansible/AnsibleVaultBuilder.java @@ -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); @@ -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); invocation.setContent(content); invocation.setInput(input); invocation.setOutput(output); diff --git a/src/main/java/org/jenkinsci/plugins/ansible/Utils.java b/src/main/java/org/jenkinsci/plugins/ansible/Utils.java index a82a305..d0bdef2 100644 --- a/src/main/java/org/jenkinsci/plugins/ansible/Utils.java +++ b/src/main/java/org/jenkinsci/plugins/ansible/Utils.java @@ -50,6 +50,7 @@ static FilePath createSshKeyFile(FilePath key, FilePath tmpPath, SSHUserPrivateK static FilePath createSshAskPassFile( FilePath script, FilePath tmpPath, SSHUserPrivateKey credentials, boolean inThisDir) throws IOException, InterruptedException { + tmpPath.mkdirs(); StringBuilder sb = new StringBuilder(); sb.append("#! /bin/sh\n").append("/bin/echo \"" + Secret.toString(credentials.getPassphrase()) + "\""); script = tmpPath.createTextTempFile("ssh", ".sh", sb.toString(), inThisDir); @@ -69,6 +70,7 @@ static FilePath createSshAskPassFile( static FilePath createVaultPasswordFile(FilePath key, FilePath tmpPath, FileCredentials credentials) throws IOException, InterruptedException { try (InputStream content = credentials.getContent()) { + tmpPath.mkdirs(); key = tmpPath.createTempFile("vault", ".password"); key.copyFrom(content); key.chmod(0400); @@ -87,6 +89,7 @@ static FilePath createVaultPasswordFile(FilePath key, FilePath tmpPath, FileCred */ static FilePath createVaultPasswordFile(FilePath key, FilePath tmpPath, StringCredentials credentials) throws IOException, InterruptedException { + tmpPath.mkdirs(); key = tmpPath.createTextTempFile( "vault", ".password", credentials.getSecret().getPlainText(), true); key.chmod(0400); diff --git a/src/test/java/org/jenkinsci/plugins/ansible/AnsibleAdHocCommandInvocationTest.java b/src/test/java/org/jenkinsci/plugins/ansible/AnsibleAdHocCommandInvocationTest.java index 5ed44e1..d1793a3 100644 --- a/src/test/java/org/jenkinsci/plugins/ansible/AnsibleAdHocCommandInvocationTest.java +++ b/src/test/java/org/jenkinsci/plugins/ansible/AnsibleAdHocCommandInvocationTest.java @@ -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; @@ -128,66 +124,6 @@ public void secure_by_default_SEC_630() throws Exception { assertThat((Map) 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 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 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 diff --git a/src/test/java/org/jenkinsci/plugins/ansible/PipelineTest.java b/src/test/java/org/jenkinsci/plugins/ansible/PipelineTest.java index b10e5c3..daf32fd 100644 --- a/src/test/java/org/jenkinsci/plugins/ansible/PipelineTest.java +++ b/src/test/java/org/jenkinsci/plugins/ansible/PipelineTest.java @@ -3,16 +3,20 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; -import com.cloudbees.plugins.credentials.CredentialsProvider; import com.cloudbees.plugins.credentials.CredentialsScope; -import com.cloudbees.plugins.credentials.CredentialsStore; import com.cloudbees.plugins.credentials.SecretBytes; +import com.cloudbees.plugins.credentials.SystemCredentialsProvider; +import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials; import com.cloudbees.plugins.credentials.domains.Domain; import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl; -import hudson.model.Label; +import hudson.plugins.sshslaves.SSHLauncher; +import hudson.plugins.sshslaves.verifiers.NonVerifyingKeyVerificationStrategy; import hudson.slaves.DumbSlave; import hudson.util.Secret; +import java.io.Closeable; import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.stream.Stream; import org.apache.commons.io.IOUtils; import org.jenkinsci.plugins.plaincredentials.FileCredentials; import org.jenkinsci.plugins.plaincredentials.StringCredentials; @@ -21,230 +25,335 @@ import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.job.WorkflowRun; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.images.builder.ImageFromDockerfile; +import org.testcontainers.junit.jupiter.Testcontainers; +@WithJenkins +@Testcontainers(disabledWithoutDocker = true) public class PipelineTest { - @ClassRule - public static JenkinsRule jenkins = new JenkinsRule(); - - private static DumbSlave agent; + // Test and support only supported ansible version (https://endoflife.date/ansible-core) + private static Stream ansibleVersions() { + return Stream.of("2.14.13", "2.15.8", "2.16.2"); + } - @BeforeClass - public static void startAgent() throws Exception { - agent = jenkins.createSlave(Label.get("test-agent")); + @ParameterizedTest + @MethodSource("ansibleVersions") + public void testMinimalPipeline(String ansibleVersion, JenkinsRule jenkins) throws Exception { + try (AnsibleAgent agent = setupAnsibleAgent(ansibleVersion, jenkins)) { + String pipeline = IOUtils.toString( + PipelineTest.class.getResourceAsStream("/pipelines/minimal.groovy"), StandardCharsets.UTF_8); + WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); + workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); + WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); + jenkins.waitForCompletion(run1); + assertThat(run1.getResult(), equalTo(hudson.model.Result.SUCCESS)); + assertThat(run1.getLog(), allOf(containsString("ansible-playbook /ansible/playbook.yml"))); + } } - private String getTmpPath() { - // In Windows the last slash is instead a backslash - if (System.getProperty("os.name").startsWith("Windows")) { - return System.getProperty("java.io.tmpdir").replace('/', '\\'); + @ParameterizedTest + @MethodSource("ansibleVersions") + public void testMinimalCheckModePipeline(String ansibleVersion, JenkinsRule jenkins) throws Exception { + try (AnsibleAgent agent = setupAnsibleAgent(ansibleVersion, jenkins)) { + String pipeline = IOUtils.toString( + PipelineTest.class.getResourceAsStream("/pipelines/minimalCheckMode.groovy"), + StandardCharsets.UTF_8); + WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); + workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); + WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); + jenkins.waitForCompletion(run1); + assertThat(run1.getResult(), equalTo(hudson.model.Result.SUCCESS)); + assertThat(run1.getLog(), allOf(containsString("ansible-playbook /ansible/playbook.yml --check"))); } - return System.getProperty("java.io.tmpdir"); } - @Test - public void testMinimalPipeline() throws Exception { - String pipeline = IOUtils.toString( - PipelineTest.class.getResourceAsStream("/pipelines/minimal.groovy"), StandardCharsets.UTF_8); - WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); - workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); - WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); - jenkins.waitForCompletion(run1); - assertThat(run1.getLog(), allOf(containsString("ansible-playbook playbook.yml"))); + @ParameterizedTest + @MethodSource("ansibleVersions") + public void testExtraVarsHiddenString(String ansibleVersion, JenkinsRule jenkins) throws Exception { + try (AnsibleAgent agent = setupAnsibleAgent(ansibleVersion, jenkins)) { + String pipeline = IOUtils.toString( + PipelineTest.class.getResourceAsStream("/pipelines/extraVarsHiddenString.groovy"), + StandardCharsets.UTF_8); + WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); + workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); + WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); + jenkins.waitForCompletion(run1); + assertThat(run1.getResult(), equalTo(hudson.model.Result.SUCCESS)); + assertThat(run1.getLog(), allOf(containsString("ansible-playbook /ansible/playbook.yml -e ********"))); + } } - @Test - public void testMinimalCheckModePipeline() throws Exception { - String pipeline = IOUtils.toString( - PipelineTest.class.getResourceAsStream("/pipelines/minimalCheckMode.groovy"), StandardCharsets.UTF_8); - WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); - workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); - WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); - jenkins.waitForCompletion(run1); - assertThat(run1.getLog(), allOf(containsString("ansible-playbook playbook.yml --check"))); + @ParameterizedTest + @MethodSource("ansibleVersions") + public void testExtraVarsMap(String ansibleVersion, JenkinsRule jenkins) throws Exception { + try (AnsibleAgent agent = setupAnsibleAgent(ansibleVersion, jenkins)) { + String pipeline = IOUtils.toString( + PipelineTest.class.getResourceAsStream("/pipelines/extraVarsMap.groovy"), StandardCharsets.UTF_8); + WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); + workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); + WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); + jenkins.waitForCompletion(run1); + assertThat(run1.getResult(), equalTo(hudson.model.Result.SUCCESS)); + assertThat( + run1.getLog(), + allOf( + containsString("ansible-playbook /ansible/playbook.yml -e foo1=bar1"), + containsString("ansible-playbook /ansible/playbook.yml -e ********"))); + } } - @Test - public void testExtraVarsHiddenString() throws Exception { - String pipeline = IOUtils.toString( - PipelineTest.class.getResourceAsStream("/pipelines/extraVarsHiddenString.groovy"), - StandardCharsets.UTF_8); - WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); - workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); - WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); - jenkins.waitForCompletion(run1); - assertThat(run1.getLog(), allOf(containsString("ansible-playbook playbook.yml -e ********"))); + @ParameterizedTest + @MethodSource("ansibleVersions") + public void testExtraVarsBoolean(String ansibleVersion, JenkinsRule jenkins) throws Exception { + try (AnsibleAgent agent = setupAnsibleAgent(ansibleVersion, jenkins)) { + String pipeline = IOUtils.toString( + PipelineTest.class.getResourceAsStream("/pipelines/extraVarsBoolean.groovy"), + StandardCharsets.UTF_8); + WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); + workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); + WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); + jenkins.waitForCompletion(run1); + assertThat(run1.getResult(), equalTo(hudson.model.Result.SUCCESS)); + assertThat( + run1.getLog(), + allOf(containsString("ansible-playbook /ansible/playbook.yml -e ******** -e ********"))); + } } - @Test - public void testExtraVarsMap() throws Exception { - String pipeline = IOUtils.toString( - PipelineTest.class.getResourceAsStream("/pipelines/extraVarsMap.groovy"), StandardCharsets.UTF_8); - WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); - workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); - WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); - jenkins.waitForCompletion(run1); - assertThat( - run1.getLog(), - allOf( - containsString("ansible-playbook playbook.yml -e foo1=bar1"), - containsString("ansible-playbook playbook.yml -e ********"))); + @ParameterizedTest + @MethodSource("ansibleVersions") + public void testExtraVarsNumeric(String ansibleVersion, JenkinsRule jenkins) throws Exception { + try (AnsibleAgent agent = setupAnsibleAgent(ansibleVersion, jenkins)) { + String pipeline = IOUtils.toString( + PipelineTest.class.getResourceAsStream("/pipelines/extraVarsNumeric.groovy"), + StandardCharsets.UTF_8); + WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); + workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); + WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); + jenkins.waitForCompletion(run1); + assertThat(run1.getResult(), equalTo(hudson.model.Result.SUCCESS)); + assertThat(run1.getLog(), allOf(containsString("ansible-playbook /ansible/playbook.yml -e ********"))); + } } - @Test - public void testExtraVarsBoolean() throws Exception { - String pipeline = IOUtils.toString( - PipelineTest.class.getResourceAsStream("/pipelines/extraVarsBoolean.groovy"), StandardCharsets.UTF_8); - WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); - workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); - WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); - jenkins.waitForCompletion(run1); - assertThat(run1.getLog(), allOf(containsString("ansible-playbook playbook.yml -e ******** -e ********"))); + @ParameterizedTest + @MethodSource("ansibleVersions") + public void testAnsiblePlaybookSshPass(String ansibleVersion, JenkinsRule jenkins) throws Exception { + try (AnsibleAgent agent = setupAnsibleAgent(ansibleVersion, jenkins)) { + UsernamePasswordCredentialsImpl usernamePassword = new UsernamePasswordCredentialsImpl( + CredentialsScope.GLOBAL, + "usernamePasswordCredentialsId", + "test username password", + "username", + "password"); + SystemCredentialsProvider.getInstance() + .getDomainCredentialsMap() + .put(Domain.global(), Collections.singletonList(usernamePassword)); + + String pipeline = IOUtils.toString( + PipelineTest.class.getResourceAsStream("/pipelines/ansiblePlaybookSshPass.groovy"), + StandardCharsets.UTF_8); + WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); + workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); + WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); + jenkins.waitForCompletion(run1); + assertThat(run1.getResult(), equalTo(hudson.model.Result.SUCCESS)); + assertThat( + run1.getLog(), + allOf(containsString("sshpass ******** ansible-playbook /ansible/playbook.yml -u username -k"))); + } } - @Test - public void testExtraVarsNumeric() throws Exception { - String pipeline = IOUtils.toString( - PipelineTest.class.getResourceAsStream("/pipelines/extraVarsNumeric.groovy"), StandardCharsets.UTF_8); - WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); - workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); - WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); - jenkins.waitForCompletion(run1); - assertThat(run1.getLog(), allOf(containsString("ansible-playbook playbook.yml -e ********"))); + @ParameterizedTest + @MethodSource("ansibleVersions") + public void testVaultCredentialsFile(String ansibleVersion, JenkinsRule jenkins) throws Exception { + try (AnsibleAgent agent = setupAnsibleAgent(ansibleVersion, jenkins)) { + FileCredentials vaultCredentials = new FileCredentialsImpl( + CredentialsScope.GLOBAL, + "vaultCredentialsFile", + "test username password", + "vault-pass.txt", + SecretBytes.fromString("text-secret")); + SystemCredentialsProvider.getInstance() + .getDomainCredentialsMap() + .put(Domain.global(), Collections.singletonList(vaultCredentials)); + + String pipeline = IOUtils.toString( + PipelineTest.class.getResourceAsStream("/pipelines/vaultCredentialsFile.groovy"), + StandardCharsets.UTF_8); + WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); + workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); + WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); + jenkins.waitForCompletion(run1); + // assertThat(run1.getResult(), equalTo(hudson.model.Result.SUCCESS)); + assertThat( + run1.getLog(), + allOf(containsString("ansible-playbook /ansible/playbook.yml --vault-password-file "))); + } } - @Test - public void testAnsiblePlaybookSshPass() throws Exception { - - UsernamePasswordCredentialsImpl usernamePassword = new UsernamePasswordCredentialsImpl( - CredentialsScope.GLOBAL, - "usernamePasswordCredentialsId", - "test username password", - "username", - "password"); - CredentialsStore store = - CredentialsProvider.lookupStores(jenkins.jenkins).iterator().next(); - store.addCredentials(Domain.global(), usernamePassword); - - String pipeline = IOUtils.toString( - PipelineTest.class.getResourceAsStream("/pipelines/ansiblePlaybookSshPass.groovy"), - StandardCharsets.UTF_8); - WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); - workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); - WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); - jenkins.waitForCompletion(run1); - assertThat( - run1.getLog(), allOf(containsString("sshpass ******** ansible-playbook playbook.yml -u username -k"))); + @ParameterizedTest + @MethodSource("ansibleVersions") + public void testVaultCredentialsString(String ansibleVersion, JenkinsRule jenkins) throws Exception { + try (AnsibleAgent agent = setupAnsibleAgent(ansibleVersion, jenkins)) { + StringCredentials vaultCredentials = new StringCredentialsImpl( + CredentialsScope.GLOBAL, + "vaultCredentialsString", + "test username password", + Secret.fromString("test-secret")); + SystemCredentialsProvider.getInstance() + .getDomainCredentialsMap() + .put(Domain.global(), Collections.singletonList(vaultCredentials)); + + String pipeline = IOUtils.toString( + PipelineTest.class.getResourceAsStream("/pipelines/vaultCredentialsString.groovy"), + StandardCharsets.UTF_8); + WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); + workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); + WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); + jenkins.waitForCompletion(run1); + assertThat(run1.getResult(), equalTo(hudson.model.Result.SUCCESS)); + assertThat( + run1.getLog(), + allOf(containsString("ansible-playbook /ansible/playbook.yml --vault-password-file"))); + } } - @Test - public void testVaultCredentialsFile() throws Exception { - - FileCredentials vaultCredentials = new FileCredentialsImpl( - CredentialsScope.GLOBAL, - "vaultCredentialsFile", - "test username password", - "vault-pass.txt", - SecretBytes.fromString("text-secret")); - CredentialsStore store = - CredentialsProvider.lookupStores(jenkins.jenkins).iterator().next(); - store.addCredentials(Domain.global(), vaultCredentials); - - String pipeline = IOUtils.toString( - PipelineTest.class.getResourceAsStream("/pipelines/vaultCredentialsFile.groovy"), - StandardCharsets.UTF_8); - WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); - workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); - WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); - jenkins.waitForCompletion(run1); - assertThat(run1.getLog(), allOf(containsString("ansible-playbook playbook.yml --vault-password-file "))); + @ParameterizedTest + @MethodSource("ansibleVersions") + public void testVaultCredentialsFileViaExtras(String ansibleVersion, JenkinsRule jenkins) throws Exception { + try (AnsibleAgent agent = setupAnsibleAgent(ansibleVersion, jenkins)) { + FileCredentials vaultCredentials = new FileCredentialsImpl( + CredentialsScope.GLOBAL, + "vaultCredentialsFileViaExtras", + "test username password", + "vault-pass.txt", + SecretBytes.fromString("text-secret")); + SystemCredentialsProvider.getInstance() + .getDomainCredentialsMap() + .put(Domain.global(), Collections.singletonList(vaultCredentials)); + + String pipeline = IOUtils.toString( + PipelineTest.class.getResourceAsStream("/pipelines/vaultCredentialsFileViaExtras.groovy"), + StandardCharsets.UTF_8); + WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); + workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); + WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); + jenkins.waitForCompletion(run1); + assertThat(run1.getResult(), equalTo(hudson.model.Result.SUCCESS)); + assertThat( + run1.getLog(), + allOf(containsString("ansible-playbook /ansible/playbook.yml --vault-password-file "))); + } } - @Test - public void testVaultCredentialsString() throws Exception { - - StringCredentials vaultCredentials = new StringCredentialsImpl( - CredentialsScope.GLOBAL, - "vaultCredentialsString", - "test username password", - Secret.fromString("test-secret")); - CredentialsStore store = - CredentialsProvider.lookupStores(jenkins.jenkins).iterator().next(); - store.addCredentials(Domain.global(), vaultCredentials); - - String pipeline = IOUtils.toString( - PipelineTest.class.getResourceAsStream("/pipelines/vaultCredentialsString.groovy"), - StandardCharsets.UTF_8); - WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); - workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); - WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); - jenkins.waitForCompletion(run1); - String tempDir = getTmpPath(); - assertThat(run1.getLog(), allOf(containsString("ansible-playbook playbook.yml --vault-password-file "))); - assertThat( - run1.getLog(), not(containsString("ansible-playbook playbook.yml --vault-password-file " + tempDir))); + @ParameterizedTest + @MethodSource("ansibleVersions") + public void testAdhocCommand(String ansibleVersion, JenkinsRule jenkins) throws Exception { + try (AnsibleAgent agent = setupAnsibleAgent(ansibleVersion, jenkins)) { + String pipeline = IOUtils.toString( + PipelineTest.class.getResourceAsStream("/pipelines/adhocCommand.groovy"), StandardCharsets.UTF_8); + WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); + workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); + WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); + jenkins.waitForCompletion(run1); + assertThat(run1.getResult(), equalTo(hudson.model.Result.SUCCESS)); + assertThat( + run1.getLog(), + allOf(containsString( + "ansible 127.0.0.1 -i /ansible/inventory.yml -a " + "\"" + "echo something" + "\""))); + } } - @Test - public void testVaultCredentialsFileViaExtras() throws Exception { - - FileCredentials vaultCredentials = new FileCredentialsImpl( - CredentialsScope.GLOBAL, - "vaultCredentialsFileViaExtras", - "test username password", - "vault-pass.txt", - SecretBytes.fromString("text-secret")); - CredentialsStore store = - CredentialsProvider.lookupStores(jenkins.jenkins).iterator().next(); - store.addCredentials(Domain.global(), vaultCredentials); - - String pipeline = IOUtils.toString( - PipelineTest.class.getResourceAsStream("/pipelines/vaultCredentialsFileViaExtras.groovy"), - StandardCharsets.UTF_8); - WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); - workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); - WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); - jenkins.waitForCompletion(run1); - assertThat(run1.getLog(), allOf(containsString("ansible-playbook playbook.yml --vault-password-file "))); + @ParameterizedTest + @MethodSource("ansibleVersions") + public void testVaultTmpPathString(String ansibleVersion, JenkinsRule jenkins) throws Exception { + try (AnsibleAgent agent = setupAnsibleAgent(ansibleVersion, jenkins)) { + FileCredentials vaultCredentials = new FileCredentialsImpl( + CredentialsScope.GLOBAL, + "vaultCredentialsFile", + "test username password", + "vault-pass.txt", + SecretBytes.fromString("text-secret")); + SystemCredentialsProvider.getInstance() + .getDomainCredentialsMap() + .put(Domain.global(), Collections.singletonList(vaultCredentials)); + + String pipeline = IOUtils.toString( + PipelineTest.class.getResourceAsStream("/pipelines/vaultTmpPath.groovy"), StandardCharsets.UTF_8); + WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); + workflowJob.setDefinition(new CpsFlowDefinition(pipeline, false)); + WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); + jenkins.waitForCompletion(run1); + // assertThat(run1.getResult(), equalTo(hudson.model.Result.SUCCESS)); + assertThat( + run1.getLog(), + allOf(containsString("ansible-playbook /ansible/playbook.yml --vault-password-file /ansible/tmp"))); + } } - @Test - public void testAdhocCommand() throws Exception { - String pipeline = IOUtils.toString( - PipelineTest.class.getResourceAsStream("/pipelines/adhocCommand.groovy"), StandardCharsets.UTF_8); - WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); - workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true)); - WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); - jenkins.waitForCompletion(run1); - assertThat( - run1.getLog(), - allOf(containsString("ansible 127.0.0.1 -i inventory -a " + "\"" + "echo something" + "\""))); + @SuppressWarnings("resource") + private AnsibleAgent setupAnsibleAgent(String ansibleVersion, JenkinsRule jenkins) throws Exception { + + // Start container + GenericContainer container = new GenericContainer<>( + new ImageFromDockerfile("ansible-" + ansibleVersion, false) + .withFileFromClasspath("Dockerfile", "docker/Dockerfile") + .withBuildArg("ANSIBLE_CORE_VERSION", ansibleVersion)) + .withExposedPorts(22); + container.start(); + + // Setup credentials to connect to container + StandardUsernameCredentials credentials = new UsernamePasswordCredentialsImpl( + CredentialsScope.SYSTEM, "test-credentials", "", "root", "password"); + SystemCredentialsProvider.getInstance() + .getDomainCredentialsMap() + .put(Domain.global(), Collections.singletonList(credentials)); + + // Create agent and connect to it + final SSHLauncher launcher = + new SSHLauncher(container.getHost(), container.getMappedPort(22), "test-credentials"); + launcher.setSshHostKeyVerificationStrategy(new NonVerifyingKeyVerificationStrategy()); + DumbSlave dumbAgent = new DumbSlave("test-node", "/home/jenkins/agent", launcher); + dumbAgent.setNodeName("test-agent"); + dumbAgent.setNumExecutors(1); + dumbAgent.setLabelString("test-agent"); + jenkins.jenkins.addNode(dumbAgent); + jenkins.waitOnline(dumbAgent); + + return new AnsibleAgent(container, dumbAgent, jenkins); } - @Test - public void testVaultTmpPathString() throws Exception { - - StringCredentials vaultCredentials = new StringCredentialsImpl( - CredentialsScope.GLOBAL, - "vaultCredentialsString", - "test username password", - Secret.fromString("test-secret")); - CredentialsStore store = - CredentialsProvider.lookupStores(jenkins.jenkins).iterator().next(); - store.addCredentials(Domain.global(), vaultCredentials); - - String pipeline = IOUtils.toString( - PipelineTest.class.getResourceAsStream("/pipelines/vaultTmpPath.groovy"), StandardCharsets.UTF_8); - WorkflowJob workflowJob = jenkins.createProject(WorkflowJob.class); - workflowJob.setDefinition(new CpsFlowDefinition(pipeline, false)); - WorkflowRun run1 = workflowJob.scheduleBuild2(0).waitForStart(); - jenkins.waitForCompletion(run1); - String tempDir = getTmpPath(); - assertThat( - run1.getLog(), allOf(containsString("ansible-playbook playbook.yml --vault-password-file " + tempDir))); + public static class AnsibleAgent implements Closeable { + + private GenericContainer container; + private DumbSlave agent; + private JenkinsRule rule; + + public AnsibleAgent(GenericContainer container, DumbSlave agent, JenkinsRule rule) { + this.container = container; + this.agent = agent; + this.rule = rule; + } + + @Override + public void close() { + if (agent != null) { + try { + rule.disconnectSlave(agent); + } catch (Exception e) { + // ignore + } + } + if (container != null) { + container.stop(); + } + } } } diff --git a/src/test/java/org/jenkinsci/plugins/ansible/jobdsl/JobDslIntegrationTest.java b/src/test/java/org/jenkinsci/plugins/ansible/jobdsl/JobDslIntegrationTest.java index 5e841ff..3a52684 100644 --- a/src/test/java/org/jenkinsci/plugins/ansible/jobdsl/JobDslIntegrationTest.java +++ b/src/test/java/org/jenkinsci/plugins/ansible/jobdsl/JobDslIntegrationTest.java @@ -130,7 +130,7 @@ public void shouldCreateJobWithVarExpander() throws Exception { assertThat("credentialsId", step.credentialsId, is("${credentials_id}")); List parameters = new ArrayList<>(); - parameters.add(new StringParameterValue("inventory_repository", "inventory")); + parameters.add(new StringParameterValue("inventory_repository", "/ansible")); parameters.add(new StringParameterValue("vault_credentials_id", "vaultCredentialsString")); parameters.add(new StringParameterValue("credentials_id", "credentialsString")); ParametersAction parametersAction = new ParametersAction(parameters); @@ -141,7 +141,7 @@ public void shouldCreateJobWithVarExpander() throws Exception { assertThat( build.getLog(), allOf(containsString( - "ansible-playbook playbook.yml -i inventory/inventory.yml -f 5 --vault-password-file "))); + "ansible-playbook playbook.yml -i /ansible/inventory.yml -f 5 --vault-password-file "))); } @Test diff --git a/src/test/resources/docker/Dockerfile b/src/test/resources/docker/Dockerfile new file mode 100644 index 0000000..c34c90c --- /dev/null +++ b/src/test/resources/docker/Dockerfile @@ -0,0 +1,28 @@ +FROM jenkins/ssh-agent:5.22.0-jdk21 + +# Define build argument for ansible-core version +ARG ANSIBLE_CORE_VERSION= + +# sshpass used by the plugin +RUN apt-get update && \ + apt-get install -y python3 python3-pip sshpass && \ + rm -rf /var/lib/apt/lists/* + +# Install ansible +RUN pip3 install --break-system-packages ansible-core==${ANSIBLE_CORE_VERSION} + +ENV PATH="${PATH}:/root/.local/bin" + +# Create ansible files +RUN mkdir -p /ansible && \ + mkdir -p /etc/ansible && \ + mkdir -p /ansible/tmp && \ + chmod 1777 /ansible/tmp && \ + echo "---\nall:\n hosts:\n local:\n ansible_connection: local" > /ansible/inventory.yml && \ + echo "---\n- hosts: local\n tasks:\n - debug:\n msg: 'Hello World'" > /ansible/playbook.yml && \ + echo "[defaults]\ninventory = /ansible/inventory.yml" > /etc/ansible/ansible.cfg + +# Test only. Safe to connect with user/password +RUN echo "password\npassword" | passwd root +RUN sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config +RUN sed -i 's/PermitRootLogin no/PermitRootLogin yes/g' /etc/ssh/sshd_config diff --git a/src/test/resources/pipelines/adhocCommand.groovy b/src/test/resources/pipelines/adhocCommand.groovy index 2ce19cb..21111b3 100644 --- a/src/test/resources/pipelines/adhocCommand.groovy +++ b/src/test/resources/pipelines/adhocCommand.groovy @@ -3,20 +3,13 @@ pipeline { label('test-agent') } stages { - stage('Create inventory') { - steps { - writeFile(encoding: 'UTF-8', file: 'inventory', text: '''127.0.0.1 ansible_connection=local''') - } - } stage('Ansible adhoc command') { steps { - warnError(message: 'ansible command not found?') { - ansibleAdhoc( - inventory: 'inventory', - hosts: '127.0.0.1', - moduleArguments: 'echo something', - ) - } + ansibleAdhoc( + inventory: '/ansible/inventory.yml', + hosts: '127.0.0.1', + moduleArguments: 'echo something', + ) } } } diff --git a/src/test/resources/pipelines/ansiblePlaybookSshPass.groovy b/src/test/resources/pipelines/ansiblePlaybookSshPass.groovy index e88854c..d95da1f 100644 --- a/src/test/resources/pipelines/ansiblePlaybookSshPass.groovy +++ b/src/test/resources/pipelines/ansiblePlaybookSshPass.groovy @@ -3,24 +3,12 @@ pipeline { label('test-agent') } stages { - stage('Create playbook') { - steps { - writeFile(encoding: 'UTF-8', file: 'playbook.yml', text: '''- hosts: localhost - connection: local - gather_facts: no - tasks: - - debug: msg=test - ''') - } - } stage('Ansible playbook') { steps { - warnError(message: 'ansible command not found?') { - ansiblePlaybook( - playbook: 'playbook.yml', - credentialsId: 'usernamePasswordCredentialsId', - ) - } + ansiblePlaybook( + playbook: '/ansible/playbook.yml', + credentialsId: 'usernamePasswordCredentialsId', + ) } } } diff --git a/src/test/resources/pipelines/extraVarsBoolean.groovy b/src/test/resources/pipelines/extraVarsBoolean.groovy index 8ca4dbd..5b592ff 100644 --- a/src/test/resources/pipelines/extraVarsBoolean.groovy +++ b/src/test/resources/pipelines/extraVarsBoolean.groovy @@ -3,24 +3,12 @@ pipeline { label('test-agent') } stages { - stage('Create playbook') { - steps { - writeFile(encoding: 'UTF-8', file: 'playbook.yml', text: '''- hosts: localhost - connection: local - gather_facts: no - tasks: - - debug: msg=test - ''') - } - } stage('Ansible playbook') { steps { - warnError(message: 'ansible command not found?') { - ansiblePlaybook( - playbook: 'playbook.yml', - extraVars: [foo1: true, foo2: false], - ) - } + ansiblePlaybook( + playbook: '/ansible/playbook.yml', + extraVars: [foo1: true, foo2: false], + ) } } } diff --git a/src/test/resources/pipelines/extraVarsHiddenString.groovy b/src/test/resources/pipelines/extraVarsHiddenString.groovy index a47cb15..ee41f2d 100644 --- a/src/test/resources/pipelines/extraVarsHiddenString.groovy +++ b/src/test/resources/pipelines/extraVarsHiddenString.groovy @@ -3,24 +3,12 @@ pipeline { label('test-agent') } stages { - stage('Create playbook') { - steps { - writeFile(encoding: 'UTF-8', file: 'playbook.yml', text: '''- hosts: localhost - connection: local - gather_facts: no - tasks: - - debug: msg=test - ''') - } - } stage('Ansible playbook') { steps { - warnError(message: 'ansible command not found?') { - ansiblePlaybook( - playbook: 'playbook.yml', - extraVars: [foo: 'bar'], - ) - } + ansiblePlaybook( + playbook: '/ansible/playbook.yml', + extraVars: [foo: 'bar'], + ) } } } diff --git a/src/test/resources/pipelines/extraVarsMap.groovy b/src/test/resources/pipelines/extraVarsMap.groovy index 381d9e5..6e1aecb 100644 --- a/src/test/resources/pipelines/extraVarsMap.groovy +++ b/src/test/resources/pipelines/extraVarsMap.groovy @@ -3,30 +3,16 @@ pipeline { label('test-agent') } stages { - stage('Create playbook') { - steps { - writeFile(encoding: 'UTF-8', file: 'playbook.yml', text: '''- hosts: localhost - connection: local - gather_facts: no - tasks: - - debug: msg=test - ''') - } - } stage('Ansible playbook') { steps { - warnError(message: 'ansible command not found?') { - ansiblePlaybook( - playbook: 'playbook.yml', - extraVars: [foo1: [value: 'bar1', hidden: false]], - ) - } - warnError(message: 'ansible command not found?') { - ansiblePlaybook( - playbook: 'playbook.yml', - extraVars: [foo2: [value: 'bar2', hidden: true]], - ) - } + ansiblePlaybook( + playbook: '/ansible/playbook.yml', + extraVars: [foo1: [value: 'bar1', hidden: false]], + ) + ansiblePlaybook( + playbook: '/ansible/playbook.yml', + extraVars: [foo2: [value: 'bar2', hidden: true]], + ) } } } diff --git a/src/test/resources/pipelines/extraVarsNumeric.groovy b/src/test/resources/pipelines/extraVarsNumeric.groovy index f0d1d04..33d13f8 100644 --- a/src/test/resources/pipelines/extraVarsNumeric.groovy +++ b/src/test/resources/pipelines/extraVarsNumeric.groovy @@ -3,24 +3,12 @@ pipeline { label('test-agent') } stages { - stage('Create playbook') { - steps { - writeFile(encoding: 'UTF-8', file: 'playbook.yml', text: '''- hosts: localhost - connection: local - gather_facts: no - tasks: - - debug: msg=test - ''') - } - } stage('Ansible playbook') { steps { - warnError(message: 'ansible command not found?') { - ansiblePlaybook( - playbook: 'playbook.yml', - extraVars: [foo1: 8], - ) - } + ansiblePlaybook( + playbook: '/ansible/playbook.yml', + extraVars: [foo1: 8], + ) } } } diff --git a/src/test/resources/pipelines/minimal.groovy b/src/test/resources/pipelines/minimal.groovy index 1c71ce2..667c8ee 100644 --- a/src/test/resources/pipelines/minimal.groovy +++ b/src/test/resources/pipelines/minimal.groovy @@ -3,21 +3,9 @@ pipeline { label('test-agent') } stages { - stage('Create playbook') { - steps { - writeFile(encoding: 'UTF-8', file: 'playbook.yml', text: '''- hosts: localhost - connection: local - gather_facts: no - tasks: - - debug: msg=test - ''') - } - } stage('Ansible playbook') { steps { - warnError(message: 'ansible command not found?') { - ansiblePlaybook(playbook: 'playbook.yml') - } + ansiblePlaybook(playbook: '/ansible/playbook.yml') } } } diff --git a/src/test/resources/pipelines/minimalCheckMode.groovy b/src/test/resources/pipelines/minimalCheckMode.groovy index 39efc98..29ef778 100644 --- a/src/test/resources/pipelines/minimalCheckMode.groovy +++ b/src/test/resources/pipelines/minimalCheckMode.groovy @@ -3,21 +3,9 @@ pipeline { label('test-agent') } stages { - stage('Create playbook') { - steps { - writeFile(encoding: 'UTF-8', file: 'playbook.yml', text: '''- hosts: localhost - connection: local - gather_facts: no - tasks: - - debug: msg=test - ''') - } - } stage('Ansible playbook') { steps { - warnError(message: 'ansible command not found?') { - ansiblePlaybook(playbook: 'playbook.yml', checkMode: true) - } + ansiblePlaybook(playbook: '/ansible/playbook.yml', checkMode: true) } } } diff --git a/src/test/resources/pipelines/vaultCredentialsFile.groovy b/src/test/resources/pipelines/vaultCredentialsFile.groovy index 727491e..a4c4a6f 100644 --- a/src/test/resources/pipelines/vaultCredentialsFile.groovy +++ b/src/test/resources/pipelines/vaultCredentialsFile.groovy @@ -3,24 +3,12 @@ pipeline { label('test-agent') } stages { - stage('Create playbook') { - steps { - writeFile(encoding: 'UTF-8', file: 'playbook.yml', text: '''- hosts: localhost - connection: local - gather_facts: no - tasks: - - debug: msg=test - ''') - } - } stage('Ansible playbook') { steps { - warnError(message: 'ansible command not found?') { - ansiblePlaybook( - playbook: 'playbook.yml', - vaultCredentialsId: 'vaultCredentialsFile', - ) - } + ansiblePlaybook( + playbook: '/ansible/playbook.yml', + vaultCredentialsId: 'vaultCredentialsFile', + ) } } } diff --git a/src/test/resources/pipelines/vaultCredentialsFileViaExtras.groovy b/src/test/resources/pipelines/vaultCredentialsFileViaExtras.groovy index 79c93f2..b7dddd6 100644 --- a/src/test/resources/pipelines/vaultCredentialsFileViaExtras.groovy +++ b/src/test/resources/pipelines/vaultCredentialsFileViaExtras.groovy @@ -3,25 +3,13 @@ pipeline { label('test-agent') } stages { - stage('Create playbook') { - steps { - writeFile(encoding: 'UTF-8', file: 'playbook.yml', text: '''- hosts: localhost - connection: local - gather_facts: no - tasks: - - debug: msg=test - ''') - } - } stage('Ansible playbook') { steps { - warnError(message: 'ansible command not found?') { - withCredentials([file(credentialsId: 'vaultCredentialsFileViaExtras', variable: 'VAULT_FILE')]) { - ansiblePlaybook( - playbook: 'playbook.yml', - extras: '--vault-password-file $VAULT_FILE', - ) - } + withCredentials([file(credentialsId: 'vaultCredentialsFileViaExtras', variable: 'VAULT_FILE')]) { + ansiblePlaybook( + playbook: '/ansible/playbook.yml', + extras: '--vault-password-file $VAULT_FILE', + ) } } } diff --git a/src/test/resources/pipelines/vaultCredentialsString.groovy b/src/test/resources/pipelines/vaultCredentialsString.groovy index a584944..ca36cab 100644 --- a/src/test/resources/pipelines/vaultCredentialsString.groovy +++ b/src/test/resources/pipelines/vaultCredentialsString.groovy @@ -3,24 +3,12 @@ pipeline { label('test-agent') } stages { - stage('Create playbook') { - steps { - writeFile(encoding: 'UTF-8', file: 'playbook.yml', text: '''- hosts: localhost - connection: local - gather_facts: no - tasks: - - debug: msg=test - ''') - } - } stage('Ansible playbook') { steps { - warnError(message: 'ansible command not found?') { - ansiblePlaybook( - playbook: 'playbook.yml', - vaultCredentialsId: 'vaultCredentialsString', - ) - } + ansiblePlaybook( + playbook: '/ansible/playbook.yml', + vaultCredentialsId: 'vaultCredentialsString', + ) } } } diff --git a/src/test/resources/pipelines/vaultTmpPath.groovy b/src/test/resources/pipelines/vaultTmpPath.groovy index 0dd6d51..92a6479 100644 --- a/src/test/resources/pipelines/vaultTmpPath.groovy +++ b/src/test/resources/pipelines/vaultTmpPath.groovy @@ -3,25 +3,13 @@ pipeline { label('test-agent') } stages { - stage('Create playbook') { - steps { - writeFile(encoding: 'UTF-8', file: 'playbook.yml', text: '''- hosts: localhost - connection: local - gather_facts: no - tasks: - - debug: msg=test - ''') - } - } stage('Ansible playbook') { steps { - warnError(message: 'ansible command not found?') { - ansiblePlaybook( - playbook: 'playbook.yml', - vaultCredentialsId: 'vaultCredentialsFile', - vaultTmpPath: System.getProperty("java.io.tmpdir"), - ) - } + ansiblePlaybook( + playbook: '/ansible/playbook.yml', + vaultCredentialsId: 'vaultCredentialsFile', + vaultTmpPath: '/ansible/tmp', + ) } } }