Support API token endpoint (v11)

This commit is contained in:
Greg Schueler 2014-04-04 11:41:09 -07:00
parent 0cb3da88ec
commit 0f8e338719
9 changed files with 350 additions and 0 deletions

View file

@ -2310,6 +2310,70 @@ public class RundeckClient implements Serializable {
return new ApiCall(this).get(new ApiPathBuilder("/system/info"), new SystemInfoParser(rootXpath()+"/system")); return new ApiCall(this).get(new ApiPathBuilder("/system/info"), new SystemInfoParser(rootXpath()+"/system"));
} }
/*
* API token
*/
/**
* List API tokens for a user.
* @param user username
* @return list of tokens
* @throws RundeckApiException
*/
public List<RundeckToken> listApiTokens(final String user) throws RundeckApiException {
AssertUtil.notNull(user, "user is mandatory to list API tokens for a user.");
return new ApiCall(this).
get(new ApiPathBuilder("/tokens/", user),
new ListParser<RundeckToken>(new RundeckTokenParser(), "/tokens/token"));
}
/**
* List all API tokens
* @return list of tokens
* @throws RundeckApiException
*/
public List<RundeckToken> listApiTokens() throws RundeckApiException {
return new ApiCall(this).
get(new ApiPathBuilder("/tokens"),
new ListParser<RundeckToken>(new RundeckTokenParser(), "/tokens/token"));
}
/**
* Generate an API token for a user.
* @param user
* @return
* @throws RundeckApiException
*/
public String generateApiToken(final String user) throws RundeckApiException{
AssertUtil.notNull(user, "user is mandatory to generate an API token for a user.");
RundeckToken result = new ApiCall(this).
post(new ApiPathBuilder("/tokens/", user).emptyContent(),
new RundeckTokenParser("/token"));
return result.getToken();
}
/**
* Delete an existing token
* @param token
* @return
* @throws RundeckApiException
*/
public boolean deleteApiToken(final String token) throws RundeckApiException{
AssertUtil.notNull(token, "token is mandatory to delete an API token.");
new ApiCall(this).delete(new ApiPathBuilder("/token/", token));
return true;
}
/**
* Return user info for an existing token
* @param token
* @return token info
* @throws RundeckApiException
*/
public RundeckToken getApiToken(final String token) throws RundeckApiException{
AssertUtil.notNull(token, "token is mandatory to get an API token.");
return new ApiCall(this).get(new ApiPathBuilder("/token/", token), new RundeckTokenParser("/token"));
}
/** /**
* @return the URL of the RunDeck instance ("http://localhost:4440", "http://rundeck.your-compagny.com/", etc) * @return the URL of the RunDeck instance ("http://localhost:4440", "http://rundeck.your-compagny.com/", etc)
*/ */

View file

@ -0,0 +1,36 @@
package org.rundeck.api.domain;
/**
* RundeckToken is ...
*
* @author Greg Schueler <greg@simplifyops.com>
* @since 2014-04-04
*/
public class RundeckToken {
private String user;
private String token;
public RundeckToken() {
}
public RundeckToken(String user, String token) {
this.setUser(user);
this.setToken(token);
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}

View file

@ -0,0 +1,33 @@
package org.rundeck.api.parser;
import org.dom4j.Node;
import org.rundeck.api.domain.RundeckToken;
/**
* RundeckTokenParser is ...
*
* @author Greg Schueler <greg@simplifyops.com>
* @since 2014-04-04
*/
public class RundeckTokenParser implements XmlNodeParser<RundeckToken> {
String xpath;
public RundeckTokenParser() {
}
public RundeckTokenParser(String xpath) {
this.xpath = xpath;
}
@Override
public RundeckToken parseXmlNode(Node node) {
Node targetNode = xpath != null ? node.selectSingleNode(xpath) : node;
RundeckToken rundeckToken = new RundeckToken();
String token = targetNode.valueOf("@id");
String user = targetNode.valueOf("@user");
rundeckToken.setToken(token);
rundeckToken.setUser(user);
return rundeckToken;
}
}

View file

@ -55,6 +55,7 @@ public class RundeckClientTest {
public static final String TEST_TOKEN_4 = "sN5RRSNvu15DnV6EcNDdc2CkdPcv3s32"; public static final String TEST_TOKEN_4 = "sN5RRSNvu15DnV6EcNDdc2CkdPcv3s32";
public static final String TEST_TOKEN_5 = "C3O6d5O98Kr6Dpv71sdE4ERdCuU12P6d"; public static final String TEST_TOKEN_5 = "C3O6d5O98Kr6Dpv71sdE4ERdCuU12P6d";
public static final String TEST_TOKEN_6 = "Do4d3NUD5DKk21DR4sNK755RcPk618vn"; public static final String TEST_TOKEN_6 = "Do4d3NUD5DKk21DR4sNK755RcPk618vn";
public static final String TEST_TOKEN_7 = "8Dp9op111ER6opsDRkddvE86K9sE499s";
@Rule @Rule
public Recorder recorder = new Recorder(); public Recorder recorder = new Recorder();
@ -1197,6 +1198,89 @@ public class RundeckClientTest {
Assert.assertEquals(RundeckWFExecState.SUCCEEDED,output.getExecutionState()); Assert.assertEquals(RundeckWFExecState.SUCCEEDED,output.getExecutionState());
} }
/**
* generate api token
*/
@Test
@Betamax(tape = "api_token_generate", mode = TapeMode.READ_ONLY)
public void generateApiToken() throws Exception {
final RundeckClient client = createClient(TEST_TOKEN_7, 11);
String token = client.generateApiToken("bob");
Assert.assertNotNull(token);
Assert.assertEquals("MiquQjELTrEaugpmdgAKs1W3a7xonAwU", token);
}
/**
* get api token
*/
@Test
@Betamax(tape = "api_token_get", mode = TapeMode.READ_ONLY)
public void getApiToken() throws Exception {
final RundeckClient client = createClient(TEST_TOKEN_7, 11);
RundeckToken token = client.getApiToken("MiquQjELTrEaugpmdgAKs1W3a7xonAwU");
Assert.assertNotNull(token);
Assert.assertEquals("MiquQjELTrEaugpmdgAKs1W3a7xonAwU", token.getToken());
Assert.assertEquals("bob", token.getUser());
}
/**
* list api tokens for user
*/
@Test
@Betamax(tape = "api_tokens_list_user", mode = TapeMode.READ_ONLY)
public void listApiTokens_user() throws Exception {
final RundeckClient client = createClient(TEST_TOKEN_7, 11);
List<RundeckToken> tokens = client.listApiTokens("bob");
Assert.assertNotNull(tokens);
Assert.assertEquals(3, tokens.size());
Assert.assertEquals("hINp5eGzvYA9UePbUChaKHd5NiRkwWbx", tokens.get(0).getToken());
Assert.assertEquals("bob", tokens.get(0).getUser());
Assert.assertEquals("NaNnwVzAHAG83qOS7Wtwh6mjcXViyWUV", tokens.get(1).getToken());
Assert.assertEquals("bob", tokens.get(1).getUser());
Assert.assertEquals("MiquQjELTrEaugpmdgAKs1W3a7xonAwU", tokens.get(2).getToken());
Assert.assertEquals("bob", tokens.get(2).getUser());
}
/**
* list api tokens all
*/
@Test
@Betamax(tape = "api_tokens_list_all"/*, mode = TapeMode.READ_ONLY*/)
public void listApiTokens() throws Exception {
final RundeckClient client = createClient(TEST_TOKEN_7, 11);
List<RundeckToken> tokens = client.listApiTokens();
Assert.assertNotNull(tokens);
Assert.assertEquals(4, tokens.size());
Assert.assertEquals("8Dp9op111ER6opsDRkddvE86K9sE499s", tokens.get(0).getToken());
Assert.assertEquals("admin", tokens.get(0).getUser());
Assert.assertEquals("hINp5eGzvYA9UePbUChaKHd5NiRkwWbx", tokens.get(1).getToken());
Assert.assertEquals("bob", tokens.get(1).getUser());
Assert.assertEquals("NaNnwVzAHAG83qOS7Wtwh6mjcXViyWUV", tokens.get(2).getToken());
Assert.assertEquals("bob", tokens.get(2).getUser());
Assert.assertEquals("MiquQjELTrEaugpmdgAKs1W3a7xonAwU", tokens.get(3).getToken());
Assert.assertEquals("bob", tokens.get(3).getUser());
}
/**
* get api token
*/
@Test
@Betamax(tape = "api_token_delete"/*, mode = TapeMode.READ_ONLY*/)
public void deleteApiToken() throws Exception {
final RundeckClient client = createClient(TEST_TOKEN_7, 11);
client.deleteApiToken("MiquQjELTrEaugpmdgAKs1W3a7xonAwU");
//get should now return 404
try {
client.getApiToken("MiquQjELTrEaugpmdgAKs1W3a7xonAwU");
Assert.fail("expected failure");
} catch (RundeckApiException.RundeckApiHttpStatusException e) {
Assert.assertEquals(404, e.getStatusCode());
}
}
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
// not that you can put whatever here, because we don't actually connect to the RunDeck instance // not that you can put whatever here, because we don't actually connect to the RunDeck instance

View file

@ -0,0 +1,36 @@
!tape
name: api_token_delete
interactions:
- recorded: 2014-04-04T18:38:18.432Z
request:
method: DELETE
uri: http://rundeck.local:4440/api/11/token/MiquQjELTrEaugpmdgAKs1W3a7xonAwU
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=j0fidhqqsmlt1qmvaawr52a42;Path=/
- recorded: 2014-04-04T18:38:18.523Z
request:
method: GET
uri: http://rundeck.local:4440/api/11/token/MiquQjELTrEaugpmdgAKs1W3a7xonAwU
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: 404
headers:
Content-Type: text/xml;charset=UTF-8
Server: Jetty(7.6.0.v20120127)
X-Rundeck-API-Version: '11'
body: "<result error='true' apiversion='11'>\n <error code='api.error.item.doesnotexist'>\n <message>Token does not exist: MiquQjELTrEaugpmdgAKs1W3a7xonAwU</message>\n </error>\n</result>"

View file

@ -0,0 +1,25 @@
!tape
name: api_token_generate
interactions:
- recorded: 2014-04-04T18:21:07.759Z
request:
method: POST
uri: http://rundeck.local:4440/api/11/tokens/bob
headers:
Accept: text/xml
Content-Length: '0'
Host: rundeck.local:4440
Proxy-Connection: Keep-Alive
User-Agent: RunDeck API Java Client 11
X-RunDeck-Auth-Token: 8Dp9op111ER6opsDRkddvE86K9sE499s
response:
status: 201
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=1gt9t2gch2zff1a0werz1us5wk;Path=/
X-Rundeck-API-Version: '11'
X-Rundeck-API-XML-Response-Wrapper: 'false'
body: !!binary |-
PHRva2VuIGlkPSdNaXF1UWpFTFRyRWF1Z3BtZGdBS3MxVzNhN3hvbkF3VScgdXNlcj0nYm9iJyAvPg==

View file

@ -0,0 +1,24 @@
!tape
name: api_token_get
interactions:
- recorded: 2014-04-04T18:23:05.986Z
request:
method: GET
uri: http://rundeck.local:4440/api/11/token/MiquQjELTrEaugpmdgAKs1W3a7xonAwU
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=1tdpszk6b3v191p0ng2u94rohw;Path=/
X-Rundeck-API-Version: '11'
X-Rundeck-API-XML-Response-Wrapper: 'false'
body: !!binary |-
PHRva2VuIGlkPSdNaXF1UWpFTFRyRWF1Z3BtZGdBS3MxVzNhN3hvbkF3VScgdXNlcj0nYm9iJyAvPg==

View file

@ -0,0 +1,24 @@
!tape
name: api_tokens_list_all
interactions:
- recorded: 2014-04-04T18:32:37.397Z
request:
method: GET
uri: http://rundeck.local:4440/api/11/tokens
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=ixag173yjktz1c5o9yrbe5z5a;Path=/
X-Rundeck-API-Version: '11'
X-Rundeck-API-XML-Response-Wrapper: 'false'
body: !!binary |-
PHRva2VucyBjb3VudD0nNCcgYWxsdXNlcnM9J3RydWUnPgogIDx0b2tlbiBpZD0nOERwOW9wMTExRVI2b3BzRFJrZGR2RTg2SzlzRTQ5OXMnIHVzZXI9J2FkbWluJyAvPgogIDx0b2tlbiBpZD0naElOcDVlR3p2WUE5VWVQYlVDaGFLSGQ1TmlSa3dXYngnIHVzZXI9J2JvYicgLz4KICA8dG9rZW4gaWQ9J05hTm53VnpBSEFHODNxT1M3V3R3aDZtamNYVml5V1VWJyB1c2VyPSdib2InIC8+CiAgPHRva2VuIGlkPSdNaXF1UWpFTFRyRWF1Z3BtZGdBS3MxVzNhN3hvbkF3VScgdXNlcj0nYm9iJyAvPgo8L3Rva2Vucz4=

View file

@ -0,0 +1,24 @@
!tape
name: api_tokens_list_user
interactions:
- recorded: 2014-04-04T18:26:33.394Z
request:
method: GET
uri: http://rundeck.local:4440/api/11/tokens/bob
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=114794elwavo26cx4ugkv7pe7;Path=/
X-Rundeck-API-Version: '11'
X-Rundeck-API-XML-Response-Wrapper: 'false'
body: !!binary |-
PHRva2VucyBjb3VudD0nMycgdXNlcj0nYm9iJz4KICA8dG9rZW4gaWQ9J2hJTnA1ZUd6dllBOVVlUGJVQ2hhS0hkNU5pUmt3V2J4JyB1c2VyPSdib2InIC8+CiAgPHRva2VuIGlkPSdOYU5ud1Z6QUhBRzgzcU9TN1d0d2g2bWpjWFZpeVdVVicgdXNlcj0nYm9iJyAvPgogIDx0b2tlbiBpZD0nTWlxdVFqRUxUckVhdWdwbWRnQUtzMVczYTd4b25Bd1UnIHVzZXI9J2JvYicgLz4KPC90b2tlbnM+