Support keyed config get/set/delete for apiv11

This commit is contained in:
Greg Schueler 2014-03-07 12:22:10 -08:00
parent 29459d9ee1
commit f49aa63043
10 changed files with 430 additions and 0 deletions

View file

@ -26,6 +26,7 @@ import org.rundeck.api.RundeckApiException.RundeckApiTokenException;
import org.rundeck.api.domain.*;
import org.rundeck.api.domain.RundeckExecution.ExecutionStatus;
import org.rundeck.api.generator.ProjectConfigGenerator;
import org.rundeck.api.generator.ProjectConfigPropertyGenerator;
import org.rundeck.api.generator.ProjectGenerator;
import org.rundeck.api.parser.*;
import org.rundeck.api.query.ExecutionQuery;
@ -380,6 +381,92 @@ public class RundeckClient implements Serializable {
return new ApiCall(this)
.get(new ApiPathBuilder("/project/", projectName, "/config"), new ProjectConfigParser("/config"));
}
/**
* Get a single project configuration key
*
* @param projectName name of the project - mandatory
* @param key name of the configuration key
*
* @return value, or null if the value is not set
*
* @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
* @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 projectName is blank (null, empty or whitespace)
*/
public String getProjectConfig(final String projectName, final String key) throws
RundeckApiException, RundeckApiLoginException,
RundeckApiTokenException, IllegalArgumentException {
AssertUtil.notBlank(projectName, "projectName is mandatory to get the config of a project !");
AssertUtil.notBlank(key, "key is mandatory to get the config key value!");
ConfigProperty configProperty = null;
try {
configProperty = new ApiCall(this)
.get(new ApiPathBuilder("/project/", projectName, "/config/", key),
new ProjectConfigPropertyParser("/property"));
} catch (RundeckApiException.RundeckApiHttpStatusException e) {
if(404==e.getStatusCode()){
return null;
}
throw e;
}
return configProperty.getValue();
}
/**
* Set a single project configuration property value
*
* @param projectName name of the project - mandatory
* @param key name of the configuration property
* @param value value of the property
*
* @return new value
*
* @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
* @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 projectName is blank (null, empty or whitespace)
*/
public String setProjectConfig(final String projectName, final String key, final String value) throws
RundeckApiException, RundeckApiLoginException,
RundeckApiTokenException, IllegalArgumentException {
AssertUtil.notBlank(projectName, "projectName is mandatory to set the config of a project !");
AssertUtil.notBlank(key, "key is mandatory to set the config key value!");
AssertUtil.notBlank(value, "value is mandatory to set the config key value!");
final ConfigProperty configProperty = new ApiCall(this)
.put(new ApiPathBuilder("/project/", projectName, "/config/", key)
.xml(new ProjectConfigPropertyGenerator(new ConfigProperty(key, value))),
new ProjectConfigPropertyParser("/property"));
return configProperty.getValue();
}
/**
* Set a single project configuration property value
*
* @param projectName name of the project - mandatory
* @param key name of the configuration property
* @param value value of the property
*
* @return new value
*
* @throws RundeckApiException in case of error when calling the API (non-existent project with this name)
* @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 projectName is blank (null, empty or whitespace)
*/
public void deleteProjectConfig(final String projectName, final String key) throws
RundeckApiException, RundeckApiLoginException,
RundeckApiTokenException, IllegalArgumentException {
AssertUtil.notBlank(projectName, "projectName is mandatory to set the config of a project !");
AssertUtil.notBlank(key, "key is mandatory to set the config key value!");
new ApiCall(this).delete(new ApiPathBuilder("/project/", projectName, "/config/",
key).accept("application/xml"));
}
/**
* Return the configuration of a project
*

View file

@ -0,0 +1,68 @@
package org.rundeck.api.domain;
import java.io.Serializable;
/**
* ConfigProperty is a single configuration property key and value.
*
* @author greg
* @since 2014-03-07
*/
public class ConfigProperty implements Serializable {
private static final long serialVersionUID = 1L;
private String key;
private String value;
public ConfigProperty() {
}
public ConfigProperty(String key, String value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ConfigProperty)) return false;
ConfigProperty that = (ConfigProperty) o;
if (!key.equals(that.key)) return false;
if (!value.equals(that.value)) return false;
return true;
}
@Override
public int hashCode() {
int result = key.hashCode();
result = 31 * result + value.hashCode();
return result;
}
@Override
public String toString() {
return "ConfigProperty{" +
"key='" + key + '\'' +
", value='" + value + '\'' +
'}';
}
}

View file

@ -0,0 +1,28 @@
package org.rundeck.api.generator;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.rundeck.api.domain.ConfigProperty;
/**
* ProjectConfigPropertyGenerator generates a {@literal <property/>} element representing a configuration property.
*
* @author greg
* @since 2014-03-07
*/
public class ProjectConfigPropertyGenerator extends BaseDocGenerator {
private ConfigProperty property;
public ProjectConfigPropertyGenerator(ConfigProperty property) {
this.property = property;
}
@Override
public Element generateXmlElement() {
Element propElem = DocumentFactory.getInstance().createElement("property");
propElem.addAttribute("key", property.getKey());
propElem.addAttribute("value", property.getValue());
return propElem;
}
}

View file

@ -0,0 +1,41 @@
package org.rundeck.api.parser;
import org.dom4j.Node;
import org.rundeck.api.domain.ConfigProperty;
/**
* ProjectConfigPropertyParser parses a {@literal <property/>} element representing
* a configuration property.
*
* @author greg
* @since 2014-03-07
*/
public class ProjectConfigPropertyParser implements XmlNodeParser<ConfigProperty> {
private String xpath;
public ProjectConfigPropertyParser() {
}
public ProjectConfigPropertyParser(final String xpath) {
this.setXpath(xpath);
}
@Override
public ConfigProperty parseXmlNode(final Node node) {
final Node propnode = getXpath() != null ? node.selectSingleNode(getXpath()) : node;
final String key = propnode.valueOf("@key");
final String value = propnode.valueOf("@value");
final ConfigProperty config = new ConfigProperty();
config.setKey(key);
config.setValue(value);
return config;
}
public String getXpath() {
return xpath;
}
public void setXpath(final String xpath) {
this.xpath = xpath;
}
}

View file

@ -116,6 +116,35 @@ public class RundeckClientTest {
Assert.assertEquals("a big amazing thingy so there.", result.getProperties().get("blha.blee"));
}
@Test
@Betamax(tape = "get_project_config_keyedv11")
public void getProjectConfigKeyed() throws Exception {
String value = createClient(TEST_TOKEN_6, 11).getProjectConfig("ABC", "project.name");
Assert.assertNotNull(value);
Assert.assertEquals("ABC", value);
}
@Test
@Betamax(tape = "get_project_config_keyed_dne_v11")
public void getProjectConfigKeyedDNE() throws Exception {
String value = createClient(TEST_TOKEN_6, 11).getProjectConfig("ABC", "does-not-exist");
Assert.assertNull(value);
}
@Test
@Betamax(tape = "set_project_config_keyedv11")
public void setProjectConfigKeyed() throws Exception {
String value = createClient(TEST_TOKEN_6, 11).setProjectConfig("ABC", "monkey-burrito", "lemon pie");
Assert.assertNotNull(value);
Assert.assertEquals("lemon pie", value);
}
@Test
@Betamax(tape = "delete_project_config_keyedv11")
public void deleteProjectConfigKeyed() throws Exception {
RundeckClient client1 = createClient(TEST_TOKEN_6, 11);
Assert.assertEquals("7up", client1.setProjectConfig("ABC", "monkey-burrito", "7up"));
client1.deleteProjectConfig("ABC", "monkey-burrito");
String value=client1.getProjectConfig("ABC", "monkey-burrito");
Assert.assertNull(value);
}
@Test
@Betamax(tape = "get_history")
public void getHistory() throws Exception {

View file

@ -0,0 +1,48 @@
package org.rundeck.api.parser;
import junit.framework.Assert;
import org.dom4j.Document;
import org.junit.Test;
import org.junit.runners.JUnit4;
import org.rundeck.api.domain.ConfigProperty;
import org.rundeck.api.domain.ProjectConfig;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
/**
* Test
*
* @author greg
* @since 2014-03-07
*/
public class ProjectConfigPropertyParserTest {
@Test
public void parseFromProject() throws Exception {
InputStream input = getClass().getResourceAsStream("projectv11.xml");
Document document = ParserHelper.loadDocument(input);
ConfigProperty config = new ProjectConfigPropertyParser("project/config/property[1]").parseXmlNode(document);
Assert.assertEquals("project.name", config.getKey());
Assert.assertEquals("ziggy", config.getValue());
/**
* <property key='project.name' value='ziggy'/>
<property key='resources.source.1.config.requireFileExists' value='false'/>
*/
}
@Test
public void parseProperty() throws Exception {
Document document = ParserHelper.loadDocument(new ByteArrayInputStream(("<property key='project.name' " +
"value='ABC' />").getBytes()));
ConfigProperty config = new ProjectConfigPropertyParser("/property").parseXmlNode(document);
Assert.assertEquals("project.name", config.getKey());
Assert.assertEquals("ABC", config.getValue());
/**
* <property key='project.name' value='ziggy'/>
<property key='resources.source.1.config.requireFileExists' value='false'/>
*/
}
}

View file

@ -0,0 +1,57 @@
!tape
name: delete_project_config_keyedv11
interactions:
- recorded: 2014-03-07T19:59:51.228Z
request:
method: PUT
uri: http://rundeck.local:4440/api/11/project/ABC/config/monkey-burrito
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 11
X-RunDeck-Auth-Token: Do4d3NUD5DKk21DR4sNK755RcPk618vn
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=bolnwf54stai1bo049hylrsua;Path=/
X-Rundeck-API-Version: '11'
X-Rundeck-API-XML-Response-Wrapper: 'false'
body: !!binary |-
PHByb3BlcnR5IGtleT0nbW9ua2V5LWJ1cnJpdG8nIHZhbHVlPSc3dXAnIC8+
- recorded: 2014-03-07T19:59:51.325Z
request:
method: DELETE
uri: http://rundeck.local:4440/api/11/project/ABC/config/monkey-burrito
headers:
Host: rundeck.local:4440
Proxy-Connection: Keep-Alive
User-Agent: RunDeck API Java Client 11
X-RunDeck-Auth-Token: Do4d3NUD5DKk21DR4sNK755RcPk618vn
response:
status: 204
headers:
Content-Type: text/html;charset=UTF-8
Server: Jetty(7.6.0.v20120127)
- recorded: 2014-03-07T19:59:51.402Z
request:
method: GET
uri: http://rundeck.local:4440/api/11/project/ABC/config/monkey-burrito
headers:
Accept: text/xml
Host: rundeck.local:4440
Proxy-Connection: Keep-Alive
User-Agent: RunDeck API Java Client 11
X-RunDeck-Auth-Token: Do4d3NUD5DKk21DR4sNK755RcPk618vn
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>property does not exist: monkey-burrito</message>\n </error>\n</result>"

View file

@ -0,0 +1,22 @@
!tape
name: get_project_config_keyed_dne_v11
interactions:
- recorded: 2014-03-07T20:19:47.533Z
request:
method: GET
uri: http://rundeck.local:4440/api/11/project/ABC/config/does-not-exist
headers:
Accept: text/xml
Host: rundeck.local:4440
Proxy-Connection: Keep-Alive
User-Agent: RunDeck API Java Client 11
X-RunDeck-Auth-Token: Do4d3NUD5DKk21DR4sNK755RcPk618vn
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=2367tnltmmec14cn79ps4fam9;Path=/
X-Rundeck-API-Version: '11'
body: "<result error='true' apiversion='11'>\n <error code='api.error.item.doesnotexist'>\n <message>property does not exist: does-not-exist</message>\n </error>\n</result>"

View file

@ -0,0 +1,24 @@
!tape
name: get_project_config_keyedv11
interactions:
- recorded: 2014-03-07T19:50:29.035Z
request:
method: GET
uri: http://rundeck.local:4440/api/11/project/ABC/config/project.name
headers:
Accept: text/xml
Host: rundeck.local:4440
Proxy-Connection: Keep-Alive
User-Agent: RunDeck API Java Client 11
X-RunDeck-Auth-Token: Do4d3NUD5DKk21DR4sNK755RcPk618vn
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=jgign9nyxeyp4istq65l86lp;Path=/
X-Rundeck-API-Version: '11'
X-Rundeck-API-XML-Response-Wrapper: 'false'
body: !!binary |-
PHByb3BlcnR5IGtleT0ncHJvamVjdC5uYW1lJyB2YWx1ZT0nQUJDJyAvPg==

View file

@ -0,0 +1,26 @@
!tape
name: set_project_config_keyedv11
interactions:
- recorded: 2014-03-07T19:59:51.009Z
request:
method: PUT
uri: http://rundeck.local:4440/api/11/project/ABC/config/monkey-burrito
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 11
X-RunDeck-Auth-Token: Do4d3NUD5DKk21DR4sNK755RcPk618vn
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=3ssp8chdwsuw16hihk5frgpzy;Path=/
X-Rundeck-API-Version: '11'
X-Rundeck-API-XML-Response-Wrapper: 'false'
body: !!binary |-
PHByb3BlcnR5IGtleT0nbW9ua2V5LWJ1cnJpdG8nIHZhbHVlPSdsZW1vbiBwaWUnIC8+