Issue #30 Add support for Group api in Hosted Chef

Adds support for the Group api in Hosted Chef. CRUD operations and the
management of the members of the group are now available.

Also cleaned up Private Chef, and will leave only those methods that are
proven to work and have a working live test.
This commit is contained in:
Ignasi Barrera 2012-12-09 19:39:36 +01:00
parent 41f671e1fa
commit f37c5991ff
4 changed files with 218 additions and 151 deletions

View File

@ -31,6 +31,7 @@ import org.jclouds.blobstore.LocalAsyncBlobStore;
import org.jclouds.blobstore.TransientApiMetadata;
import org.jclouds.chef.ChefApi;
import org.jclouds.chef.ChefAsyncApi;
import org.jclouds.chef.config.Validator;
import org.jclouds.chef.domain.Client;
import org.jclouds.chef.functions.ClientForGroup;
import org.jclouds.chef.functions.RunListForGroup;
@ -48,10 +49,12 @@ import org.jclouds.rest.config.RestModule;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.statements.chef.InstallChefGems;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.MapMaker;
import com.google.inject.AbstractModule;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Provides;
import com.google.inject.name.Names;
@ -67,26 +70,29 @@ public class TransientChefApiModule extends AbstractModule {
protected void configure() {
install(new RestModule());
bind(ChefAsyncApi.class).to(TransientChefAsyncApi.class).asEagerSingleton();
// forward all requests from TransientChefApi to ChefAsyncApi. needs above binding as cannot proxy a class
BinderUtils.bindClient(binder(), TransientChefApi.class, ChefAsyncApi.class, ImmutableMap.<Class<?>, Class<?>>of());
// forward all requests from TransientChefApi to ChefAsyncApi. needs above
// binding as cannot proxy a class
BinderUtils.bindClient(binder(), TransientChefApi.class, ChefAsyncApi.class,
ImmutableMap.<Class<?>, Class<?>> of());
bind(ChefApi.class).to(TransientChefApi.class);
bind(LocalAsyncBlobStore.class).annotatedWith(Names.named("databags")).toInstance(
ContextBuilder.newBuilder(new TransientApiMetadata()).modules(
ContextBuilder
.newBuilder(new TransientApiMetadata())
.modules(
ImmutableSet.<Module> of(new ExecutorServiceModule(MoreExecutors.sameThreadExecutor(),
MoreExecutors.sameThreadExecutor()))).buildInjector().getInstance(
LocalAsyncBlobStore.class));
MoreExecutors.sameThreadExecutor()))).buildInjector()
.getInstance(LocalAsyncBlobStore.class));
bind(Statement.class).annotatedWith(Names.named("installChefGems")).to(InstallChefGems.class);
}
@Provides
@Singleton
public PrivateKey provideKey(Crypto crypto, @Credential String pem) throws InvalidKeySpecException,
IOException {
return crypto.rsaKeyFactory().generatePrivate(Pems.privateKeySpec(InputSuppliers.of(pem)));
public PrivateKey provideKey(Crypto crypto, @Credential String pem) throws InvalidKeySpecException, IOException {
return crypto.rsaKeyFactory().generatePrivate(Pems.privateKeySpec(InputSuppliers.of(pem)));
}
@Provides
@Singleton
Map<String, List<String>> runListForTag(RunListForGroup runListForTag) {
@ -99,5 +105,19 @@ public class TransientChefApiModule extends AbstractModule {
return new MapMaker().makeComputingMap(tagToClient);
}
@Provides
@Singleton
@Validator
public Optional<String> provideValidatorName(Injector injector) {
return Optional.absent();
}
@Provides
@Singleton
@Validator
public Optional<PrivateKey> provideValidatorCredential(Crypto crypto, Injector injector)
throws InvalidKeySpecException, IOException {
return Optional.absent();
}
}

View File

@ -0,0 +1,48 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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;
import org.jclouds.chef.filters.SignedHeaderAuth;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.rest.internal.BaseRestApiExpectTest;
import com.google.common.base.Functions;
import com.google.common.collect.ImmutableMap;
/**
* Base class for Chef Api expect tests.
*
* @author Ignasi Barrera
*/
public abstract class BaseChefApiExectTest<S> extends BaseRestApiExpectTest<S> {
public static final String PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAyb2ZJJqGm0KKR+8nfQJNsSd+F9tXNMV7CfOcW6jsqs8EZgiV\nR09hD1IYOj4YqM0qJONlgyg4xRWewdSG7QTPj1lJpVAida9sXy2+kzyagZA1Am0O\nZcbqb5hoeIDgcX+eDa79s0u0DomjcfO9EKhvHLBz+zM+3QqPRkPV8nYTbfs+HjVz\nzOU6D1B0XR3+IPZZl2AnWs2d0qhnStHcDUvnRVQ0P482YwN9VgceOZtpPz0DCKEJ\n5Tx5STub8k0/zt/VAMHQafLSuQMLd2s4ZLuOZptN//uAsTmxireqd37z+8ZTdBbJ\n8LEpJ+iCXuSfm5aUh7iw6oxvToY2AL53+jK2UQIDAQABAoIBAQDA88B3i/xWn0vX\nBVxFamCYoecuNjGwXXkSyZew616A+EOCu47bh4aTurdFbYL0YFaAtaWvzlaN2eHg\nDb+HDuTefE29+WkcGk6SshPmiz5T0XOCAICWw6wSVDkHmGwS4jZvbAFm7W8nwGk9\nYhxgxFiRngswJZFopOLoF5WXs2td8guIYNslMpo7tu50iFnBHwKO2ZsPAk8t9nnS\nxlDavKruymEmqHCr3+dtio5eaenJcp3fjoXBQOKUk3ipII29XRB8NqeCVV/7Kxwq\nckqOBEbRwBclckyIbD+RiAgKvOelORjEiE9R42vuqvxRA6k9kd9o7utlX0AUtpEn\n3gZc6LepAoGBAP9ael5Y75+sK2JJUNOOhO8ae45cdsilp2yI0X+UBaSuQs2+dyPp\nkpEHAxd4pmmSvn/8c9TlEZhr+qYbABXVPlDncxpIuw2Ajbk7s/S4XaSKsRqpXL57\nzj/QOqLkRk8+OVV9q6lMeQNqLtEj1u6JPviX70Ro+FQtRttNOYbfdP/fAoGBAMpA\nXjR5woV5sUb+REg9vEuYo8RSyOarxqKFCIXVUNsLOx+22+AK4+CQpbueWN7jotrl\nYD6uT6svWi3AAC7kiY0UI/fjVPRCUi8tVoQUE0TaU5VLITaYOB+W/bBaDE4M9560\n1NuDWO90baA5dfU44iuzva02rGJXK9+nS3o8nk/PAoGBALOL6djnDe4mwAaG6Jco\ncd4xr8jkyPzCRZuyBCSBbwphIUXLc7hDprPky064ncJD1UDmwIdkXd/fpMkg2QmA\n/CUk6LEFjMisqHojOaCL9gQZJPhLN5QUN2x1PJWGjs1vQh8Tkx0iUUCOa8bQPXNR\n+34OTsW6TUna4CSZAycLfhffAoGBAIggVsefBCvuQkF0NeUhmDCRZfhnd8y55RHR\n1HCvqKIlpv+rhcX/zmyBLuteopYyRJRsOiE2FW00i8+rIPRu4Z3Q5nybx7w3PzV9\noHN5R5baE9OyI4KpZWztpYYitZF67NcnAvVULHHOvVJQGnKYfLHJYmrJF7GA1ojM\nAuMdFbjFAoGAPxUhxwFy8gaqBahKUEZn4F81HFP5ihGhkT4QL6AFPO2e+JhIGjuR\n27+85hcFqQ+HHVtFsm81b/a+R7P4UuCRgc8eCjxQMoJ1Xl4n7VbjPbHMnIN0Ryvd\nO4ZpWDWYnCO021JTOUUOJ4J/y0416Bvkw0z59y7sNX7wDBBHHbK/XCc=\n-----END RSA PRIVATE KEY-----\n";
protected SignedHeaderAuth signedHeaderAuth;
public BaseChefApiExectTest() {
credential = PRIVATE_KEY;
signedHeaderAuth = createInjector(Functions.forMap(ImmutableMap.<HttpRequest, HttpResponse> of()),
createModule(), setupProperties()).getInstance(SignedHeaderAuth.class);
}
protected HttpRequest signed(HttpRequest input) {
return signedHeaderAuth.filter(input);
}
}

View File

@ -61,6 +61,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.Closeables;
import com.google.common.primitives.Bytes;
/**
* Tests behavior of {@code ChefApi}
*
@ -72,14 +73,14 @@ public abstract class BaseChefApiLiveTest<C extends Context> extends BaseChefCon
public static final String ADMIN_PREFIX = System.getProperty("user.name") + "-jcloudstest-adm";
public static final String VALIDATOR_PREFIX = System.getProperty("user.name") + "-jcloudstest-val";
private String validatorIdentity;
private String validatorCredential;
private C validatorContext;
private ChefApi validatorClient;
protected String validatorIdentity;
protected String validatorCredential;
protected C validatorContext;
protected ChefApi validatorClient;
// It may take a bit until the search index is populated
protected int maxWaitForIndexInMs = 60000;
protected ChefApi chefApi;
protected Properties setupValidatorProperties() {
@ -126,8 +127,8 @@ public abstract class BaseChefApiLiveTest<C extends Context> extends BaseChefCon
ChecksumStatus status = site.getChecksums().get(md5);
if (status.needsUpload()) {
//context.utils().http().put(status.getUrl(), content);
chefApi.uploadContent(status.getUrl(), content);
// context.utils().http().put(status.getUrl(), content);
chefApi.uploadContent(status.getUrl(), content);
}
chefApi.commitSandbox(site.getSandboxId(), true);
@ -146,22 +147,22 @@ public abstract class BaseChefApiLiveTest<C extends Context> extends BaseChefCon
@Test(dependsOnMethods = "testCreateClient")
public void testGenerateKeyForClient() throws Exception {
String credential = Pems.pem(chefApi.generateKeyForClient(PREFIX).getPrivateKey());
assertClientCreated(PREFIX, credential);
String credential = Pems.pem(chefApi.generateKeyForClient(PREFIX).getPrivateKey());
assertClientCreated(PREFIX, credential);
}
@Test
public void testListCookbooks() throws Exception {
Set<String> cookbookNames = chefApi.listCookbooks();
assertFalse(cookbookNames.isEmpty());
for (String cookbook : cookbookNames)
for (String cookbook : cookbookNames) {
for (String version : chefApi.getVersionsOfCookbook(cookbook)) {
CookbookVersion cookbookO = chefApi.getCookbook(cookbook, version);
for (Resource resource : ImmutableList.<Resource> builder().addAll(cookbookO.getDefinitions()).addAll(
cookbookO.getFiles()).addAll(cookbookO.getLibraries()).addAll(cookbookO.getSuppliers()).addAll(
cookbookO.getRecipes()).addAll(cookbookO.getResources()).addAll(cookbookO.getRootFiles()).addAll(
cookbookO.getTemplates()).build()) {
for (Resource resource : ImmutableList.<Resource> builder().addAll(cookbookO.getDefinitions())
.addAll(cookbookO.getFiles()).addAll(cookbookO.getLibraries()).addAll(cookbookO.getSuppliers())
.addAll(cookbookO.getRecipes()).addAll(cookbookO.getResources()).addAll(cookbookO.getRootFiles())
.addAll(cookbookO.getTemplates()).build()) {
try {
InputStream stream = chefApi.getResourceContents(resource);
byte[] md5 = CryptoStreams.md5(InputSuppliers.of(stream));
@ -171,23 +172,25 @@ public abstract class BaseChefApiLiveTest<C extends Context> extends BaseChefCon
}
}
}
}
}
@Test(dependsOnMethods = "testCreateNewCookbook")
public void testUpdateCookbook() throws Exception {
CookbookVersion cookbook = chefApi.getCookbook(PREFIX, "0.0.0");
assertNotNull(chefApi.updateCookbook(PREFIX, "0.0.0", cookbook));
}
@Test(dependsOnMethods = {"testCreateNewCookbook", "testUpdateCookbook"})
@Test(dependsOnMethods = { "testCreateNewCookbook", "testUpdateCookbook" })
public void testDeleteCookbook() throws Exception {
assertNotNull(chefApi.deleteCookbook(PREFIX, "0.0.0"));
}
@Test(expectedExceptions = AuthorizationException.class)
public void testValidatorCannotListClients() throws Exception {
for (String client : validatorClient.listClients())
for (String client : validatorClient.listClients()) {
assertNotNull(validatorClient.getClient(client));
}
}
@Test(expectedExceptions = AuthorizationException.class)
@ -197,8 +200,8 @@ public abstract class BaseChefApiLiveTest<C extends Context> extends BaseChefCon
@Test
public void testValidatorCreateClient() throws Exception {
String credential = Pems.pem(validatorClient.createClient(VALIDATOR_PREFIX).getPrivateKey());
assertClientCreated(VALIDATOR_PREFIX, credential);
String credential = Pems.pem(validatorClient.createClient(VALIDATOR_PREFIX).getPrivateKey());
assertClientCreated(VALIDATOR_PREFIX, credential);
}
@Test
@ -209,9 +212,9 @@ public abstract class BaseChefApiLiveTest<C extends Context> extends BaseChefCon
@Test
public void testCreateAdminClient() throws Exception {
String credential = Pems.pem(chefApi.createClient(ADMIN_PREFIX, CreateClientOptions.Builder.admin())
.getPrivateKey());
assertClientCreated(ADMIN_PREFIX, credential);
String credential = Pems.pem(chefApi.createClient(ADMIN_PREFIX, CreateClientOptions.Builder.admin())
.getPrivateKey());
assertClientCreated(ADMIN_PREFIX, credential);
}
@Test
@ -306,16 +309,16 @@ public abstract class BaseChefApiLiveTest<C extends Context> extends BaseChefCon
Properties config = new Properties();
config.setProperty("foo", "bar");
chefApi.deleteDatabagItem(PREFIX, PREFIX);
databagItem = chefApi.createDatabagItem(PREFIX,
new DatabagItem("config", context.utils().json().toJson(config)));
databagItem = chefApi.createDatabagItem(PREFIX, new DatabagItem("config", context.utils().json().toJson(config)));
assertNotNull(databagItem);
assertEquals(databagItem.getId(), "config");
// The databagItem json contains extra keys: (the name and the type if the item)
// The databagItem json contains extra keys: (the name and the type if the
// item)
Properties props = context.utils().json().fromJson(databagItem.toString(), Properties.class);
for (Object key : config.keySet()) {
assertTrue(props.containsKey(key));
assertEquals(config.get(key), props.get(key));
assertTrue(props.containsKey(key));
assertEquals(config.get(key), props.get(key));
}
}
@ -346,28 +349,28 @@ public abstract class BaseChefApiLiveTest<C extends Context> extends BaseChefCon
SearchResult<? extends Node> results = chefApi.searchNodes();
assertNotNull(results);
}
@Test(dependsOnMethods = {"testListSearchIndexes", "testCreateNode"})
@Test(dependsOnMethods = { "testListSearchIndexes", "testCreateNode" })
public void testSearchNodesWithOptions() throws Exception {
RetryablePredicate<SearchOptions> waitForIndex =
new RetryablePredicate<SearchOptions>(new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends Node> results = chefApi.searchNodes(input);
assertNotNull(results);
if(results.size() > 0) {
assertEquals(results.size(), 1);
assertEquals(results.iterator().next().getName(), PREFIX);
return true;
} else {
// The index may still not be populated
return false;
}
}
}, maxWaitForIndexInMs, 5000L, TimeUnit.MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX);
assertTrue(waitForIndex.apply(options));
RetryablePredicate<SearchOptions> waitForIndex = new RetryablePredicate<SearchOptions>(
new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends Node> results = chefApi.searchNodes(input);
assertNotNull(results);
if (results.size() > 0) {
assertEquals(results.size(), 1);
assertEquals(results.iterator().next().getName(), PREFIX);
return true;
} else {
// The index may still not be populated
return false;
}
}
}, maxWaitForIndexInMs, 5000L, TimeUnit.MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX);
assertTrue(waitForIndex.apply(options));
}
@Test
@ -375,28 +378,28 @@ public abstract class BaseChefApiLiveTest<C extends Context> extends BaseChefCon
SearchResult<? extends Client> results = chefApi.searchClients();
assertNotNull(results);
}
@Test(dependsOnMethods = {"testListSearchIndexes", "testCreateClient"})
@Test(dependsOnMethods = { "testListSearchIndexes", "testCreateClient" })
public void testSearchClientsWithOptions() throws Exception {
RetryablePredicate<SearchOptions> waitForIndex =
new RetryablePredicate<SearchOptions>(new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends Client> results = chefApi.searchClients(input);
assertNotNull(results);
if(results.size() > 0) {
assertEquals(results.size(), 1);
assertEquals(results.iterator().next().getName(), PREFIX);
return true;
} else {
// The index may still not be populated
return false;
}
}
}, maxWaitForIndexInMs, 5000L, TimeUnit.MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX);
assertTrue(waitForIndex.apply(options));
RetryablePredicate<SearchOptions> waitForIndex = new RetryablePredicate<SearchOptions>(
new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends Client> results = chefApi.searchClients(input);
assertNotNull(results);
if (results.size() > 0) {
assertEquals(results.size(), 1);
assertEquals(results.iterator().next().getName(), PREFIX);
return true;
} else {
// The index may still not be populated
return false;
}
}
}, maxWaitForIndexInMs, 5000L, TimeUnit.MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX);
assertTrue(waitForIndex.apply(options));
}
@Test
@ -404,57 +407,57 @@ public abstract class BaseChefApiLiveTest<C extends Context> extends BaseChefCon
SearchResult<? extends Role> results = chefApi.searchRoles();
assertNotNull(results);
}
@Test(dependsOnMethods = {"testListSearchIndexes", "testCreateRole"})
@Test(dependsOnMethods = { "testListSearchIndexes", "testCreateRole" })
public void testSearchRolesWithOptions() throws Exception {
RetryablePredicate<SearchOptions> waitForIndex =
new RetryablePredicate<SearchOptions>(new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends Role> results = chefApi.searchRoles(input);
assertNotNull(results);
if(results.size() > 0) {
assertEquals(results.size(), 1);
assertEquals(results.iterator().next().getName(), PREFIX);
return true;
} else {
// The index may still not be populated
return false;
}
}
}, maxWaitForIndexInMs, 5000L, TimeUnit.MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX);
assertTrue(waitForIndex.apply(options));
RetryablePredicate<SearchOptions> waitForIndex = new RetryablePredicate<SearchOptions>(
new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends Role> results = chefApi.searchRoles(input);
assertNotNull(results);
if (results.size() > 0) {
assertEquals(results.size(), 1);
assertEquals(results.iterator().next().getName(), PREFIX);
return true;
} else {
// The index may still not be populated
return false;
}
}
}, maxWaitForIndexInMs, 5000L, TimeUnit.MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX);
assertTrue(waitForIndex.apply(options));
}
@Test(dependsOnMethods = {"testListSearchIndexes", "testDatabagItemExists"})
@Test(dependsOnMethods = { "testListSearchIndexes", "testDatabagItemExists" })
public void testSearchDatabag() throws Exception {
SearchResult<? extends DatabagItem> results = chefApi.searchDatabag(PREFIX);
assertNotNull(results);
}
@Test(dependsOnMethods = {"testListSearchIndexes", "testDatabagItemExists"})
@Test(dependsOnMethods = { "testListSearchIndexes", "testDatabagItemExists" })
public void testSearchDatabagWithOptions() throws Exception {
RetryablePredicate<SearchOptions> waitForIndex =
new RetryablePredicate<SearchOptions>(new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends DatabagItem> results = chefApi.searchDatabag(PREFIX, input);
assertNotNull(results);
if(results.size() > 0) {
assertEquals(results.size(), 1);
assertEquals(results.iterator().next().getId(), databagItem.getId());
return true;
} else {
// The index may still not be populated
return false;
}
}
}, maxWaitForIndexInMs, 5000L, TimeUnit.MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("id:" + databagItem.getId());
assertTrue(waitForIndex.apply(options));
RetryablePredicate<SearchOptions> waitForIndex = new RetryablePredicate<SearchOptions>(
new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends DatabagItem> results = chefApi.searchDatabag(PREFIX, input);
assertNotNull(results);
if (results.size() > 0) {
assertEquals(results.size(), 1);
assertEquals(results.iterator().next().getId(), databagItem.getId());
return true;
} else {
// The index may still not be populated
return false;
}
}
}, maxWaitForIndexInMs, 5000L, TimeUnit.MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("id:" + databagItem.getId());
assertTrue(waitForIndex.apply(options));
}
@Test(expectedExceptions = ResourceNotFoundException.class, dependsOnMethods = "testListSearchIndexes")
@ -462,7 +465,7 @@ public abstract class BaseChefApiLiveTest<C extends Context> extends BaseChefCon
SearchResult<? extends DatabagItem> results = chefApi.searchDatabag("whoopie");
assertNotNull(results);
}
@AfterClass(groups = { "live", "integration" })
@Override
public void tearDownContext() {
@ -475,22 +478,20 @@ public abstract class BaseChefApiLiveTest<C extends Context> extends BaseChefCon
chefApi.deleteDatabag(PREFIX);
super.tearDownContext();
}
private void assertClientCreated(String identity, String credential) {
Properties overrides = super.setupProperties();
overrides.setProperty(provider + ".identity", identity);
overrides.setProperty(provider + ".credential", credential);
C clientContext = createContext(overrides, setupModules());
try {
Client client = getChefApi(clientContext).getClient(identity);
assertNotNull(client);
} finally {
Closeables.closeQuietly(clientContext);
}
private void assertClientCreated(String identity, String credential) {
Properties overrides = super.setupProperties();
overrides.setProperty(provider + ".identity", identity);
overrides.setProperty(provider + ".credential", credential);
C clientContext = createContext(overrides, setupModules());
try {
Client client = getChefApi(clientContext).getClient(identity);
assertNotNull(client);
} finally {
Closeables.closeQuietly(clientContext);
}
}
}

View File

@ -73,7 +73,7 @@ public class TransientChefApiIntegrationTest extends BaseChefContextLiveTest<Che
Properties config = new Properties();
config.setProperty("foo", "bar");
databagItem = context.getApi().createDatabagItem(PREFIX,
new DatabagItem("config", context.utils().json().toJson(config)));
new DatabagItem("config", context.utils().json().toJson(config)));
assertNotNull(databagItem);
assertEquals(databagItem.getId(), "config");
assertEquals(config, context.utils().json().fromJson(databagItem.toString(), Properties.class));
@ -91,16 +91,14 @@ public class TransientChefApiIntegrationTest extends BaseChefContextLiveTest<Che
context.getApi().updateDatabagItem(PREFIX, databagItem);
}
}
@Override
protected ChefApi getChefApi(ChefContext context)
{
return context.getApi();
protected ChefApi getChefApi(ChefContext context) {
return context.getApi();
}
@Override
protected TypeToken<ChefContext> contextType()
{
return TypeToken.of(ChefContext.class);
protected TypeToken<ChefContext> contextType() {
return TypeToken.of(ChefContext.class);
}
}