From 2c31105e56c10e7ef2590aaecb08ffb2d0d6da1b Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Wed, 23 Apr 2014 18:29:16 -0700 Subject: [PATCH 01/34] Update maven-release-plugin to 2.3.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index eebf968..1546bf1 100644 --- a/pom.xml +++ b/pom.xml @@ -108,7 +108,7 @@ 2.3 2.6 2.4 - 2.2.1 + 2.3.2 2.5 3.0 2.1.2 From d3cad78f3d90a0eb00e8c0883e7d1336b9561354 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Wed, 23 Apr 2014 18:43:00 -0700 Subject: [PATCH 02/34] [maven-release-plugin] prepare release rundeck-api-java-client-11.0-redo3 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index eebf968..a39e4f7 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.rundeck rundeck-api-java-client - 11.0-SNAPSHOT + 11.0 jar RunDeck API - Java Client Java client for the RunDeck REST API From 7b6259b66b011c34cbc014e67cdc1a8882c98a22 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Wed, 23 Apr 2014 18:43:04 -0700 Subject: [PATCH 03/34] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a39e4f7..722956b 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.rundeck rundeck-api-java-client - 11.0 + 11.1-SNAPSHOT jar RunDeck API - Java Client Java client for the RunDeck REST API From bbe599b915fa662a088cf559579f165a33c45b22 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Thu, 6 Nov 2014 08:49:25 -0800 Subject: [PATCH 04/34] Add todo --- src/site/confluence/status.confluence | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/site/confluence/status.confluence b/src/site/confluence/status.confluence index 39a2185..c161cf4 100644 --- a/src/site/confluence/status.confluence +++ b/src/site/confluence/status.confluence @@ -113,3 +113,11 @@ h2. RunDeck API version 11 * API Token create - OK * API Token list - OK * API Token delete - OK + +h2. Rundeck API version 12 + +[Documentation of the RunDeck API version 12|http://rundeck.org/2.2.0/api/index.html] + +* Bulk delete executions - TBD +* Delete execution - TBD +* Delete all executions for a job - TBD From a7c0c22699475fd31ceb283b8e35e5d516f7135f Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Thu, 6 Nov 2014 09:32:30 -0800 Subject: [PATCH 05/34] Add bulk Delete executions endpoint --- .../java/org/rundeck/api/RundeckClient.java | 28 ++++++- .../api/domain/DeleteExecutionsResponse.java | 84 +++++++++++++++++++ .../generator/DeleteExecutionsGenerator.java | 38 +++++++++ .../DeleteExecutionsResponseParser.java | 52 ++++++++++++ .../org/rundeck/api/RundeckClientTest.java | 82 ++++++++++++++++++ .../tapes/delete_executions_mixed.yaml | 26 ++++++ .../tapes/delete_executions_success.yaml | 26 ++++++ .../tapes/delete_executions_unauthorized.yaml | 26 ++++++ 8 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/rundeck/api/domain/DeleteExecutionsResponse.java create mode 100644 src/main/java/org/rundeck/api/generator/DeleteExecutionsGenerator.java create mode 100644 src/main/java/org/rundeck/api/parser/DeleteExecutionsResponseParser.java create mode 100644 src/test/resources/betamax/tapes/delete_executions_mixed.yaml create mode 100644 src/test/resources/betamax/tapes/delete_executions_success.yaml create mode 100644 src/test/resources/betamax/tapes/delete_executions_unauthorized.yaml diff --git a/src/main/java/org/rundeck/api/RundeckClient.java b/src/main/java/org/rundeck/api/RundeckClient.java index 8462dba..93ced66 100644 --- a/src/main/java/org/rundeck/api/RundeckClient.java +++ b/src/main/java/org/rundeck/api/RundeckClient.java @@ -23,6 +23,7 @@ import org.rundeck.api.RundeckApiException.RundeckApiLoginException; import org.rundeck.api.RundeckApiException.RundeckApiTokenException; import org.rundeck.api.domain.*; import org.rundeck.api.domain.RundeckExecution.ExecutionStatus; +import org.rundeck.api.generator.DeleteExecutionsGenerator; import org.rundeck.api.generator.ProjectConfigGenerator; import org.rundeck.api.generator.ProjectConfigPropertyGenerator; import org.rundeck.api.generator.ProjectGenerator; @@ -95,6 +96,7 @@ public class RundeckClient implements Serializable { V9(9), V10(10), V11(11), + V12(12), ; private int versionNumber; @@ -108,7 +110,7 @@ public class RundeckClient implements Serializable { } } /** Version of the API supported */ - public static final transient int API_VERSION = Version.V11.getVersionNumber(); + public static final transient int API_VERSION = Version.V12.getVersionNumber(); private static final String API = "/api/"; @@ -1643,6 +1645,30 @@ public class RundeckClient implements Serializable { return new ApiCall(this).get(apiPath, new AbortParser(rootXpath()+"/abort")); } + /** + * Delete a set of executions, identified by the given IDs + * + * @param executionIds set of identifiers for the executions - mandatory + * @return a {@link RundeckExecution} instance - won't be null + * @throws RundeckApiException in case of error when calling the API (non-existent execution with this ID) + * @throws RundeckApiLoginException if the login fails (in case of login-based authentication) + * @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication) + * @throws IllegalArgumentException if the executionId is null + */ + public DeleteExecutionsResponse deleteExecutions(Set executionIds) + throws RundeckApiException, RundeckApiLoginException, + RundeckApiTokenException, IllegalArgumentException + { + AssertUtil.notNull(executionIds, "executionIds is mandatory to abort an execution !"); + final ApiPathBuilder apiPath = new ApiPathBuilder("/executions/delete").xml( + new DeleteExecutionsGenerator(executionIds) + ); + return new ApiCall(this).post( + apiPath, + new DeleteExecutionsResponseParser( rootXpath() + "/deleteExecutions") + ); + } + /* * History */ diff --git a/src/main/java/org/rundeck/api/domain/DeleteExecutionsResponse.java b/src/main/java/org/rundeck/api/domain/DeleteExecutionsResponse.java new file mode 100644 index 0000000..6d1f53b --- /dev/null +++ b/src/main/java/org/rundeck/api/domain/DeleteExecutionsResponse.java @@ -0,0 +1,84 @@ +package org.rundeck.api.domain; + +import java.io.Serializable; +import java.util.List; + +/** + * DeleteExecutionsResponse is ... + * + * @author Greg Schueler + * @since 2014-11-06 + */ +public class DeleteExecutionsResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + private int failedCount; + private int successCount; + private boolean allsuccessful; + private int requestCount; + private List failures; + + public int getFailedCount() { + return failedCount; + } + + public void setFailedCount(final int failedCount) { + this.failedCount = failedCount; + } + + public int getSuccessCount() { + return successCount; + } + + public void setSuccessCount(final int successCount) { + this.successCount = successCount; + } + + public boolean isAllsuccessful() { + return allsuccessful; + } + + public void setAllsuccessful(final boolean allsuccessful) { + this.allsuccessful = allsuccessful; + } + + public int getRequestCount() { + return requestCount; + } + + public void setRequestCount(final int requestCount) { + this.requestCount = requestCount; + } + + public List getFailures() { + return failures; + } + + public void setFailures(final List failures) { + this.failures = failures; + } + + public static class DeleteFailure implements Serializable{ + + private static final long serialVersionUID = 1L; + private Long executionId; + private String message; + + public Long getExecutionId() { + return executionId; + } + + public void setExecutionId(final Long executionId) { + this.executionId = executionId; + } + + public String getMessage() { + return message; + } + + public void setMessage(final String message) { + this.message = message; + } + } +} diff --git a/src/main/java/org/rundeck/api/generator/DeleteExecutionsGenerator.java b/src/main/java/org/rundeck/api/generator/DeleteExecutionsGenerator.java new file mode 100644 index 0000000..8efd2bf --- /dev/null +++ b/src/main/java/org/rundeck/api/generator/DeleteExecutionsGenerator.java @@ -0,0 +1,38 @@ +package org.rundeck.api.generator; + +import org.dom4j.DocumentFactory; +import org.dom4j.Element; +import org.rundeck.api.domain.ProjectConfig; + +import java.util.List; +import java.util.Set; + +/** + * DeleteExecutionsGenerator is ... + * + * @author Greg Schueler + * @since 2014-11-06 + */ +public class DeleteExecutionsGenerator extends BaseDocGenerator { + private Set executionIds; + + public DeleteExecutionsGenerator(final Set executionIds) { + this.executionIds = executionIds; + } + + @Override public Element generateXmlElement() { + Element rootElem = DocumentFactory.getInstance().createElement("executions"); + for (Long executionId : executionIds) { + rootElem.addElement("execution").addAttribute("id", Long.toString(executionId)); + } + return rootElem; + } + + public Set getExecutionIds() { + return executionIds; + } + + public void setExecutionIds(final Set executionIds) { + this.executionIds = executionIds; + } +} diff --git a/src/main/java/org/rundeck/api/parser/DeleteExecutionsResponseParser.java b/src/main/java/org/rundeck/api/parser/DeleteExecutionsResponseParser.java new file mode 100644 index 0000000..c3de8af --- /dev/null +++ b/src/main/java/org/rundeck/api/parser/DeleteExecutionsResponseParser.java @@ -0,0 +1,52 @@ +package org.rundeck.api.parser; + +import org.dom4j.Node; +import org.rundeck.api.domain.DeleteExecutionsResponse; + +import java.util.ArrayList; +import java.util.List; + +/** + * DeleteExecutionsResponseParser is ... + * + * @author Greg Schueler + * @since 2014-11-06 + */ +public class DeleteExecutionsResponseParser implements XmlNodeParser { + private String xpath; + + public DeleteExecutionsResponseParser(final String xpath) { + this.xpath = xpath; + } + + @Override public DeleteExecutionsResponse parseXmlNode(final Node node) { + final Node baseNode = xpath != null ? node.selectSingleNode(xpath) : node; + + final DeleteExecutionsResponse response = new DeleteExecutionsResponse(); + response.setAllsuccessful(Boolean.parseBoolean(baseNode.valueOf("@allsuccessful"))); + response.setRequestCount(Integer.parseInt(baseNode.valueOf("@requestCount"))); + response.setSuccessCount(Integer.parseInt(baseNode.valueOf("successful/@count"))); + + final Node failedNode = baseNode.selectSingleNode("failed"); + //parse failures + final List failures = new ArrayList + (); + int failedCount = 0; + if (null != failedNode) { + failedCount = Integer.parseInt(baseNode.valueOf("failed/@count")); + final List list = baseNode.selectNodes("failed/execution"); + + for (final Object o : list) { + final Node execNode = (Node) o; + final DeleteExecutionsResponse.DeleteFailure deleteFailure = + new DeleteExecutionsResponse.DeleteFailure(); + deleteFailure.setExecutionId(Long.parseLong(execNode.valueOf("@id"))); + deleteFailure.setMessage(execNode.valueOf("@message")); + failures.add(deleteFailure); + } + } + response.setFailedCount(failedCount); + response.setFailures(failures); + return response; + } +} diff --git a/src/test/java/org/rundeck/api/RundeckClientTest.java b/src/test/java/org/rundeck/api/RundeckClientTest.java index fb01b80..27fa3eb 100644 --- a/src/test/java/org/rundeck/api/RundeckClientTest.java +++ b/src/test/java/org/rundeck/api/RundeckClientTest.java @@ -56,6 +56,7 @@ public class RundeckClientTest { public static final String TEST_TOKEN_5 = "C3O6d5O98Kr6Dpv71sdE4ERdCuU12P6d"; public static final String TEST_TOKEN_6 = "Do4d3NUD5DKk21DR4sNK755RcPk618vn"; public static final String TEST_TOKEN_7 = "8Dp9op111ER6opsDRkddvE86K9sE499s"; + public static final String TEST_TOKEN_8 = "GG7uj1y6UGahOs7QlmeN2sIwz1Y2j7zI"; @Rule public Recorder recorder = new Recorder(); @@ -1490,6 +1491,87 @@ public class RundeckClientTest { } } + /** + * delete executions with failure + */ + @Test + @Betamax(tape = "delete_executions_unauthorized", mode = TapeMode.READ_ONLY) + public void deleteExecutionsUnauthorized() throws Exception { + final RundeckClient client = createClient(TEST_TOKEN_8, 12); + final DeleteExecutionsResponse response = client.deleteExecutions( + new HashSet() {{ + add(640L); + add(641L); + }} + ); + Assert.assertEquals(2, response.getRequestCount()); + Assert.assertEquals(0, response.getSuccessCount()); + Assert.assertEquals(2, response.getFailedCount()); + Assert.assertFalse(response.isAllsuccessful()); + Assert.assertNotNull(response.getFailures()); + Assert.assertEquals(2, response.getFailures().size()); + Assert.assertEquals(Long.valueOf(641L), response.getFailures().get(0).getExecutionId()); + Assert.assertEquals( + "Unauthorized: Delete execution in project test", + response.getFailures().get(0).getMessage() + ); + Assert.assertEquals(Long.valueOf(640L), response.getFailures().get(1).getExecutionId()); + Assert.assertEquals( + "Unauthorized: Delete execution in project test", + response.getFailures().get(1).getMessage() + ); + } + /** + * delete executions with success + */ + @Test + @Betamax(tape = "delete_executions_success", mode = TapeMode.READ_ONLY) + public void deleteExecutionsSuccess() throws Exception { + final RundeckClient client = createClient(TEST_TOKEN_8, 12); + final DeleteExecutionsResponse response = client.deleteExecutions( + new HashSet() {{ + add(640L); + add(641L); + }} + ); + Assert.assertEquals(2, response.getRequestCount()); + Assert.assertEquals(2, response.getSuccessCount()); + Assert.assertEquals(0, response.getFailedCount()); + Assert.assertTrue(response.isAllsuccessful()); + Assert.assertNotNull(response.getFailures()); + Assert.assertEquals(0, response.getFailures().size()); + } + /** + * delete executions mixed success + */ + @Test + @Betamax(tape = "delete_executions_mixed", mode = TapeMode.READ_ONLY) + public void deleteExecutionsMixed() throws Exception { + final RundeckClient client = createClient(TEST_TOKEN_8, 12); + final DeleteExecutionsResponse response = client.deleteExecutions( + new HashSet() {{ + add(642L); + add(640L); + add(1640L); + }} + ); + Assert.assertEquals(3, response.getRequestCount()); + Assert.assertEquals(1, response.getSuccessCount()); + Assert.assertEquals(2, response.getFailedCount()); + Assert.assertFalse(response.isAllsuccessful()); + Assert.assertNotNull(response.getFailures()); + Assert.assertEquals(2, response.getFailures().size()); + Assert.assertEquals(Long.valueOf(1640L), response.getFailures().get(0).getExecutionId()); + Assert.assertEquals( + "Execution Not found: 1640", + response.getFailures().get(0).getMessage() + ); + Assert.assertEquals(Long.valueOf(640L), response.getFailures().get(1).getExecutionId()); + Assert.assertEquals( + "Execution Not found: 640", + response.getFailures().get(1).getMessage() + ); + } @Before public void setUp() throws Exception { // not that you can put whatever here, because we don't actually connect to the RunDeck instance diff --git a/src/test/resources/betamax/tapes/delete_executions_mixed.yaml b/src/test/resources/betamax/tapes/delete_executions_mixed.yaml new file mode 100644 index 0000000..c21657d --- /dev/null +++ b/src/test/resources/betamax/tapes/delete_executions_mixed.yaml @@ -0,0 +1,26 @@ +!tape +name: delete_executions_mixed +interactions: +- recorded: 2014-11-06T17:29:44.266Z + request: + method: POST + uri: http://rundeck.local:4440/api/12/executions/delete + headers: + Accept: text/xml + Content-Type: application/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + Transfer-Encoding: chunked + User-Agent: RunDeck API Java Client 12 + X-RunDeck-Auth-Token: GG7uj1y6UGahOs7QlmeN2sIwz1Y2j7zI + response: + status: 200 + headers: + Content-Type: application/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=smlj6wcfe4yccemt6bptnmgy;Path=/ + X-Rundeck-API-Version: '12' + X-Rundeck-API-XML-Response-Wrapper: 'false' + body: !!binary |- + PGRlbGV0ZUV4ZWN1dGlvbnMgcmVxdWVzdENvdW50PSczJyBhbGxzdWNjZXNzZnVsPSdmYWxzZSc+CiAgPHN1Y2Nlc3NmdWwgY291bnQ9JzEnIC8+CiAgPGZhaWxlZCBjb3VudD0nMic+CiAgICA8ZXhlY3V0aW9uIGlkPScxNjQwJyBtZXNzYWdlPSdFeGVjdXRpb24gTm90IGZvdW5kOiAxNjQwJyAvPgogICAgPGV4ZWN1dGlvbiBpZD0nNjQwJyBtZXNzYWdlPSdFeGVjdXRpb24gTm90IGZvdW5kOiA2NDAnIC8+CiAgPC9mYWlsZWQ+CjwvZGVsZXRlRXhlY3V0aW9ucz4= diff --git a/src/test/resources/betamax/tapes/delete_executions_success.yaml b/src/test/resources/betamax/tapes/delete_executions_success.yaml new file mode 100644 index 0000000..d412342 --- /dev/null +++ b/src/test/resources/betamax/tapes/delete_executions_success.yaml @@ -0,0 +1,26 @@ +!tape +name: delete_executions_success +interactions: +- recorded: 2014-11-06T17:24:56.487Z + request: + method: POST + uri: http://rundeck.local:4440/api/12/executions/delete + headers: + Accept: text/xml + Content-Type: application/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + Transfer-Encoding: chunked + User-Agent: RunDeck API Java Client 12 + X-RunDeck-Auth-Token: GG7uj1y6UGahOs7QlmeN2sIwz1Y2j7zI + response: + status: 200 + headers: + Content-Type: application/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=1xueq6cjfrsnxjn43hcfadqyk;Path=/ + X-Rundeck-API-Version: '12' + X-Rundeck-API-XML-Response-Wrapper: 'false' + body: !!binary |- + PGRlbGV0ZUV4ZWN1dGlvbnMgcmVxdWVzdENvdW50PScyJyBhbGxzdWNjZXNzZnVsPSd0cnVlJz4KICA8c3VjY2Vzc2Z1bCBjb3VudD0nMicgLz4KPC9kZWxldGVFeGVjdXRpb25zPg== diff --git a/src/test/resources/betamax/tapes/delete_executions_unauthorized.yaml b/src/test/resources/betamax/tapes/delete_executions_unauthorized.yaml new file mode 100644 index 0000000..2f89d99 --- /dev/null +++ b/src/test/resources/betamax/tapes/delete_executions_unauthorized.yaml @@ -0,0 +1,26 @@ +!tape +name: delete_executions_success +interactions: +- recorded: 2014-11-06T17:15:24.673Z + request: + method: POST + uri: http://rundeck.local:4440/api/12/executions/delete + headers: + Accept: text/xml + Content-Type: application/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + Transfer-Encoding: chunked + User-Agent: RunDeck API Java Client 12 + X-RunDeck-Auth-Token: GG7uj1y6UGahOs7QlmeN2sIwz1Y2j7zI + response: + status: 200 + headers: + Content-Type: application/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=1kzmot0r2scpjfxlcpfthh7tz;Path=/ + X-Rundeck-API-Version: '12' + X-Rundeck-API-XML-Response-Wrapper: 'false' + body: !!binary |- + PGRlbGV0ZUV4ZWN1dGlvbnMgcmVxdWVzdENvdW50PScyJyBhbGxzdWNjZXNzZnVsPSdmYWxzZSc+CiAgPHN1Y2Nlc3NmdWwgY291bnQ9JzAnIC8+CiAgPGZhaWxlZCBjb3VudD0nMic+CiAgICA8ZXhlY3V0aW9uIGlkPSc2NDEnIG1lc3NhZ2U9J1VuYXV0aG9yaXplZDogRGVsZXRlIGV4ZWN1dGlvbiBpbiBwcm9qZWN0IHRlc3QnIC8+CiAgICA8ZXhlY3V0aW9uIGlkPSc2NDAnIG1lc3NhZ2U9J1VuYXV0aG9yaXplZDogRGVsZXRlIGV4ZWN1dGlvbiBpbiBwcm9qZWN0IHRlc3QnIC8+CiAgPC9mYWlsZWQ+CjwvZGVsZXRlRXhlY3V0aW9ucz4= From b1c0a45da68c22d0ec8c1da134e2310039e9058f Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Thu, 6 Nov 2014 09:42:34 -0800 Subject: [PATCH 06/34] Fix javadoc, require nonzero size of executionIds --- src/main/java/org/rundeck/api/RundeckClient.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/rundeck/api/RundeckClient.java b/src/main/java/org/rundeck/api/RundeckClient.java index 93ced66..e68dd10 100644 --- a/src/main/java/org/rundeck/api/RundeckClient.java +++ b/src/main/java/org/rundeck/api/RundeckClient.java @@ -1649,17 +1649,20 @@ public class RundeckClient implements Serializable { * Delete a set of executions, identified by the given IDs * * @param executionIds set of identifiers for the executions - mandatory - * @return a {@link RundeckExecution} instance - won't be null + * @return a {@link DeleteExecutionsResponse} instance - won't be null * @throws RundeckApiException in case of error when calling the API (non-existent execution with this ID) * @throws RundeckApiLoginException if the login fails (in case of login-based authentication) * @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication) - * @throws IllegalArgumentException if the executionId is null + * @throws IllegalArgumentException if the executionIds is null */ - public DeleteExecutionsResponse deleteExecutions(Set executionIds) + public DeleteExecutionsResponse deleteExecutions(final Set executionIds) throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException { AssertUtil.notNull(executionIds, "executionIds is mandatory to abort an execution !"); + if (executionIds.size() < 1) { + throw new IllegalArgumentException("executionIds cannot be empty"); + } final ApiPathBuilder apiPath = new ApiPathBuilder("/executions/delete").xml( new DeleteExecutionsGenerator(executionIds) ); From e092ccdb1374df19882d1c4b892afbb0112cff3a Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Thu, 6 Nov 2014 09:48:55 -0800 Subject: [PATCH 07/34] Add delete single execution --- .../java/org/rundeck/api/RundeckClient.java | 17 +++++++++ .../org/rundeck/api/RundeckClientTest.java | 36 +++++++++++++++++++ .../tapes/delete_execution_failure.yaml | 21 +++++++++++ .../tapes/delete_execution_success.yaml | 19 ++++++++++ 4 files changed, 93 insertions(+) create mode 100644 src/test/resources/betamax/tapes/delete_execution_failure.yaml create mode 100644 src/test/resources/betamax/tapes/delete_execution_success.yaml diff --git a/src/main/java/org/rundeck/api/RundeckClient.java b/src/main/java/org/rundeck/api/RundeckClient.java index e68dd10..7811807 100644 --- a/src/main/java/org/rundeck/api/RundeckClient.java +++ b/src/main/java/org/rundeck/api/RundeckClient.java @@ -1672,6 +1672,23 @@ public class RundeckClient implements Serializable { ); } + /** + * Delete a single execution, identified by the given ID + * + * @param executionId identifier for the execution - mandatory + * @throws RundeckApiException in case of error when calling the API (non-existent execution with this ID) + * @throws RundeckApiLoginException if the login fails (in case of login-based authentication) + * @throws RundeckApiTokenException if the token is invalid (in case of token-based authentication) + * @throws IllegalArgumentException if the executionId is null + */ + public void deleteExecution(final Long executionId) + throws RundeckApiException, RundeckApiLoginException, + RundeckApiTokenException, IllegalArgumentException + { + AssertUtil.notNull(executionId, "executionId is mandatory to abort an execution !"); + new ApiCall(this).delete(new ApiPathBuilder("/execution/", executionId.toString())); + } + /* * History */ diff --git a/src/test/java/org/rundeck/api/RundeckClientTest.java b/src/test/java/org/rundeck/api/RundeckClientTest.java index 27fa3eb..e72aeb9 100644 --- a/src/test/java/org/rundeck/api/RundeckClientTest.java +++ b/src/test/java/org/rundeck/api/RundeckClientTest.java @@ -1572,6 +1572,42 @@ public class RundeckClientTest { response.getFailures().get(1).getMessage() ); } + /** + * delete single execution success + */ + @Test + @Betamax(tape = "delete_execution_success", mode = TapeMode.READ_ONLY) + public void deleteExecutionSuccess() throws Exception { + final RundeckClient client = createClient(TEST_TOKEN_8, 12); + client.deleteExecution(643L); + } + /** + * delete single execution failure (does not exist) + */ + @Test + @Betamax(tape = "delete_execution_failure", mode = TapeMode.READ_ONLY) + public void deleteExecutionFailure() throws Exception { + final RundeckClient client = createClient(TEST_TOKEN_8, 12); + try { + client.deleteExecution(640L); + Assert.fail(); + } catch (RundeckApiException.RundeckApiHttpStatusException e) { + Assert.assertEquals(404, e.getStatusCode()); + } + } + /** + * delete single execution null input + */ + @Test + public void deleteExecutionNullInput() throws Exception { + final RundeckClient client = createClient(TEST_TOKEN_8, 12); + try { + client.deleteExecution(null); + Assert.fail(); + } catch (IllegalArgumentException e) { + + } + } @Before public void setUp() throws Exception { // not that you can put whatever here, because we don't actually connect to the RunDeck instance diff --git a/src/test/resources/betamax/tapes/delete_execution_failure.yaml b/src/test/resources/betamax/tapes/delete_execution_failure.yaml new file mode 100644 index 0000000..fa26b88 --- /dev/null +++ b/src/test/resources/betamax/tapes/delete_execution_failure.yaml @@ -0,0 +1,21 @@ +!tape +name: delete_execution_failure +interactions: +- recorded: 2014-11-06T17:45:47.952Z + request: + method: DELETE + uri: http://rundeck.local:4440/api/12/execution/640 + headers: + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 12 + X-RunDeck-Auth-Token: GG7uj1y6UGahOs7QlmeN2sIwz1Y2j7zI + response: + status: 404 + headers: + Content-Type: text/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=1eynpbisggwsy18ax352yya8k0;Path=/ + X-Rundeck-API-Version: '12' + body: "\n \n Execution ID does not exist: 640\n \n" diff --git a/src/test/resources/betamax/tapes/delete_execution_success.yaml b/src/test/resources/betamax/tapes/delete_execution_success.yaml new file mode 100644 index 0000000..3c2555a --- /dev/null +++ b/src/test/resources/betamax/tapes/delete_execution_success.yaml @@ -0,0 +1,19 @@ +!tape +name: delete_execution_success +interactions: +- recorded: 2014-11-06T17:45:47.749Z + request: + method: DELETE + uri: http://rundeck.local:4440/api/12/execution/643 + headers: + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 12 + X-RunDeck-Auth-Token: GG7uj1y6UGahOs7QlmeN2sIwz1Y2j7zI + response: + status: 204 + headers: + Content-Type: text/html;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=1hlysemt7deir1j9r7l6ildg5x;Path=/ From a598c76d8eebeb8f5c91344209ab468ecd1c1bec Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Thu, 6 Nov 2014 10:05:35 -0800 Subject: [PATCH 08/34] Add delete all job executions endpoint --- .../java/org/rundeck/api/RundeckClient.java | 31 ++++++++++++++-- .../org/rundeck/api/RundeckClientTest.java | 36 +++++++++++++++++++ .../delete_all_job_executions_success.yaml | 23 ++++++++++++ ...elete_all_job_executions_unauthorized.yaml | 21 +++++++++++ 4 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 src/test/resources/betamax/tapes/delete_all_job_executions_success.yaml create mode 100644 src/test/resources/betamax/tapes/delete_all_job_executions_unauthorized.yaml diff --git a/src/main/java/org/rundeck/api/RundeckClient.java b/src/main/java/org/rundeck/api/RundeckClient.java index 7811807..5e3e1c0 100644 --- a/src/main/java/org/rundeck/api/RundeckClient.java +++ b/src/main/java/org/rundeck/api/RundeckClient.java @@ -1642,7 +1642,32 @@ public class RundeckClient implements Serializable { if(null!=asUser) { apiPath.param("asUser", asUser); } - return new ApiCall(this).get(apiPath, new AbortParser(rootXpath()+"/abort")); + return new ApiCall(this).get(apiPath, new AbortParser(rootXpath() + "/abort")); + } + + /** + * Delete all executions for a job specified by a job ID + * + * @param jobId Identifier for the job + * + * @return a {@link DeleteExecutionsResponse} instance - won't be null + * + * @throws RundeckApiException in case of error when calling the API (non-existent + * execution with this ID) + * @throws RundeckApiLoginException if the login fails (in case of login-based authentication) + * @throws RundeckApiTokenException if the token is invalid (in case of token-based + * authentication) + * @throws IllegalArgumentException if the executionIds is null + */ + public DeleteExecutionsResponse deleteAllJobExecutions(final String jobId) + throws RundeckApiException, RundeckApiLoginException, + RundeckApiTokenException, IllegalArgumentException + { + AssertUtil.notNull(jobId, "jobId is mandatory to delete executions!"); + return new ApiCall(this).delete( + new ApiPathBuilder("/job/",jobId,"/executions"), + new DeleteExecutionsResponseParser(rootXpath() + "/deleteExecutions") + ); } /** @@ -1659,7 +1684,7 @@ public class RundeckClient implements Serializable { throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException { - AssertUtil.notNull(executionIds, "executionIds is mandatory to abort an execution !"); + AssertUtil.notNull(executionIds, "executionIds is mandatory to delete executions!"); if (executionIds.size() < 1) { throw new IllegalArgumentException("executionIds cannot be empty"); } @@ -1685,7 +1710,7 @@ public class RundeckClient implements Serializable { throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException { - AssertUtil.notNull(executionId, "executionId is mandatory to abort an execution !"); + AssertUtil.notNull(executionId, "executionId is mandatory to delete an execution!"); new ApiCall(this).delete(new ApiPathBuilder("/execution/", executionId.toString())); } diff --git a/src/test/java/org/rundeck/api/RundeckClientTest.java b/src/test/java/org/rundeck/api/RundeckClientTest.java index e72aeb9..b4f5ff4 100644 --- a/src/test/java/org/rundeck/api/RundeckClientTest.java +++ b/src/test/java/org/rundeck/api/RundeckClientTest.java @@ -1572,6 +1572,42 @@ public class RundeckClientTest { response.getFailures().get(1).getMessage() ); } + /** + * delete executions with failure + */ + @Test + @Betamax(tape = "delete_all_job_executions_unauthorized", mode = TapeMode.READ_ONLY) + public void deleteAllJobExecutionsUnauthorized() throws Exception { + final RundeckClient client = createClient(TEST_TOKEN_8, 12); + try { + final DeleteExecutionsResponse response = client.deleteAllJobExecutions( + "764c1209-68ed-4185-8d43-a739364bf156" + ); + Assert.fail(); + } catch (RundeckApiException.RundeckApiTokenException e) { + e.printStackTrace(); + } + } + + /** + * + * @throws Exception + */ + @Test + @Betamax(tape = "delete_all_job_executions_success", mode = TapeMode.READ_ONLY) + public void deleteAllJobExecutionsSuccess() throws Exception { + final RundeckClient client = createClient(TEST_TOKEN_8, 12); + final DeleteExecutionsResponse response = client.deleteAllJobExecutions( + "764c1209-68ed-4185-8d43-a739364bf156" + ); + Assert.assertEquals(2, response.getRequestCount()); + Assert.assertEquals(2, response.getSuccessCount()); + Assert.assertEquals(0, response.getFailedCount()); + Assert.assertTrue(response.isAllsuccessful()); + Assert.assertNotNull(response.getFailures()); + Assert.assertEquals(0, response.getFailures().size()); + } + /** * delete single execution success */ diff --git a/src/test/resources/betamax/tapes/delete_all_job_executions_success.yaml b/src/test/resources/betamax/tapes/delete_all_job_executions_success.yaml new file mode 100644 index 0000000..b68b5e2 --- /dev/null +++ b/src/test/resources/betamax/tapes/delete_all_job_executions_success.yaml @@ -0,0 +1,23 @@ +!tape +name: delete_all_job_executions_success +interactions: +- recorded: 2014-11-06T18:03:44.789Z + request: + method: DELETE + uri: http://rundeck.local:4440/api/12/job/764c1209-68ed-4185-8d43-a739364bf156/executions + headers: + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 12 + X-RunDeck-Auth-Token: GG7uj1y6UGahOs7QlmeN2sIwz1Y2j7zI + response: + status: 200 + headers: + Content-Type: application/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=cqqoff205qus10sz1v3t54rk7;Path=/ + X-Rundeck-API-Version: '12' + X-Rundeck-API-XML-Response-Wrapper: 'false' + body: !!binary |- + PGRlbGV0ZUV4ZWN1dGlvbnMgcmVxdWVzdENvdW50PScyJyBhbGxzdWNjZXNzZnVsPSd0cnVlJz4KICA8c3VjY2Vzc2Z1bCBjb3VudD0nMicgLz4KPC9kZWxldGVFeGVjdXRpb25zPg== diff --git a/src/test/resources/betamax/tapes/delete_all_job_executions_unauthorized.yaml b/src/test/resources/betamax/tapes/delete_all_job_executions_unauthorized.yaml new file mode 100644 index 0000000..f4f898b --- /dev/null +++ b/src/test/resources/betamax/tapes/delete_all_job_executions_unauthorized.yaml @@ -0,0 +1,21 @@ +!tape +name: delete_all_job_executions_unauthorized +interactions: +- recorded: 2014-11-06T17:57:02.905Z + request: + method: DELETE + uri: http://rundeck.local:4440/api/12/job/764c1209-68ed-4185-8d43-a739364bf156/executions + headers: + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 12 + X-RunDeck-Auth-Token: GG7uj1y6UGahOs7QlmeN2sIwz1Y2j7zI + response: + status: 403 + headers: + Content-Type: text/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=splzhkd5xunl1noidus2o7im3;Path=/ + X-Rundeck-API-Version: '12' + body: "\n \n Not authorized for action \"Delete Execution\" for Project test\n \n" From 40f5c5b891b8256d41b33562337b48035c97bdac Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Thu, 6 Nov 2014 10:06:07 -0800 Subject: [PATCH 09/34] Update API v12 todo --- src/site/confluence/status.confluence | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/site/confluence/status.confluence b/src/site/confluence/status.confluence index c161cf4..343131c 100644 --- a/src/site/confluence/status.confluence +++ b/src/site/confluence/status.confluence @@ -118,6 +118,6 @@ h2. Rundeck API version 12 [Documentation of the RunDeck API version 12|http://rundeck.org/2.2.0/api/index.html] -* Bulk delete executions - TBD -* Delete execution - TBD -* Delete all executions for a job - TBD +* Bulk delete executions - OK +* Delete execution - OK +* Delete all executions for a job - OK From e2839d6244777115e608fc019d497d2b99f42266 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Thu, 6 Nov 2014 10:24:51 -0800 Subject: [PATCH 10/34] Expect 204 response for job delete for #14 --- .../java/org/rundeck/api/RundeckClient.java | 3 ++- .../org/rundeck/api/RundeckClientTest.java | 26 +++++++++++++++++++ .../resources/betamax/tapes/delete_job.yaml | 19 ++++++++++++++ .../betamax/tapes/delete_job_not_found.yaml | 21 +++++++++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 src/test/resources/betamax/tapes/delete_job.yaml create mode 100644 src/test/resources/betamax/tapes/delete_job_not_found.yaml diff --git a/src/main/java/org/rundeck/api/RundeckClient.java b/src/main/java/org/rundeck/api/RundeckClient.java index 8462dba..bc23457 100644 --- a/src/main/java/org/rundeck/api/RundeckClient.java +++ b/src/main/java/org/rundeck/api/RundeckClient.java @@ -1039,7 +1039,8 @@ public class RundeckClient implements Serializable { public String deleteJob(String jobId) throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException { AssertUtil.notBlank(jobId, "jobId is mandatory to delete a job !"); - return new ApiCall(this).delete(new ApiPathBuilder("/job/", jobId), new StringParser(rootXpath()+"/success/message")); + new ApiCall(this).delete(new ApiPathBuilder("/job/", jobId)); + return "Job " + jobId + " was deleted successfully"; } /** * Delete multiple jobs, identified by the given IDs diff --git a/src/test/java/org/rundeck/api/RundeckClientTest.java b/src/test/java/org/rundeck/api/RundeckClientTest.java index fb01b80..5dc6d59 100644 --- a/src/test/java/org/rundeck/api/RundeckClientTest.java +++ b/src/test/java/org/rundeck/api/RundeckClientTest.java @@ -1489,6 +1489,32 @@ public class RundeckClientTest { Assert.assertEquals(404,e.getStatusCode()); } } + /** + * delete job + */ + @Test + @Betamax(tape = "delete_job", mode = TapeMode.READ_ONLY) + public void deleteJob() throws Exception { + final RundeckClient client = createClient(TEST_TOKEN_7, 11); + String result = client.deleteJob("api-test-job-run-scheduled"); + + Assert.assertEquals("Job api-test-job-run-scheduled was deleted successfully", result); + } + /** + * delete job (DNE) + */ + @Test + @Betamax(tape = "delete_job_not_found", mode = TapeMode.READ_ONLY) + public void deleteJobNotFound() throws Exception { + final RundeckClient client = createClient(TEST_TOKEN_7, 11); + try { + String result = client.deleteJob("does-not-exist"); + Assert.fail(); + } catch (RundeckApiException.RundeckApiHttpStatusException e) { + Assert.assertEquals(404, e.getStatusCode()); + } + + } @Before public void setUp() throws Exception { diff --git a/src/test/resources/betamax/tapes/delete_job.yaml b/src/test/resources/betamax/tapes/delete_job.yaml new file mode 100644 index 0000000..29e33df --- /dev/null +++ b/src/test/resources/betamax/tapes/delete_job.yaml @@ -0,0 +1,19 @@ +!tape +name: delete_job +interactions: +- recorded: 2014-11-06T18:14:48.773Z + request: + method: DELETE + uri: http://rundeck.local:4440/api/11/job/api-test-job-run-scheduled + headers: + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 204 + headers: + Content-Type: text/html;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=1hb33nx0a7qv21gyuoqes2pahg;Path=/ diff --git a/src/test/resources/betamax/tapes/delete_job_not_found.yaml b/src/test/resources/betamax/tapes/delete_job_not_found.yaml new file mode 100644 index 0000000..f7540a6 --- /dev/null +++ b/src/test/resources/betamax/tapes/delete_job_not_found.yaml @@ -0,0 +1,21 @@ +!tape +name: delete_job_not_found +interactions: +- recorded: 2014-11-06T18:21:13.147Z + request: + method: DELETE + uri: http://rundeck.local:4440/api/11/job/does-not-exist + headers: + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 404 + headers: + Content-Type: text/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=1sxop3bupsrqb1gupbru3vklba;Path=/ + X-Rundeck-API-Version: '12' + body: "\n \n Job ID does not exist: does-not-exist\n \n" From e73bb27058c3e7f55d8b7c06e19f3292fe0d95d1 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Thu, 6 Nov 2014 10:33:59 -0800 Subject: [PATCH 11/34] Release info --- src/changes/changes.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 825c4ca..6f25616 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -22,6 +22,11 @@ Vincent Behar + + + Issue #14: deleteJob fails + + Project creation Get Project configuration From 7228205e57064ca124d546d6be7ec7df7aa0c710 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Thu, 6 Nov 2014 10:35:13 -0800 Subject: [PATCH 12/34] [maven-release-plugin] prepare release rundeck-api-java-client-11.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 722956b..a7b9d1e 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.rundeck rundeck-api-java-client - 11.1-SNAPSHOT + 11.1 jar RunDeck API - Java Client Java client for the RunDeck REST API From d7928bc37e259f96d2d5dfb416c738f826facaf8 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Thu, 6 Nov 2014 10:35:17 -0800 Subject: [PATCH 13/34] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a7b9d1e..7d506cd 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.rundeck rundeck-api-java-client - 11.1 + 11.2-SNAPSHOT jar RunDeck API - Java Client Java client for the RunDeck REST API From 75231805ecd1981ef4797846a4c41e207b31a4e7 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Fri, 7 Nov 2014 15:37:19 -0800 Subject: [PATCH 14/34] Test query parameter generation for date strings --- .../api/ExecutionQueryParametersTest.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/test/java/org/rundeck/api/ExecutionQueryParametersTest.java diff --git a/src/test/java/org/rundeck/api/ExecutionQueryParametersTest.java b/src/test/java/org/rundeck/api/ExecutionQueryParametersTest.java new file mode 100644 index 0000000..dad5254 --- /dev/null +++ b/src/test/java/org/rundeck/api/ExecutionQueryParametersTest.java @@ -0,0 +1,54 @@ +package org.rundeck.api; + +import junit.framework.Assert; +import org.junit.Test; +import org.rundeck.api.query.ExecutionQuery; + +import java.util.Arrays; +import java.util.Date; + +/** + * ExecutionQueryParametersTest is ... + * + * @author Greg Schueler + * @since 2014-11-07 + */ +public class ExecutionQueryParametersTest { + + @Test + public void stringParameter() { + ExecutionQuery.Builder description = ExecutionQuery.builder().description("a description"); + ExecutionQueryParameters executionQueryParameters = new ExecutionQueryParameters( + description.build() + ); + ApiPathBuilder param = new ApiPathBuilder("").param(executionQueryParameters); + Assert.assertEquals("?descFilter=a+description", param.toString()); + } + @Test + public void listParameter() { + ExecutionQuery.Builder description = ExecutionQuery.builder().excludeJobList( + Arrays.asList( + "a", + "b" + ) + ); + ExecutionQueryParameters executionQueryParameters = new ExecutionQueryParameters( + description.build() + ); + ApiPathBuilder param = new ApiPathBuilder("").param(executionQueryParameters); + Assert.assertEquals("?excludeJobListFilter=a&excludeJobListFilter=b", param.toString()); + } + @Test + public void dateParameter() { + ExecutionQuery.Builder description = ExecutionQuery.builder().end( + new Date(1347581178168L) + ); + ExecutionQueryParameters executionQueryParameters = new ExecutionQueryParameters( + description.build() + ); + ApiPathBuilder param = new ApiPathBuilder("").param(executionQueryParameters); + //nb: timezone should be GMT + //2012-09-14T00:06:18Z + Assert.assertEquals("?end=2012-09-14T00%3A06%3A18Z", param.toString()); + } +} From 3219161dd34a23bcbfc7cb355e54e536e4b4544c Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Fri, 7 Nov 2014 15:42:22 -0800 Subject: [PATCH 15/34] Use GMT time zone for date formatter --- src/main/java/org/rundeck/api/QueryParameterBuilder.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/rundeck/api/QueryParameterBuilder.java b/src/main/java/org/rundeck/api/QueryParameterBuilder.java index 6fd0126..23db9bb 100644 --- a/src/main/java/org/rundeck/api/QueryParameterBuilder.java +++ b/src/main/java/org/rundeck/api/QueryParameterBuilder.java @@ -36,6 +36,9 @@ import java.util.*; abstract class QueryParameterBuilder implements ApiPathBuilder.BuildsParameters { public static final String W3C_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; static final SimpleDateFormat format = new SimpleDateFormat(W3C_DATE_FORMAT); + static { + format.setTimeZone(TimeZone.getTimeZone("GMT")); + } /** * Add a value to the builder for a given key From 7bad157911feb120e57d8bf5d542ba34f8726efe Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Fri, 7 Nov 2014 15:42:37 -0800 Subject: [PATCH 16/34] Fix expected generated dates for executions test --- src/test/resources/betamax/tapes/get_executions.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/resources/betamax/tapes/get_executions.yaml b/src/test/resources/betamax/tapes/get_executions.yaml index 740a0c5..f87fb2d 100644 --- a/src/test/resources/betamax/tapes/get_executions.yaml +++ b/src/test/resources/betamax/tapes/get_executions.yaml @@ -38,7 +38,7 @@ interactions: - recorded: 2012-09-14T22:04:13.342Z request: method: GET - uri: http://rundeck.local:4440/api/5/executions?project=blah&begin=2012-09-13T17%3A06%3A18Z&max=2&offset=0 + uri: http://rundeck.local:4440/api/5/executions?project=blah&begin=2012-09-14T00%3A06%3A18Z&max=2&offset=0 headers: Accept: text/xml Host: rundeck.local:4440 @@ -54,7 +54,7 @@ interactions: - recorded: 2012-09-14T22:04:13.404Z request: method: GET - uri: http://rundeck.local:4440/api/5/executions?project=blah&end=2012-09-13T17%3A06%3A18Z&max=2&offset=0 + uri: http://rundeck.local:4440/api/5/executions?project=blah&end=2012-09-14T00%3A06%3A18Z&max=2&offset=0 headers: Accept: text/xml Host: rundeck.local:4440 From 18ec800264d9fcaefced41329c5be973f36cca1e Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Fri, 7 Nov 2014 11:12:02 -0800 Subject: [PATCH 17/34] Test expected API v11 response --- .../rundeck/api/parser/PagedResultParser.java | 11 +- .../org/rundeck/api/RundeckClientTest.java | 126 ++++++ .../betamax/tapes/get_executions_v11.yaml | 419 ++++++++++++++++++ 3 files changed, 554 insertions(+), 2 deletions(-) create mode 100644 src/test/resources/betamax/tapes/get_executions_v11.yaml diff --git a/src/main/java/org/rundeck/api/parser/PagedResultParser.java b/src/main/java/org/rundeck/api/parser/PagedResultParser.java index 3eed01c..3389a87 100644 --- a/src/main/java/org/rundeck/api/parser/PagedResultParser.java +++ b/src/main/java/org/rundeck/api/parser/PagedResultParser.java @@ -26,6 +26,7 @@ package org.rundeck.api.parser; import org.dom4j.Element; import org.dom4j.Node; +import org.rundeck.api.RundeckApiException; import org.rundeck.api.util.PagedResults; import java.util.*; @@ -38,7 +39,7 @@ import java.util.*; */ public class PagedResultParser implements XmlNodeParser> { ListParser itemParser; - String xpath; + private String xpath; /** * Create a PagedResultParser @@ -54,7 +55,9 @@ public class PagedResultParser implements XmlNodeParser> { @Override public PagedResults parseXmlNode(Node node) { Node pagedNodeContainer = node.selectSingleNode(xpath); - + if(null==pagedNodeContainer) { + throw new RundeckApiException("XML content did not match XPATH expression: " + xpath); + } Element el = (Element) pagedNodeContainer; final int max = integerAttribute(el, "max", -1); final int offset = integerAttribute(el, "offset", -1); @@ -113,4 +116,8 @@ public class PagedResultParser implements XmlNodeParser> { } return parseMax; } + + public String getXpath() { + return xpath; + } } diff --git a/src/test/java/org/rundeck/api/RundeckClientTest.java b/src/test/java/org/rundeck/api/RundeckClientTest.java index 21f306f..d4d844e 100644 --- a/src/test/java/org/rundeck/api/RundeckClientTest.java +++ b/src/test/java/org/rundeck/api/RundeckClientTest.java @@ -402,6 +402,132 @@ public class RundeckClientTest { .build(), 2L, 0L); assertPageResults(adhocTest, 2, 2, 2, 0, 2); } + @Test + @Betamax(tape = "get_executions_v11", + mode = TapeMode.READ_ONLY, + match = {MatchRule.uri, MatchRule.headers, MatchRule.method, MatchRule.path, MatchRule.query}) + public void getExecutionsV11() throws Exception { + + RundeckClient client = createClient(TEST_TOKEN_7, 11); + + + final String projectName = "blah"; + final PagedResults jobTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .job("test job") + .build(), + 2L, + 0L); + assertPageResults(jobTest, 2, 2, 2, 0, 2); + final PagedResults jobExactTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .jobExact("test job") + .build(), + 2L, + 0L); + assertPageResults(jobExactTest, 2, 2, 2, 0, 2); + final PagedResults excludeJobTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .excludeJob("test job") + .build(), + 2L, + 0L); + assertPageResults(excludeJobTest, 2, 2, 2, 0, 2); + final PagedResults excludeJobExactTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .excludeJobExact("test job") + .build(), + 2L, + 0L); + assertPageResults(excludeJobExactTest, 2, 2, 2, 0, 2); + final PagedResults descriptionTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .description("a description") + .build(), 2L, 0L); + assertPageResults(descriptionTest, 2, 2, 2, 0, 2); + final PagedResults abortedbyTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .abortedby("admin") + .build(), + 2L, + 0L); + assertPageResults(abortedbyTest, 1, 1, 2, 0, 1); + final PagedResults beginTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .begin(new Date(1347581178168L)) + .build(), 2L, 0L); + assertPageResults(beginTest, 2, 2, 2, 0, 6); + final PagedResults endTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .end(new Date(1415388156385L)) + .build(), 2L, 0L); + assertPageResults(endTest, 2, 2, 2, 0, 4); + final List excludeJobIdList = Arrays.asList("123", "456"); + final PagedResults excludeJobIdListTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .excludeJobIdList(excludeJobIdList) + .build(), 2L, 0L); + assertPageResults(excludeJobIdListTest, 2, 2, 2, 0, 4); + final List jobList = Arrays.asList("fruit/mango", "fruit/lemon"); + final PagedResults jobListTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .jobList(jobList) + .build(), 2L, 0L); + assertPageResults(jobListTest, 2, 2, 2, 0, 2); + final List excludeJobList = Arrays.asList("a/path/job1", "path/to/job2"); + final PagedResults excludeJobListTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .excludeJobList(excludeJobList) + .build(), 2L, 0L); + assertPageResults(excludeJobListTest, 2, 2, 2, 0, 4); + final List list = Arrays.asList("9aa33253-17a3-4dce-890c-e5f10f9f00d6", + "2dd94199-00c4-4690-9b4d-beda4812bed0"); + final PagedResults jobIdListTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .jobIdList(list) + .build(), 2L, 0L); + assertPageResults(jobIdListTest, 2, 2, 2, 0, 2); + final PagedResults groupPathTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .groupPath("fruit") + .build(), + 2L, + 0L); + assertPageResults(groupPathTest, 2, 2, 2, 0, 2); + final PagedResults groupPathExactTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .groupPathExact("fruit") + .build(), 2L, 0L); + assertPageResults(groupPathExactTest, 2, 2, 2, 0, 2); + + final PagedResults excludeGroupPathTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .excludeGroupPath("fruit") + .build(), + 2L, + 0L); + assertPageResults(excludeGroupPathTest, 2, 2, 2, 0, 2); + final PagedResults excliudeGroupPathExactTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .excludeGroupPathExact("fruit") + .build(), 2L, 0L); + assertPageResults(excliudeGroupPathExactTest, 2, 2, 2, 0, 2); + + final PagedResults recentTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .recent("1h").build(), 2L, 0L); + assertPageResults(recentTest, 2, 2, 2, 0, 2); + final PagedResults statusTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .status(RundeckExecution.ExecutionStatus.SUCCEEDED) + .build(), 2L, 0L); + assertPageResults(statusTest, 2, 2, 2, 0, 3); + final PagedResults adhocTest = client.getExecutions(ExecutionQuery.builder() + .project(projectName) + .adhoc(true) + .build(), 2L, 0L); + assertPageResults(adhocTest, 2, 2, 2, 0, 2); + } /** * Test paging values from results diff --git a/src/test/resources/betamax/tapes/get_executions_v11.yaml b/src/test/resources/betamax/tapes/get_executions_v11.yaml new file mode 100644 index 0000000..ae592b0 --- /dev/null +++ b/src/test/resources/betamax/tapes/get_executions_v11.yaml @@ -0,0 +1,419 @@ +!tape +name: get_executions_v11 +interactions: +- recorded: 2014-11-07T23:18:13.076Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?jobFilter=test+job&project=blah&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=1jt4f1ctz8i6rfsou34u5suz2;Path=/ + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T18:51:44Z\n 2014-11-07T18:51:49Z\n \n test job\n\ + \ \n blah\n a description\n \n sleep 5\n \n \n \n \n\ + \ \n \n admin\n 2014-11-07T18:51:32Z\n 2014-11-07T18:51:39Z\n\ + \ admin\n \n test job\n \n blah\n a description\n\ + \ \n sleep 5\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:18:13.426Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?jobExactFilter=test+job&project=blah&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T18:51:44Z\n 2014-11-07T18:51:49Z\n \n test job\n\ + \ \n blah\n a description\n \n sleep 5\n \n \n \n \n\ + \ \n \n admin\n 2014-11-07T18:51:32Z\n 2014-11-07T18:51:39Z\n\ + \ admin\n \n test job\n \n blah\n a description\n\ + \ \n sleep 5\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:18:13.591Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?excludeJobFilter=test+job&project=blah&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T18:54:10Z\n 2014-11-07T18:54:16Z\n \n mango\n \ + \ fruit\n blah\n \n \n sleep 5\n \n \n \n \n\ + \ \n \n admin\n 2014-11-07T18:54:08Z\n 2014-11-07T18:54:14Z\n \n lemon\n fruit\n blah\n \n\ + \ \n sleep 5\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:18:13.748Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?excludeJobExactFilter=test+job&project=blah&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T18:54:10Z\n 2014-11-07T18:54:16Z\n \n mango\n \ + \ fruit\n blah\n \n \n sleep 5\n \n \n \n \n\ + \ \n \n admin\n 2014-11-07T18:54:08Z\n 2014-11-07T18:54:14Z\n \n lemon\n fruit\n blah\n \n\ + \ \n sleep 5\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:18:13.897Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?project=blah&descFilter=a+description&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T18:51:44Z\n 2014-11-07T18:51:49Z\n \n test job\n\ + \ \n blah\n a description\n \n sleep 5\n \n \n \n \n\ + \ \n \n admin\n 2014-11-07T18:51:32Z\n 2014-11-07T18:51:39Z\n\ + \ admin\n \n test job\n \n blah\n a description\n\ + \ \n sleep 5\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:18:14.025Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?project=blah&abortedbyFilter=admin&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T18:51:32Z\n 2014-11-07T18:51:39Z\n admin\n \n\ + \ test job\n \n blah\n a description\n \n sleep 5\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:18:14.155Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?project=blah&begin=2012-09-14T00%3A06%3A18Z&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T23:17:55Z\n\ + \ 2014-11-07T23:17:56Z\n echo bye ; false\n \n \n \n \n \n \n admin\n 2014-11-07T23:17:47Z\n 2014-11-07T23:17:50Z\n\ + \ echo hi ; false\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:19:50.560Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?project=blah&end=2014-11-07T19%3A22%3A36Z&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=1olgmevldd8n2d4lib3pzifep;Path=/ + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T18:54:10Z\n 2014-11-07T18:54:16Z\n \n mango\n \ + \ fruit\n blah\n \n \n sleep 5\n \n \n \n \n\ + \ \n \n admin\n 2014-11-07T18:54:08Z\n 2014-11-07T18:54:14Z\n \n lemon\n fruit\n blah\n \n\ + \ \n sleep 5\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:19:50.701Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?project=blah&excludeJobIdListFilter=123&excludeJobIdListFilter=456&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T18:54:10Z\n 2014-11-07T18:54:16Z\n \n mango\n \ + \ fruit\n blah\n \n \n sleep 5\n \n \n \n \n\ + \ \n \n admin\n 2014-11-07T18:54:08Z\n 2014-11-07T18:54:14Z\n \n lemon\n fruit\n blah\n \n\ + \ \n sleep 5\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:19:50.837Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?project=blah&jobListFilter=fruit%2Fmango&jobListFilter=fruit%2Flemon&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T18:54:10Z\n 2014-11-07T18:54:16Z\n \n mango\n \ + \ fruit\n blah\n \n \n sleep 5\n \n \n \n \n\ + \ \n \n admin\n 2014-11-07T18:54:08Z\n 2014-11-07T18:54:14Z\n \n lemon\n fruit\n blah\n \n\ + \ \n sleep 5\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:19:50.966Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?project=blah&excludeJobListFilter=a%2Fpath%2Fjob1&excludeJobListFilter=path%2Fto%2Fjob2&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T18:54:10Z\n 2014-11-07T18:54:16Z\n \n mango\n \ + \ fruit\n blah\n \n \n sleep 5\n \n \n \n \n\ + \ \n \n admin\n 2014-11-07T18:54:08Z\n 2014-11-07T18:54:14Z\n \n lemon\n fruit\n blah\n \n\ + \ \n sleep 5\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:19:51.097Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?project=blah&jobIdListFilter=9aa33253-17a3-4dce-890c-e5f10f9f00d6&jobIdListFilter=2dd94199-00c4-4690-9b4d-beda4812bed0&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T18:54:10Z\n 2014-11-07T18:54:16Z\n \n mango\n \ + \ fruit\n blah\n \n \n sleep 5\n \n \n \n \n\ + \ \n \n admin\n 2014-11-07T18:54:08Z\n 2014-11-07T18:54:14Z\n \n lemon\n fruit\n blah\n \n\ + \ \n sleep 5\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:19:51.229Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?project=blah&groupPath=fruit&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T18:54:10Z\n 2014-11-07T18:54:16Z\n \n mango\n \ + \ fruit\n blah\n \n \n sleep 5\n \n \n \n \n\ + \ \n \n admin\n 2014-11-07T18:54:08Z\n 2014-11-07T18:54:14Z\n \n lemon\n fruit\n blah\n \n\ + \ \n sleep 5\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:19:51.358Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?project=blah&groupPathExact=fruit&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T18:54:10Z\n 2014-11-07T18:54:16Z\n \n mango\n \ + \ fruit\n blah\n \n \n sleep 5\n \n \n \n \n\ + \ \n \n admin\n 2014-11-07T18:54:08Z\n 2014-11-07T18:54:14Z\n \n lemon\n fruit\n blah\n \n\ + \ \n sleep 5\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:19:51.483Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?project=blah&excludeGroupPath=fruit&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T18:51:44Z\n 2014-11-07T18:51:49Z\n \n test job\n\ + \ \n blah\n a description\n \n sleep 5\n \n \n \n \n\ + \ \n \n admin\n 2014-11-07T18:51:32Z\n 2014-11-07T18:51:39Z\n\ + \ admin\n \n test job\n \n blah\n a description\n\ + \ \n sleep 5\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:19:51.607Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?project=blah&excludeGroupPathExact=fruit&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T18:51:44Z\n 2014-11-07T18:51:49Z\n \n test job\n\ + \ \n blah\n a description\n \n sleep 5\n \n \n \n \n\ + \ \n \n admin\n 2014-11-07T18:51:32Z\n 2014-11-07T18:51:39Z\n\ + \ admin\n \n test job\n \n blah\n a description\n\ + \ \n sleep 5\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:19:51.724Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?project=blah&recentFilter=1h&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T23:17:55Z\n\ + \ 2014-11-07T23:17:56Z\n echo bye ; false\n \n \n \n \n \n \n admin\n 2014-11-07T23:17:47Z\n 2014-11-07T23:17:50Z\n\ + \ echo hi ; false\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:19:51.845Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?project=blah&statusFilter=succeeded&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T18:54:10Z\n 2014-11-07T18:54:16Z\n \n mango\n \ + \ fruit\n blah\n \n \n sleep 5\n \n \n \n \n\ + \ \n \n admin\n 2014-11-07T18:54:08Z\n 2014-11-07T18:54:14Z\n \n lemon\n fruit\n blah\n \n\ + \ \n sleep 5\n \n \n \n \n \n \n" +- recorded: 2014-11-07T23:20:12.975Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/executions?project=blah&adhoc=true&max=2&offset=0 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=11ubcx5ejb1sr6nycorkmdrg3;Path=/ + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-07T23:17:55Z\n\ + \ 2014-11-07T23:17:56Z\n echo bye ; false\n \n \n \n \n \n \n admin\n 2014-11-07T23:17:47Z\n 2014-11-07T23:17:50Z\n\ + \ echo hi ; false\n \n \n \n \n \n \n" From c8e1315612ab873f075a6b63ec46838636b08bb5 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Fri, 7 Nov 2014 15:23:12 -0800 Subject: [PATCH 18/34] Patch rundeck API v11 bug for execution query results --- .../java/org/rundeck/api/RundeckClient.java | 19 ++++++++-- .../parser/PagedResultParser_BugPatchV11.java | 35 +++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/rundeck/api/parser/PagedResultParser_BugPatchV11.java diff --git a/src/main/java/org/rundeck/api/RundeckClient.java b/src/main/java/org/rundeck/api/RundeckClient.java index 8ada6d9..101bf6d 100644 --- a/src/main/java/org/rundeck/api/RundeckClient.java +++ b/src/main/java/org/rundeck/api/RundeckClient.java @@ -1587,13 +1587,26 @@ public class RundeckClient implements Serializable { .param(new ExecutionQueryParameters(query)) .param("max", max) .param("offset", offset), - new PagedResultParser( - new ListParser(new ExecutionParser(), "execution"), - rootXpath()+"/executions" + patchApiV11Response( + new PagedResultParser( + new ListParser(new ExecutionParser(), "execution"), + rootXpath() + "/executions" + ) ) ); } + /** + * Fix potential buggy response from Rundeck, where <result> wrapper exists + * even if it should not. + * @param parser + * @return + */ + private XmlNodeParser> patchApiV11Response + (final PagedResultParser parser) { + return new PagedResultParser_BugPatchV11(parser); + } + /** * Get a single execution, identified by the given ID * diff --git a/src/main/java/org/rundeck/api/parser/PagedResultParser_BugPatchV11.java b/src/main/java/org/rundeck/api/parser/PagedResultParser_BugPatchV11.java new file mode 100644 index 0000000..083b3d1 --- /dev/null +++ b/src/main/java/org/rundeck/api/parser/PagedResultParser_BugPatchV11.java @@ -0,0 +1,35 @@ +package org.rundeck.api.parser; + +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.dom4j.Node; +import org.rundeck.api.util.PagedResults; + +/** + * WRaps a {@link PagedResultParser} to detect whether the result XML incorrectly is wrapped with a + * <result> element. + * + * @author Greg Schueler + * @since 2014-11-07 + */ +public class PagedResultParser_BugPatchV11 implements XmlNodeParser> { + PagedResultParser parser; + + public PagedResultParser_BugPatchV11(final PagedResultParser parser) { + this.parser = parser; + } + + @Override public PagedResults parseXmlNode(final Node node) { + Node sourceNode = node; + final Node tested = sourceNode.selectSingleNode(parser.getXpath()); + if (null == tested && !parser.getXpath().startsWith("result")) { + //prepend /result + if (null != sourceNode.selectSingleNode("result" + parser.getXpath())) { + sourceNode = sourceNode.selectSingleNode("result" + parser.getXpath()); + sourceNode.getParent().remove(sourceNode); + DocumentHelper.createDocument((Element) sourceNode); + } + } + return parser.parseXmlNode(sourceNode); + } +} From 8cc48ecd89952080fba13be6020f65f662c69898 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Mon, 10 Nov 2014 11:14:27 -0800 Subject: [PATCH 19/34] Test api v11 response for trigger job --- .../org/rundeck/api/RundeckClientTest.java | 37 +++++++++++++++++++ .../betamax/tapes/trigger_job_basic_v11.yaml | 24 ++++++++++++ .../tapes/trigger_job_basic_v11_patch.yaml | 24 ++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 src/test/resources/betamax/tapes/trigger_job_basic_v11.yaml create mode 100644 src/test/resources/betamax/tapes/trigger_job_basic_v11_patch.yaml diff --git a/src/test/java/org/rundeck/api/RundeckClientTest.java b/src/test/java/org/rundeck/api/RundeckClientTest.java index d4d844e..97b743d 100644 --- a/src/test/java/org/rundeck/api/RundeckClientTest.java +++ b/src/test/java/org/rundeck/api/RundeckClientTest.java @@ -634,6 +634,43 @@ public class RundeckClientTest { Assert.assertEquals(RundeckExecution.ExecutionStatus.RUNNING, test.getStatus()); } + @Test + @Betamax(tape = "trigger_job_basic_v11") + public void triggerJobBasic_v11() throws Exception { + RundeckClient client = createClient(TEST_TOKEN_7, 11); + + final RundeckExecution test + = client.triggerJob(RunJobBuilder.builder().setJobId("bda8b956-43a5-4eef-9c67" + + "-3f27cc0ee1a5").build()); + + Assert.assertEquals((Long) 943L, test.getId()); + Assert.assertEquals(null, test.getArgstring()); + Assert.assertEquals(null, test.getAbortedBy()); + Assert.assertEquals("echo hi there ${job.username} ; sleep 90", test.getDescription()); + Assert.assertEquals("admin", test.getStartedBy()); + Assert.assertEquals(RundeckExecution.ExecutionStatus.RUNNING, test.getStatus()); + } + + /** + * Response for API v11 incorrectly includes <result>, but we should handle this case + * @throws Exception + */ + @Test + @Betamax(tape = "trigger_job_basic_v11_patch") + public void triggerJobBasic_v11_patch() throws Exception { + RundeckClient client = createClient(TEST_TOKEN_7, 11); + + final RundeckExecution test + = client.triggerJob(RunJobBuilder.builder().setJobId("bda8b956-43a5-4eef-9c67" + + "-3f27cc0ee1a5").build()); + + Assert.assertEquals((Long) 944L, test.getId()); + Assert.assertEquals(null, test.getArgstring()); + Assert.assertEquals(null, test.getAbortedBy()); + Assert.assertEquals("echo hi there ${job.username} ; sleep 90", test.getDescription()); + Assert.assertEquals("admin", test.getStartedBy()); + Assert.assertEquals(RundeckExecution.ExecutionStatus.RUNNING, test.getStatus()); + } @Test @Betamax(tape = "trigger_job_as_user") diff --git a/src/test/resources/betamax/tapes/trigger_job_basic_v11.yaml b/src/test/resources/betamax/tapes/trigger_job_basic_v11.yaml new file mode 100644 index 0000000..d6539c5 --- /dev/null +++ b/src/test/resources/betamax/tapes/trigger_job_basic_v11.yaml @@ -0,0 +1,24 @@ +!tape +name: trigger_job_basic_v11 +interactions: +- recorded: 2014-11-08T00:00:58.749Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/job/bda8b956-43a5-4eef-9c67-3f27cc0ee1a5/run + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: application/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=19ui1v6otua3h1714jv2zbkbid;Path=/ + X-Rundeck-API-Version: '12' + X-Rundeck-API-XML-Response-Wrapper: 'false' + body: !!binary |- + PGV4ZWN1dGlvbnMgY291bnQ9JzEnPgogIDxleGVjdXRpb24gaWQ9Jzk0MycgaHJlZj0naHR0cDovL2RpZ25hbjo0NDQwL2V4ZWN1dGlvbi9mb2xsb3cvOTQzJyBzdGF0dXM9J3J1bm5pbmcnIHByb2plY3Q9J2RlbW8nPgogICAgPHVzZXI+YWRtaW48L3VzZXI+CiAgICA8ZGF0ZS1zdGFydGVkIHVuaXh0aW1lPScxNDE1NDA0ODU4NTE4Jz4yMDE0LTExLTA4VDAwOjAwOjU4WjwvZGF0ZS1zdGFydGVkPgogICAgPGpvYiBpZD0nYmRhOGI5NTYtNDNhNS00ZWVmLTljNjctM2YyN2NjMGVlMWE1Jz4KICAgICAgPG5hbWU+YSBqb2I8L25hbWU+CiAgICAgIDxncm91cD48L2dyb3VwPgogICAgICA8cHJvamVjdD5kZW1vPC9wcm9qZWN0PgogICAgICA8ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj4KICAgIDwvam9iPgogICAgPGRlc2NyaXB0aW9uPmVjaG8gaGkgdGhlcmUgJHtqb2IudXNlcm5hbWV9IDsgc2xlZXAgOTA8L2Rlc2NyaXB0aW9uPgogICAgPGFyZ3N0cmluZyAvPgogIDwvZXhlY3V0aW9uPgo8L2V4ZWN1dGlvbnM+ diff --git a/src/test/resources/betamax/tapes/trigger_job_basic_v11_patch.yaml b/src/test/resources/betamax/tapes/trigger_job_basic_v11_patch.yaml new file mode 100644 index 0000000..7731908 --- /dev/null +++ b/src/test/resources/betamax/tapes/trigger_job_basic_v11_patch.yaml @@ -0,0 +1,24 @@ +!tape +name: trigger_job_basic_v11_patch +interactions: +- recorded: 2014-11-08T00:05:15.235Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/job/bda8b956-43a5-4eef-9c67-3f27cc0ee1a5/run + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=1dfooymrwshimhr8fe4ncoc93;Path=/ + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-08T00:05:14Z\n\ + \ \n a job\n \n demo\n \n \n echo hi there ${job.username}\ + \ ; sleep 90\n \n \n \n" From bceb1ec4c6c862d3e08ecb0f6c99b380af2923f0 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Mon, 10 Nov 2014 11:15:23 -0800 Subject: [PATCH 20/34] Refactor apiv11 result unwrap to utility class --- .../java/org/rundeck/api/RundeckClient.java | 21 ++--- .../org/rundeck/api/parser/APIV11Helper.java | 78 +++++++++++++++++++ .../parser/PagedResultParser_BugPatchV11.java | 35 --------- 3 files changed, 85 insertions(+), 49 deletions(-) create mode 100644 src/main/java/org/rundeck/api/parser/APIV11Helper.java delete mode 100644 src/main/java/org/rundeck/api/parser/PagedResultParser_BugPatchV11.java diff --git a/src/main/java/org/rundeck/api/RundeckClient.java b/src/main/java/org/rundeck/api/RundeckClient.java index 101bf6d..a610219 100644 --- a/src/main/java/org/rundeck/api/RundeckClient.java +++ b/src/main/java/org/rundeck/api/RundeckClient.java @@ -1587,26 +1587,19 @@ public class RundeckClient implements Serializable { .param(new ExecutionQueryParameters(query)) .param("max", max) .param("offset", offset), - patchApiV11Response( + APIV11Helper.unwrapIfNeeded( new PagedResultParser( - new ListParser(new ExecutionParser(), "execution"), + new ListParser( + new ExecutionParser(), + "execution" + ), rootXpath() + "/executions" - ) + ), + rootXpath() + "/executions" ) ); } - /** - * Fix potential buggy response from Rundeck, where <result> wrapper exists - * even if it should not. - * @param parser - * @return - */ - private XmlNodeParser> patchApiV11Response - (final PagedResultParser parser) { - return new PagedResultParser_BugPatchV11(parser); - } - /** * Get a single execution, identified by the given ID * diff --git a/src/main/java/org/rundeck/api/parser/APIV11Helper.java b/src/main/java/org/rundeck/api/parser/APIV11Helper.java new file mode 100644 index 0000000..a9711b2 --- /dev/null +++ b/src/main/java/org/rundeck/api/parser/APIV11Helper.java @@ -0,0 +1,78 @@ +package org.rundeck.api.parser; + +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.dom4j.Node; + +/** + * Utility to handle API v11 responses with <result> wrapper element. + * + * @author Greg Schueler + * @since 2014-11-10 + */ +public class APIV11Helper { + + /** + * Detect and remove extra <result> wrapper around xml response. + * @param parser + * @param xpath + * @param + * @return + */ + public static XmlNodeParser unwrapIfNeeded( + final XmlNodeParser parser, + final String xpath + ) { + return new NodeParser_unwrap(parser, xpath); + } + + static class NodeParser_unwrap implements XmlNodeParser { + XmlNodeParser parser; + String xpath; + + public NodeParser_unwrap(final XmlNodeParser parser, final String xpath) { + this.parser = parser; + this.xpath = xpath; + } + + @Override public T parseXmlNode(final Node node) { + + Node sourceNode = unwrapResultElement(node, xpath); + return parser.parseXmlNode(sourceNode); + } + } + + /** + * Test the node for matching the xpath string, if it doesnt match, attempt to prefix it with + * "result" and match that. If that matches, return the first child of the 'result' element. + * + * @param node + * @param xpath + * + * @return + */ + public static Node unwrapResultElement(final Node node, final String xpath) { + Node sourceNode = node; + final Node tested = sourceNode.selectSingleNode(xpath); + if (null == tested && !xpath.startsWith("result")) { + //prepend /result + if (null != sourceNode.selectSingleNode("result" + xpath)) { + Node resultNode = sourceNode.selectSingleNode("result"); + if (resultNode instanceof Element) { + Element result = (Element) resultNode; + if (result.elements().size() == 1) { + + Node node1 = (Node) result.elements().get(0); + if (node1 instanceof Element) { + sourceNode = node1; + + sourceNode.getParent().remove(sourceNode); + DocumentHelper.createDocument((Element) sourceNode); + } + } + } + } + } + return sourceNode; + } +} diff --git a/src/main/java/org/rundeck/api/parser/PagedResultParser_BugPatchV11.java b/src/main/java/org/rundeck/api/parser/PagedResultParser_BugPatchV11.java deleted file mode 100644 index 083b3d1..0000000 --- a/src/main/java/org/rundeck/api/parser/PagedResultParser_BugPatchV11.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.rundeck.api.parser; - -import org.dom4j.DocumentHelper; -import org.dom4j.Element; -import org.dom4j.Node; -import org.rundeck.api.util.PagedResults; - -/** - * WRaps a {@link PagedResultParser} to detect whether the result XML incorrectly is wrapped with a - * <result> element. - * - * @author Greg Schueler - * @since 2014-11-07 - */ -public class PagedResultParser_BugPatchV11 implements XmlNodeParser> { - PagedResultParser parser; - - public PagedResultParser_BugPatchV11(final PagedResultParser parser) { - this.parser = parser; - } - - @Override public PagedResults parseXmlNode(final Node node) { - Node sourceNode = node; - final Node tested = sourceNode.selectSingleNode(parser.getXpath()); - if (null == tested && !parser.getXpath().startsWith("result")) { - //prepend /result - if (null != sourceNode.selectSingleNode("result" + parser.getXpath())) { - sourceNode = sourceNode.selectSingleNode("result" + parser.getXpath()); - sourceNode.getParent().remove(sourceNode); - DocumentHelper.createDocument((Element) sourceNode); - } - } - return parser.parseXmlNode(sourceNode); - } -} From 39fd86ae6db8c9dd8d1bd468f0c6312d9649cd52 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Mon, 10 Nov 2014 11:16:01 -0800 Subject: [PATCH 21/34] Trigger job handles buggy api v11 response --- src/main/java/org/rundeck/api/RundeckClient.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/rundeck/api/RundeckClient.java b/src/main/java/org/rundeck/api/RundeckClient.java index a610219..7112a58 100644 --- a/src/main/java/org/rundeck/api/RundeckClient.java +++ b/src/main/java/org/rundeck/api/RundeckClient.java @@ -1085,7 +1085,16 @@ public class RundeckClient implements Serializable { if(null!=jobRun.getAsUser()) { apiPath.param("asUser", jobRun.getAsUser()); } - return new ApiCall(this).get(apiPath, new ExecutionParser(rootXpath()+"/executions/execution")); + return new ApiCall(this).get(apiPath, + APIV11Helper.unwrapIfNeeded( + new ExecutionParser( + rootXpath() + + "/executions/execution" + ), rootXpath() + + "/executions/execution" + ) + + ); } From 1f2ffeebacc0db1a2d58f3b38beea7787fb9e5f5 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Mon, 10 Nov 2014 12:08:39 -0800 Subject: [PATCH 22/34] getExecution handles buggy xml wrapper --- src/main/java/org/rundeck/api/RundeckClient.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/rundeck/api/RundeckClient.java b/src/main/java/org/rundeck/api/RundeckClient.java index 7112a58..fb2ef09 100644 --- a/src/main/java/org/rundeck/api/RundeckClient.java +++ b/src/main/java/org/rundeck/api/RundeckClient.java @@ -1622,8 +1622,15 @@ public class RundeckClient implements Serializable { public RundeckExecution getExecution(Long executionId) throws RundeckApiException, RundeckApiLoginException, RundeckApiTokenException, IllegalArgumentException { AssertUtil.notNull(executionId, "executionId is mandatory to get the details of an execution !"); - return new ApiCall(this).get(new ApiPathBuilder("/execution/", executionId.toString()), - new ExecutionParser(rootXpath()+"/executions/execution")); + return new ApiCall(this).get( + new ApiPathBuilder("/execution/", executionId.toString()), + APIV11Helper.unwrapIfNeeded( + new ExecutionParser( + rootXpath() + "/executions/execution" + ), + rootXpath() + "/executions/execution" + ) + ); } /** From e98a3a0ad948e3256e7898a7288a8ea68d9989c0 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Mon, 10 Nov 2014 12:09:06 -0800 Subject: [PATCH 23/34] Add tests for api v11 responses --- .../org/rundeck/api/RundeckClientTest.java | 130 ++++++++++++++++++ .../betamax/tapes/get_execution.yaml | 25 ++++ .../betamax/tapes/get_execution_v11.yaml | 24 ++++ .../tapes/get_execution_v11_buggy.yaml | 24 ++++ .../tapes/trigger_adhoc_command_v11.yaml | 43 ++++++ .../trigger_adhoc_command_v11_buggy.yaml | 42 ++++++ .../tapes/trigger_adhoc_script_v11.yaml | 45 ++++++ .../tapes/trigger_adhoc_script_v11_buggy.yaml | 44 ++++++ 8 files changed, 377 insertions(+) create mode 100644 src/test/resources/betamax/tapes/get_execution.yaml create mode 100644 src/test/resources/betamax/tapes/get_execution_v11.yaml create mode 100644 src/test/resources/betamax/tapes/get_execution_v11_buggy.yaml create mode 100644 src/test/resources/betamax/tapes/trigger_adhoc_command_v11.yaml create mode 100644 src/test/resources/betamax/tapes/trigger_adhoc_command_v11_buggy.yaml create mode 100644 src/test/resources/betamax/tapes/trigger_adhoc_script_v11.yaml create mode 100644 src/test/resources/betamax/tapes/trigger_adhoc_script_v11_buggy.yaml diff --git a/src/test/java/org/rundeck/api/RundeckClientTest.java b/src/test/java/org/rundeck/api/RundeckClientTest.java index 97b743d..04211f6 100644 --- a/src/test/java/org/rundeck/api/RundeckClientTest.java +++ b/src/test/java/org/rundeck/api/RundeckClientTest.java @@ -275,7 +275,47 @@ public class RundeckClientTest { } Assert.assertEquals(Arrays.asList("bob"), names); } + @Test + @Betamax(tape="get_execution") + public void getExecution() throws Exception{ + RundeckClient client = createClient(TEST_TOKEN_7, 5); + RundeckExecution execution = client.getExecution(945L); + Assert.assertEquals("echo test trigger_adhoc_command", execution.getDescription()); + Assert.assertEquals("2 seconds", execution.getDuration()); + Assert.assertEquals("test", execution.getProject()); + Assert.assertEquals("admin", execution.getStartedBy()); + Assert.assertEquals(null, execution.getJob()); + Assert.assertEquals(null, execution.getAbortedBy()); + } + @Test + @Betamax(tape="get_execution_v11") + public void getExecution_v11() throws Exception{ + RundeckClient client = createClient(TEST_TOKEN_7, 11); + RundeckExecution execution = client.getExecution(945L); + Assert.assertEquals("echo test trigger_adhoc_command", execution.getDescription()); + Assert.assertEquals("2 seconds", execution.getDuration()); + Assert.assertEquals("test", execution.getProject()); + Assert.assertEquals("admin", execution.getStartedBy()); + Assert.assertEquals(null, execution.getJob()); + Assert.assertEquals(null, execution.getAbortedBy()); + } + /** + * Test incorrect <result> wrapper is handled correctly + * @throws Exception + */ + @Test + @Betamax(tape="get_execution_v11_buggy") + public void getExecution_v11_buggy() throws Exception{ + RundeckClient client = createClient(TEST_TOKEN_7, 11); + RundeckExecution execution = client.getExecution(945L); + Assert.assertEquals("echo test trigger_adhoc_command", execution.getDescription()); + Assert.assertEquals("2 seconds", execution.getDuration()); + Assert.assertEquals("test", execution.getProject()); + Assert.assertEquals("admin", execution.getStartedBy()); + Assert.assertEquals(null, execution.getJob()); + Assert.assertEquals(null, execution.getAbortedBy()); + } @Test @Betamax(tape = "get_executions", mode = TapeMode.READ_ONLY, @@ -634,6 +674,11 @@ public class RundeckClientTest { Assert.assertEquals(RundeckExecution.ExecutionStatus.RUNNING, test.getStatus()); } + + /** + * API v11 request to trigger job, with expected xml response without <result> wrapper + * @throws Exception + */ @Test @Betamax(tape = "trigger_job_basic_v11") public void triggerJobBasic_v11() throws Exception { @@ -730,6 +775,43 @@ public class RundeckClientTest { Assert.assertEquals(RundeckExecution.ExecutionStatus.SUCCEEDED, test.getStatus()); } + @Test + @Betamax(tape = "trigger_adhoc_command_v11_buggy") + public void triggerAdhocCommand_v11_buggy() throws Exception { + RundeckClient client = createClient(TEST_TOKEN_7, 11); + + final RundeckExecution test + = client.triggerAdhocCommand(RunAdhocCommandBuilder.builder() + .setProject("test") + .setCommand("echo test trigger_adhoc_command") + .build()); + + Assert.assertEquals((Long) 945L, test.getId()); + Assert.assertEquals(null, test.getArgstring()); + Assert.assertEquals(null, test.getAbortedBy()); + Assert.assertEquals("echo test trigger_adhoc_command", test.getDescription()); + Assert.assertEquals("admin", test.getStartedBy()); + Assert.assertEquals(RundeckExecution.ExecutionStatus.RUNNING, test.getStatus()); + } + @Test + @Betamax(tape = "trigger_adhoc_command_v11") + public void triggerAdhocCommand_v11() throws Exception { + RundeckClient client = createClient(TEST_TOKEN_7, 11); + + final RundeckExecution test + = client.triggerAdhocCommand(RunAdhocCommandBuilder.builder() + .setProject("test") + .setCommand("echo test trigger_adhoc_command") + .build()); + + Assert.assertEquals((Long) 946L, test.getId()); + Assert.assertEquals(null, test.getArgstring()); + Assert.assertEquals(null, test.getAbortedBy()); + Assert.assertEquals("echo test trigger_adhoc_command", test.getDescription()); + Assert.assertEquals("admin", test.getStartedBy()); + Assert.assertEquals(RundeckExecution.ExecutionStatus.RUNNING, test.getStatus()); + } + @Test @Betamax(tape = "trigger_adhoc_command_as_user") @@ -794,6 +876,54 @@ public class RundeckClientTest { Assert.assertEquals(RundeckExecution.ExecutionStatus.RUNNING, test.getStatus()); } + + /** + * Handle incorrect <result> wrapper for v11 response + * @throws Exception + */ + @Test + @Betamax(tape = "trigger_adhoc_script_v11_buggy") + public void triggerAdhocScript_v11_buggy() throws Exception { + RundeckClient client = createClient(TEST_TOKEN_7, 11); + String script = "#!/bin/bash\n" + + "echo test trigger_adhoc_script\n"; + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(script.getBytes()); + + final RundeckExecution test + = client.triggerAdhocScript(RunAdhocScriptBuilder.builder().setProject("test").setScript + (byteArrayInputStream).build()); + + Assert.assertEquals((Long) 947L, test.getId()); + Assert.assertEquals(null, test.getArgstring()); + Assert.assertEquals(null, test.getAbortedBy()); + Assert.assertEquals("#!/bin/bash\necho test trigger_adhoc_script", test.getDescription()); + Assert.assertEquals("admin", test.getStartedBy()); + Assert.assertEquals(RundeckExecution.ExecutionStatus.RUNNING, test.getStatus()); + } + /** + * Handle v11 response without <result> wrapper + * @throws Exception + */ + @Test + @Betamax(tape = "trigger_adhoc_script_v11") + public void triggerAdhocScript_v11() throws Exception { + RundeckClient client = createClient(TEST_TOKEN_7, 11); + String script = "#!/bin/bash\n" + + "echo test trigger_adhoc_script\n"; + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(script.getBytes()); + + final RundeckExecution test + = client.triggerAdhocScript(RunAdhocScriptBuilder.builder().setProject("test").setScript + (byteArrayInputStream).build()); + + Assert.assertEquals((Long) 948L, test.getId()); + Assert.assertEquals(null, test.getArgstring()); + Assert.assertEquals(null, test.getAbortedBy()); + Assert.assertEquals("#!/bin/bash\necho test trigger_adhoc_script", test.getDescription()); + Assert.assertEquals("admin", test.getStartedBy()); + Assert.assertEquals(RundeckExecution.ExecutionStatus.RUNNING, test.getStatus()); + } + @Test @Betamax(tape = "trigger_adhoc_script_as_user") public void triggerAdhocScriptAsUser() throws Exception { diff --git a/src/test/resources/betamax/tapes/get_execution.yaml b/src/test/resources/betamax/tapes/get_execution.yaml new file mode 100644 index 0000000..d460f9d --- /dev/null +++ b/src/test/resources/betamax/tapes/get_execution.yaml @@ -0,0 +1,25 @@ +!tape +name: get_execution +interactions: +- recorded: 2014-11-10T19:43:41.415Z + request: + method: GET + uri: http://rundeck.local:4440/api/5/execution/945 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 5 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=1x4pkxxmmforonss2ga8ylvdc;Path=/ + X-Rundeck-API-Version: '12' + X-Rundeck-API-XML-Response-Wrapper: 'true' + body: "\n \n \n admin\n 2014-11-10T19:18:36Z\n\ + \ 2014-11-10T19:18:38Z\n echo test trigger_adhoc_command\n \n \n \n \n \ + \ \n \n" diff --git a/src/test/resources/betamax/tapes/get_execution_v11.yaml b/src/test/resources/betamax/tapes/get_execution_v11.yaml new file mode 100644 index 0000000..450b2d6 --- /dev/null +++ b/src/test/resources/betamax/tapes/get_execution_v11.yaml @@ -0,0 +1,24 @@ +!tape +name: get_execution_v11 +interactions: +- recorded: 2014-11-10T19:44:57.642Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/execution/945 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: application/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=yzyycrxo7utb154qrsuggbtp6;Path=/ + X-Rundeck-API-Version: '12' + X-Rundeck-API-XML-Response-Wrapper: 'false' + body: !!binary |- + PGV4ZWN1dGlvbnMgY291bnQ9JzEnPgogIDxleGVjdXRpb24gaWQ9Jzk0NScgaHJlZj0naHR0cDovL2RpZ25hbjo0NDQwL2V4ZWN1dGlvbi9mb2xsb3cvOTQ1JyBzdGF0dXM9J3N1Y2NlZWRlZCcgcHJvamVjdD0ndGVzdCc+CiAgICA8dXNlcj5hZG1pbjwvdXNlcj4KICAgIDxkYXRlLXN0YXJ0ZWQgdW5peHRpbWU9JzE0MTU2NDcxMTY3MzknPjIwMTQtMTEtMTBUMTk6MTg6MzZaPC9kYXRlLXN0YXJ0ZWQ+CiAgICA8ZGF0ZS1lbmRlZCB1bml4dGltZT0nMTQxNTY0NzExODkzMSc+MjAxNC0xMS0xMFQxOToxODozOFo8L2RhdGUtZW5kZWQ+CiAgICA8ZGVzY3JpcHRpb24+ZWNobyB0ZXN0IHRyaWdnZXJfYWRob2NfY29tbWFuZDwvZGVzY3JpcHRpb24+CiAgICA8YXJnc3RyaW5nIC8+CiAgICA8c3VjY2Vzc2Z1bE5vZGVzPgogICAgICA8bm9kZSBuYW1lPSdkaWduYW4nIC8+CiAgICA8L3N1Y2Nlc3NmdWxOb2Rlcz4KICA8L2V4ZWN1dGlvbj4KPC9leGVjdXRpb25zPg== diff --git a/src/test/resources/betamax/tapes/get_execution_v11_buggy.yaml b/src/test/resources/betamax/tapes/get_execution_v11_buggy.yaml new file mode 100644 index 0000000..12eed0e --- /dev/null +++ b/src/test/resources/betamax/tapes/get_execution_v11_buggy.yaml @@ -0,0 +1,24 @@ +!tape +name: get_execution_v11_buggy +interactions: +- recorded: 2014-11-10T19:47:33.973Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/execution/945 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=prilmlypvi8r14cvs72xu9865;Path=/ + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-10T19:18:36Z\n\ + \ 2014-11-10T19:18:38Z\n echo test trigger_adhoc_command\n \n \n \n \n \ + \ \n \n" diff --git a/src/test/resources/betamax/tapes/trigger_adhoc_command_v11.yaml b/src/test/resources/betamax/tapes/trigger_adhoc_command_v11.yaml new file mode 100644 index 0000000..c7dc62a --- /dev/null +++ b/src/test/resources/betamax/tapes/trigger_adhoc_command_v11.yaml @@ -0,0 +1,43 @@ +!tape +name: trigger_adhoc_command_v11 +interactions: +- recorded: 2014-11-10T19:37:31.471Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/run/command?project=test&exec=echo+test+trigger_adhoc_command + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: application/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=1lzqzroq2oz9d1oiwcyb9qjsk8;Path=/ + X-Rundeck-API-Version: '12' + X-Rundeck-API-XML-Response-Wrapper: 'false' + body: !!binary |- + PGV4ZWN1dGlvbiBpZD0nOTQ2JyAvPg== +- recorded: 2014-11-10T19:37:31.807Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/execution/946 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: application/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + X-Rundeck-API-XML-Response-Wrapper: 'false' + body: !!binary |- + PGV4ZWN1dGlvbnMgY291bnQ9JzEnPgogIDxleGVjdXRpb24gaWQ9Jzk0NicgaHJlZj0naHR0cDovL2RpZ25hbjo0NDQwL2V4ZWN1dGlvbi9mb2xsb3cvOTQ2JyBzdGF0dXM9J3J1bm5pbmcnIHByb2plY3Q9J3Rlc3QnPgogICAgPHVzZXI+YWRtaW48L3VzZXI+CiAgICA8ZGF0ZS1zdGFydGVkIHVuaXh0aW1lPScxNDE1NjQ4MjUxMTg0Jz4yMDE0LTExLTEwVDE5OjM3OjMxWjwvZGF0ZS1zdGFydGVkPgogICAgPGRlc2NyaXB0aW9uPmVjaG8gdGVzdCB0cmlnZ2VyX2FkaG9jX2NvbW1hbmQ8L2Rlc2NyaXB0aW9uPgogICAgPGFyZ3N0cmluZyAvPgogIDwvZXhlY3V0aW9uPgo8L2V4ZWN1dGlvbnM+ diff --git a/src/test/resources/betamax/tapes/trigger_adhoc_command_v11_buggy.yaml b/src/test/resources/betamax/tapes/trigger_adhoc_command_v11_buggy.yaml new file mode 100644 index 0000000..5f29a07 --- /dev/null +++ b/src/test/resources/betamax/tapes/trigger_adhoc_command_v11_buggy.yaml @@ -0,0 +1,42 @@ +!tape +name: trigger_adhoc_command_v11_buggy +interactions: +- recorded: 2014-11-10T19:18:37.071Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/run/command?project=test&exec=echo+test+trigger_adhoc_command + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: application/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=jjryjdfuxtdw1808gclmb7uuj;Path=/ + X-Rundeck-API-Version: '12' + X-Rundeck-API-XML-Response-Wrapper: 'false' + body: !!binary |- + PGV4ZWN1dGlvbiBpZD0nOTQ1JyAvPg== +- recorded: 2014-11-10T19:18:37.444Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/execution/945 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-10T19:18:36Z\n\ + \ echo test trigger_adhoc_command\n \n \n \n" diff --git a/src/test/resources/betamax/tapes/trigger_adhoc_script_v11.yaml b/src/test/resources/betamax/tapes/trigger_adhoc_script_v11.yaml new file mode 100644 index 0000000..8b133c0 --- /dev/null +++ b/src/test/resources/betamax/tapes/trigger_adhoc_script_v11.yaml @@ -0,0 +1,45 @@ +!tape +name: trigger_adhoc_script_v11 +interactions: +- recorded: 2014-11-10T20:04:36.573Z + request: + method: POST + uri: http://rundeck.local:4440/api/11/run/script?project=test + headers: + Accept: text/xml + Content-Type: multipart/form-data; boundary=W2S1I8XOmvOWsdnLEHprcw3N6cQveJEm_aV17Oz + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + Transfer-Encoding: chunked + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: application/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=18uoooauscne2eqtuq466djm;Path=/ + X-Rundeck-API-Version: '12' + X-Rundeck-API-XML-Response-Wrapper: 'false' + body: !!binary |- + PGV4ZWN1dGlvbiBpZD0nOTQ4JyAvPg== +- recorded: 2014-11-10T20:04:36.876Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/execution/948 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: application/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + X-Rundeck-API-XML-Response-Wrapper: 'false' + body: !!binary |- + PGV4ZWN1dGlvbnMgY291bnQ9JzEnPgogIDxleGVjdXRpb24gaWQ9Jzk0OCcgaHJlZj0naHR0cDovL2RpZ25hbjo0NDQwL2V4ZWN1dGlvbi9mb2xsb3cvOTQ4JyBzdGF0dXM9J3J1bm5pbmcnIHByb2plY3Q9J3Rlc3QnPgogICAgPHVzZXI+YWRtaW48L3VzZXI+CiAgICA8ZGF0ZS1zdGFydGVkIHVuaXh0aW1lPScxNDE1NjQ5ODc2MzA1Jz4yMDE0LTExLTEwVDIwOjA0OjM2WjwvZGF0ZS1zdGFydGVkPgogICAgPGRlc2NyaXB0aW9uPiMhL2Jpbi9iYXNoCmVjaG8gdGVzdCB0cmlnZ2VyX2FkaG9jX3NjcmlwdAo8L2Rlc2NyaXB0aW9uPgogICAgPGFyZ3N0cmluZyAvPgogIDwvZXhlY3V0aW9uPgo8L2V4ZWN1dGlvbnM+ diff --git a/src/test/resources/betamax/tapes/trigger_adhoc_script_v11_buggy.yaml b/src/test/resources/betamax/tapes/trigger_adhoc_script_v11_buggy.yaml new file mode 100644 index 0000000..970ba9a --- /dev/null +++ b/src/test/resources/betamax/tapes/trigger_adhoc_script_v11_buggy.yaml @@ -0,0 +1,44 @@ +!tape +name: trigger_adhoc_script_v11_buggy +interactions: +- recorded: 2014-11-10T19:54:03.631Z + request: + method: POST + uri: http://rundeck.local:4440/api/11/run/script?project=test + headers: + Accept: text/xml + Content-Type: multipart/form-data; boundary=7ijcD_EYqXFXKLau3Bg9Oy0PIqf37Vn + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + Transfer-Encoding: chunked + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: application/xml;charset=UTF-8 + Expires: Thu, 01 Jan 1970 00:00:00 GMT + Server: Jetty(7.6.0.v20120127) + Set-Cookie: JSESSIONID=z5e76c45acya1h081pryh4avz;Path=/ + X-Rundeck-API-Version: '12' + X-Rundeck-API-XML-Response-Wrapper: 'false' + body: !!binary |- + PGV4ZWN1dGlvbiBpZD0nOTQ3JyAvPg== +- recorded: 2014-11-10T19:54:03.770Z + request: + method: GET + uri: http://rundeck.local:4440/api/11/execution/947 + headers: + Accept: text/xml + Host: rundeck.local:4440 + Proxy-Connection: Keep-Alive + User-Agent: RunDeck API Java Client 11 + X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s + response: + status: 200 + headers: + Content-Type: text/xml;charset=UTF-8 + Server: Jetty(7.6.0.v20120127) + X-Rundeck-API-Version: '12' + body: "\n \n \n admin\n 2014-11-10T19:54:03Z\n\ + \ #!/bin/bash\necho test trigger_adhoc_script\n\n \n \n \n" From ea5f82714d9e090f893da6fb0a0d486f5fac2663 Mon Sep 17 00:00:00 2001 From: Sylvain Bugat Date: Sun, 23 Nov 2014 15:42:14 +0100 Subject: [PATCH 24/34] Add maven prerequisites for dependencies check Maven plugin version upgrade 1.2 -> 2.1 Add dependencies-check-rules.xml to ignore unreleased versions --- dependencies-check-rules.xml | 13 +++++++++++++ pom.xml | 36 +++++++++++++++++++++++++----------- 2 files changed, 38 insertions(+), 11 deletions(-) create mode 100644 dependencies-check-rules.xml diff --git a/dependencies-check-rules.xml b/dependencies-check-rules.xml new file mode 100644 index 0000000..9721dde --- /dev/null +++ b/dependencies-check-rules.xml @@ -0,0 +1,13 @@ + + + + + .*[\.-](?i)alpha[0-9]*$ + .*[\.-](?i)b(eta)?-?[0-9]*$ + .*[\.-](?i)rc?[0-9]*$ + .*[\.-](?i)draft.*$ + + diff --git a/pom.xml b/pom.xml index 7d506cd..b125fb5 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,10 @@ 4.0.0 + + 2.2.1 + + org.sonatype.oss @@ -88,6 +92,16 @@ 1.6 UTF-8 + + 4.1.2 + 2.6 + 2.1 + 1.6.1 + 1.1.1 + 4.10 + 1.0 + 1.8.4 + 1.7 2.2.2 @@ -114,7 +128,7 @@ 2.1.2 2.10 2.4 - 1.2 + 2.1 @@ -392,7 +406,7 @@ - mercury + file:./dependencies-check-rules.xml @@ -423,52 +437,52 @@ org.apache.httpcomponents httpclient - 4.1.2 + ${apache.httpcomponents.version} org.apache.httpcomponents httpmime - 4.1.2 + ${apache.httpcomponents.version} commons-lang commons-lang - 2.6 + ${commons-lang.version} commons-io commons-io - 2.1 + ${commons-io.version} dom4j dom4j - 1.6.1 + ${dom4j.version} jaxen jaxen - 1.1.1 + ${jaxen.version} junit junit - 4.10 + ${junit.version} test com.github.robfletcher betamax - 1.0 + ${betamax.version} test org.codehaus.groovy groovy-all - 1.8.4 + ${groovy.version} test From b3839f089b9b0db866bab01606781a0107d850b1 Mon Sep 17 00:00:00 2001 From: Sylvain Bugat Date: Mon, 24 Nov 2014 21:59:30 +0100 Subject: [PATCH 25/34] Httpcomponents upgrade MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 4.1.2 -> 4.3.6: tested OK on unit tests and on RundeckMonitor OWASP A9 fix know vulnérabilies: CVE-2014-3577: org.apache.http.conn.ssl.AbstractVerifier in Apache HttpComponents HttpClient before 4.3.5 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b125fb5..9977654 100644 --- a/pom.xml +++ b/pom.xml @@ -93,7 +93,7 @@ UTF-8 - 4.1.2 + 4.3.6 2.6 2.1 1.6.1 From c1a1f3c365e1dc9a3b8314c6e3030229090dbe29 Mon Sep 17 00:00:00 2001 From: Sylvain Bugat Date: Mon, 24 Nov 2014 22:02:56 +0100 Subject: [PATCH 26/34] Deprecation fix apache.httpcomponents fix deprecation due to apache.httpcomponents upgrade and fixing some code warnings --- src/main/java/org/rundeck/api/ApiCall.java | 39 +++++++++++----------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/rundeck/api/ApiCall.java b/src/main/java/org/rundeck/api/ApiCall.java index 71a9808..da5c5a6 100644 --- a/src/main/java/org/rundeck/api/ApiCall.java +++ b/src/main/java/org/rundeck/api/ApiCall.java @@ -37,7 +37,6 @@ import org.apache.http.params.HttpProtocolParams; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; import org.apache.http.util.EntityUtils; -import org.dom4j.Document; import org.rundeck.api.RundeckApiException.RundeckApiLoginException; import org.rundeck.api.RundeckApiException.RundeckApiTokenException; import org.rundeck.api.parser.ParserHelper; @@ -59,7 +58,7 @@ import java.util.Map.Entry; /** * Class responsible for making the HTTP API calls - * + * * @author Vincent Behar */ class ApiCall { @@ -72,10 +71,10 @@ class ApiCall { /** {@link RundeckClient} instance holding the RunDeck url and the credentials */ private final RundeckClient client; - + /** * Build a new instance, linked to the given RunDeck client - * + * * @param client holding the RunDeck url and the credentials * @throws IllegalArgumentException if client is null */ @@ -87,7 +86,7 @@ class ApiCall { /** * Try to "ping" the RunDeck instance to see if it is alive - * + * * @throws RundeckApiException if the ping fails */ public void ping() throws RundeckApiException { @@ -127,7 +126,7 @@ class ApiCall { /** * Test the login-based authentication on the RunDeck instance - * + * * @throws RundeckApiLoginException if the login fails * @see #testAuth() */ @@ -144,7 +143,7 @@ class ApiCall { /** * Test the token-based authentication on the RunDeck instance - * + * * @throws RundeckApiTokenException if the token is invalid * @see #testAuth() */ @@ -161,7 +160,7 @@ class ApiCall { /** * Execute an HTTP GET request to the RunDeck instance, on the given path. We will login first, and then execute the * API call. At the end, the given parser will be used to convert the response to a more useful result object. - * + * * @param apiPath on which we will make the HTTP request - see {@link ApiPathBuilder} * @param parser used to parse the response * @return the result of the call, as formatted by the parser @@ -181,7 +180,7 @@ class ApiCall { /** * Execute an HTTP GET request to the RunDeck instance, on the given path. We will login first, and then execute the * API call. - * + * * @param apiPath on which we will make the HTTP request - see {@link ApiPathBuilder} * @return a new {@link InputStream} instance, not linked with network resources * @throws RundeckApiException in case of error when calling the API @@ -206,7 +205,7 @@ class ApiCall { /** * Execute an HTTP GET request to the RunDeck instance, on the given path. We will login first, and then execute the * API call without appending the API_ENDPOINT to the URL. - * + * * @param apiPath on which we will make the HTTP request - see {@link ApiPathBuilder} * @return a new {@link InputStream} instance, not linked with network resources * @throws RundeckApiException in case of error when calling the API @@ -248,11 +247,11 @@ class ApiCall { return get(apiPath, parser); } } - + /** * Execute an HTTP POST request to the RunDeck instance, on the given path. We will login first, and then execute * the API call. At the end, the given parser will be used to convert the response to a more useful result object. - * + * * @param apiPath on which we will make the HTTP request - see {@link ApiPathBuilder} * @param parser used to parse the response * @return the result of the call, as formatted by the parser @@ -322,7 +321,7 @@ class ApiCall { /** * Execute an HTTP DELETE request to the RunDeck instance, on the given path. We will login first, and then execute * the API call. At the end, the given parser will be used to convert the response to a more useful result object. - * + * * @param apiPath on which we will make the HTTP request - see {@link ApiPathBuilder} * @param parser used to parse the response * @return the result of the call, as formatted by the parser @@ -354,7 +353,7 @@ class ApiCall { /** * Execute an HTTP request to the RunDeck instance. We will login first, and then execute the API call. At the end, * the given parser will be used to convert the response to a more useful result object. - * + * * @param request to execute. see {@link HttpGet}, {@link HttpDelete}, and so on... * @param parser used to parse the response * @return the result of the call, as formatted by the parser @@ -400,7 +399,7 @@ class ApiCall { } /** * Execute an HTTP request to the RunDeck instance. We will login first, and then execute the API call. - * + * * @param request to execute. see {@link HttpGet}, {@link HttpDelete}, and so on... * @return a new {@link InputStream} instance, not linked with network resources * @throws RundeckApiException in case of error when calling the API @@ -594,7 +593,7 @@ class ApiCall { /** * Do the actual work of login, using the given {@link HttpClient} instance. You'll need to re-use this instance * when making API calls (such as running a job). Only use this in case of login-based authentication. - * + * * @param httpClient pre-instantiated * @throws RundeckApiLoginException if the login failed */ @@ -639,11 +638,11 @@ class ApiCall { while (true) { try { HttpPost postLogin = new HttpPost(location); - List params = new ArrayList(); + List params = new ArrayList(); params.add(new BasicNameValuePair("j_username", client.getLogin())); params.add(new BasicNameValuePair("j_password", client.getPassword())); params.add(new BasicNameValuePair("action", "login")); - postLogin.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); + postLogin.setEntity(new UrlEncodedFormEntity(params, Consts.UTF_8)); HttpResponse response = httpClient.execute(postLogin); if (response.getStatusLine().getStatusCode() / 100 == 3) { @@ -663,7 +662,7 @@ class ApiCall { } try { - String content = EntityUtils.toString(response.getEntity(), HTTP.UTF_8); + String content = EntityUtils.toString(response.getEntity(), Consts.UTF_8); if (StringUtils.contains(content, "j_security_check")) { throw new RundeckApiLoginException("Login failed for user " + client.getLogin()); } @@ -689,7 +688,7 @@ class ApiCall { /** * Instantiate a new {@link HttpClient} instance, configured to accept all SSL certificates - * + * * @return an {@link HttpClient} instance - won't be null */ private HttpClient instantiateHttpClient() { From 008a8c3ce42129a32a8ec2e50fa655f7a1a1639d Mon Sep 17 00:00:00 2001 From: Sylvain Bugat Date: Mon, 24 Nov 2014 22:28:06 +0100 Subject: [PATCH 27/34] Spell correction --- dependencies-check-rules.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies-check-rules.xml b/dependencies-check-rules.xml index 9721dde..ead5a09 100644 --- a/dependencies-check-rules.xml +++ b/dependencies-check-rules.xml @@ -3,7 +3,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0 http://mojo.codehaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd"> - + .*[\.-](?i)alpha[0-9]*$ .*[\.-](?i)b(eta)?-?[0-9]*$ From 92d15c0748a0d61e99524ea183e33ccf73283413 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Mon, 24 Nov 2014 14:05:00 -0800 Subject: [PATCH 28/34] Update to version 12.0-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9977654..15770f2 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ org.rundeck rundeck-api-java-client - 11.2-SNAPSHOT + 12.0-SNAPSHOT jar RunDeck API - Java Client Java client for the RunDeck REST API From 5bf4be0bc82724016ce417da0fbc4eaeea87a1f2 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Tue, 25 Nov 2014 10:38:49 -0800 Subject: [PATCH 29/34] Update changelog for v 12.0 --- src/changes/changes.xml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 6f25616..98deb4a 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -19,9 +19,21 @@ xsi:schemaLocation="http://maven.apache.org/changes/1.0.0 http://maven.apache.org/xsd/changes-1.0.0.xsd"> Changelog - Vincent Behar + Greg Schueler + + + Pull Request #18: OWASP A9 fix know vulnerabilities: CVE-2014-3577: in Apache + HttpComponents HttpClient before 4.3.5. + + + Add API v12 support + + + Issue #17: Handle incorrect API v11 responses + + Issue #14: deleteJob fails From 68717ae8641311047a05befd251e0269880db99e Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Tue, 25 Nov 2014 10:56:45 -0800 Subject: [PATCH 30/34] Update download page --- src/site/confluence/download.confluence | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/site/confluence/download.confluence b/src/site/confluence/download.confluence index 5929431..b959285 100644 --- a/src/site/confluence/download.confluence +++ b/src/site/confluence/download.confluence @@ -7,13 +7,10 @@ The library is hosted on the [Maven Central Repository|http://search.maven.org/] You can see all versions and download the files with this query : [g:"org.rundeck" AND a:"rundeck-api-java-client"|http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.rundeck%22%20AND%20a%3A%22rundeck-api-java-client%22]. -Alternatively, you can download [releases|https://oss.sonatype.org/content/repositories/releases/org/rundeck/rundeck-api-java-client/] or [snapshots|https://oss.sonatype.org/content/repositories/snapshots/org/rundeck/rundeck-api-java-client/] from [Sonatype Nexus OSS instance|https://oss.sonatype.org/] (which is then synchronized to Maven Central). +Alternatively, you can download [releases|https://oss.sonatype.org/content/repositories/releases/org/rundeck/rundeck-api-java-client/] from [Sonatype Nexus OSS instance|https://oss.sonatype.org/] (which is then synchronized to Maven Central). h2. Manual download If you want to use this library from a [scripting language|./scripting.html], it is often easier to download a single *jar* file with all dependencies included (named "*rundeck-api-java-client-VERSION-jar-with-dependencies.jar *") -You can download such files on GitHub : [https://github.com/vbehar/rundeck-api-java-client/downloads] (for each release) - -You can also download the latest version (not yet released) on Jenkins : [https://rundeck-api-java-client.ci.cloudbees.com/job/master/lastSuccessfulBuild/artifact/target/] - +You can download such files on GitHub : [https://github.com/rundeck/rundeck-api-java-client/releases] (for each release) From 19527ea32513ae0e4e39f4afa9bf09f8075b6dc9 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Tue, 25 Nov 2014 10:59:16 -0800 Subject: [PATCH 31/34] Fix creation of rundeck client in examples --- src/site/confluence/groovy.confluence | 22 +++++++++++----------- src/site/confluence/jruby.confluence | 20 ++++++++++---------- src/site/confluence/jython.confluence | 18 +++++++++--------- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/site/confluence/groovy.confluence b/src/site/confluence/groovy.confluence index 6dc06e5..e5366a4 100644 --- a/src/site/confluence/groovy.confluence +++ b/src/site/confluence/groovy.confluence @@ -11,10 +11,10 @@ Save the following script in a file named "{{rundeck.groovy}}", and execute it w {code} // we use Grape (Ivy) to download the lib (and its dependencies) from Maven Central Repository -@Grab(group='org.rundeck', module='rundeck-api-java-client', version='2.0') +@Grab(group='org.rundeck', module='rundeck-api-java-client', version='12.0') import org.rundeck.api.RundeckClient -rundeck = new RundeckClient("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() println "RunDeck uptime : ${rundeck.systemInfo.uptime}" println "All RunDeck projects : ${rundeck.projects}" @@ -28,7 +28,7 @@ You can also [download|./download.html] the lib and all its dependencies in 1 bi {code} import org.rundeck.api.RundeckClient -rundeck = new RundeckClient("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() println "RunDeck uptime : ${rundeck.systemInfo.uptime}" println "All RunDeck projects : ${rundeck.projects}" @@ -44,18 +44,18 @@ Starting with RunDeck API 2, there are 2 ways to authenticate : * the *token-based authentication* : with a unique token that you can generate from the RunDeck webUI {code} -// using login-based authentication (admin/admin is the default login/password for a new RunDeck instance) : -rundeck = new RundeckClient("http://localhost:4440", "admin", "admin"); +// using login-based authentication (admin/admin is the default login/password for a new Rundeck instance) : +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() // using token-based authentication : -rundeck = new RundeckClient("http://localhost:4440", "PDDNKo5VE29kpk4prOUDr2rsKdRkEvsD"); +rundeck = RundeckClient.builder().url("http://localhost:4440").token("PDDNKo5VE29kpk4prOUDr2rsKdRkEvsD").build() {code} h2. Running a job {code} import org.rundeck.api.RundeckClient -rundeck = new RundeckClient("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() // find a job from its name, group and project job = rundeck.findJob("my-project", "main-group/sub-group", "job-name") @@ -80,7 +80,7 @@ h2. Running an ad-hoc command {code} import org.rundeck.api.RundeckClient -rundeck = new RundeckClient("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() // trigger the execution of the "uptime" command on the RunDeck server execution = rundeck.triggerAdhocCommand("my-project", "uptime") @@ -93,7 +93,7 @@ h2. Running an ad-hoc script {code} import org.rundeck.api.RundeckClient -rundeck = new RundeckClient("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() // trigger the execution of a custom bash script on the RunDeck server execution = rundeck.triggerAdhocScript("my-project", "/tmp/my-script.sh") @@ -106,7 +106,7 @@ h2. Exporting jobs {code} import org.rundeck.api.RundeckClient -rundeck = new RundeckClient("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() rundeck.exportJobsToFile("/tmp/jobs.xml", "xml", "my-project") rundeck.exportJobToFile("/tmp/job.yaml", "yaml", "job-id") @@ -116,7 +116,7 @@ h2. Importing jobs {code} import org.rundeck.api.RundeckClient -rundeck = new RundeckClient("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() result = rundeck.importJobs("/tmp/jobs.xml", "xml") println "${result.succeededJobs.size} jobs successfully imported, ${result.skippedJobs.size} jobs skipped, and ${result.failedJobs.size} jobs failed" diff --git a/src/site/confluence/jruby.confluence b/src/site/confluence/jruby.confluence index cedb4ae..be1abf4 100644 --- a/src/site/confluence/jruby.confluence +++ b/src/site/confluence/jruby.confluence @@ -14,7 +14,7 @@ require 'java' require '/path/to/rundeck-api-java-client-VERSION-jar-with-dependencies.jar' import org.rundeck.api.RundeckClient -rundeck = RundeckClient.new("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() puts "RunDeck uptime : #{rundeck.systemInfo.uptime}" puts "All RunDeck projects : #{rundeck.projects}" @@ -28,7 +28,7 @@ You can also add the library to the classpath : save the following script in a f {code} import org.rundeck.api.RundeckClient -rundeck = RundeckClient.new("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() puts "RunDeck uptime : #{rundeck.systemInfo.uptime}" puts "All RunDeck projects : #{rundeck.projects}" @@ -44,11 +44,11 @@ Starting with RunDeck API 2, there are 2 ways to authenticate : * the *token-based authentication* : with a unique token that you can generate from the RunDeck webUI {code} -// using login-based authentication (admin/admin is the default login/password for a new RunDeck instance) : -rundeck = RundeckClient.new("http://localhost:4440", "admin", "admin"); +// using login-based authentication (admin/admin is the default login/password for a new Rundeck instance) : +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() // using token-based authentication : -rundeck = RundeckClient.new("http://localhost:4440", "PDDNKo5VE29kpk4prOUDr2rsKdRkEvsD"); +rundeck = RundeckClient.builder().url("http://localhost:4440").token("PDDNKo5VE29kpk4prOUDr2rsKdRkEvsD").build() {code} h2. Running a job @@ -58,7 +58,7 @@ import org.rundeck.api.RundeckClient import org.rundeck.api.OptionsBuilder import org.rundeck.api.NodeFiltersBuilder -rundeck = RundeckClient.new("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() // find a job from its name, group and project job = rundeck.findJob("my-project", "main-group/sub-group", "job-name") @@ -85,7 +85,7 @@ h2. Running an ad-hoc command import org.rundeck.api.RundeckClient import org.rundeck.api.NodeFiltersBuilder -rundeck = RundeckClient.new("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() // trigger the execution of the "uptime" command on the RunDeck server execution = rundeck.triggerAdhocCommand("my-project", "uptime") @@ -101,7 +101,7 @@ import org.rundeck.api.RundeckClient import org.rundeck.api.OptionsBuilder import org.rundeck.api.NodeFiltersBuilder -rundeck = RundeckClient.new("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() // trigger the execution of a custom bash script on the RunDeck server execution = rundeck.triggerAdhocScript("my-project", "/tmp/my-script.sh") @@ -114,7 +114,7 @@ h2. Exporting jobs {code} import org.rundeck.api.RundeckClient -rundeck = RundeckClient.new("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() rundeck.exportJobsToFile("/tmp/jobs.xml", "xml", "my-project") rundeck.exportJobToFile("/tmp/job.yaml", "yaml", "job-id") @@ -124,7 +124,7 @@ h2. Importing jobs {code} import org.rundeck.api.RundeckClient -rundeck = RundeckClient.new("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() result = rundeck.importJobs("/tmp/jobs.xml", "xml") puts "#{result.succeededJobs.size} jobs successfully imported, #{result.skippedJobs.size} jobs skipped, and #{result.failedJobs.size} jobs failed" diff --git a/src/site/confluence/jython.confluence b/src/site/confluence/jython.confluence index b2dbc94..88019aa 100644 --- a/src/site/confluence/jython.confluence +++ b/src/site/confluence/jython.confluence @@ -12,7 +12,7 @@ Save the following script in a file named "{{rundeck.py}}", and execute it with {code} from org.rundeck.api import RundeckClient -rundeck = RundeckClient("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() print("RunDeck uptime : %s" % rundeck.systemInfo.uptime) print("All RunDeck projects : %s" % rundeck.projects) @@ -28,11 +28,11 @@ Starting with RunDeck API 2, there are 2 ways to authenticate : * the *token-based authentication* : with a unique token that you can generate from the RunDeck webUI {code} -// using login-based authentication (admin/admin is the default login/password for a new RunDeck instance) : -rundeck = RundeckClient("http://localhost:4440", "admin", "admin"); +// using login-based authentication (admin/admin is the default login/password for a new Rundeck instance) : +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() // using token-based authentication : -rundeck = RundeckClient("http://localhost:4440", "PDDNKo5VE29kpk4prOUDr2rsKdRkEvsD"); +rundeck = RundeckClient.builder().url("http://localhost:4440").token("PDDNKo5VE29kpk4prOUDr2rsKdRkEvsD").build() {code} h2. Running a job @@ -42,7 +42,7 @@ from org.rundeck.api import RundeckClient from org.rundeck.api import OptionsBuilder from org.rundeck.api import NodeFiltersBuilder -rundeck = RundeckClient("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() // find a job from its name, group and project job = rundeck.findJob("my-project", "main-group/sub-group", "job-name") @@ -69,7 +69,7 @@ h2. Running an ad-hoc command from org.rundeck.api import RundeckClient from org.rundeck.api import NodeFiltersBuilder -rundeck = RundeckClient("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() // trigger the execution of the "uptime" command on the RunDeck server execution = rundeck.triggerAdhocCommand("my-project", "uptime") @@ -85,7 +85,7 @@ from org.rundeck.api import RundeckClient from org.rundeck.api import OptionsBuilder from org.rundeck.api import NodeFiltersBuilder -rundeck = RundeckClient("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() // trigger the execution of a custom bash script on the RunDeck server execution = rundeck.triggerAdhocScript("my-project", "/tmp/my-script.sh") @@ -98,7 +98,7 @@ h2. Exporting jobs {code} from org.rundeck.api import RundeckClient -rundeck = RundeckClient("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() rundeck.exportJobsToFile("/tmp/jobs.xml", "xml", "my-project") rundeck.exportJobToFile("/tmp/job.yaml", "yaml", "job-id") @@ -108,7 +108,7 @@ h2. Importing jobs {code} from org.rundeck.api import RundeckClient -rundeck = RundeckClient("http://localhost:4440", "admin", "admin") +rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() result = rundeck.importJobs("/tmp/jobs.xml", "xml") print("%s jobs successfully imported, %s jobs skipped, and %s jobs failed" % (result.succeededJobs.size, result.skippedJobs.size, result.failedJobs.size)) From d612f3c88bb554adc85499d24c1926a49a7c1134 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Tue, 25 Nov 2014 10:59:27 -0800 Subject: [PATCH 32/34] text fix naming RunDeck to Rundeck --- src/site/confluence/groovy.confluence | 32 +++++++++--------- src/site/confluence/jruby.confluence | 32 +++++++++--------- src/site/confluence/jython.confluence | 22 ++++++------ src/site/confluence/status.confluence | 48 +++++++++++++-------------- src/site/site.xml | 6 ++-- 5 files changed, 70 insertions(+), 70 deletions(-) diff --git a/src/site/confluence/groovy.confluence b/src/site/confluence/groovy.confluence index e5366a4..20fd4d4 100644 --- a/src/site/confluence/groovy.confluence +++ b/src/site/confluence/groovy.confluence @@ -1,5 +1,5 @@ -h1. Using the RunDeck API from Groovy scripts +h1. Using the Rundeck API from Groovy scripts Here are some examples of what you can do with this lib and a few lines of [Groovy|http://groovy.codehaus.org/]. @@ -16,11 +16,11 @@ import org.rundeck.api.RundeckClient rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() -println "RunDeck uptime : ${rundeck.systemInfo.uptime}" -println "All RunDeck projects : ${rundeck.projects}" -println "All RunDeck nodes : ${rundeck.nodes}" -println "All RunDeck jobs : ${rundeck.jobs}" -println "All RunDeck running executions : ${rundeck.runningExecutions}" +println "Rundeck uptime : ${rundeck.systemInfo.uptime}" +println "All Rundeck projects : ${rundeck.projects}" +println "All Rundeck nodes : ${rundeck.nodes}" +println "All Rundeck jobs : ${rundeck.jobs}" +println "All Rundeck running executions : ${rundeck.runningExecutions}" {code} You can also [download|./download.html] the lib and all its dependencies in 1 big jar file, and add it to your classpath before running your script : save the following script in a file named "{{rundeck.groovy}}", and execute it with "{{groovy -cp /path/to/rundeck-api-java-client-VERSION-jar-with-dependencies.jar rundeck.groovy}}". @@ -30,18 +30,18 @@ import org.rundeck.api.RundeckClient rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() -println "RunDeck uptime : ${rundeck.systemInfo.uptime}" -println "All RunDeck projects : ${rundeck.projects}" -println "All RunDeck nodes : ${rundeck.nodes}" -println "All RunDeck jobs : ${rundeck.jobs}" -println "All RunDeck running executions : ${rundeck.runningExecutions}" +println "Rundeck uptime : ${rundeck.systemInfo.uptime}" +println "All Rundeck projects : ${rundeck.projects}" +println "All Rundeck nodes : ${rundeck.nodes}" +println "All Rundeck jobs : ${rundeck.jobs}" +println "All Rundeck running executions : ${rundeck.runningExecutions}" {code} h2. Authentication -Starting with RunDeck API 2, there are 2 ways to authenticate : +Starting with Rundeck API 2, there are 2 ways to authenticate : * the *login-based authentication* : with your login and password -* the *token-based authentication* : with a unique token that you can generate from the RunDeck webUI +* the *token-based authentication* : with a unique token that you can generate from the Rundeck webUI {code} // using login-based authentication (admin/admin is the default login/password for a new Rundeck instance) : @@ -82,7 +82,7 @@ h2. Running an ad-hoc command import org.rundeck.api.RundeckClient rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() -// trigger the execution of the "uptime" command on the RunDeck server +// trigger the execution of the "uptime" command on the Rundeck server execution = rundeck.triggerAdhocCommand("my-project", "uptime") // run the "uptime" command on all unix nodes @@ -95,7 +95,7 @@ h2. Running an ad-hoc script import org.rundeck.api.RundeckClient rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() -// trigger the execution of a custom bash script on the RunDeck server +// trigger the execution of a custom bash script on the Rundeck server execution = rundeck.triggerAdhocScript("my-project", "/tmp/my-script.sh") // run a bash script (with options) on all unix nodes @@ -124,5 +124,5 @@ println "${result.succeededJobs.size} jobs successfully imported, ${result.skipp h2. And more... -See the API documentation of the [RundeckClient|./apidocs/reference/org/rundeck/api/RundeckClient.html] class for more interactions with your RunDeck instance... +See the API documentation of the [RundeckClient|./apidocs/reference/org/rundeck/api/RundeckClient.html] class for more interactions with your Rundeck instance... diff --git a/src/site/confluence/jruby.confluence b/src/site/confluence/jruby.confluence index be1abf4..d761a36 100644 --- a/src/site/confluence/jruby.confluence +++ b/src/site/confluence/jruby.confluence @@ -1,5 +1,5 @@ -h1. Using the RunDeck API from JRuby scripts +h1. Using the Rundeck API from JRuby scripts Here are some examples of what you can do with this lib and a few lines of [Ruby|http://www.jruby.org/] (for the rubyist that don't fear running on the JVM !) @@ -16,11 +16,11 @@ import org.rundeck.api.RundeckClient rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() -puts "RunDeck uptime : #{rundeck.systemInfo.uptime}" -puts "All RunDeck projects : #{rundeck.projects}" -puts "All RunDeck nodes : #{rundeck.nodes}" -puts "All RunDeck jobs : #{rundeck.jobs}" -puts "All RunDeck running executions : #{rundeck.runningExecutions}" +puts "Rundeck uptime : #{rundeck.systemInfo.uptime}" +puts "All Rundeck projects : #{rundeck.projects}" +puts "All Rundeck nodes : #{rundeck.nodes}" +puts "All Rundeck jobs : #{rundeck.jobs}" +puts "All Rundeck running executions : #{rundeck.runningExecutions}" {code} You can also add the library to the classpath : save the following script in a file named "{{rundeck.rb}}", and execute it with "{{jruby -rjava -J-cp /path/to/rundeck-api-java-client-VERSION-jar-with-dependencies.jar rundeck.rb}}". @@ -30,18 +30,18 @@ import org.rundeck.api.RundeckClient rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() -puts "RunDeck uptime : #{rundeck.systemInfo.uptime}" -puts "All RunDeck projects : #{rundeck.projects}" -puts "All RunDeck nodes : #{rundeck.nodes}" -puts "All RunDeck jobs : #{rundeck.jobs}" -puts "All RunDeck running executions : #{rundeck.runningExecutions}" +puts "Rundeck uptime : #{rundeck.systemInfo.uptime}" +puts "All Rundeck projects : #{rundeck.projects}" +puts "All Rundeck nodes : #{rundeck.nodes}" +puts "All Rundeck jobs : #{rundeck.jobs}" +puts "All Rundeck running executions : #{rundeck.runningExecutions}" {code} h2. Authentication -Starting with RunDeck API 2, there are 2 ways to authenticate : +Starting with Rundeck API 2, there are 2 ways to authenticate : * the *login-based authentication* : with your login and password -* the *token-based authentication* : with a unique token that you can generate from the RunDeck webUI +* the *token-based authentication* : with a unique token that you can generate from the Rundeck webUI {code} // using login-based authentication (admin/admin is the default login/password for a new Rundeck instance) : @@ -87,7 +87,7 @@ import org.rundeck.api.NodeFiltersBuilder rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() -// trigger the execution of the "uptime" command on the RunDeck server +// trigger the execution of the "uptime" command on the Rundeck server execution = rundeck.triggerAdhocCommand("my-project", "uptime") // run the "uptime" command on all unix nodes @@ -103,7 +103,7 @@ import org.rundeck.api.NodeFiltersBuilder rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() -// trigger the execution of a custom bash script on the RunDeck server +// trigger the execution of a custom bash script on the Rundeck server execution = rundeck.triggerAdhocScript("my-project", "/tmp/my-script.sh") // run a bash script (with options) on all unix nodes @@ -132,5 +132,5 @@ puts "#{result.succeededJobs.size} jobs successfully imported, #{result.skippedJ h2. And more... -See the API documentation of the [RundeckClient|./apidocs/reference/org/rundeck/api/RundeckClient.html] class for more interactions with your RunDeck instance... +See the API documentation of the [RundeckClient|./apidocs/reference/org/rundeck/api/RundeckClient.html] class for more interactions with your Rundeck instance... diff --git a/src/site/confluence/jython.confluence b/src/site/confluence/jython.confluence index 88019aa..8e8bb0d 100644 --- a/src/site/confluence/jython.confluence +++ b/src/site/confluence/jython.confluence @@ -1,5 +1,5 @@ -h1. Using the RunDeck API from Jython scripts +h1. Using the Rundeck API from Jython scripts Here are some examples of what you can do with this lib and a few lines of [Python|http://www.jython.org/] (for the pythonist that don't fear running on the JVM !) @@ -14,18 +14,18 @@ from org.rundeck.api import RundeckClient rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() -print("RunDeck uptime : %s" % rundeck.systemInfo.uptime) -print("All RunDeck projects : %s" % rundeck.projects) -print("All RunDeck nodes : %s" % rundeck.nodes) -print("All RunDeck jobs : %s" % rundeck.jobs) -print("All RunDeck running executions : %s" % rundeck.runningExecutions) +print("Rundeck uptime : %s" % rundeck.systemInfo.uptime) +print("All Rundeck projects : %s" % rundeck.projects) +print("All Rundeck nodes : %s" % rundeck.nodes) +print("All Rundeck jobs : %s" % rundeck.jobs) +print("All Rundeck running executions : %s" % rundeck.runningExecutions) {code} h2. Authentication -Starting with RunDeck API 2, there are 2 ways to authenticate : +Starting with Rundeck API 2, there are 2 ways to authenticate : * the *login-based authentication* : with your login and password -* the *token-based authentication* : with a unique token that you can generate from the RunDeck webUI +* the *token-based authentication* : with a unique token that you can generate from the Rundeck webUI {code} // using login-based authentication (admin/admin is the default login/password for a new Rundeck instance) : @@ -71,7 +71,7 @@ from org.rundeck.api import NodeFiltersBuilder rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() -// trigger the execution of the "uptime" command on the RunDeck server +// trigger the execution of the "uptime" command on the Rundeck server execution = rundeck.triggerAdhocCommand("my-project", "uptime") // run the "uptime" command on all unix nodes @@ -87,7 +87,7 @@ from org.rundeck.api import NodeFiltersBuilder rundeck = RundeckClient.builder().url("http://localhost:4440").login("admin", "admin").build() -// trigger the execution of a custom bash script on the RunDeck server +// trigger the execution of a custom bash script on the Rundeck server execution = rundeck.triggerAdhocScript("my-project", "/tmp/my-script.sh") // run a bash script (with options) on all unix nodes @@ -116,5 +116,5 @@ print("%s jobs successfully imported, %s jobs skipped, and %s jobs failed" % (re h2. And more... -See the API documentation of the [RundeckClient|./apidocs/reference/org/rundeck/api/RundeckClient.html] class for more interactions with your RunDeck instance... +See the API documentation of the [RundeckClient|./apidocs/reference/org/rundeck/api/RundeckClient.html] class for more interactions with your Rundeck instance... diff --git a/src/site/confluence/status.confluence b/src/site/confluence/status.confluence index 343131c..df82d52 100644 --- a/src/site/confluence/status.confluence +++ b/src/site/confluence/status.confluence @@ -1,9 +1,9 @@ -h1. Status of the implementation of the RunDeck API +h1. Status of the implementation of the Rundeck API -h2. RunDeck API version 1 +h2. Rundeck API version 1 -[Documentation of the RunDeck API version 1|http://rundeck.org/1.2.1/RunDeck-Guide.html#rundeck-api] +[Documentation of the Rundeck API version 1|http://rundeck.org/1.2.1/Rundeck-Guide.html#rundeck-api] * Login-based authentication - OK * System Info - OK @@ -26,67 +26,67 @@ h2. RunDeck API version 1 * Listing Resources - OK * Getting Resource Info - OK -h2. RunDeck API version 2 +h2. Rundeck API version 2 -[Documentation of the RunDeck API version 2|http://rundeck.org/1.3.2/api/index.html] +[Documentation of the Rundeck API version 2|http://rundeck.org/1.3.2/api/index.html] * Token-based authentication - OK * Listing Jobs for a Project - *TODO* * Updating and Listing Resources for a Project - *TODO* * Refreshing Resources for a Project - *TODO* -h2. RunDeck API version 3 +h2. Rundeck API version 3 -[Documentation of the RunDeck API version 3|http://rundeck.org/1.4.2/api/index.html] +[Documentation of the Rundeck API version 3|http://rundeck.org/1.4.2/api/index.html] * (only updates to Resource endpoints) - *TODO* -h2. RunDeck API version 4 +h2. Rundeck API version 4 -[Documentation of the RunDeck API version 4|http://rundeck.org/1.4.3/api/index.html] +[Documentation of the Rundeck API version 4|http://rundeck.org/1.4.3/api/index.html] * Running Adhoc Script URLs - *TODO* -h2. RunDeck API version 5 +h2. Rundeck API version 5 -[Documentation of the RunDeck API version 5|http://rundeck.org/1.4.4/api/index.html] +[Documentation of the Rundeck API version 5|http://rundeck.org/1.4.4/api/index.html] * Bulk Job Delete - OK * Execution Output - OK * Execution Query - OK * History list query - OK -h2. RunDeck API version 6 +h2. Rundeck API version 6 -[Documentation of the RunDeck API version 6|http://rundeck.org/1.5/api/index.html] +[Documentation of the Rundeck API version 6|http://rundeck.org/1.5/api/index.html] * Execution Output format fixed - OK -h2. RunDeck API version 7 +h2. Rundeck API version 7 -[Documentation of the RunDeck API version 7|http://rundeck.org/1.5.3/api/index.html] +[Documentation of the Rundeck API version 7|http://rundeck.org/1.5.3/api/index.html] * Incubator for cluster mode job takeover - *TODO* -h2. RunDeck API version 8 +h2. Rundeck API version 8 -[Documentation of the RunDeck API version 8|http://rundeck.org/1.6.0/api/index.html] +[Documentation of the Rundeck API version 8|http://rundeck.org/1.6.0/api/index.html] * scriptInterpreter addition to run script and run url - OK * project parameter added to jobs import - OK -h2. RunDeck API version 9 +h2. Rundeck API version 9 -[Documentation of the RunDeck API version 9|http://rundeck.org/1.6.1/api/index.html] +[Documentation of the Rundeck API version 9|http://rundeck.org/1.6.1/api/index.html] * list running executions across all projects - OK * include project name in execution results - OK * Add uuidOption parameter to allow removing imported UUIDs to avoid creation conflicts - OK -h2. RunDeck API version 10 +h2. Rundeck API version 10 -[Documentation of the RunDeck API version 10|http://rundeck.org/2.0.0/api/index.html] +[Documentation of the Rundeck API version 10|http://rundeck.org/2.0.0/api/index.html] * Execution State - Retrieve workflow step and node state information - OK * Execution Output with State - Retrieve log output with state change information - OK @@ -95,9 +95,9 @@ h2. RunDeck API version 10 * Deprecation: Remove methods deprecated until version 10. - OK -h2. RunDeck API version 11 +h2. Rundeck API version 11 -[Documentation of the RunDeck API version 11|http://rundeck.org/2.1.0/api/index.html] +[Documentation of the Rundeck API version 11|http://rundeck.org/2.1.0/api/index.html] * Project creation - OK * Get Project configuration - OK @@ -116,7 +116,7 @@ h2. RunDeck API version 11 h2. Rundeck API version 12 -[Documentation of the RunDeck API version 12|http://rundeck.org/2.2.0/api/index.html] +[Documentation of the Rundeck API version 12|http://rundeck.org/2.2.0/api/index.html] * Bulk delete executions - OK * Delete execution - OK diff --git a/src/site/site.xml b/src/site/site.xml index 2e2843a..db7f566 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -28,8 +28,8 @@ - - + + @@ -46,7 +46,7 @@ From a299c12c39cfa6d273f06eb63376661aa50ae4ef Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Tue, 25 Nov 2014 11:04:25 -0800 Subject: [PATCH 33/34] [maven-release-plugin] prepare release rundeck-api-java-client-12.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 15770f2..77fe8b5 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ org.rundeck rundeck-api-java-client - 12.0-SNAPSHOT + 12.0 jar RunDeck API - Java Client Java client for the RunDeck REST API From 4d49ef39bd0dd4812d95e75d3b1282c21ebeb9f4 Mon Sep 17 00:00:00 2001 From: Greg Schueler Date: Tue, 25 Nov 2014 11:04:29 -0800 Subject: [PATCH 34/34] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 77fe8b5..813f635 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ org.rundeck rundeck-api-java-client - 12.0 + 12.1-SNAPSHOT jar RunDeck API - Java Client Java client for the RunDeck REST API