mirror of https://github.com/apache/jclouds.git
JCLOUDS-1072: Add support for environment-specific run lists to Role
This commit is contained in:
parent
2bd0550110
commit
27b3a844f8
|
@ -20,14 +20,18 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty;
|
||||
|
||||
import java.beans.ConstructorProperties;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.domain.JsonBall;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
|
@ -44,6 +48,10 @@ public class Role {
|
|||
private ImmutableMap.Builder<String, JsonBall> overrideAttributes = ImmutableMap.builder();
|
||||
private ImmutableMap.Builder<String, JsonBall> defaultAttributes = ImmutableMap.builder();
|
||||
private ImmutableList.Builder<String> runList = ImmutableList.builder();
|
||||
// envRunList is a nested set of collections. The Immutable* classes in google collections don't appear to
|
||||
// support this nested immutability, so the builder will utilize native collections as the envRunList is
|
||||
// assembled. An immutable, nested map of collections will be assembled in the build() method.
|
||||
private Map<String, List<String>> envRunList = new HashMap<String, List<String>>();
|
||||
|
||||
public Builder name(String name) {
|
||||
this.name = checkNotNull(name, "name");
|
||||
|
@ -85,8 +93,40 @@ public class Role {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder envRunList(Map<String, List<String>> envRunList) {
|
||||
this.envRunList.putAll(checkNotNull(envRunList, "envRunList"));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder envRunList(String name, List<String> runList) {
|
||||
this.envRunList.put(checkNotNull(name, "name"), checkNotNull(runList, "runList"));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder envRunListElement(String name, String value) {
|
||||
checkNotNull(name, "name");
|
||||
checkNotNull(value, "value");
|
||||
List<String> runList = this.envRunList.get(name);
|
||||
if (runList == null) {
|
||||
runList = new ArrayList<String>();
|
||||
this.envRunList.put(name, runList);
|
||||
}
|
||||
runList.add(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Role build() {
|
||||
return new Role(name, description, defaultAttributes.build(), runList.build(), overrideAttributes.build());
|
||||
// Assemble an immutable envRunList where each entry is an immutable list of entries.
|
||||
Map<String, List<String>> immutableEnvRunList = Maps.transformValues(envRunList,
|
||||
new Function<List<String>, List<String>>() {
|
||||
@Override
|
||||
public List<String> apply(List<String> input) {
|
||||
return ImmutableList.copyOf(input);
|
||||
}
|
||||
});
|
||||
|
||||
return new Role(name, description, defaultAttributes.build(), runList.build(), overrideAttributes.build(),
|
||||
immutableEnvRunList);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,6 +138,8 @@ public class Role {
|
|||
private final Map<String, JsonBall> defaultAttributes;
|
||||
@SerializedName("run_list")
|
||||
private final List<String> runList;
|
||||
@SerializedName("env_run_lists")
|
||||
private Map<String, List<String>> envRunList;
|
||||
|
||||
// internal
|
||||
@SerializedName("json_class")
|
||||
|
@ -105,14 +147,17 @@ public class Role {
|
|||
@SerializedName("chef_type")
|
||||
private final String _chefType = "role";
|
||||
|
||||
@ConstructorProperties({ "name", "description", "default_attributes", "run_list", "override_attributes" })
|
||||
@ConstructorProperties({ "name", "description", "default_attributes", "run_list", "override_attributes",
|
||||
"env_run_lists" })
|
||||
protected Role(String name, String description, @Nullable Map<String, JsonBall> defaultAttributes,
|
||||
@Nullable List<String> runList, @Nullable Map<String, JsonBall> overrideAttributes) {
|
||||
@Nullable List<String> runList, @Nullable Map<String, JsonBall> overrideAttributes,
|
||||
@Nullable Map<String, List<String>> envRunList) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.defaultAttributes = copyOfOrEmpty(defaultAttributes);
|
||||
this.runList = copyOfOrEmpty(runList);
|
||||
this.overrideAttributes = copyOfOrEmpty(overrideAttributes);
|
||||
this.envRunList = envRunList;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
@ -135,6 +180,10 @@ public class Role {
|
|||
return runList;
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getEnvRunList() {
|
||||
return envRunList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
|
@ -146,6 +195,7 @@ public class Role {
|
|||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + ((overrideAttributes == null) ? 0 : overrideAttributes.hashCode());
|
||||
result = prime * result + ((runList == null) ? 0 : runList.hashCode());
|
||||
result = prime * result + ((envRunList == null) ? 0 : envRunList.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -193,13 +243,19 @@ public class Role {
|
|||
return false;
|
||||
} else if (!runList.equals(other.runList))
|
||||
return false;
|
||||
if (envRunList == null) {
|
||||
if (other.envRunList != null)
|
||||
return false;
|
||||
} else if (!envRunList.equals(other.envRunList))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Role [name=" + name + ", description=" + description + ", defaultAttributes=" + defaultAttributes
|
||||
+ ", overrideAttributes=" + overrideAttributes + ", runList=" + runList + "]";
|
||||
+ ", overrideAttributes=" + overrideAttributes + ", runList=" + runList
|
||||
+ ", envRunList=" + this.envRunList + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import static com.google.common.collect.Iterables.any;
|
|||
import static com.google.common.collect.Iterables.isEmpty;
|
||||
import static com.google.common.hash.Hashing.md5;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static org.jclouds.chef.domain.RoleTest.verifyRunListForEnvironment;
|
||||
import static org.jclouds.util.Closeables2.closeQuietly;
|
||||
import static org.jclouds.util.Predicates2.retry;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
@ -243,12 +244,27 @@ public class ChefApiLiveTest extends BaseChefLiveTest {
|
|||
|
||||
@Test
|
||||
public void testCreateRole() throws Exception {
|
||||
String env1 = "env1";
|
||||
String env2 = "env2";
|
||||
String env1Alpha = "env1.alpha";
|
||||
String env2Alpha = "env2.alpha";
|
||||
String env2Bravo = "env2.bravo";
|
||||
|
||||
api.deleteRole(PREFIX);
|
||||
api.createRole(Role.builder().name(PREFIX).runListElement("recipe[java]").build());
|
||||
api.createRole(Role.builder().name(PREFIX).runListElement("recipe[java]")
|
||||
.envRunListElement(env1, env1Alpha)
|
||||
.envRunListElement(env2, env2Alpha)
|
||||
.envRunListElement(env2, env2Bravo)
|
||||
.build());
|
||||
Role role = api.getRole(PREFIX);
|
||||
assertNotNull(role, "Created role should not be null");
|
||||
assertEquals(role.getName(), PREFIX);
|
||||
assertEquals(role.getRunList(), Collections.singleton("recipe[java]"));
|
||||
|
||||
assertNotNull(role.getEnvRunList(), "envRunList should not be null");
|
||||
assertEquals(role.getEnvRunList().size(), 2, "envRunList.size should be 2");
|
||||
verifyRunListForEnvironment(role.getEnvRunList(), env1, env1Alpha);
|
||||
verifyRunListForEnvironment(role.getEnvRunList(), env2, env2Alpha, env2Bravo);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testCreateRole")
|
||||
|
|
|
@ -357,13 +357,18 @@ public class ChefApiTest extends BaseRestAnnotationProcessingTest<ChefApi> {
|
|||
public void testCreateRole() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(ChefApi.class, "createRole", Role.class);
|
||||
GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method,
|
||||
ImmutableList.<Object> of(Role.builder().name("testrole").runListElement("recipe[java]").build())));
|
||||
ImmutableList.<Object> of(Role.builder().name("testrole").runListElement("recipe[java]")
|
||||
.envRunListElement("erl.one", "erl.one.alpha")
|
||||
.envRunListElement("erl.one", "erl.one.bravo")
|
||||
.envRunListElement("erl.two", "erl.two.alpha")
|
||||
.envRunListElement("erl.two", "erl.two.bravo")
|
||||
.build())));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "POST http://localhost:4000/roles HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION
|
||||
+ "-test\n");
|
||||
assertPayloadEquals(httpRequest, "{\"name\":\"testrole\",\"override_attributes\":{},\"default_attributes\":{},"
|
||||
+ "\"run_list\":[\"recipe[java]\"],\"json_class\":\"Chef::Role\",\"chef_type\":\"role\"}",
|
||||
+ "\"run_list\":[\"recipe[java]\"],\"env_run_lists\":{\"erl.one\":[\"erl.one.alpha\",\"erl.one.bravo\"],\"erl.two\":[\"erl.two.alpha\",\"erl.two.bravo\"]},\"json_class\":\"Chef::Role\",\"chef_type\":\"role\"}",
|
||||
"application/json", false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class);
|
||||
|
@ -377,13 +382,18 @@ public class ChefApiTest extends BaseRestAnnotationProcessingTest<ChefApi> {
|
|||
public void testUpdateRole() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Invokable<?, ?> method = method(ChefApi.class, "updateRole", Role.class);
|
||||
GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method,
|
||||
ImmutableList.<Object> of(Role.builder().name("testrole").runListElement("recipe[java]").build())));
|
||||
ImmutableList.<Object> of(Role.builder().name("testrole").runListElement("recipe[java]")
|
||||
.envRunListElement("erl.one", "erl.one.alpha")
|
||||
.envRunListElement("erl.one", "erl.one.bravo")
|
||||
.envRunListElement("erl.two", "erl.two.alpha")
|
||||
.envRunListElement("erl.two", "erl.two.bravo")
|
||||
.build())));
|
||||
|
||||
assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/roles/testrole HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION
|
||||
+ "-test\n");
|
||||
assertPayloadEquals(httpRequest, "{\"name\":\"testrole\",\"override_attributes\":{},\"default_attributes\":{},"
|
||||
+ "\"run_list\":[\"recipe[java]\"],\"json_class\":\"Chef::Role\",\"chef_type\":\"role\"}",
|
||||
+ "\"run_list\":[\"recipe[java]\"],\"env_run_lists\":{\"erl.one\":[\"erl.one.alpha\",\"erl.one.bravo\"],\"erl.two\":[\"erl.two.alpha\",\"erl.two.bravo\"]},\"json_class\":\"Chef::Role\",\"chef_type\":\"role\"}",
|
||||
"application/json", false);
|
||||
|
||||
assertResponseParserClassEquals(method, httpRequest, ParseJson.class);
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jclouds.chef.domain;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertNotEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Tests behaviors of {@code Role}.
|
||||
*/
|
||||
@Test(groups = { "unit" })
|
||||
public class RoleTest {
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void canNotAddEnvRunListMapThatIsNull() {
|
||||
Role.builder().envRunList((Map<String, List<String>>) null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void canNotAddRunListForEnvironmentThatIsNull() {
|
||||
Role.builder().envRunList("does.not.matter", (List<String>) null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void canNotUseNullEnvNameWhenAddingEnvRunListEntry() {
|
||||
Role.builder().envRunListElement((String) null, "does.not.matter");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void canNotUseNullEntryWhenAddingEnvRunListEntry() {
|
||||
Role.builder().envRunListElement("does.not.matter", (String) null);
|
||||
}
|
||||
|
||||
public void multipleEnvRunListsCanBePopulated() {
|
||||
String env1 = "env1";
|
||||
String env2 = "env2";
|
||||
String env1Alpha = "env1.alpha";
|
||||
String env2Alpha = "env2.alpha";
|
||||
String env2Bravo = "env2.bravo";
|
||||
Role role = Role.builder().envRunListElement(env1, env1Alpha).envRunListElement(env2, env2Alpha)
|
||||
.envRunListElement(env2, env2Bravo).build();
|
||||
Map<String, List<String>> envRunList = role.getEnvRunList();
|
||||
assertNotNull(envRunList, "envRunList");
|
||||
assertEquals(envRunList.size(), 2, "envRunList.size");
|
||||
|
||||
verifyRunListForEnvironment(envRunList, env1, env1Alpha);
|
||||
verifyRunListForEnvironment(envRunList, env2, env2Alpha, env2Bravo);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
||||
public void envRunListOnNewlyBuiltRoleIsImmutable() {
|
||||
String env = "env";
|
||||
Role role = Role.builder().envRunListElement(env, env + "1").build();
|
||||
role.getEnvRunList().put("does.not.matter", new ArrayList<String>());
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
||||
public void envRunListEntriesOnNewlyBuiltRoleIsImmutable() {
|
||||
String env = "env";
|
||||
Role role = Role.builder().envRunListElement(env, env + "1").build();
|
||||
role.getEnvRunList().get(env).add("does.not.matter");
|
||||
}
|
||||
|
||||
public void rolesWithSameEnvRunListAreEqual() {
|
||||
String env = "env";
|
||||
String entry = "entry";
|
||||
|
||||
Role role1 = Role.builder().envRunListElement(env, entry).build();
|
||||
Role role2 = Role.builder().envRunListElement(env, entry).build();
|
||||
|
||||
assertEquals(role1.hashCode(), role2.hashCode(), "hashCodes should be equal");
|
||||
assertEquals(role1, role2, "role1 should equal role2");
|
||||
assertEquals(role2, role1, "role2 should equal role1");
|
||||
}
|
||||
|
||||
public void rolesWithDifferentEnvRunListAreNotEqual() {
|
||||
String env = "env";
|
||||
String entry = "entry";
|
||||
|
||||
Role role1 = Role.builder().envRunListElement(env, entry.toUpperCase()).build();
|
||||
Role role2 = Role.builder().envRunListElement(env, entry.toLowerCase()).build();
|
||||
|
||||
assertNotEquals(role1.hashCode(), role2.hashCode(), "hashCodes should not be equal");
|
||||
assertNotEquals(role1, role2, "role1 should not equal role2");
|
||||
assertNotEquals(role2, role1, "role2 should not equal role1");
|
||||
}
|
||||
|
||||
public static void verifyRunListForEnvironment(Map<String, List<String>> envRunList, String envName,
|
||||
String... expectedEntries) {
|
||||
assertTrue(envRunList.containsKey(envName), "envRunList contains " + envName);
|
||||
assertEquals(envRunList.get(envName).size(), expectedEntries.length, "envRunList size for '" + envName);
|
||||
assertTrue(envRunList.get(envName).containsAll(Arrays.asList(expectedEntries)), "envRunList for e1 contains "
|
||||
+ Arrays.asList(expectedEntries));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue