JCLOUDS-717: Join Enterprise and OpenSource Chef

This commit is contained in:
Ignasi Barrera 2015-10-30 00:42:03 +01:00
parent c9306c1fc8
commit 9df30c5a09
42 changed files with 891 additions and 1310 deletions

View File

@ -19,7 +19,7 @@
#^{:author "Adrian Cole"
:doc "A clojure binding to the jclouds chef interface.
Here's a quick example of how to manipulate a databag on the Opscode Platform,
Here's a quick example of how to manipulate a databag on the Chef Platform,
which is basically Chef Server as a Service.
(use 'org.jclouds.chef)
@ -28,7 +28,7 @@ which is basically Chef Server as a Service.
;; load the rsa key from ~/.chef/CLIENT_NAME.pem
(def credential (load-pem client))
;; create a connection to the opscode platform
;; create a connection to the chef platform
(def chef (chef-service \"chef\" client credential :chef.endpoint \"https://api.opscode.com/organizations/YOUR_ORG\"))
(with-chef-service [chef]

View File

@ -55,10 +55,11 @@ import org.jclouds.chef.domain.Role;
import org.jclouds.chef.domain.Sandbox;
import org.jclouds.chef.domain.SearchResult;
import org.jclouds.chef.domain.UploadSandbox;
import org.jclouds.chef.features.OrganizationApi;
import org.jclouds.chef.filters.SignedHeaderAuth;
import org.jclouds.chef.functions.ParseCookbookDefinitionFromJson;
import org.jclouds.chef.functions.ParseCookbookDefinitionListFromJson;
import org.jclouds.chef.functions.ParseCookbookNamesFromJson;
import org.jclouds.chef.functions.ParseCookbookDefinitionFromJson;
import org.jclouds.chef.functions.ParseCookbookVersionsFromJson;
import org.jclouds.chef.functions.ParseKeySetFromJson;
import org.jclouds.chef.functions.ParseSearchClientsFromJson;
@ -71,6 +72,7 @@ import org.jclouds.chef.options.CreateClientOptions;
import org.jclouds.chef.options.SearchOptions;
import org.jclouds.io.Payload;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Headers;
@ -85,6 +87,7 @@ import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.WrapWith;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.base.Optional;
import com.google.inject.Provides;
/**
@ -100,6 +103,12 @@ public interface ChefApi extends Closeable {
*/
@Provides
ChefService chefService();
/**
* Provides access to the organization, user and group management endpoints.
*/
@Delegate
Optional<OrganizationApi> organizationApi();
// Clients

View File

@ -40,7 +40,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
/**
* Implementation of {@link ApiMetadata} for OpsCode's Chef api.
* Implementation of {@link ApiMetadata} for Chef.
*/
@AutoService(ApiMetadata.class)
public class ChefApiMetadata extends BaseHttpApiMetadata<ChefApi> {
@ -48,7 +48,7 @@ public class ChefApiMetadata extends BaseHttpApiMetadata<ChefApi> {
/**
* The default Chef Server API version to use.
*/
public static final String DEFAULT_API_VERSION = "0.10.8";
public static final String DEFAULT_API_VERSION = "12.0.2";
@Override
public Builder toBuilder() {
@ -86,11 +86,11 @@ public class ChefApiMetadata extends BaseHttpApiMetadata<ChefApi> {
protected Builder() {
id("chef")
.name("OpsCode Chef Api")
.name("Chef Api")
.identityName("User")
.credentialName("Certificate")
.version(DEFAULT_API_VERSION)
.documentation(URI.create("http://wiki.opscode.com/display/chef/Server+API"))
.documentation(URI.create("https://docs.chef.io/api_chef_server.html"))
.defaultEndpoint("http://localhost:4000")
.defaultProperties(ChefApiMetadata.defaultProperties())
.defaultModules(

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.enterprisechef.binders;
package org.jclouds.chef.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@ -24,7 +24,7 @@ import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.enterprisechef.domain.Group;
import org.jclouds.chef.domain.Group;
import org.jclouds.http.HttpRequest;
import org.jclouds.json.Json;
import org.jclouds.rest.binders.BindToJsonPayload;

View File

@ -14,13 +14,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.enterprisechef.binders;
package org.jclouds.chef.binders;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Singleton;
import org.jclouds.enterprisechef.domain.Group;
import org.jclouds.chef.domain.Group;
import com.google.common.base.Function;

View File

@ -1,204 +0,0 @@
/*
* 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.config;
import static com.google.common.base.Suppliers.compose;
import static com.google.common.base.Suppliers.memoizeWithExpiration;
import static com.google.common.base.Throwables.propagate;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.chef.config.ChefProperties.CHEF_VALIDATOR_CREDENTIAL;
import static org.jclouds.chef.config.ChefProperties.CHEF_VALIDATOR_NAME;
import static org.jclouds.crypto.Pems.privateKeySpec;
import java.io.IOException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.chef.domain.BootstrapConfig;
import org.jclouds.chef.domain.Client;
import org.jclouds.chef.functions.BootstrapConfigForGroup;
import org.jclouds.chef.functions.ClientForGroup;
import org.jclouds.chef.handlers.ChefApiErrorRetryHandler;
import org.jclouds.chef.handlers.ChefErrorHandler;
import org.jclouds.crypto.Crypto;
import org.jclouds.crypto.Pems;
import org.jclouds.date.DateService;
import org.jclouds.date.TimeStamp;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.rest.ConfiguresHttpApi;
import org.jclouds.rest.config.HttpApiModule;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Supplier;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.io.ByteSource;
import com.google.inject.ConfigurationException;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Provides;
import com.google.inject.name.Names;
/**
* Configures the Chef connection.
*/
@ConfiguresHttpApi
public abstract class BaseChefHttpApiModule<S> extends HttpApiModule<S> {
@Provides
@TimeStamp
protected final String guiceProvideTimeStamp(@TimeStamp Supplier<String> cache) {
return provideTimeStamp(cache);
}
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
return cache.get();
}
/**
* borrowing concurrency code to ensure that caching takes place properly
*/
@Provides
@TimeStamp
final Supplier<String> provideTimeStampCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds, final DateService dateService) {
return memoizeWithExpiration(new Supplier<String>() {
@Override
public String get() {
return dateService.iso8601SecondsDateFormat();
}
}, seconds, TimeUnit.SECONDS);
}
// TODO: potentially change this
@Provides
@Singleton
public final Supplier<PrivateKey> supplyKey(final LoadingCache<Credentials, PrivateKey> keyCache,
@org.jclouds.location.Provider final Supplier<Credentials> creds) {
return compose(new Function<Credentials, PrivateKey>() {
@Override
public PrivateKey apply(Credentials in) {
return keyCache.getUnchecked(in);
}
}, creds);
}
@Provides
@Singleton
final LoadingCache<Credentials, PrivateKey> privateKeyCache(PrivateKeyForCredentials loader) {
// throw out the private key related to old credentials
return CacheBuilder.newBuilder().maximumSize(2).build(loader);
}
/**
* it is relatively expensive to extract a private key from a PEM. cache the
* relationship between current credentials so that the private key is only
* recalculated once.
*/
@VisibleForTesting
@Singleton
private static class PrivateKeyForCredentials extends CacheLoader<Credentials, PrivateKey> {
private final Crypto crypto;
@Inject
private PrivateKeyForCredentials(Crypto crypto) {
this.crypto = crypto;
}
@Override
public PrivateKey load(Credentials in) {
try {
return crypto.rsaKeyFactory().generatePrivate(
privateKeySpec(ByteSource.wrap(in.credential.getBytes(Charsets.UTF_8))));
} catch (InvalidKeySpecException e) {
throw propagate(e);
} catch (IOException e) {
throw propagate(e);
}
}
}
@Provides
@Singleton
@Validator
public final Optional<String> provideValidatorName(Injector injector) {
// Named properties can not be injected as optional here, so let's use the
// injector to bypass it
Key<String> key = Key.get(String.class, Names.named(CHEF_VALIDATOR_NAME));
try {
return Optional.<String> of(injector.getInstance(key));
} catch (ConfigurationException ex) {
return Optional.<String> absent();
}
}
@Provides
@Singleton
@Validator
public final Optional<PrivateKey> provideValidatorCredential(Crypto crypto, Injector injector)
throws InvalidKeySpecException, IOException {
// Named properties can not be injected as optional here, so let's use the
// injector to bypass it
Key<String> key = Key.get(String.class, Names.named(CHEF_VALIDATOR_CREDENTIAL));
try {
String validatorCredential = injector.getInstance(key);
PrivateKey validatorKey = crypto.rsaKeyFactory().generatePrivate(
Pems.privateKeySpec(ByteSource.wrap(validatorCredential.getBytes(Charsets.UTF_8))));
return Optional.<PrivateKey> of(validatorKey);
} catch (ConfigurationException ex) {
return Optional.<PrivateKey> absent();
}
}
@Provides
@Singleton
final CacheLoader<String, BootstrapConfig> bootstrapConfigForGroup(BootstrapConfigForGroup bootstrapConfigForGroup) {
return CacheLoader.from(bootstrapConfigForGroup);
}
@Provides
@Singleton
final CacheLoader<String, Client> groupToClient(ClientForGroup clientForGroup) {
return CacheLoader.from(clientForGroup);
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ChefErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ChefErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ChefErrorHandler.class);
}
@Override
protected void bindRetryHandlers() {
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(ChefApiErrorRetryHandler.class);
}
}

View File

@ -16,13 +16,191 @@
*/
package org.jclouds.chef.config;
import static com.google.common.base.Suppliers.compose;
import static com.google.common.base.Suppliers.memoizeWithExpiration;
import static com.google.common.base.Throwables.propagate;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.chef.config.ChefProperties.CHEF_VALIDATOR_CREDENTIAL;
import static org.jclouds.chef.config.ChefProperties.CHEF_VALIDATOR_NAME;
import static org.jclouds.crypto.Pems.privateKeySpec;
import java.io.IOException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.chef.ChefApi;
import org.jclouds.chef.domain.BootstrapConfig;
import org.jclouds.chef.domain.Client;
import org.jclouds.chef.functions.BootstrapConfigForGroup;
import org.jclouds.chef.functions.ClientForGroup;
import org.jclouds.chef.handlers.ChefApiErrorRetryHandler;
import org.jclouds.chef.handlers.ChefErrorHandler;
import org.jclouds.crypto.Crypto;
import org.jclouds.crypto.Pems;
import org.jclouds.date.DateService;
import org.jclouds.date.TimeStamp;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.rest.ConfiguresHttpApi;
import org.jclouds.rest.config.HttpApiModule;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Supplier;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.io.ByteSource;
import com.google.inject.ConfigurationException;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Provides;
import com.google.inject.name.Names;
/**
* Configures the Chef connection.
*/
@ConfiguresHttpApi
public class ChefHttpApiModule extends BaseChefHttpApiModule<ChefApi> {
public class ChefHttpApiModule extends HttpApiModule<ChefApi> {
@Provides
@TimeStamp
protected final String guiceProvideTimeStamp(@TimeStamp Supplier<String> cache) {
return provideTimeStamp(cache);
}
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
return cache.get();
}
/**
* borrowing concurrency code to ensure that caching takes place properly
*/
@Provides
@TimeStamp
final Supplier<String> provideTimeStampCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
final DateService dateService) {
return memoizeWithExpiration(new Supplier<String>() {
@Override
public String get() {
return dateService.iso8601SecondsDateFormat();
}
}, seconds, TimeUnit.SECONDS);
}
// TODO: potentially change this
@Provides
@Singleton
public final Supplier<PrivateKey> supplyKey(final LoadingCache<Credentials, PrivateKey> keyCache,
@org.jclouds.location.Provider final Supplier<Credentials> creds) {
return compose(new Function<Credentials, PrivateKey>() {
@Override
public PrivateKey apply(Credentials in) {
return keyCache.getUnchecked(in);
}
}, creds);
}
@Provides
@Singleton
final LoadingCache<Credentials, PrivateKey> privateKeyCache(PrivateKeyForCredentials loader) {
// throw out the private key related to old credentials
return CacheBuilder.newBuilder().maximumSize(2).build(loader);
}
/**
* it is relatively expensive to extract a private key from a PEM. cache the
* relationship between current credentials so that the private key is only
* recalculated once.
*/
@VisibleForTesting
@Singleton
private static class PrivateKeyForCredentials extends CacheLoader<Credentials, PrivateKey> {
private final Crypto crypto;
@Inject
private PrivateKeyForCredentials(Crypto crypto) {
this.crypto = crypto;
}
@Override
public PrivateKey load(Credentials in) {
try {
return crypto.rsaKeyFactory().generatePrivate(
privateKeySpec(ByteSource.wrap(in.credential.getBytes(Charsets.UTF_8))));
} catch (InvalidKeySpecException e) {
throw propagate(e);
} catch (IOException e) {
throw propagate(e);
}
}
}
@Provides
@Singleton
@Validator
public final Optional<String> provideValidatorName(Injector injector) {
// Named properties can not be injected as optional here, so let's use the
// injector to bypass it
Key<String> key = Key.get(String.class, Names.named(CHEF_VALIDATOR_NAME));
try {
return Optional.<String> of(injector.getInstance(key));
} catch (ConfigurationException ex) {
return Optional.<String> absent();
}
}
@Provides
@Singleton
@Validator
public final Optional<PrivateKey> provideValidatorCredential(Crypto crypto, Injector injector)
throws InvalidKeySpecException, IOException {
// Named properties can not be injected as optional here, so let's use the
// injector to bypass it
Key<String> key = Key.get(String.class, Names.named(CHEF_VALIDATOR_CREDENTIAL));
try {
String validatorCredential = injector.getInstance(key);
PrivateKey validatorKey = crypto.rsaKeyFactory().generatePrivate(
Pems.privateKeySpec(ByteSource.wrap(validatorCredential.getBytes(Charsets.UTF_8))));
return Optional.<PrivateKey> of(validatorKey);
} catch (ConfigurationException ex) {
return Optional.<PrivateKey> absent();
}
}
@Provides
@Singleton
final CacheLoader<String, BootstrapConfig> bootstrapConfigForGroup(BootstrapConfigForGroup bootstrapConfigForGroup) {
return CacheLoader.from(bootstrapConfigForGroup);
}
@Provides
@Singleton
final CacheLoader<String, Client> groupToClient(ClientForGroup clientForGroup) {
return CacheLoader.from(clientForGroup);
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ChefErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ChefErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ChefErrorHandler.class);
}
@Override
protected void bindRetryHandlers() {
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(ChefApiErrorRetryHandler.class);
}
}

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.enterprisechef.domain;
package org.jclouds.chef.domain;
import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty;
import static com.google.common.base.Preconditions.checkNotNull;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.enterprisechef.domain;
package org.jclouds.chef.domain;
import static com.google.common.base.Preconditions.checkNotNull;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.enterprisechef;
package org.jclouds.chef.features;
import java.util.Set;
@ -31,18 +31,19 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.Constants;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.chef.ChefApi;
import org.jclouds.chef.binders.BindGroupToUpdateRequestJsonPayload;
import org.jclouds.chef.binders.GroupName;
import org.jclouds.chef.domain.Group;
import org.jclouds.chef.domain.User;
import org.jclouds.chef.filters.SignedHeaderAuth;
import org.jclouds.chef.functions.ParseKeySetFromJson;
import org.jclouds.enterprisechef.binders.BindGroupToUpdateRequestJsonPayload;
import org.jclouds.enterprisechef.binders.GroupName;
import org.jclouds.enterprisechef.domain.Group;
import org.jclouds.enterprisechef.domain.User;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SinceApiVersion;
import org.jclouds.rest.annotations.WrapWith;
/**
@ -51,7 +52,8 @@ import org.jclouds.rest.annotations.WrapWith;
@RequestFilters(SignedHeaderAuth.class)
@Consumes(MediaType.APPLICATION_JSON)
@Headers(keys = "X-Chef-Version", values = "{" + Constants.PROPERTY_API_VERSION + "}")
public interface EnterpriseChefApi extends ChefApi {
@SinceApiVersion("12.0.0")
public interface OrganizationApi extends ChefApi {
/**
* Retrieves an existing user.
*

View File

@ -63,7 +63,7 @@ import com.google.common.io.ByteSource;
/**
* Ported from mixlib-authentication in order to sign Chef requests.
*
* @see <a href= "http://github.com/opscode/mixlib-authentication" />
* @see <a href= "https://github.com/chef/mixlib-authentication" />
*/
@Singleton
public class SignedHeaderAuth implements HttpRequestFilter {

View File

@ -20,7 +20,7 @@ package org.jclouds.chef.options;
* Options for the create client method.
*/
public class CreateClientOptions implements Cloneable {
/** Administrator flag. This flag will be ignored in Opscode Hosted Chef. */
/** Administrator flag. This flag will be ignored in Chef 12. */
private boolean admin;
public CreateClientOptions() {

View File

@ -33,6 +33,7 @@ public abstract class BaseChefApiExpectTest<S> extends BaseRestApiExpectTest<S>
protected SignedHeaderAuth signedHeaderAuth;
public BaseChefApiExpectTest() {
provider = "chef";
credential = PRIVATE_KEY;
signedHeaderAuth = createInjector(Functions.forMap(ImmutableMap.<HttpRequest, HttpResponse> of()),
createModule(), setupProperties()).getInstance(SignedHeaderAuth.class);

View File

@ -0,0 +1,55 @@
/*
* 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;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import java.io.IOException;
import org.jclouds.ContextBuilder;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "ChefApiDelegationTest")
public class ChefApiDelegationTest {
public void testOrganizationApiNotAvailableInOldVersions() throws IOException {
ChefApi chef = ContextBuilder.newBuilder(new ChefApiMetadata())
.credentials("foo", "bar")
.apiVersion("11.0.4")
.buildApi(ChefApi.class);
try {
assertFalse(chef.organizationApi().isPresent());
} finally {
chef.close();
}
}
public void testOrganizationApiPresentInRecentVersions() throws IOException {
ChefApi chef = ContextBuilder.newBuilder(new ChefApiMetadata())
.credentials("foo", "bar")
.apiVersion("12.0.4")
.buildApi(ChefApi.class);
try {
assertTrue(chef.organizationApi().isPresent());
} finally {
chef.close();
}
}
}

View File

@ -42,9 +42,6 @@ import com.google.inject.Module;
*/
@Test(groups = "unit", testName = "ChefApiExpectTest")
public class ChefApiExpectTest extends BaseChefApiExpectTest<ChefApi> {
public ChefApiExpectTest() {
provider = "chef";
}
private HttpRequest.Builder<?> getHttpRequestBuilder(String method, String endPoint) {
return HttpRequest.builder() //

View File

@ -16,17 +16,527 @@
*/
package org.jclouds.chef;
import org.jclouds.chef.internal.BaseChefApiLiveTest;
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.util.Closeables2.closeQuietly;
import static org.jclouds.util.Predicates2.retry;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import org.jclouds.chef.domain.ChecksumStatus;
import org.jclouds.chef.domain.Client;
import org.jclouds.chef.domain.CookbookDefinition;
import org.jclouds.chef.domain.CookbookVersion;
import org.jclouds.chef.domain.DatabagItem;
import org.jclouds.chef.domain.Environment;
import org.jclouds.chef.domain.Metadata;
import org.jclouds.chef.domain.Node;
import org.jclouds.chef.domain.Resource;
import org.jclouds.chef.domain.Role;
import org.jclouds.chef.domain.Sandbox;
import org.jclouds.chef.domain.SearchResult;
import org.jclouds.chef.domain.UploadSandbox;
import org.jclouds.chef.internal.BaseChefLiveTest;
import org.jclouds.chef.options.CreateClientOptions;
import org.jclouds.chef.options.SearchOptions;
import org.jclouds.crypto.Pems;
import org.jclouds.io.ByteStreams2;
import org.jclouds.io.Payloads;
import org.jclouds.io.payloads.FilePayload;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
/**
* Tests behavior of {@code ChefApi} against a Chef Server <= 0.9.8.
*/
@Test(groups = { "live" })
public class ChefApiLiveTest extends BaseChefApiLiveTest<ChefApi> {
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.hash.Hashing;
import com.google.common.io.Files;
import com.google.common.primitives.Bytes;
protected ChefApiLiveTest() {
provider = "chef";
/**
* Tests behavior of {@code ChefApi}
*/
@Test(groups = { "live", "integration" })
public class ChefApiLiveTest extends BaseChefLiveTest {
public static final String PREFIX = "jcloudstest-" + System.getProperty("user.name");
public static final String ADMIN_PREFIX = "jcloudstest-adm-" + System.getProperty("user.name");
public static final String ENV_NODE = PREFIX + "-env-node";
// It may take a bit until the search index is populated
protected int maxWaitForIndexInMs = 60000;
// The id of the data bag item used in search tests
private String databagitemId;
public void testCreateNewCookbook() throws Exception {
// Define the file you want in the cookbook
File file = new File(System.getProperty("user.dir"), "pom.xml");
FilePayload content = uploadAndGetFilePayload(file);
// Create the metadata of the cookbook
Metadata metadata = Metadata.builder() //
.name(PREFIX) //
.version("0.0.0") //
.description("Jclouds test uploaded cookbook") //
.maintainer("jclouds") //
.maintainerEmail("someone@jclouds.org") //
.license("Apache 2.0") //
.build();
// Create a new cookbook
CookbookVersion cookbook = CookbookVersion.builder(PREFIX, "0.0.0") //
.metadata(metadata) //
.rootFile(Resource.builder().fromPayload(content).build()) //
.attribute(Resource.builder().fromPayload(content).name("default.rb").build())
.build();
// upload the cookbook to the remote server
api.updateCookbook(PREFIX, "0.0.0", cookbook);
}
private FilePayload uploadAndGetFilePayload(File file) throws IOException {
FilePayload content = Payloads.newFilePayload(file);
content.getContentMetadata().setContentType("application/x-binary");
// Get an md5 so that you can see if the server already has it or not
content.getContentMetadata().setContentMD5(Files.asByteSource(file).hash(Hashing.md5()).asBytes());
// Note that java collections cannot effectively do equals or hashcodes on
// byte arrays, so let's convert to a list of bytes.
List<Byte> md5 = Bytes.asList(content.getContentMetadata().getContentMD5());
// Request an upload site for this file
UploadSandbox site = api.createUploadSandboxForChecksums(ImmutableSet.of(md5));
assertTrue(site.getChecksums().containsKey(md5), md5 + " not in " + site.getChecksums());
try {
// Upload the file contents, if still not uploaded
ChecksumStatus status = site.getChecksums().get(md5);
if (status.needsUpload()) {
api.uploadContent(status.getUrl(), content);
}
Sandbox sandbox = api.commitSandbox(site.getSandboxId(), true);
assertTrue(sandbox.isCompleted(), "Sandbox should be completed after uploading");
} catch (RuntimeException e) {
api.commitSandbox(site.getSandboxId(), false);
fail("Could not upload content");
}
return content;
}
public void testListCookbooks() throws Exception {
Set<String> cookbookNames = api.listCookbooks();
assertFalse(cookbookNames.isEmpty(), "No cookbooks were found");
for (String cookbookName : cookbookNames) {
Set<String> versions = api.listVersionsOfCookbook(cookbookName);
assertFalse(versions.isEmpty(), "There are no versions of the cookbook: " + cookbookName);
for (String version : api.listVersionsOfCookbook(cookbookName)) {
CookbookVersion cookbook = api.getCookbook(cookbookName, version);
assertNotNull(cookbook, "Could not get cookbook: " + cookbookName);
}
}
}
@Test(dependsOnMethods = "testListCookbooks")
public void testListCookbookVersionsWithChefService() throws Exception {
Iterable<? extends CookbookVersion> cookbooks = chefService.listCookbookVersions();
assertFalse(isEmpty(cookbooks), "No cookbooks were found");
}
@Test(dependsOnMethods = "testListCookbookVersionsWithChefService")
public void testDownloadCookbooks() throws Exception {
Iterable<? extends CookbookVersion> cookbooks = chefService.listCookbookVersions();
for (CookbookVersion cookbook : cookbooks) {
for (Resource resource : ImmutableList.<Resource> builder().addAll(cookbook.getDefinitions())
.addAll(cookbook.getFiles()).addAll(cookbook.getLibraries()).addAll(cookbook.getSuppliers())
.addAll(cookbook.getRecipes()).addAll(cookbook.getResources()).addAll(cookbook.getRootFiles())
.addAll(cookbook.getTemplates()).addAll(cookbook.getAttributes()).build()) {
InputStream stream = api.getResourceContents(resource);
assertNotNull(stream, "Resource contents are null for resource: " + resource.getName());
byte[] md5 = ByteStreams2.hashAndClose(stream, md5()).asBytes();
assertEquals(md5, resource.getChecksum());
}
}
}
@Test(dependsOnMethods = "testCreateNewCookbook")
public void testUpdateCookbook() throws Exception {
CookbookVersion cookbook = api.getCookbook(PREFIX, "0.0.0");
assertNotNull(cookbook, "Cookbook not found: " + PREFIX);
assertNotNull(api.updateCookbook(PREFIX, "0.0.0", cookbook), "Updated cookbook was null");
}
@Test(dependsOnMethods = { "testCreateNewCookbook", "testUpdateCookbook" })
public void testDeleteCookbook() throws Exception {
assertNotNull(api.deleteCookbook(PREFIX, "0.0.0"), "Deleted cookbook was null");
}
@Test
public void testCreateClient() throws Exception {
api.deleteClient(PREFIX);
String credential = Pems.pem(api.createClient(PREFIX).getPrivateKey());
assertClientCreated(PREFIX, credential);
}
@Test
public void testCreateAdminClient() throws Exception {
api.deleteClient(ADMIN_PREFIX);
String credential = Pems.pem(api.createClient(ADMIN_PREFIX, CreateClientOptions.Builder.admin()).getPrivateKey());
assertClientCreated(ADMIN_PREFIX, credential);
}
@Test(dependsOnMethods = "testCreateClient")
public void testGenerateKeyForClient() throws Exception {
String credential = Pems.pem(api.generateKeyForClient(PREFIX).getPrivateKey());
assertClientCreated(PREFIX, credential);
}
@Test
public void testListNodes() throws Exception {
Set<String> nodes = api.listNodes();
assertNotNull(nodes, "No nodes were found");
}
@Test(dependsOnMethods = "testCreateRole")
public void testCreateNode() throws Exception {
api.deleteNode(PREFIX);
api.createNode(Node.builder().name(PREFIX).runListElement("role[" + PREFIX + "]").environment("_default").build());
Node node = api.getNode(PREFIX);
// TODO check recipes
assertNotNull(node, "Created node should not be null");
Set<String> nodes = api.listNodes();
assertTrue(nodes.contains(PREFIX), String.format("node %s not in %s", PREFIX, nodes));
}
@Test(dependsOnMethods = "testCreateNode")
public void testUpdateNode() throws Exception {
for (String nodename : api.listNodes()) {
Node node = api.getNode(nodename);
api.updateNode(node);
}
}
@Test
public void testListRoles() throws Exception {
Set<String> roles = api.listRoles();
assertNotNull(roles, "Role list was null");
}
@Test
public void testCreateRole() throws Exception {
api.deleteRole(PREFIX);
api.createRole(Role.builder().name(PREFIX).runListElement("recipe[java]").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]"));
}
@Test(dependsOnMethods = "testCreateRole")
public void testUpdateRole() throws Exception {
for (String rolename : api.listRoles()) {
Role role = api.getRole(rolename);
api.updateRole(role);
}
}
@Test
public void testListDatabags() throws Exception {
Set<String> databags = api.listDatabags();
assertNotNull(databags, "Data bag list was null");
}
@Test
public void testCreateDatabag() throws Exception {
api.deleteDatabag(PREFIX);
api.createDatabag(PREFIX);
}
@Test(dependsOnMethods = "testCreateDatabagItem")
public void testListDatabagItems() throws Exception {
Set<String> databagItems = api.listDatabagItems(PREFIX);
assertNotNull(databagItems, "Data bag item list was null");
}
@Test(dependsOnMethods = "testCreateDatabag")
public void testCreateDatabagItem() throws Exception {
Properties config = new Properties();
config.setProperty("foo", "bar");
api.deleteDatabagItem(PREFIX, PREFIX);
DatabagItem databagItem = api.createDatabagItem(PREFIX, new DatabagItem("config", json.toJson(config)));
databagitemId = databagItem.getId();
assertNotNull(databagItem, "Created data bag item should not be null");
assertEquals(databagItem.getId(), "config");
// The databagItem json contains extra keys: (the name and the type if the
// item)
Properties props = json.fromJson(databagItem.toString(), Properties.class);
for (Object key : config.keySet()) {
assertTrue(props.containsKey(key));
assertEquals(config.get(key), props.get(key));
}
}
@Test(dependsOnMethods = "testCreateDatabagItem")
public void testUpdateDatabagItem() throws Exception {
for (String databagItemId : api.listDatabagItems(PREFIX)) {
DatabagItem databagItem = api.getDatabagItem(PREFIX, databagItemId);
api.updateDatabagItem(PREFIX, databagItem);
}
}
@Test(dependsOnMethods = "testSearchDatabagWithOptions")
public void testDeleteDatabagItem() throws Exception {
for (String databagItemId : api.listDatabagItems(PREFIX)) {
DatabagItem databagItem = api.deleteDatabagItem(PREFIX, databagItemId);
assertNotNull(databagItem, "Deleted data bag item should not be null");
assertEquals(databagItem.getId(), databagItemId, "Deleted data bag item id must match the original id");
assertNull(api.getDatabagItem(PREFIX, databagItemId), "Data bag item should not exist");
}
}
@Test
public void testListSearchIndexes() throws Exception {
Set<String> indexes = api.listSearchIndexes();
assertNotNull(indexes, "The index list should not be null");
assertTrue(indexes.contains("node"));
assertTrue(indexes.contains("client"));
assertTrue(indexes.contains("role"));
}
@Test
public void testSearchNodes() throws Exception {
SearchResult<? extends Node> results = api.searchNodes();
assertNotNull(results, "Node result list should not be null");
}
@Test(dependsOnMethods = { "testListSearchIndexes", "testCreateNode" })
public void testSearchNodesWithOptions() throws Exception {
Predicate<SearchOptions> waitForIndex = retry(new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends Node> results = api.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, MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX);
assertTrue(waitForIndex.apply(options));
}
@Test
public void testSearchClients() throws Exception {
SearchResult<? extends Client> results = api.searchClients();
assertNotNull(results, "Client result list should not be null");
}
@Test(dependsOnMethods = { "testListSearchIndexes", "testCreateClient" })
public void testSearchClientsWithOptions() throws Exception {
Predicate<SearchOptions> waitForIndex = retry(new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends Client> results = api.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, MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX);
assertTrue(waitForIndex.apply(options));
}
@Test
public void testSearchRoles() throws Exception {
SearchResult<? extends Role> results = api.searchRoles();
assertNotNull(results, "Role result list should not be null");
}
@Test(dependsOnMethods = { "testListSearchIndexes", "testCreateRole" })
public void testSearchRolesWithOptions() throws Exception {
Predicate<SearchOptions> waitForIndex = retry(new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends Role> results = api.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, MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX);
assertTrue(waitForIndex.apply(options));
}
@Test(dependsOnMethods = { "testListSearchIndexes", "testCreateDatabagItem" })
public void testSearchDatabag() throws Exception {
SearchResult<? extends DatabagItem> results = api.searchDatabagItems(PREFIX);
assertNotNull(results, "Data bag item result list should not be null");
}
@Test(dependsOnMethods = { "testListSearchIndexes", "testCreateDatabagItem" })
public void testSearchDatabagWithOptions() throws Exception {
Predicate<SearchOptions> waitForIndex = retry(new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends DatabagItem> results = api.searchDatabagItems(PREFIX, input);
assertNotNull(results);
if (results.size() > 0) {
assertEquals(results.size(), 1);
assertEquals(results.iterator().next().getId(), databagitemId);
return true;
} else {
// The index may still not be populated
return false;
}
}
}, maxWaitForIndexInMs, 5000L, MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("id:" + databagitemId);
assertTrue(waitForIndex.apply(options));
}
@Test(expectedExceptions = ResourceNotFoundException.class, dependsOnMethods = "testListSearchIndexes")
public void testSearchDatabagNotFound() throws Exception {
SearchResult<? extends DatabagItem> results = api.searchDatabagItems("whoopie");
assertNotNull(results, "Data bag item result list should not be null");
}
@Test
public void testCreateEnvironment() {
api.deleteEnvironment(PREFIX);
api.createEnvironment(Environment.builder().name(PREFIX).description(PREFIX).build());
Environment env = api.getEnvironment(PREFIX);
assertNotNull(env, "Created environment should not be null");
assertEquals(env.getName(), PREFIX);
assertEquals(env.getDescription(), PREFIX);
}
@Test(dependsOnMethods = "testCreateEnvironment")
public void testListEnvironment() {
Set<String> envList = api.listEnvironments();
assertNotNull(envList, "Environment list was null");
assertTrue(envList.contains(PREFIX));
}
@Test(dependsOnMethods = "testCreateEnvironment")
public void testSearchEnvironments() throws Exception {
SearchResult<? extends Environment> results = api.searchEnvironments();
assertNotNull(results, "Environment result list was null");
}
@Test(dependsOnMethods = { "testListSearchIndexes", "testCreateEnvironment" })
public void testSearchEnvironmentsWithOptions() throws Exception {
Predicate<SearchOptions> waitForIndex = retry(new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends Environment> results = api.searchEnvironments(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, MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX);
assertTrue(waitForIndex.apply(options));
}
@Test(dependsOnMethods = "testCreateEnvironment")
public void testListRecipesInEnvironment() {
Set<String> recipeList = api.listRecipesInEnvironment(PREFIX);
assertTrue(!recipeList.isEmpty());
}
@Test(dependsOnMethods = "testCreateEnvironment")
public void testListNodesInEnvironment() {
api.deleteNode(ENV_NODE);
api.createNode(Node.builder().name(ENV_NODE).runListElement("role[" + PREFIX + "]").environment(PREFIX).build());
Node node = api.getNode(ENV_NODE);
assertNotNull(node, "Created node should not be null");
Set<String> nodeList = api.listNodesInEnvironment(PREFIX);
assertTrue(!nodeList.isEmpty());
}
@Test(dependsOnMethods = "testCreateNewCookbook")
public void testListCookbooksInEnvironment() throws Exception {
Set<CookbookDefinition> cookbooks = api.listCookbooksInEnvironment("_default");
assertTrue(any(cookbooks, new Predicate<CookbookDefinition>() {
@Override
public boolean apply(CookbookDefinition input) {
return PREFIX.equals(input.getName());
}}), String.format("Cookbook %s not in %s", PREFIX, cookbooks));
}
@AfterClass(groups = { "live", "integration" })
@Override
public void tearDown() {
api.deleteClient(PREFIX);
api.deleteClient(ADMIN_PREFIX);
api.deleteNode(PREFIX);
api.deleteNode(ENV_NODE);
api.deleteRole(PREFIX);
api.deleteDatabag(PREFIX);
api.deleteEnvironment(PREFIX);
super.tearDown();
}
private void assertClientCreated(String identity, String credential) {
Properties overrides = super.setupProperties();
overrides.setProperty(provider + ".identity", identity);
overrides.setProperty(provider + ".credential", credential);
ChefApi clientApi = create(overrides, setupModules());
try {
Client client = clientApi.getClient(identity);
assertNotNull(client, "Client not found: " + identity);
} finally {
closeQuietly(clientApi);
}
}
}

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.enterprisechef.binders;
package org.jclouds.chef.binders;
import static org.testng.Assert.assertEquals;
@ -23,7 +23,7 @@ import java.net.URI;
import org.jclouds.chef.ChefApiMetadata;
import org.jclouds.chef.config.ChefParserModule;
import org.jclouds.enterprisechef.domain.Group;
import org.jclouds.chef.domain.Group;
import org.jclouds.http.HttpRequest;
import org.jclouds.json.config.GsonModule;
import org.jclouds.rest.annotations.ApiVersion;

View File

@ -14,13 +14,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.enterprisechef.binders;
package org.jclouds.chef.binders;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import org.jclouds.enterprisechef.domain.Group;
import org.jclouds.chef.domain.Group;
import org.testng.annotations.Test;
/**

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.enterprisechef;
package org.jclouds.chef.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
@ -24,15 +24,16 @@ import java.util.Set;
import javax.ws.rs.core.MediaType;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.chef.BaseChefApiExpectTest;
import org.jclouds.chef.ChefApi;
import org.jclouds.chef.ChefApiMetadata;
import org.jclouds.chef.config.ChefHttpApiModule;
import org.jclouds.chef.domain.Group;
import org.jclouds.chef.domain.User;
import org.jclouds.date.TimeStamp;
import org.jclouds.enterprisechef.config.EnterpriseChefHttpApiModule;
import org.jclouds.enterprisechef.domain.Group;
import org.jclouds.enterprisechef.domain.User;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.rest.ConfiguresHttpApi;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.Test;
@ -41,128 +42,125 @@ import com.google.common.base.Supplier;
import com.google.inject.Module;
/**
* Expect tests for the {@link EnterpriseChefApi} class.
* Expect tests for the {@link OrganizationApi} class.
*/
@Test(groups = "unit", testName = "EnterpriseChefApiExpectTest")
public class EnterpriseChefApiExpectTest extends BaseChefApiExpectTest<EnterpriseChefApi> {
public EnterpriseChefApiExpectTest() {
provider = "enterprisechef";
}
@Test(groups = "unit", testName = "OrganizationApiExpectTest")
public class OrganizationApiExpectTest extends BaseChefApiExpectTest<ChefApi> {
public void testGetUserReturns2xx() {
EnterpriseChefApi api = requestSendsResponse(
ChefApi api = requestSendsResponse(
signed(HttpRequest.builder() //
.method("GET") //
.endpoint("https://api.opscode.com/users/nacx") //
.endpoint("http://localhost:4000/users/nacx") //
.addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) //
.addHeader("Accept", MediaType.APPLICATION_JSON).build()), //
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/user.json", MediaType.APPLICATION_JSON)) //
.build());
User user = api.getUser("nacx");
User user = api.organizationApi().get().getUser("nacx");
assertEquals(user.getUsername(), "nacx");
assertEquals(user.getDisplayName(), "Ignasi Barrera");
}
public void testGetUserReturns404() {
EnterpriseChefApi api = requestSendsResponse(signed(HttpRequest.builder() //
ChefApi api = requestSendsResponse(signed(HttpRequest.builder() //
.method("GET") //
.endpoint("https://api.opscode.com/users/foo") //
.endpoint("http://localhost:4000/users/foo") //
.addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) //
.addHeader("Accept", MediaType.APPLICATION_JSON) //
.build()), //
HttpResponse.builder().statusCode(404).build());
assertNull(api.getUser("foo"));
assertNull(api.organizationApi().get().getUser("foo"));
}
public void testListGroups() {
EnterpriseChefApi api = requestSendsResponse(
ChefApi api = requestSendsResponse(
signed(HttpRequest.builder() //
.method("GET") //
.endpoint("https://api.opscode.com/groups") //
.endpoint("http://localhost:4000/groups") //
.addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) //
.addHeader("Accept", MediaType.APPLICATION_JSON).build()), //
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/groups.json", MediaType.APPLICATION_JSON)) //
.build());
Set<String> groups = api.listGroups();
Set<String> groups = api.organizationApi().get().listGroups();
assertEquals(groups.size(), 5);
assertTrue(groups.contains("admins"));
}
public void testGetGroupReturns2xx() {
EnterpriseChefApi api = requestSendsResponse(
ChefApi api = requestSendsResponse(
signed(HttpRequest.builder() //
.method("GET") //
.endpoint("https://api.opscode.com/groups/admins") //
.endpoint("http://localhost:4000/groups/admins") //
.addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) //
.addHeader("Accept", MediaType.APPLICATION_JSON).build()), //
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/group.json", MediaType.APPLICATION_JSON)) //
.build());
Group group = api.getGroup("admins");
Group group = api.organizationApi().get().getGroup("admins");
assertEquals(group.getName(), "admins");
assertEquals(group.getGroupname(), "admins");
}
public void testGetGroupReturns404() {
EnterpriseChefApi api = requestSendsResponse(signed(HttpRequest.builder() //
ChefApi api = requestSendsResponse(signed(HttpRequest.builder() //
.method("GET") //
.endpoint("https://api.opscode.com/groups/foo") //
.endpoint("http://localhost:4000/groups/foo") //
.addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) //
.addHeader("Accept", MediaType.APPLICATION_JSON) //
.build()), //
HttpResponse.builder().statusCode(404).build());
assertNull(api.getGroup("foo"));
assertNull(api.organizationApi().get().getGroup("foo"));
}
public void testCreateGroupReturns2xx() {
EnterpriseChefApi api = requestSendsResponse(signed(HttpRequest.builder() //
ChefApi api = requestSendsResponse(signed(HttpRequest.builder() //
.method("POST") //
.endpoint("https://api.opscode.com/groups") //
.endpoint("http://localhost:4000/groups") //
.addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) //
.addHeader("Accept", MediaType.APPLICATION_JSON) //
.payload(payloadFromStringWithContentType("{\"groupname\":\"foo\"}", MediaType.APPLICATION_JSON)) //
.build()), //
HttpResponse.builder().statusCode(201).build());
api.createGroup("foo");
api.organizationApi().get().createGroup("foo");
}
public void testDeleteGroupReturns2xx() {
EnterpriseChefApi api = requestSendsResponse(signed(HttpRequest.builder() //
ChefApi api = requestSendsResponse(signed(HttpRequest.builder() //
.method("DELETE") //
.endpoint("https://api.opscode.com/groups/foo") //
.endpoint("http://localhost:4000/groups/foo") //
.addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) //
.addHeader("Accept", MediaType.APPLICATION_JSON) //
.build()), //
HttpResponse.builder().statusCode(200).build());
api.deleteGroup("foo");
api.organizationApi().get().deleteGroup("foo");
}
@Test(expectedExceptions = ResourceNotFoundException.class)
public void testDeleteGroupFailsOn404() {
EnterpriseChefApi api = requestSendsResponse(signed(HttpRequest.builder() //
ChefApi api = requestSendsResponse(signed(HttpRequest.builder() //
.method("DELETE") //
.endpoint("https://api.opscode.com/groups/foo") //
.endpoint("http://localhost:4000/groups/foo") //
.addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) //
.addHeader("Accept", MediaType.APPLICATION_JSON) //
.build()), //
HttpResponse.builder().statusCode(404).build());
api.deleteGroup("foo");
api.organizationApi().get().deleteGroup("foo");
}
public void testUpdateGroupReturns2xx() {
EnterpriseChefApi api = requestSendsResponse(signed(HttpRequest.builder() //
ChefApi api = requestSendsResponse(signed(HttpRequest.builder() //
.method("PUT") //
.endpoint("https://api.opscode.com/groups/admins") //
.endpoint("http://localhost:4000/groups/admins") //
.addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) //
.addHeader("Accept", MediaType.APPLICATION_JSON) //
.payload(payloadFromResourceWithContentType("/group-update.json", MediaType.APPLICATION_JSON)) //
@ -170,14 +168,14 @@ public class EnterpriseChefApiExpectTest extends BaseChefApiExpectTest<Enterpris
HttpResponse.builder().statusCode(200).build());
Group group = Group.builder("admins").client("abiquo").group("admins").user("nacx").build();
api.updateGroup(group);
api.organizationApi().get().updateGroup(group);
}
@Test(expectedExceptions = ResourceNotFoundException.class)
public void testUpdateGroupFailsOn404() {
EnterpriseChefApi api = requestSendsResponse(signed(HttpRequest.builder() //
ChefApi api = requestSendsResponse(signed(HttpRequest.builder() //
.method("PUT") //
.endpoint("https://api.opscode.com/groups/admins") //
.endpoint("http://localhost:4000/groups/admins") //
.addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) //
.addHeader("Accept", MediaType.APPLICATION_JSON) //
.payload(payloadFromResourceWithContentType("/group-update.json", MediaType.APPLICATION_JSON)) //
@ -185,16 +183,16 @@ public class EnterpriseChefApiExpectTest extends BaseChefApiExpectTest<Enterpris
HttpResponse.builder().statusCode(404).build());
Group group = Group.builder("admins").client("abiquo").group("admins").user("nacx").build();
api.updateGroup(group);
api.organizationApi().get().updateGroup(group);
}
@Override
protected Module createModule() {
return new TestEnterpriseChefHttpApiModule();
return new TestChefHttpApiModule();
}
@ConfiguresHttpApi
static class TestEnterpriseChefHttpApiModule extends EnterpriseChefHttpApiModule {
static class TestChefHttpApiModule extends ChefHttpApiModule {
@Override
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
return "timestamp";
@ -202,8 +200,8 @@ public class EnterpriseChefApiExpectTest extends BaseChefApiExpectTest<Enterpris
}
@Override
protected ProviderMetadata createProviderMetadata() {
return new EnterpriseChefProviderMetadata();
protected ApiMetadata createApiMetadata() {
return new ChefApiMetadata();
}
}

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.enterprisechef;
package org.jclouds.chef.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
@ -25,98 +25,96 @@ import static org.testng.Assert.assertTrue;
import java.util.Set;
import java.util.UUID;
import org.jclouds.chef.internal.BaseChefApiLiveTest;
import org.jclouds.enterprisechef.domain.Group;
import org.jclouds.enterprisechef.domain.User;
import org.jclouds.chef.domain.Group;
import org.jclouds.chef.domain.User;
import org.jclouds.chef.internal.BaseChefLiveTest;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.SkipException;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
* Tests behavior of the EnterpriseChefApi.
* Tests behavior of the OrganizationApi.
*/
@Test(groups = "live", singleThreaded = true, testName = "EnterpriseChefApiLiveTest")
public class EnterpriseChefApiLiveTest extends BaseChefApiLiveTest<EnterpriseChefApi> {
@Test(groups = "live", singleThreaded = true, testName = "OrganizationApiLiveTest")
public class OrganizationApiLiveTest extends BaseChefLiveTest {
private static final String GROUP_NAME = System.getProperty("user.name") + "-jcloudstest";
private static final String ORG_NAME = System.getProperty("test.enterprisechef.org");
public EnterpriseChefApiLiveTest() {
provider = "enterprisechef";
}
private OrganizationApi orgApi;
@Override
@Test
public void testSearchClientsWithOptions() throws Exception {
// This test will fail because Enterprise Chef does not index client name.
// Once it is fixes, the test should succeed.
// See: http://tickets.opscode.com/browse/CHEF-2477
super.testSearchClientsWithOptions();
@BeforeMethod
public void skipIfApiNotAvailable() {
// Throwing SkipExceptions only works with @Test and @BeforeMethod methods
if (!api.organizationApi().isPresent()) {
throw new SkipException("Organization api not available in this Chef version");
}
orgApi = api.organizationApi().get();
}
public void testGetUser() {
User user = api.getUser(identity);
User user = orgApi.getUser(identity);
assertEquals(user.getUsername(), identity);
assertNotNull(user.getPublicKey());
}
public void testGetUnexistingUser() {
User user = api.getUser(UUID.randomUUID().toString());
User user = orgApi.getUser(UUID.randomUUID().toString());
assertNull(user);
}
public void testListGroups() {
Set<String> groups = api.listGroups();
Set<String> groups = orgApi.listGroups();
assertNotNull(groups);
assertFalse(groups.isEmpty());
}
public void testGetUnexistingGroup() {
Group group = api.getGroup(UUID.randomUUID().toString());
Group group = orgApi.getGroup(UUID.randomUUID().toString());
assertNull(group);
}
public void testCreateGroup() {
api.createGroup(GROUP_NAME);
Group group = api.getGroup(GROUP_NAME);
orgApi.createGroup(GROUP_NAME);
Group group = orgApi.getGroup(GROUP_NAME);
assertNotNull(group);
assertEquals(group.getGroupname(), GROUP_NAME);
}
@Test(dependsOnMethods = "testCreateGroup")
public void testUpdateGroup() {
Group group = api.getGroup(GROUP_NAME);
Group group = orgApi.getGroup(GROUP_NAME);
Group updated = Group.builder(group.getGroupname()) //
.actors(group.getActors()) //
.orgname(group.getOrgname()) //
.name(group.getName()) //
.groups(group.getGroups()) //
.client(ORG_NAME + "-validator") //
.client(group.getOrgname() + "-validator") //
.user(identity) //
.build();
api.updateGroup(updated);
group = api.getGroup(GROUP_NAME);
orgApi.updateGroup(updated);
group = orgApi.getGroup(GROUP_NAME);
assertNotNull(group);
assertTrue(group.getUsers().contains(identity));
assertTrue(group.getClients().contains(ORG_NAME + "-validator"));
assertTrue(group.getClients().contains(group.getOrgname() + "-validator"));
}
@Test(expectedExceptions = ResourceNotFoundException.class)
public void testUpdateUnexistingGroup() {
api.updateGroup(Group.builder(UUID.randomUUID().toString()).build());
orgApi.updateGroup(Group.builder(UUID.randomUUID().toString()).build());
}
@Test(dependsOnMethods = "testUpdateGroup")
@Test(dependsOnMethods = "testUpdateGroup", alwaysRun = true)
public void testDeleteGroup() {
api.deleteGroup(GROUP_NAME);
Group group = api.getGroup(GROUP_NAME);
orgApi.deleteGroup(GROUP_NAME);
Group group = orgApi.getGroup(GROUP_NAME);
assertNull(group);
}
@Test(expectedExceptions = ResourceNotFoundException.class)
public void testDeleteUnexistingGroup() {
api.deleteGroup(UUID.randomUUID().toString());
orgApi.deleteGroup(UUID.randomUUID().toString());
}
}

View File

@ -88,7 +88,6 @@ public class ParseClientFromJsonTest {
publicKey = crypto.rsaKeyFactory().generatePublic(publicKeySpec);
}
@SuppressWarnings("resource")
public void testClientWithPubKey() throws IOException, CertificateException, NoSuchAlgorithmException {
Client user = Client.builder().certificate(certificate).orgname("jclouds").clientname("adriancole-jcloudstest")
@ -99,7 +98,6 @@ public class ParseClientFromJsonTest {
.payload(ParseClientFromJsonTest.class.getResourceAsStream("/client.json")).build()), user);
}
@SuppressWarnings("resource")
public void testClientWithoutPubKey() throws IOException, CertificateException, NoSuchAlgorithmException {
Client user = Client.builder().certificate(certificate).orgname("jclouds").clientname("adriancole-jcloudstest")

View File

@ -1,542 +0,0 @@
/*
* 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.internal;
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.util.Closeables2.closeQuietly;
import static org.jclouds.util.Predicates2.retry;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import org.jclouds.chef.ChefApi;
import org.jclouds.chef.domain.ChecksumStatus;
import org.jclouds.chef.domain.Client;
import org.jclouds.chef.domain.CookbookDefinition;
import org.jclouds.chef.domain.CookbookVersion;
import org.jclouds.chef.domain.DatabagItem;
import org.jclouds.chef.domain.Environment;
import org.jclouds.chef.domain.Metadata;
import org.jclouds.chef.domain.Node;
import org.jclouds.chef.domain.Resource;
import org.jclouds.chef.domain.Role;
import org.jclouds.chef.domain.Sandbox;
import org.jclouds.chef.domain.SearchResult;
import org.jclouds.chef.domain.UploadSandbox;
import org.jclouds.chef.options.CreateClientOptions;
import org.jclouds.chef.options.SearchOptions;
import org.jclouds.crypto.Pems;
import org.jclouds.io.ByteStreams2;
import org.jclouds.io.Payloads;
import org.jclouds.io.payloads.FilePayload;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.hash.Hashing;
import com.google.common.io.Files;
import com.google.common.primitives.Bytes;
/**
* Tests behavior of {@code ChefApi}
*/
@Test(groups = { "live", "integration" })
public abstract class BaseChefApiLiveTest<A extends ChefApi> extends BaseChefLiveTest<A> {
public static final String PREFIX = "jcloudstest-" + System.getProperty("user.name");
public static final String ADMIN_PREFIX = "jcloudstest-adm-" + System.getProperty("user.name");
public static final String ENV_NODE = PREFIX + "-env-node";
// It may take a bit until the search index is populated
protected int maxWaitForIndexInMs = 60000;
// The id of the data bag item used in search tests
private String databagitemId;
public void testCreateNewCookbook() throws Exception {
// Define the file you want in the cookbook
File file = new File(System.getProperty("user.dir"), "pom.xml");
FilePayload content = uploadAndGetFilePayload(file);
// Create the metadata of the cookbook
Metadata metadata = Metadata.builder() //
.name(PREFIX) //
.version("0.0.0") //
.description("Jclouds test uploaded cookbook") //
.maintainer("jclouds") //
.maintainerEmail("someone@jclouds.org") //
.license("Apache 2.0") //
.build();
// Create a new cookbook
CookbookVersion cookbook = CookbookVersion.builder(PREFIX, "0.0.0") //
.metadata(metadata) //
.rootFile(Resource.builder().fromPayload(content).build()) //
.attribute(Resource.builder().fromPayload(content).name("default.rb").build())
.build();
// upload the cookbook to the remote server
api.updateCookbook(PREFIX, "0.0.0", cookbook);
}
private FilePayload uploadAndGetFilePayload(File file) throws IOException {
FilePayload content = Payloads.newFilePayload(file);
content.getContentMetadata().setContentType("application/x-binary");
// Get an md5 so that you can see if the server already has it or not
content.getContentMetadata().setContentMD5(Files.asByteSource(file).hash(Hashing.md5()).asBytes());
// Note that java collections cannot effectively do equals or hashcodes on
// byte arrays, so let's convert to a list of bytes.
List<Byte> md5 = Bytes.asList(content.getContentMetadata().getContentMD5());
// Request an upload site for this file
UploadSandbox site = api.createUploadSandboxForChecksums(ImmutableSet.of(md5));
assertTrue(site.getChecksums().containsKey(md5), md5 + " not in " + site.getChecksums());
try {
// Upload the file contents, if still not uploaded
ChecksumStatus status = site.getChecksums().get(md5);
if (status.needsUpload()) {
api.uploadContent(status.getUrl(), content);
}
Sandbox sandbox = api.commitSandbox(site.getSandboxId(), true);
assertTrue(sandbox.isCompleted(), "Sandbox should be completed after uploading");
} catch (RuntimeException e) {
api.commitSandbox(site.getSandboxId(), false);
fail("Could not upload content");
}
return content;
}
public void testListCookbooks() throws Exception {
Set<String> cookbookNames = api.listCookbooks();
assertFalse(cookbookNames.isEmpty(), "No cookbooks were found");
for (String cookbookName : cookbookNames) {
Set<String> versions = api.listVersionsOfCookbook(cookbookName);
assertFalse(versions.isEmpty(), "There are no versions of the cookbook: " + cookbookName);
for (String version : api.listVersionsOfCookbook(cookbookName)) {
CookbookVersion cookbook = api.getCookbook(cookbookName, version);
assertNotNull(cookbook, "Could not get cookbook: " + cookbookName);
}
}
}
@Test(dependsOnMethods = "testListCookbooks")
public void testListCookbookVersionsWithChefService() throws Exception {
Iterable<? extends CookbookVersion> cookbooks = chefService.listCookbookVersions();
assertFalse(isEmpty(cookbooks), "No cookbooks were found");
}
@Test(dependsOnMethods = "testListCookbookVersionsWithChefService")
public void testDownloadCookbooks() throws Exception {
Iterable<? extends CookbookVersion> cookbooks = chefService.listCookbookVersions();
for (CookbookVersion cookbook : cookbooks) {
for (Resource resource : ImmutableList.<Resource> builder().addAll(cookbook.getDefinitions())
.addAll(cookbook.getFiles()).addAll(cookbook.getLibraries()).addAll(cookbook.getSuppliers())
.addAll(cookbook.getRecipes()).addAll(cookbook.getResources()).addAll(cookbook.getRootFiles())
.addAll(cookbook.getTemplates()).addAll(cookbook.getAttributes()).build()) {
InputStream stream = api.getResourceContents(resource);
assertNotNull(stream, "Resource contents are null for resource: " + resource.getName());
byte[] md5 = ByteStreams2.hashAndClose(stream, md5()).asBytes();
assertEquals(md5, resource.getChecksum());
}
}
}
@Test(dependsOnMethods = "testCreateNewCookbook")
public void testUpdateCookbook() throws Exception {
CookbookVersion cookbook = api.getCookbook(PREFIX, "0.0.0");
assertNotNull(cookbook, "Cookbook not found: " + PREFIX);
assertNotNull(api.updateCookbook(PREFIX, "0.0.0", cookbook), "Updated cookbook was null");
}
@Test(dependsOnMethods = { "testCreateNewCookbook", "testUpdateCookbook" })
public void testDeleteCookbook() throws Exception {
assertNotNull(api.deleteCookbook(PREFIX, "0.0.0"), "Deleted cookbook was null");
}
@Test
public void testCreateClient() throws Exception {
api.deleteClient(PREFIX);
String credential = Pems.pem(api.createClient(PREFIX).getPrivateKey());
assertClientCreated(PREFIX, credential);
}
@Test
public void testCreateAdminClient() throws Exception {
api.deleteClient(ADMIN_PREFIX);
String credential = Pems.pem(api.createClient(ADMIN_PREFIX, CreateClientOptions.Builder.admin()).getPrivateKey());
assertClientCreated(ADMIN_PREFIX, credential);
}
@Test(dependsOnMethods = "testCreateClient")
public void testGenerateKeyForClient() throws Exception {
String credential = Pems.pem(api.generateKeyForClient(PREFIX).getPrivateKey());
assertClientCreated(PREFIX, credential);
}
@Test
public void testListNodes() throws Exception {
Set<String> nodes = api.listNodes();
assertNotNull(nodes, "No nodes were found");
}
@Test(dependsOnMethods = "testCreateRole")
public void testCreateNode() throws Exception {
api.deleteNode(PREFIX);
api.createNode(Node.builder().name(PREFIX).runListElement("role[" + PREFIX + "]").environment("_default").build());
Node node = api.getNode(PREFIX);
// TODO check recipes
assertNotNull(node, "Created node should not be null");
Set<String> nodes = api.listNodes();
assertTrue(nodes.contains(PREFIX), String.format("node %s not in %s", PREFIX, nodes));
}
@Test(dependsOnMethods = "testCreateNode")
public void testUpdateNode() throws Exception {
for (String nodename : api.listNodes()) {
Node node = api.getNode(nodename);
api.updateNode(node);
}
}
@Test
public void testListRoles() throws Exception {
Set<String> roles = api.listRoles();
assertNotNull(roles, "Role list was null");
}
@Test
public void testCreateRole() throws Exception {
api.deleteRole(PREFIX);
api.createRole(Role.builder().name(PREFIX).runListElement("recipe[java]").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]"));
}
@Test(dependsOnMethods = "testCreateRole")
public void testUpdateRole() throws Exception {
for (String rolename : api.listRoles()) {
Role role = api.getRole(rolename);
api.updateRole(role);
}
}
@Test
public void testListDatabags() throws Exception {
Set<String> databags = api.listDatabags();
assertNotNull(databags, "Data bag list was null");
}
@Test
public void testCreateDatabag() throws Exception {
api.deleteDatabag(PREFIX);
api.createDatabag(PREFIX);
}
@Test(dependsOnMethods = "testCreateDatabagItem")
public void testListDatabagItems() throws Exception {
Set<String> databagItems = api.listDatabagItems(PREFIX);
assertNotNull(databagItems, "Data bag item list was null");
}
@Test(dependsOnMethods = "testCreateDatabag")
public void testCreateDatabagItem() throws Exception {
Properties config = new Properties();
config.setProperty("foo", "bar");
api.deleteDatabagItem(PREFIX, PREFIX);
DatabagItem databagItem = api.createDatabagItem(PREFIX, new DatabagItem("config", json.toJson(config)));
databagitemId = databagItem.getId();
assertNotNull(databagItem, "Created data bag item should not be null");
assertEquals(databagItem.getId(), "config");
// The databagItem json contains extra keys: (the name and the type if the
// item)
Properties props = json.fromJson(databagItem.toString(), Properties.class);
for (Object key : config.keySet()) {
assertTrue(props.containsKey(key));
assertEquals(config.get(key), props.get(key));
}
}
@Test(dependsOnMethods = "testCreateDatabagItem")
public void testUpdateDatabagItem() throws Exception {
for (String databagItemId : api.listDatabagItems(PREFIX)) {
DatabagItem databagItem = api.getDatabagItem(PREFIX, databagItemId);
api.updateDatabagItem(PREFIX, databagItem);
}
}
@Test(dependsOnMethods = "testSearchDatabagWithOptions")
public void testDeleteDatabagItem() throws Exception {
for (String databagItemId : api.listDatabagItems(PREFIX)) {
DatabagItem databagItem = api.deleteDatabagItem(PREFIX, databagItemId);
assertNotNull(databagItem, "Deleted data bag item should not be null");
assertEquals(databagItem.getId(), databagItemId, "Deleted data bag item id must match the original id");
assertNull(api.getDatabagItem(PREFIX, databagItemId), "Data bag item should not exist");
}
}
@Test
public void testListSearchIndexes() throws Exception {
Set<String> indexes = api.listSearchIndexes();
assertNotNull(indexes, "The index list should not be null");
assertTrue(indexes.contains("node"));
assertTrue(indexes.contains("client"));
assertTrue(indexes.contains("role"));
}
@Test
public void testSearchNodes() throws Exception {
SearchResult<? extends Node> results = api.searchNodes();
assertNotNull(results, "Node result list should not be null");
}
@Test(dependsOnMethods = { "testListSearchIndexes", "testCreateNode" })
public void testSearchNodesWithOptions() throws Exception {
Predicate<SearchOptions> waitForIndex = retry(new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends Node> results = api.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, MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX);
assertTrue(waitForIndex.apply(options));
}
@Test
public void testSearchClients() throws Exception {
SearchResult<? extends Client> results = api.searchClients();
assertNotNull(results, "Client result list should not be null");
}
@Test(dependsOnMethods = { "testListSearchIndexes", "testCreateClient" })
public void testSearchClientsWithOptions() throws Exception {
Predicate<SearchOptions> waitForIndex = retry(new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends Client> results = api.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, MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX);
assertTrue(waitForIndex.apply(options));
}
@Test
public void testSearchRoles() throws Exception {
SearchResult<? extends Role> results = api.searchRoles();
assertNotNull(results, "Role result list should not be null");
}
@Test(dependsOnMethods = { "testListSearchIndexes", "testCreateRole" })
public void testSearchRolesWithOptions() throws Exception {
Predicate<SearchOptions> waitForIndex = retry(new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends Role> results = api.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, MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX);
assertTrue(waitForIndex.apply(options));
}
@Test(dependsOnMethods = { "testListSearchIndexes", "testCreateDatabagItem" })
public void testSearchDatabag() throws Exception {
SearchResult<? extends DatabagItem> results = api.searchDatabagItems(PREFIX);
assertNotNull(results, "Data bag item result list should not be null");
}
@Test(dependsOnMethods = { "testListSearchIndexes", "testCreateDatabagItem" })
public void testSearchDatabagWithOptions() throws Exception {
Predicate<SearchOptions> waitForIndex = retry(new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends DatabagItem> results = api.searchDatabagItems(PREFIX, input);
assertNotNull(results);
if (results.size() > 0) {
assertEquals(results.size(), 1);
assertEquals(results.iterator().next().getId(), databagitemId);
return true;
} else {
// The index may still not be populated
return false;
}
}
}, maxWaitForIndexInMs, 5000L, MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("id:" + databagitemId);
assertTrue(waitForIndex.apply(options));
}
@Test(expectedExceptions = ResourceNotFoundException.class, dependsOnMethods = "testListSearchIndexes")
public void testSearchDatabagNotFound() throws Exception {
SearchResult<? extends DatabagItem> results = api.searchDatabagItems("whoopie");
assertNotNull(results, "Data bag item result list should not be null");
}
@Test
public void testCreateEnvironment() {
api.deleteEnvironment(PREFIX);
api.createEnvironment(Environment.builder().name(PREFIX).description(PREFIX).build());
Environment env = api.getEnvironment(PREFIX);
assertNotNull(env, "Created environment should not be null");
assertEquals(env.getName(), PREFIX);
assertEquals(env.getDescription(), PREFIX);
}
@Test(dependsOnMethods = "testCreateEnvironment")
public void testListEnvironment() {
Set<String> envList = api.listEnvironments();
assertNotNull(envList, "Environment list was null");
assertTrue(envList.contains(PREFIX));
}
@Test(dependsOnMethods = "testCreateEnvironment")
public void testSearchEnvironments() throws Exception {
SearchResult<? extends Environment> results = api.searchEnvironments();
assertNotNull(results, "Environment result list was null");
}
@Test(dependsOnMethods = { "testListSearchIndexes", "testCreateEnvironment" })
public void testSearchEnvironmentsWithOptions() throws Exception {
Predicate<SearchOptions> waitForIndex = retry(new Predicate<SearchOptions>() {
@Override
public boolean apply(SearchOptions input) {
SearchResult<? extends Environment> results = api.searchEnvironments(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, MILLISECONDS);
SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX);
assertTrue(waitForIndex.apply(options));
}
@Test(dependsOnMethods = "testCreateEnvironment")
public void testListRecipesInEnvironment() {
Set<String> recipeList = api.listRecipesInEnvironment(PREFIX);
assertTrue(!recipeList.isEmpty());
}
@Test(dependsOnMethods = "testCreateEnvironment")
public void testListNodesInEnvironment() {
api.deleteNode(ENV_NODE);
api.createNode(Node.builder().name(ENV_NODE).runListElement("role[" + PREFIX + "]").environment(PREFIX).build());
Node node = api.getNode(ENV_NODE);
assertNotNull(node, "Created node should not be null");
Set<String> nodeList = api.listNodesInEnvironment(PREFIX);
assertTrue(!nodeList.isEmpty());
}
@Test(dependsOnMethods = "testCreateNewCookbook")
public void testListCookbooksInEnvironment() throws Exception {
Set<CookbookDefinition> cookbooks = api.listCookbooksInEnvironment("_default");
assertTrue(any(cookbooks, new Predicate<CookbookDefinition>() {
@Override
public boolean apply(CookbookDefinition input) {
return PREFIX.equals(input.getName());
}}), String.format("Cookbook %s not in %s", PREFIX, cookbooks));
}
@AfterClass(groups = { "live", "integration" })
@Override
public void tearDown() {
api.deleteClient(PREFIX);
api.deleteClient(ADMIN_PREFIX);
api.deleteNode(PREFIX);
api.deleteNode(ENV_NODE);
api.deleteRole(PREFIX);
api.deleteDatabag(PREFIX);
api.deleteEnvironment(PREFIX);
super.tearDown();
}
private void assertClientCreated(String identity, String credential) {
Properties overrides = super.setupProperties();
overrides.setProperty(provider + ".identity", identity);
overrides.setProperty(provider + ".credential", credential);
A clientApi = create(overrides, setupModules());
try {
Client client = clientApi.getClient(identity);
assertNotNull(client, "Client not found: " + identity);
} finally {
closeQuietly(clientApi);
}
}
}

View File

@ -16,8 +16,6 @@
*/
package org.jclouds.chef.internal;
import static org.jclouds.reflect.Types2.checkBound;
import java.io.File;
import java.io.IOException;
import java.util.Properties;
@ -31,12 +29,11 @@ import org.testng.annotations.Test;
import com.google.common.base.Charsets;
import com.google.common.base.Throwables;
import com.google.common.io.Files;
import com.google.common.reflect.TypeToken;
import com.google.inject.Injector;
import com.google.inject.Module;
@Test(groups = "live")
public abstract class BaseChefLiveTest<A extends ChefApi> extends BaseApiLiveTest<A> {
public abstract class BaseChefLiveTest extends BaseApiLiveTest<ChefApi> {
protected Injector injector;
protected ChefService chefService;
@ -64,9 +61,9 @@ public abstract class BaseChefLiveTest<A extends ChefApi> extends BaseApiLiveTes
}
@Override
protected A create(Properties props, Iterable<Module> modules) {
protected ChefApi create(Properties props, Iterable<Module> modules) {
injector = newBuilder().modules(modules).overrides(props).buildInjector();
return injector.getInstance(resolveApiClass());
return injector.getInstance(ChefApi.class);
}
protected String setCredentialFromPemFile(Properties overrides, String identity, String key) {
@ -86,11 +83,4 @@ public abstract class BaseChefLiveTest<A extends ChefApi> extends BaseApiLiveTes
return credentialFromFile;
}
@SuppressWarnings("unchecked")
private Class<A> resolveApiClass() {
return Class.class.cast(checkBound(new TypeToken<A>(getClass()) {
private static final long serialVersionUID = 1L;
}).getRawType());
}
}

View File

@ -1,60 +0,0 @@
/*
* 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.internal;
import java.util.Map;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.chef.ChefApi;
import org.jclouds.chef.ChefApiMetadata;
import org.jclouds.chef.config.ChefBootstrapModule;
import org.jclouds.chef.config.ChefHttpApiModule;
import org.jclouds.chef.config.ChefParserModule;
import org.jclouds.domain.JsonBall;
import org.jclouds.ohai.AutomaticSupplier;
import org.jclouds.ohai.config.ConfiguresOhai;
import org.jclouds.ohai.config.OhaiModule;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
@Test(groups = "live")
@Deprecated
public class BaseStubbedOhaiLiveTest extends BaseChefLiveTest<ChefApi> {
@ConfiguresOhai
static class TestOhaiModule extends OhaiModule {
@Override
protected Supplier<Map<String, JsonBall>> provideAutomatic(AutomaticSupplier in) {
return Suppliers.<Map<String, JsonBall>> ofInstance(ImmutableMap.of("foo", new JsonBall("bar")));
}
}
@Override
protected ApiMetadata createApiMetadata() {
return new ChefApiMetadata()
.toBuilder()
.defaultModules(
ImmutableSet.<Class<? extends Module>> of(ChefHttpApiModule.class, ChefParserModule.class,
ChefBootstrapModule.class, TestOhaiModule.class)).build();
}
}

View File

@ -19,7 +19,6 @@ package org.jclouds.chef.strategy.internal;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import org.jclouds.chef.ChefApi;
import org.jclouds.chef.internal.BaseChefLiveTest;
import org.testng.annotations.Test;
@ -29,7 +28,7 @@ import com.google.common.collect.ImmutableSet;
* Tests behavior of {@code CleanupStaleNodesAndClientsImpl} strategies
*/
@Test(groups = "live", testName = "CleanupStaleNodesAndClientsImplLiveTest")
public class CleanupStaleNodesAndClientsImplLiveTest extends BaseChefLiveTest<ChefApi> {
public class CleanupStaleNodesAndClientsImplLiveTest extends BaseChefLiveTest {
private CreateNodeAndPopulateAutomaticAttributesImpl creator;
private CleanupStaleNodesAndClientsImpl strategy;

View File

@ -20,7 +20,6 @@ import static org.testng.Assert.assertEquals;
import java.util.Set;
import org.jclouds.chef.ChefApi;
import org.jclouds.chef.domain.Node;
import org.jclouds.chef.internal.BaseChefLiveTest;
import org.jclouds.ohai.config.OhaiModule.CurrentUserProvider;
@ -33,7 +32,7 @@ import com.google.common.collect.ImmutableSet;
* strategies
*/
@Test(groups = "live", testName = "CreateNodeAndPopulateAutomaticAttributesImplLiveTest")
public class CreateNodeAndPopulateAutomaticAttributesImplLiveTest extends BaseChefLiveTest<ChefApi> {
public class CreateNodeAndPopulateAutomaticAttributesImplLiveTest extends BaseChefLiveTest {
private CurrentUserProvider currentUserProvider;
private CreateNodeAndPopulateAutomaticAttributesImpl strategy;

View File

@ -16,9 +16,9 @@
*/
package org.jclouds.chef.strategy.internal;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import java.util.Map;

View File

@ -19,7 +19,6 @@ package org.jclouds.chef.strategy.internal;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import org.jclouds.chef.ChefApi;
import org.jclouds.chef.internal.BaseChefLiveTest;
import org.testng.annotations.Test;
@ -29,7 +28,7 @@ import com.google.common.collect.ImmutableSet;
* Tests behavior of {@code DeleteAllApisAndNodesInListImpl} strategies
*/
@Test(groups = "live", testName = "DeleteAllApisAndNodesInListImplLiveTest")
public class DeleteAllApisAndNodesInListImplLiveTest extends BaseChefLiveTest<ChefApi> {
public class DeleteAllApisAndNodesInListImplLiveTest extends BaseChefLiveTest {
private DeleteAllNodesInListImpl strategy;
private CreateNodeAndPopulateAutomaticAttributesImpl creator;

View File

@ -25,9 +25,6 @@ import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import org.jclouds.chef.ChefApi;
import org.jclouds.chef.domain.ChecksumStatus;
import org.jclouds.chef.domain.CookbookVersion;
import org.jclouds.chef.domain.Metadata;
@ -44,12 +41,14 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.hash.Hashing;
import com.google.common.io.Files;
import com.google.common.primitives.Bytes;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
/**
* Tests behavior of {@code ListCookbookVersionsInEnvironmentImpl} strategies
*/
@Test(groups = "live", testName = "ListCookbookVersionsInEnvironmentImplLiveTest")
public class ListCookbookVersionsInEnvironmentImplLiveTest extends BaseChefLiveTest<ChefApi> {
public class ListCookbookVersionsInEnvironmentImplLiveTest extends BaseChefLiveTest {
public static final String PREFIX = "jcloudstest-strategy-" + System.getProperty("user.name");
private ListCookbookVersionsInEnvironmentImpl strategy;

View File

@ -19,23 +19,22 @@ package org.jclouds.chef.strategy.internal;
import static com.google.common.collect.Iterables.size;
import static org.testng.Assert.assertTrue;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import org.jclouds.chef.ChefApi;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.jclouds.chef.internal.BaseChefLiveTest;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
/**
* Tests behavior of {@code ListNodesImpl} strategies
*/
@Test(groups = "live", testName = "ListNodesImplLiveTest")
public class ListNodesImplLiveTest extends BaseChefLiveTest<ChefApi> {
public class ListNodesImplLiveTest extends BaseChefLiveTest {
private ListNodesImpl strategy;
private CreateNodeAndPopulateAutomaticAttributesImpl creator;

View File

@ -19,23 +19,22 @@ package org.jclouds.chef.strategy.internal;
import static com.google.common.collect.Iterables.size;
import static org.testng.Assert.assertTrue;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import org.jclouds.chef.ChefApi;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.jclouds.chef.internal.BaseChefLiveTest;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
/**
* Tests behavior of {@code ListNodesInEnvironmentImpl} strategies
*/
@Test(groups = "live", testName = "ListNodesInEnvironmentImplLiveTest")
public class ListNodesInEnvironmentImplLiveTest extends BaseChefLiveTest<ChefApi> {
public class ListNodesInEnvironmentImplLiveTest extends BaseChefLiveTest {
private ListNodesInEnvironmentImpl strategy;
private CreateNodeAndPopulateAutomaticAttributesImpl creator;

View File

@ -20,7 +20,6 @@ import static org.testng.Assert.assertEquals;
import java.util.Set;
import org.jclouds.chef.ChefApi;
import org.jclouds.chef.domain.Node;
import org.jclouds.chef.internal.BaseChefLiveTest;
import org.jclouds.ohai.config.OhaiModule.CurrentUserProvider;
@ -32,7 +31,7 @@ import com.google.common.collect.ImmutableSet;
* Tests behavior of {@code UpdateAutomaticAttributesOnNodeImpl} strategies
*/
@Test(groups = "live", testName = "UpdateAutomaticAttributesOnNodeImplLiveTest")
public class UpdateAutomaticAttributesOnNodeImplLiveTest extends BaseChefLiveTest<ChefApi> {
public class UpdateAutomaticAttributesOnNodeImplLiveTest extends BaseChefLiveTest {
private CurrentUserProvider currentUserProvider;
private UpdateAutomaticAttributesOnNodeImpl strategy;

View File

@ -1,6 +1,6 @@
{
"display_name" : "Ignasi Barrera",
"email" : "myemail@enterprisechef.org",
"email" : "myemail@chef.org",
"first_name" : "Ignasi",
"last_name" : "Barrera",
"middle_name" : "",

View File

@ -1,114 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-project</artifactId>
<version>2.0.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.apache.jclouds.provider</groupId>
<artifactId>enterprisechef</artifactId>
<name>jclouds Enterprise Chef provider</name>
<description>jclouds components to access Enterprise Chef</description>
<properties>
<test.enterprisechef.org>YOUR_ORG</test.enterprisechef.org>
<test.enterprisechef.endpoint>https://api.opscode.com/organizations/${test.enterprisechef.org}</test.enterprisechef.endpoint>
<test.enterprisechef.api-version />
<test.enterprisechef.build-version />
<test.enterprisechef.identity>YOUR_USER</test.enterprisechef.identity>
<test.enterprisechef.credential>${user.home}/.chef/${test.enterprisechef.org}/${test.enterprisechef.identity}.pem</test.enterprisechef.credential>
<jclouds.osgi.export>org.jclouds.enterprisechef*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.jclouds.api</groupId>
<artifactId>chef</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.jclouds.api</groupId>
<artifactId>chef</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.jclouds.driver</groupId>
<artifactId>jclouds-slf4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemPropertyVariables>
<test.enterprisechef.org>${test.enterprisechef.org}</test.enterprisechef.org>
<test.enterprisechef.endpoint>${test.enterprisechef.endpoint}</test.enterprisechef.endpoint>
<test.enterprisechef.api-version>${test.enterprisechef.api-version}</test.enterprisechef.api-version>
<test.enterprisechef.build-version>${test.enterprisechef.build-version}</test.enterprisechef.build-version>
<test.enterprisechef.identity>${test.enterprisechef.identity}</test.enterprisechef.identity>
<test.enterprisechef.credential>${test.enterprisechef.credential}</test.enterprisechef.credential>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -1,81 +0,0 @@
/*
* 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.enterprisechef;
import java.net.URI;
import java.util.Properties;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.chef.ChefApiMetadata;
import org.jclouds.chef.config.ChefBootstrapModule;
import org.jclouds.chef.config.ChefParserModule;
import org.jclouds.enterprisechef.config.EnterpriseChefHttpApiModule;
import org.jclouds.ohai.config.JMXOhaiModule;
import org.jclouds.rest.internal.BaseHttpApiMetadata;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
/**
* Implementation of {@link ApiMetadata} for the Enterprise Chef api.
*/
public class EnterpriseChefApiMetadata extends BaseHttpApiMetadata<EnterpriseChefApi> {
@Override
public Builder toBuilder() {
return new Builder().fromApiMetadata(this);
}
public EnterpriseChefApiMetadata() {
this(new Builder());
}
protected EnterpriseChefApiMetadata(final Builder builder) {
super(builder);
}
public static Properties defaultProperties() {
return ChefApiMetadata.defaultProperties();
}
public static class Builder extends BaseHttpApiMetadata.Builder<EnterpriseChefApi, Builder> {
protected Builder() {
id("enterprisechef")
.name("Enterprise Chef Api")
.identityName("User")
.credentialName("Certificate")
.version(ChefApiMetadata.DEFAULT_API_VERSION)
.documentation(URI.create("http://www.opscode.com/support"))
.defaultEndpoint("https://api.opscode.com")
.defaultProperties(EnterpriseChefApiMetadata.defaultProperties())
.defaultModules(
ImmutableSet.<Class<? extends Module>> of(EnterpriseChefHttpApiModule.class,
ChefParserModule.class, ChefBootstrapModule.class, JMXOhaiModule.class));
}
@Override
public EnterpriseChefApiMetadata build() {
return new EnterpriseChefApiMetadata(this);
}
@Override
protected Builder self() {
return this;
}
}
}

View File

@ -1,79 +0,0 @@
/*
* 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.enterprisechef;
import java.net.URI;
import java.util.Properties;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.providers.internal.BaseProviderMetadata;
import com.google.auto.service.AutoService;
/**
* Implementation of @ link ProviderMetadata} for Enterprise Chef
*/
@AutoService(ProviderMetadata.class)
public class EnterpriseChefProviderMetadata extends BaseProviderMetadata {
public static Builder builder() {
return new Builder();
}
@Override
public Builder toBuilder() {
return builder().fromProviderMetadata(this);
}
public EnterpriseChefProviderMetadata() {
super(builder());
}
public EnterpriseChefProviderMetadata(final Builder builder) {
super(builder);
}
public static Properties defaultProperties() {
Properties properties = new Properties();
return properties;
}
public static class Builder extends BaseProviderMetadata.Builder {
protected Builder() {
id("enterprisechef") //
.name("OpsCode Enterprise Chef") //
.endpoint("https://api.opscode.com") //
.homepage(URI.create("https://manage.opscode.com")) //
.console(URI.create("https://manage.opscode.com")) //
.apiMetadata(new EnterpriseChefApiMetadata()) //
.defaultProperties(EnterpriseChefProviderMetadata.defaultProperties());
}
@Override
public EnterpriseChefProviderMetadata build() {
return new EnterpriseChefProviderMetadata(this);
}
@Override
public Builder fromProviderMetadata(final ProviderMetadata in) {
super.fromProviderMetadata(in);
return this;
}
}
}

View File

@ -1,36 +0,0 @@
/*
* 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.enterprisechef.config;
import org.jclouds.chef.ChefApi;
import org.jclouds.chef.config.BaseChefHttpApiModule;
import org.jclouds.enterprisechef.EnterpriseChefApi;
import org.jclouds.rest.ConfiguresHttpApi;
/**
* Configures the Enterprise Chef connection.
*/
@ConfiguresHttpApi
public class EnterpriseChefHttpApiModule extends BaseChefHttpApiModule<EnterpriseChefApi> {
@Override
protected void configure() {
super.configure();
bind(ChefApi.class).to(EnterpriseChefApi.class);
}
}

View File

@ -1,31 +0,0 @@
/*
* 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.enterprisechef;
import org.jclouds.providers.internal.BaseProviderMetadataTest;
import org.testng.annotations.Test;
/**
* Unit tests for the {@link EnterpriseChefProviderMetadata} class.
*/
@Test(groups = "unit", testName = "EnterpriseChefProviderTest")
public class EnterpriseChefProviderMetadataTest extends BaseProviderMetadataTest {
public EnterpriseChefProviderMetadataTest() {
super(new EnterpriseChefProviderMetadata(), new EnterpriseChefApiMetadata());
}
}

View File

@ -72,6 +72,5 @@
<module>aws-route53</module>
<module>ultradns-ws</module>
<module>dynect</module>
<module>enterprisechef</module>
</modules>
</project>