mirror of https://github.com/apache/jclouds.git
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
270dfcbff2
|
@ -179,11 +179,13 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
final String finalMarker = options.getMarker();
|
||||
StorageMetadata lastMarkerMetadata = find(contents, new Predicate<StorageMetadata>() {
|
||||
public boolean apply(StorageMetadata metadata) {
|
||||
return metadata.getName().equals(finalMarker);
|
||||
return metadata.getName().compareTo(finalMarker) >= 0;
|
||||
}
|
||||
});
|
||||
contents = contents.tailSet(lastMarkerMetadata);
|
||||
contents.remove(lastMarkerMetadata);
|
||||
if (finalMarker.equals(lastMarkerMetadata.getName())) {
|
||||
contents.remove(lastMarkerMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
final String prefix = options.getDir();
|
||||
|
|
|
@ -22,6 +22,7 @@ import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursi
|
|||
import static org.jclouds.concurrent.FutureIterables.awaitCompletion;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
|
@ -31,17 +32,18 @@ import javax.inject.Singleton;
|
|||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.blobstore.AsyncBlobStore;
|
||||
import org.jclouds.blobstore.domain.PageSet;
|
||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||
import org.jclouds.blobstore.internal.BlobRuntimeException;
|
||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||
import org.jclouds.blobstore.reference.BlobStoreConstants;
|
||||
import org.jclouds.blobstore.strategy.ClearContainerStrategy;
|
||||
import org.jclouds.blobstore.strategy.ClearListStrategy;
|
||||
import org.jclouds.blobstore.strategy.ListContainerStrategy;
|
||||
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.inject.Inject;
|
||||
|
@ -57,7 +59,6 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr
|
|||
@Named(BlobStoreConstants.BLOBSTORE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
protected final ListContainerStrategy listContainer;
|
||||
protected final BackoffLimitedRetryHandler retryHandler;
|
||||
private final ExecutorService userExecutor;
|
||||
|
||||
|
@ -71,12 +72,11 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr
|
|||
|
||||
@Inject
|
||||
DeleteAllKeysInList(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
|
||||
AsyncBlobStore connection, ListContainerStrategy listContainer,
|
||||
AsyncBlobStore connection,
|
||||
BackoffLimitedRetryHandler retryHandler) {
|
||||
|
||||
this.userExecutor = userExecutor;
|
||||
this.connection = connection;
|
||||
this.listContainer = listContainer;
|
||||
this.retryHandler = retryHandler;
|
||||
}
|
||||
|
||||
|
@ -84,19 +84,31 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr
|
|||
execute(containerName, recursive());
|
||||
}
|
||||
|
||||
public void execute(final String containerName, final ListContainerOptions options) {
|
||||
public void execute(final String containerName, ListContainerOptions options) {
|
||||
String message = options.getDir() != null ? String.format("clearing path %s/%s",
|
||||
containerName, options.getDir()) : String.format("clearing container %s",
|
||||
containerName);
|
||||
options = options.clone();
|
||||
if (options.isRecursive())
|
||||
message = message + " recursively";
|
||||
Map<StorageMetadata, Exception> exceptions = Maps.newHashMap();
|
||||
PageSet<? extends StorageMetadata> listing;
|
||||
Iterable<? extends StorageMetadata> toDelete;
|
||||
for (int i = 0; i < 3; i++) { // TODO parameterize
|
||||
toDelete = getResourcesToDelete(containerName, options);
|
||||
if (Iterables.isEmpty(toDelete)) {
|
||||
break;
|
||||
int maxErrors = 3; // TODO parameterize
|
||||
for (int i = 0; i < maxErrors; ) {
|
||||
try {
|
||||
listing = connection.list(containerName, options).get();
|
||||
} catch (ExecutionException ee) {
|
||||
++i;
|
||||
if (i == maxErrors) {
|
||||
throw new BlobRuntimeException("list error", ee.getCause());
|
||||
}
|
||||
retryHandler.imposeBackoffExponentialDelay(i, message);
|
||||
continue;
|
||||
} catch (InterruptedException ie) {
|
||||
throw Throwables.propagate(ie);
|
||||
}
|
||||
toDelete = filterListing(listing, options);
|
||||
|
||||
Map<StorageMetadata, Future<?>> responses = Maps.newHashMap();
|
||||
try {
|
||||
|
@ -127,24 +139,30 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr
|
|||
exceptions = awaitCompletion(responses, userExecutor, maxTime, logger, message);
|
||||
}
|
||||
if (!exceptions.isEmpty()) {
|
||||
retryHandler.imposeBackoffExponentialDelay(i + 1, message);
|
||||
++i;
|
||||
retryHandler.imposeBackoffExponentialDelay(i, message);
|
||||
continue;
|
||||
}
|
||||
|
||||
String marker = listing.getNextMarker();
|
||||
if (marker == null) {
|
||||
break;
|
||||
}
|
||||
options = options.afterMarker(marker);
|
||||
}
|
||||
if (!exceptions.isEmpty())
|
||||
throw new BlobRuntimeException(String.format("error %s: %s", message, exceptions));
|
||||
toDelete = getResourcesToDelete(containerName, options);
|
||||
assert Iterables.isEmpty(toDelete) : String.format("items remaining %s: %s", message,
|
||||
toDelete);
|
||||
}
|
||||
|
||||
private boolean parentIsFolder(final ListContainerOptions options, final StorageMetadata md) {
|
||||
return (options.getDir() != null && md.getName().indexOf('/') == -1);
|
||||
}
|
||||
|
||||
private Iterable<? extends StorageMetadata> getResourcesToDelete(final String containerName,
|
||||
private Iterable<? extends StorageMetadata> filterListing(
|
||||
final PageSet<? extends StorageMetadata> listing,
|
||||
final ListContainerOptions options) {
|
||||
Iterable<? extends StorageMetadata> toDelete = Iterables.filter(listContainer.execute(
|
||||
containerName, options), new Predicate<StorageMetadata>() {
|
||||
Iterable<? extends StorageMetadata> toDelete = Iterables.filter(listing,
|
||||
new Predicate<StorageMetadata>() {
|
||||
|
||||
@Override
|
||||
public boolean apply(StorageMetadata input) {
|
||||
|
|
|
@ -35,17 +35,17 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||
* Provides asynchronous access to Service via their REST API.
|
||||
* <p/>
|
||||
*
|
||||
* @see ServiceClient
|
||||
* @see AuthenticationClient
|
||||
* @see <a href=
|
||||
* "http://docs.openstack.org/api/openstack-identity-service/2.0/content/Service_API_Client_Operations.html"
|
||||
* />
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Path("/v1.1")
|
||||
public interface ServiceAsyncClient {
|
||||
public interface AuthenticationAsyncClient {
|
||||
|
||||
/**
|
||||
* @see ServiceClient#authenticate
|
||||
* @see AuthenticationClient#authenticate
|
||||
*/
|
||||
@POST
|
||||
@SelectJson("auth")
|
|
@ -27,13 +27,13 @@ import org.jclouds.openstack.keystone.v1_1.domain.Auth;
|
|||
* Provides synchronous access to the KeyStone Service API.
|
||||
* <p/>
|
||||
*
|
||||
* @see ServiceAsyncClient
|
||||
* @see AuthenticationAsyncClient
|
||||
* @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Service_API_Client_Operations.html"
|
||||
* />
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
|
||||
public interface ServiceClient {
|
||||
public interface AuthenticationClient {
|
||||
|
||||
/**
|
||||
* Authenticate to generate a token.
|
|
@ -35,8 +35,8 @@ import org.jclouds.http.annotation.ClientError;
|
|||
import org.jclouds.location.Provider;
|
||||
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
||||
import org.jclouds.openstack.Authentication;
|
||||
import org.jclouds.openstack.keystone.v1_1.ServiceAsyncClient;
|
||||
import org.jclouds.openstack.keystone.v1_1.ServiceClient;
|
||||
import org.jclouds.openstack.keystone.v1_1.AuthenticationAsyncClient;
|
||||
import org.jclouds.openstack.keystone.v1_1.AuthenticationClient;
|
||||
import org.jclouds.openstack.keystone.v1_1.domain.Auth;
|
||||
import org.jclouds.openstack.keystone.v1_1.handlers.RetryOnRenew;
|
||||
import org.jclouds.openstack.keystone.v1_1.suppliers.RegionIdToURIFromAuthForServiceSupplier;
|
||||
|
@ -63,7 +63,7 @@ public class AuthenticationServiceModule extends AbstractModule {
|
|||
}).to(GetAuth.class);
|
||||
// ServiceClient is used directly for filters and retry handlers, so let's bind it
|
||||
// explicitly
|
||||
bindClientAndAsyncClient(binder(), ServiceClient.class, ServiceAsyncClient.class);
|
||||
bindClientAndAsyncClient(binder(), AuthenticationClient.class, AuthenticationAsyncClient.class);
|
||||
install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
|
||||
RegionIdToURIFromAuthForServiceSupplier.class).build(RegionIdToURISupplier.Factory.class));
|
||||
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class);
|
||||
|
@ -88,7 +88,7 @@ public class AuthenticationServiceModule extends AbstractModule {
|
|||
public static class GetAuth extends RetryOnTimeOutExceptionFunction<Credentials, Auth> {
|
||||
|
||||
@Inject
|
||||
public GetAuth(final ServiceClient client) {
|
||||
public GetAuth(final AuthenticationClient client) {
|
||||
super(new Function<Credentials, Auth>() {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -37,16 +37,16 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||
* Provides asynchronous access to Service via their REST API.
|
||||
* <p/>
|
||||
*
|
||||
* @see ServiceClient
|
||||
* @see AuthenticationClient
|
||||
* @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Service_API_Client_Operations.html"
|
||||
* />
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Path("/v2.0")
|
||||
public interface ServiceAsyncClient {
|
||||
public interface AuthenticationAsyncClient {
|
||||
|
||||
/**
|
||||
* @see ServiceClient#authenticateTenantWithCredentials(String,PasswordCredentials)
|
||||
* @see AuthenticationClient#authenticateTenantWithCredentials(String,PasswordCredentials)
|
||||
*/
|
||||
@POST
|
||||
@SelectJson("access")
|
||||
|
@ -57,7 +57,7 @@ public interface ServiceAsyncClient {
|
|||
PasswordCredentials passwordCredentials);
|
||||
|
||||
/**
|
||||
* @see ServiceClient#authenticateTenantWithCredentials(String,ApiAccessKeyCredentials)
|
||||
* @see AuthenticationClient#authenticateTenantWithCredentials(String,ApiAccessKeyCredentials)
|
||||
*/
|
||||
@POST
|
||||
@SelectJson("access")
|
|
@ -29,13 +29,13 @@ import org.jclouds.openstack.keystone.v2_0.domain.PasswordCredentials;
|
|||
* Provides synchronous access to the KeyStone Service API.
|
||||
* <p/>
|
||||
*
|
||||
* @see ServiceAsyncClient
|
||||
* @see AuthenticationAsyncClient
|
||||
* @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Service_API_Client_Operations.html"
|
||||
* />
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
|
||||
public interface ServiceClient {
|
||||
public interface AuthenticationClient {
|
||||
|
||||
/**
|
||||
* Authenticate to generate a token.
|
|
@ -40,12 +40,14 @@ import org.jclouds.location.suppliers.ZoneIdsSupplier;
|
|||
import org.jclouds.location.suppliers.derived.RegionIdsFromRegionIdToURIKeySet;
|
||||
import org.jclouds.location.suppliers.derived.ZoneIdsFromZoneIdToURIKeySet;
|
||||
import org.jclouds.openstack.Authentication;
|
||||
import org.jclouds.openstack.keystone.v2_0.ServiceAsyncClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.ServiceClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.AuthenticationAsyncClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.AuthenticationClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
||||
import org.jclouds.openstack.keystone.v2_0.functions.AuthenticateApiAccessKeyCredentials;
|
||||
import org.jclouds.openstack.keystone.v2_0.functions.AuthenticatePasswordCredentials;
|
||||
import org.jclouds.openstack.keystone.v2_0.handlers.RetryOnRenew;
|
||||
import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURIFromAccessForTypeAndVersionSupplier;
|
||||
import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURISupplier;
|
||||
import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToURIFromAccessForTypeAndVersionSupplier;
|
||||
import org.jclouds.openstack.keystone.v2_0.suppliers.ZoneIdToURIFromAccessForTypeAndVersionSupplier;
|
||||
import org.jclouds.rest.annotations.ApiVersion;
|
||||
|
@ -85,6 +87,8 @@ public class KeystoneAuthenticationModule extends AbstractModule {
|
|||
protected void configure() {
|
||||
install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
|
||||
RegionIdToURIFromAccessForTypeAndVersionSupplier.class).build(RegionIdToURISupplier.Factory.class));
|
||||
install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
|
||||
RegionIdToAdminURIFromAccessForTypeAndVersionSupplier.class).build(RegionIdToAdminURISupplier.Factory.class));
|
||||
// dynamically build the region list as opposed to from properties
|
||||
bind(RegionIdsSupplier.class).to(RegionIdsFromRegionIdToURIKeySet.class);
|
||||
}
|
||||
|
@ -98,6 +102,16 @@ public class KeystoneAuthenticationModule extends AbstractModule {
|
|||
RegionIdToURISupplier.Factory factory) {
|
||||
return factory.createForApiTypeAndVersion(serviceType, apiVersion);
|
||||
}
|
||||
|
||||
// supply the region to id to AdminURL map from keystone, based on the servicetype and api version in
|
||||
// config
|
||||
@Provides
|
||||
@Singleton
|
||||
protected RegionIdToAdminURISupplier provideRegionIdToAdminURISupplierForApiVersion(
|
||||
@Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
|
||||
RegionIdToAdminURISupplier.Factory factory) {
|
||||
return factory.createForApiTypeAndVersion(serviceType, apiVersion);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -132,7 +146,7 @@ public class KeystoneAuthenticationModule extends AbstractModule {
|
|||
bind(CredentialType.class).toProvider(CredentialTypeFromPropertyOrDefault.class);
|
||||
// ServiceClient is used directly for filters and retry handlers, so let's bind it
|
||||
// explicitly
|
||||
bindClientAndAsyncClient(binder(), ServiceClient.class, ServiceAsyncClient.class);
|
||||
bindClientAndAsyncClient(binder(), AuthenticationClient.class, AuthenticationAsyncClient.class);
|
||||
install(locationModule);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.openstack.domain.Link;
|
||||
import org.jclouds.openstack.domain.Resource;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Objects.ToStringHelper;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Class ApiMetadata
|
||||
*/
|
||||
public class ApiMetadata extends Resource {
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public Builder toBuilder() {
|
||||
return new Builder().fromApiMetadata(this);
|
||||
}
|
||||
|
||||
public static class Builder extends Resource.Builder {
|
||||
private String status;
|
||||
private Date updated;
|
||||
private Set<MediaType> mediaTypes = Sets.newLinkedHashSet();
|
||||
|
||||
public Builder status(String status) {
|
||||
this.status = status;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder updated(Date updated) {
|
||||
this.updated = updated;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder mediaTypes(Set<MediaType> mediaTypes) {
|
||||
this.mediaTypes = mediaTypes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ApiMetadata build() {
|
||||
return new ApiMetadata(id, name, links, updated, status, mediaTypes);
|
||||
}
|
||||
|
||||
public Builder fromApiMetadata(ApiMetadata in) {
|
||||
return fromResource(in)
|
||||
.status(in.getStatus())
|
||||
.updated(in.getUpdated())
|
||||
.mediaTypes(in.getMediaTypes());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder id(String id) {
|
||||
return Builder.class.cast(super.id(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder name(String name) {
|
||||
return Builder.class.cast(super.name(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder links(Set<Link> links) {
|
||||
return Builder.class.cast(super.links(links));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Builder fromResource(Resource in) {
|
||||
return Builder.class.cast(super.fromResource(in));
|
||||
}
|
||||
}
|
||||
|
||||
private final String status;
|
||||
private final Date updated;
|
||||
@SerializedName("media-types")
|
||||
private final Set<MediaType> mediaTypes;
|
||||
|
||||
protected ApiMetadata(String id, String name, Set<Link> links, Date updated, String status, Set<MediaType> mediaTypes) {
|
||||
super(id, name, links);
|
||||
this.status = status;
|
||||
this.updated = updated;
|
||||
this.mediaTypes = ImmutableSet.copyOf(checkNotNull(mediaTypes, "mediaTypes"));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
@Nullable
|
||||
public String getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
@Nullable
|
||||
public Date getUpdated() {
|
||||
return this.updated;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
@Nullable
|
||||
public Set<MediaType> getMediaTypes() {
|
||||
return Collections.unmodifiableSet(this.mediaTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(status, updated, mediaTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null || getClass() != obj.getClass()) return false;
|
||||
ApiMetadata that = ApiMetadata.class.cast(obj);
|
||||
return Objects.equal(this.status, that.status)
|
||||
&& Objects.equal(this.updated, that.updated)
|
||||
&& Objects.equal(this.mediaTypes, that.mediaTypes)
|
||||
;
|
||||
}
|
||||
|
||||
protected ToStringHelper string() {
|
||||
return super.string()
|
||||
.add("status", status)
|
||||
.add("updated", updated)
|
||||
.add("mediaTypes", mediaTypes);
|
||||
}
|
||||
|
||||
}
|
|
@ -55,6 +55,7 @@ public class Endpoint implements Comparable<Endpoint> {
|
|||
protected String region;
|
||||
protected URI publicURL;
|
||||
protected URI internalURL;
|
||||
protected URI adminURL;
|
||||
protected String tenantId;
|
||||
|
||||
/**
|
||||
|
@ -89,6 +90,14 @@ public class Endpoint implements Comparable<Endpoint> {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Endpoint#getInternalURL()
|
||||
*/
|
||||
public Builder adminURL(URI adminURL) {
|
||||
this.adminURL = checkNotNull(adminURL, "adminURL");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Endpoint#getTenantId()
|
||||
*/
|
||||
|
@ -98,7 +107,7 @@ public class Endpoint implements Comparable<Endpoint> {
|
|||
}
|
||||
|
||||
public Endpoint build() {
|
||||
return new Endpoint(versionId, region, publicURL, internalURL, tenantId);
|
||||
return new Endpoint(versionId, region, publicURL, internalURL, adminURL, tenantId);
|
||||
}
|
||||
|
||||
public Builder fromEndpoint(Endpoint from) {
|
||||
|
@ -113,17 +122,20 @@ public class Endpoint implements Comparable<Endpoint> {
|
|||
protected final String region;
|
||||
protected final URI publicURL;
|
||||
protected final URI internalURL;
|
||||
protected final URI adminURL;
|
||||
|
||||
// renamed half-way through
|
||||
@Deprecated
|
||||
protected String tenantName;
|
||||
protected final String tenantId;
|
||||
|
||||
protected Endpoint(String versionId, String region, @Nullable URI publicURL, @Nullable URI internalURL,
|
||||
@Nullable String tenantId) {
|
||||
@Nullable URI adminURL, @Nullable String tenantId) {
|
||||
this.versionId = checkNotNull(versionId, "versionId");
|
||||
this.region = checkNotNull(region, "region");
|
||||
this.publicURL = publicURL;
|
||||
this.internalURL = internalURL;
|
||||
this.adminURL = adminURL;
|
||||
this.tenantId = tenantId;
|
||||
}
|
||||
|
||||
|
@ -160,6 +172,14 @@ public class Endpoint implements Comparable<Endpoint> {
|
|||
return internalURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the admin url of the endpoint
|
||||
*/
|
||||
@Nullable
|
||||
public URI getAdminURL() {
|
||||
return adminURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the tenant versionId of the endpoint or null
|
||||
*/
|
||||
|
@ -176,7 +196,7 @@ public class Endpoint implements Comparable<Endpoint> {
|
|||
if (object instanceof Endpoint) {
|
||||
final Endpoint other = Endpoint.class.cast(object);
|
||||
return equal(getVersionId(), other.getVersionId()) && equal(region, other.region) && equal(publicURL, other.publicURL)
|
||||
&& equal(internalURL, other.internalURL) && equal(getTenantId(), other.getTenantId());
|
||||
&& equal(internalURL, other.internalURL) && equal(adminURL, other.adminURL) && equal(getTenantId(), other.getTenantId());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -184,13 +204,13 @@ public class Endpoint implements Comparable<Endpoint> {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(getVersionId(), region, publicURL, internalURL, getTenantId());
|
||||
return Objects.hashCode(getVersionId(), region, publicURL, internalURL, adminURL, getTenantId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper("").add("versionId", getVersionId()).add("region", region).add("publicURL", publicURL).add("internalURL",
|
||||
internalURL).add("tenantId", getTenantId()).toString();
|
||||
internalURL).add("adminURL", adminURL).add("tenantId", getTenantId()).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.domain;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Objects.ToStringHelper;
|
||||
|
||||
/**
|
||||
* Class MediaType
|
||||
*/
|
||||
public class MediaType {
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public Builder toBuilder() {
|
||||
return builder().fromMediaType(this);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private String base;
|
||||
private String type;
|
||||
|
||||
public Builder base(String base) {
|
||||
this.base = base;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder type(String type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MediaType build() {
|
||||
return new MediaType(this);
|
||||
}
|
||||
|
||||
public Builder fromMediaType(MediaType in) {
|
||||
return this.base(in.getBase()).type(in.getType());
|
||||
}
|
||||
}
|
||||
|
||||
private final String base;
|
||||
private final String type;
|
||||
|
||||
protected MediaType(Builder builder) {
|
||||
this.base = builder.base;
|
||||
this.type = builder.type;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
@Nullable
|
||||
public String getBase() {
|
||||
return this.base;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
@Nullable
|
||||
public String getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(base, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null || getClass() != obj.getClass()) return false;
|
||||
MediaType that = MediaType.class.cast(obj);
|
||||
return Objects.equal(this.base, that.base)
|
||||
&& Objects.equal(this.type, that.type)
|
||||
;
|
||||
}
|
||||
|
||||
protected ToStringHelper string() {
|
||||
return Objects.toStringHelper("")
|
||||
.add("base", base)
|
||||
.add("type", type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return string().toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -52,7 +52,7 @@ public class Service implements Comparable<Service> {
|
|||
protected Set<Endpoint> endpoints = ImmutableSet.of();
|
||||
|
||||
/**
|
||||
* @see Service#getId()
|
||||
* @see Service#getType()
|
||||
*/
|
||||
public Builder type(String type) {
|
||||
this.type = checkNotNull(type, "type");
|
||||
|
|
|
@ -23,12 +23,16 @@ import static com.google.common.base.Objects.equal;
|
|||
import static com.google.common.base.Objects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import javax.ws.rs.DefaultValue;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* A container used to group or isolate resources and/or identity objects. Depending on the service
|
||||
* operator, a tenant may map to a customer, account, organization, or project.
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
* @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Identity-Service-Concepts-e1362.html"
|
||||
* />
|
||||
|
@ -46,6 +50,7 @@ public class Tenant implements Comparable<Tenant> {
|
|||
public static class Builder {
|
||||
protected String id;
|
||||
protected String name;
|
||||
protected String description;
|
||||
|
||||
/**
|
||||
* @see Tenant#getId()
|
||||
|
@ -63,8 +68,16 @@ public class Tenant implements Comparable<Tenant> {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Tenant#getDescription()
|
||||
*/
|
||||
public Builder description(String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Tenant build() {
|
||||
return new Tenant(id, name);
|
||||
return new Tenant(id, name, description);
|
||||
}
|
||||
|
||||
public Builder fromTenant(Tenant from) {
|
||||
|
@ -74,15 +87,17 @@ public class Tenant implements Comparable<Tenant> {
|
|||
|
||||
protected final String id;
|
||||
protected final String name;
|
||||
protected final String description;
|
||||
|
||||
public Tenant(String id, String name) {
|
||||
protected Tenant(String id, String name, String description) {
|
||||
this.id = checkNotNull(id, "id");
|
||||
this.name = checkNotNull(name, "name");
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* When providing an ID, it is assumed that the tenant exists in the current OpenStack deployment
|
||||
*
|
||||
*
|
||||
* @return the id of the tenant in the current OpenStack deployment
|
||||
*/
|
||||
public String getId() {
|
||||
|
@ -96,6 +111,14 @@ public class Tenant implements Comparable<Tenant> {
|
|||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the description of the tenant
|
||||
*/
|
||||
@Nullable
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object) {
|
||||
|
@ -103,7 +126,8 @@ public class Tenant implements Comparable<Tenant> {
|
|||
}
|
||||
if (object instanceof Tenant) {
|
||||
final Tenant other = Tenant.class.cast(object);
|
||||
return equal(id, other.id) && equal(name, other.name);
|
||||
return equal(id, other.id) && equal(name, other.name)
|
||||
&& equal(description, other.description);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -111,12 +135,12 @@ public class Tenant implements Comparable<Tenant> {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(id, name);
|
||||
return Objects.hashCode(id, name, description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper("").add("id", id).add("name", name).toString();
|
||||
return toStringHelper("").add("id", id).add("name", name).add("description", description).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -98,11 +98,17 @@ public class User implements Comparable<User> {
|
|||
protected final String name;
|
||||
protected final Set<Role> roles;
|
||||
|
||||
public User(String id, String name, Set<Role> roles) {
|
||||
protected User(String id, String name, Set<Role> roles) {
|
||||
this.id = checkNotNull(id, "id");
|
||||
this.name = checkNotNull(name, "name");
|
||||
this.roles = ImmutableSet.copyOf(checkNotNull(roles, "roles"));
|
||||
}
|
||||
|
||||
protected User() {
|
||||
id = null;
|
||||
name = null;
|
||||
roles = ImmutableSet.of();
|
||||
}
|
||||
|
||||
/**
|
||||
* When providing an ID, it is assumed that the user exists in the current OpenStack deployment
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
|
||||
/**
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
@Singleton
|
||||
public class AdminURL implements EndpointToSupplierAdminURI {
|
||||
@Override
|
||||
public Supplier<URI> apply(Endpoint input) {
|
||||
return Suppliers.ofInstance(input.getAdminURL());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "supplyAdminURL()";
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@ import javax.inject.Inject;
|
|||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.openstack.keystone.v2_0.ServiceClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.AuthenticationClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.ApiAccessKeyCredentials;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
|
@ -31,10 +31,10 @@ import com.google.common.base.Function;
|
|||
|
||||
@Singleton
|
||||
public class AuthenticateApiAccessKeyCredentials implements Function<Credentials, Access> {
|
||||
private final ServiceClient client;
|
||||
private final AuthenticationClient client;
|
||||
|
||||
@Inject
|
||||
public AuthenticateApiAccessKeyCredentials(ServiceClient client) {
|
||||
public AuthenticateApiAccessKeyCredentials(AuthenticationClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ package org.jclouds.openstack.keystone.v2_0.functions;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.openstack.keystone.v2_0.ServiceClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.AuthenticationClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.PasswordCredentials;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
|
@ -28,10 +28,10 @@ import org.jclouds.rest.AuthorizationException;
|
|||
import com.google.common.base.Function;
|
||||
|
||||
public class AuthenticatePasswordCredentials implements Function<Credentials, Access> {
|
||||
private final ServiceClient client;
|
||||
private final AuthenticationClient client;
|
||||
|
||||
@Inject
|
||||
public AuthenticatePasswordCredentials(ServiceClient client) {
|
||||
public AuthenticatePasswordCredentials(AuthenticationClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
||||
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
/**
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
@ImplementedBy(AdminURL.class)
|
||||
public interface EndpointToSupplierAdminURI extends EndpointToSupplierURI {
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package org.jclouds.openstack.keystone.v2_0.functions;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.location.functions.RegionToEndpoint;
|
||||
import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURISupplier;
|
||||
|
||||
/**
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
public class RegionToAdminEndpointURI extends RegionToEndpoint {
|
||||
@Inject
|
||||
public RegionToAdminEndpointURI(RegionIdToAdminURISupplier regionToEndpointSupplier) {
|
||||
super(regionToEndpointSupplier);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.suppliers;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
||||
import org.jclouds.openstack.keystone.v2_0.functions.EndpointToRegion;
|
||||
import org.jclouds.openstack.keystone.v2_0.functions.EndpointToSupplierAdminURI;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
@Singleton
|
||||
public class RegionIdToAdminURIFromAccessForTypeAndVersionSupplier extends
|
||||
LocationIdToURIFromAccessForTypeAndVersionSupplier implements RegionIdToAdminURISupplier {
|
||||
@Inject
|
||||
public RegionIdToAdminURIFromAccessForTypeAndVersionSupplier(Supplier<Access> access,
|
||||
EndpointToSupplierAdminURI endpointToSupplierURI, EndpointToRegion endpointToRegion,
|
||||
@Assisted("apiType") String apiType, @Assisted("apiVersion") String apiVersion) {
|
||||
super(access, endpointToSupplierURI, endpointToRegion, apiType, apiVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "regionIdToAdminURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package org.jclouds.openstack.keystone.v2_0.suppliers;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.inject.ImplementedBy;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
/**
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
@ImplementedBy(RegionIdToAdminURIFromAccessForTypeAndVersionSupplier.class)
|
||||
public interface RegionIdToAdminURISupplier extends Supplier<Map<String, Supplier<URI>>> {
|
||||
static interface Factory {
|
||||
/**
|
||||
*
|
||||
* @param apiType
|
||||
* type of the api, according to the provider. ex. {@code compute} {@code
|
||||
* object-store}
|
||||
* @param apiVersion
|
||||
* version of the api
|
||||
* @return regions mapped to default uri
|
||||
*/
|
||||
RegionIdToAdminURISupplier createForApiTypeAndVersion(@Assisted("apiType") String apiType,
|
||||
@Assisted("apiVersion") String apiVersion);
|
||||
}
|
||||
}
|
|
@ -41,4 +41,8 @@ public interface ServiceType {
|
|||
* Image Service (Glance)
|
||||
*/
|
||||
public static final String IMAGE = "image";
|
||||
/**
|
||||
* Identity Service (Keystone)
|
||||
*/
|
||||
public static final String IDENTITY = "identity";
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
@Test(groups = "unit", testName = "AdminURLTest")
|
||||
public class AdminURLTest {
|
||||
private final AdminURL fn = new AdminURL();
|
||||
|
||||
public void testAdminURL() {
|
||||
assertEquals(fn.apply(
|
||||
Endpoint.builder().region("LON").versionId("1.0").adminURL(
|
||||
URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
|
||||
.build()).get(), URI
|
||||
.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"));
|
||||
}
|
||||
|
||||
public void testPublicURLNullReturnsInternalURL() {
|
||||
assertEquals(fn
|
||||
.apply(
|
||||
Endpoint.builder().region("lon").versionId("1.0")
|
||||
.internalURL(URI.create("https://192.168.1.1")).build()).get(), null);
|
||||
}
|
||||
|
||||
}
|
|
@ -67,11 +67,13 @@ public class ParseAccessTest extends BaseItemParserTest<Access> {
|
|||
Service.builder().name("Object Storage").type("object-store").endpoints(
|
||||
Endpoint.builder().tenantId("40806637803162").publicURL(
|
||||
URI.create("https://objects.jclouds.org/v1.0/40806637803162"))
|
||||
.adminURL(URI.create("https://objects.jclouds.org/v1.0/"))
|
||||
.region("region-a.geo-1").versionId("1.0").build()).build(),
|
||||
|
||||
Service.builder().name("Identity").type("identity").endpoints(
|
||||
Endpoint.builder().publicURL(URI.create("https://csnode.jclouds.org/v2.0/")).region(
|
||||
"region-a.geo-1").versionId("2.0").build()).build(),
|
||||
Endpoint.builder().publicURL(URI.create("https://csnode.jclouds.org/v2.0/"))
|
||||
.adminURL(URI.create("https://csnode.jclouds.org:35357/v2.0/"))
|
||||
.region("region-a.geo-1").versionId("2.0").build()).build(),
|
||||
|
||||
Service.builder().name("Image Management").type("image").endpoints(
|
||||
Endpoint.builder().tenantId("40806637803162").publicURL(
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.parse;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||
import org.jclouds.json.BaseItemParserTest;
|
||||
import org.jclouds.openstack.domain.Link;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Role;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Service;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Token;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.User;
|
||||
import org.jclouds.rest.annotations.SelectJson;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
@Test(groups = "unit", testName = "ParseApiMetadataTest")
|
||||
public class ParseApiMetadataTest extends BaseItemParserTest<ApiMetadata> {
|
||||
|
||||
@Override
|
||||
public String resource() {
|
||||
return "/apiMetadataResponse.json";
|
||||
}
|
||||
|
||||
@Override
|
||||
@SelectJson("version")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public ApiMetadata expected() {
|
||||
return ApiMetadata.builder().id("v2.0")
|
||||
.links(ImmutableSet.of(Link.builder().relation(Link.Relation.SELF).href(URI.create("http://172.16.89.140:5000/v2.0/")).build(),
|
||||
Link.builder().relation(Link.Relation.DESCRIBEDBY).type("text/html").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/content/")).build(),
|
||||
Link.builder().relation(Link.Relation.DESCRIBEDBY).type("application/pdf").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf")).build()
|
||||
))
|
||||
.status("beta")
|
||||
.updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-11-19T00:00:00Z"))
|
||||
.mediaTypes(ImmutableSet.of(
|
||||
org.jclouds.openstack.keystone.v2_0.domain.MediaType.builder().base("application/json").type("application/vnd.openstack.identity-v2.0+json").build(),
|
||||
org.jclouds.openstack.keystone.v2_0.domain.MediaType.builder().base("application/xml").type("application/vnd.openstack.identity-v2.0+xml").build()
|
||||
))
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.suppliers;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
||||
import org.jclouds.openstack.keystone.v2_0.parse.ParseAccessTest;
|
||||
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.Maps;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
|
||||
/**
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
@Test(groups = "unit", testName = "RegionIdToAdminURIFromAccessForTypeAndVersionSupplierTest")
|
||||
public class RegionIdToAdminURIFromAccessForTypeAndVersionSupplierTest {
|
||||
private final RegionIdToAdminURISupplier.Factory factory = Guice.createInjector(new AbstractModule() {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
|
||||
RegionIdToAdminURIFromAccessForTypeAndVersionSupplier.class).build(RegionIdToAdminURISupplier.Factory.class));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Provides
|
||||
@Singleton
|
||||
public Supplier<Access> provide() {
|
||||
return Suppliers.ofInstance(new ParseAccessTest().expected());
|
||||
}
|
||||
}).getInstance(RegionIdToAdminURISupplier.Factory.class);
|
||||
|
||||
public void testRegionMatches() {
|
||||
assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("identity", "2.0").get(), Suppliers
|
||||
.<URI> supplierFunction()), ImmutableMap.of("region-a.geo-1", URI.create("https://csnode.jclouds.org:35357/v2.0/")));
|
||||
Map<String, URI> map = Maps.newLinkedHashMap();
|
||||
map.put("region-a.geo-1", null);
|
||||
assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.1").get(), Suppliers
|
||||
.<URI> supplierFunction()), map);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{"version": {"status": "beta", "updated": "2011-11-19T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}, {"base": "application/xml", "type": "application/vnd.openstack.identity-v2.0+xml"}], "id": "v2.0", "links": [{"href": "http://172.16.89.140:5000/v2.0/", "rel": "self"}, {"href": "http://docs.openstack.org/api/openstack-identity-service/2.0/content/", "type": "text/html", "rel": "describedby"}, {"href": "http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf", "type": "application/pdf", "rel": "describedby"}]}}
|
|
@ -56,9 +56,11 @@
|
|||
"type": "identity",
|
||||
"endpoints": [
|
||||
{
|
||||
"adminURL": "https://csnode.jclouds.org:35357/v2.0/",
|
||||
"publicURL": "https://csnode.jclouds.org/v2.0/",
|
||||
"region": "region-a.geo-1",
|
||||
"id": "2.0",
|
||||
"versionId":"2.0",
|
||||
"list": "https://csnode.jclouds.org/extension"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -367,12 +367,15 @@ public abstract class BaseRestClientExpectTest<S> {
|
|||
*/
|
||||
public boolean httpRequestsAreEqual(HttpRequest a, HttpRequest b) {
|
||||
try {
|
||||
if (a == null || b == null) {
|
||||
return false;
|
||||
}
|
||||
if (a.getPayload() == null || b.getPayload() == null) {
|
||||
return Objects.equal(a, b);
|
||||
}
|
||||
|
||||
switch (compareHttpRequestAsType(a)) {
|
||||
case XML: {
|
||||
if (a == null || b == null || a.getPayload() == null || b.getPayload() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Diff diff = XMLUnit.compareXML(Strings2.toStringAndClose(a.getPayload().getInput()), Strings2
|
||||
.toStringAndClose(b.getPayload().getInput()));
|
||||
|
||||
|
@ -404,10 +407,7 @@ public abstract class BaseRestClientExpectTest<S> {
|
|||
|
||||
return diff.identical() && Objects.equal(a.getHeaders(), b.getHeaders());
|
||||
}
|
||||
case JSON: {
|
||||
if (a == null || b == null || a.getPayload() == null || b.getPayload() == null) {
|
||||
return false;
|
||||
}
|
||||
case JSON: {
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonElement payloadA = parser.parse(Strings2.toStringAndClose(a.getPayload().getInput()));
|
||||
JsonElement payloadB = parser.parse(Strings2.toStringAndClose(b.getPayload().getInput()));
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.dmtf;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.dmtf.cim.ResourceAllocationSettingData;
|
||||
import org.jclouds.dmtf.cim.ResourceAllocationSettingData.ResourceType;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author danikov
|
||||
*/
|
||||
public class CIMPredicates {
|
||||
|
||||
/**
|
||||
* Return resource allocations of the specific type.
|
||||
*
|
||||
* @param type
|
||||
* type to match the items
|
||||
* @return predicate
|
||||
*/
|
||||
public static Predicate<ResourceAllocationSettingData> resourceTypeIn(final ResourceType... types) {
|
||||
checkNotNull(types, "resourceTypes");
|
||||
final Set<ResourceType> resourceTypes = ImmutableSet.copyOf(types);
|
||||
return new Predicate<ResourceAllocationSettingData>() {
|
||||
@Override
|
||||
public boolean apply(ResourceAllocationSettingData in) {
|
||||
return resourceTypes.contains(in.getResourceType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "resourceTypeIn(" + resourceTypes + ")";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.dmtf.cim.functions;
|
||||
|
||||
import static com.google.common.collect.Iterables.filter;
|
||||
import static com.google.common.collect.Iterables.find;
|
||||
import static com.google.common.collect.Iterables.transform;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.compute.domain.HardwareBuilder;
|
||||
import org.jclouds.compute.domain.Processor;
|
||||
import org.jclouds.compute.domain.Volume;
|
||||
import org.jclouds.compute.domain.internal.VolumeImpl;
|
||||
import org.jclouds.dmtf.CIMPredicates;
|
||||
import org.jclouds.dmtf.cim.ResourceAllocationSettingData;
|
||||
import org.jclouds.dmtf.cim.ResourceAllocationSettingData.ResourceType;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class HardwareBuilderFromResourceAllocations implements
|
||||
Function<Iterable<? extends ResourceAllocationSettingData>, HardwareBuilder> {
|
||||
@Override
|
||||
public HardwareBuilder apply(Iterable<? extends ResourceAllocationSettingData> from) {
|
||||
HardwareBuilder builder = new HardwareBuilder();
|
||||
builder.volumes(transform(filter(from, CIMPredicates.resourceTypeIn(ResourceType.DISK_DRIVE,
|
||||
ResourceType.BASE_PARTITIONABLE_UNIT, ResourceType.PARTITIONABLE_UNIT)),
|
||||
new Function<ResourceAllocationSettingData, Volume>() {
|
||||
|
||||
@Override
|
||||
public Volume apply(ResourceAllocationSettingData from) {
|
||||
return HardwareBuilderFromResourceAllocations.this.apply(from);
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
builder.ram((int) find(from, CIMPredicates.resourceTypeIn(ResourceType.MEMORY)).getVirtualQuantity().longValue());
|
||||
|
||||
builder.processors(transform(filter(from, CIMPredicates.resourceTypeIn(ResourceType.PROCESSOR)),
|
||||
new Function<ResourceAllocationSettingData, Processor>() {
|
||||
|
||||
@Override
|
||||
public Processor apply(ResourceAllocationSettingData arg0) {
|
||||
return new Processor(arg0.getVirtualQuantity().longValue(), 1);
|
||||
}
|
||||
}));
|
||||
return builder;
|
||||
}
|
||||
|
||||
public Volume apply(ResourceAllocationSettingData from) {
|
||||
return new VolumeImpl(from.getAddressOnParent() + "", Volume.Type.LOCAL, from.getVirtualQuantity() == null ? null
|
||||
: from.getVirtualQuantity().longValue() / 1024 / 1024f, null, "0".equals(from.getAddressOnParent())
|
||||
|| ResourceType.BASE_PARTITIONABLE_UNIT.equals(from.getResourceType()), true);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. jclouds licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
-->
|
||||
<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.jclouds</groupId>
|
||||
<artifactId>jclouds-project</artifactId>
|
||||
<version>1.5.0-SNAPSHOT</version>
|
||||
<relativePath>../../project/pom.xml</relativePath>
|
||||
</parent>
|
||||
<groupId>org.jclouds.labs</groupId>
|
||||
<artifactId>openstack-keystone</artifactId>
|
||||
<name>jcloud openstack-keystone api</name>
|
||||
<description>jclouds components to access an implementation of OpenStack Keystone</description>
|
||||
<packaging>bundle</packaging>
|
||||
|
||||
<properties>
|
||||
<!-- keystone endpoint -->
|
||||
<test.openstack-keystone.endpoint>http://localhost:5000</test.openstack-keystone.endpoint>
|
||||
<!-- keystone version -->
|
||||
<test.openstack-keystone.api-version>2.0</test.openstack-keystone.api-version>
|
||||
<test.openstack-keystone.build-version></test.openstack-keystone.build-version>
|
||||
<test.openstack-keystone.identity>FIXME_IDENTITY</test.openstack-keystone.identity>
|
||||
<test.openstack-keystone.credential>FIXME_CREDENTIALS</test.openstack-keystone.credential>
|
||||
<test.jclouds.keystone.credential-type>passwordCredentials</test.jclouds.keystone.credential-type>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jclouds.common</groupId>
|
||||
<artifactId>openstack-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jclouds</groupId>
|
||||
<artifactId>jclouds-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jclouds.common</groupId>
|
||||
<artifactId>openstack-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.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>
|
||||
<version>1.0.0</version>
|
||||
<scope>test</scope>
|
||||
</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.openstack-keystone.endpoint>${test.openstack-keystone.endpoint}</test.openstack-keystone.endpoint>
|
||||
<test.openstack-keystone.api-version>${test.openstack-keystone.api-version}</test.openstack-keystone.api-version>
|
||||
<test.openstack-keystone.build-version>${test.openstack-keystone.build-version}</test.openstack-keystone.build-version>
|
||||
<test.openstack-keystone.identity>${test.openstack-keystone.identity}</test.openstack-keystone.identity>
|
||||
<test.openstack-keystone.credential>${test.openstack-keystone.credential}</test.openstack-keystone.credential>
|
||||
<test.jclouds.keystone.credential-type>${test.jclouds.keystone.credential-type}</test.jclouds.keystone.credential-type>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
|
||||
<Export-Package>org.jclouds.openstack.keystone.v2_0*;version="${project.version}"</Export-Package>
|
||||
<Import-Package>
|
||||
org.jclouds.rest.internal;version="${project.version}",
|
||||
org.jclouds*;version="${project.version}",
|
||||
*
|
||||
</Import-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,177 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.HEAD;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.openstack.filters.AuthenticateRequest;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Role;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Token;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.User;
|
||||
import org.jclouds.rest.annotations.ExceptionParser;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.annotations.SelectJson;
|
||||
import org.jclouds.rest.annotations.SkipEncoding;
|
||||
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
||||
import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404;
|
||||
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to Admin via their REST API.
|
||||
* <p/>
|
||||
*
|
||||
* @see AdminClient
|
||||
* @see <a href=
|
||||
* "http://docs.openstack.org/api/openstack-identity-service/2.0/content/Admin_API_Service_Developer_Operations-d1e1356.html"
|
||||
* />
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
@SkipEncoding({ '/', '=' })
|
||||
public interface AdminAsyncClient {
|
||||
/**
|
||||
* @see AdminClient#getApiMetadata()
|
||||
*/
|
||||
@GET
|
||||
@SelectJson("version")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/")
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<ApiMetadata> getApiMetadata();
|
||||
|
||||
/**
|
||||
* @see AdminClient#listTenants()
|
||||
*/
|
||||
@GET
|
||||
@SelectJson("tenants")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/tenants")
|
||||
@RequestFilters(AuthenticateRequest.class)
|
||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||
ListenableFuture<Set<Tenant>> listTenants();
|
||||
|
||||
/** @see AdminClient#getToken(String) */
|
||||
@GET
|
||||
@SelectJson("token")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/tokens/{token}")
|
||||
@RequestFilters(AuthenticateRequest.class)
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<Token> getToken(@PathParam("token") String token);
|
||||
|
||||
/** @see AdminClient#getUserOfToken(String) */
|
||||
@GET
|
||||
@SelectJson("user")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/tokens/{token}")
|
||||
@RequestFilters(AuthenticateRequest.class)
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<User> getUserOfToken(@PathParam("token") String token);
|
||||
|
||||
/** @see AdminClient#checkTokenIsValid(String) */
|
||||
@HEAD
|
||||
@Path("/tokens/{token}")
|
||||
@RequestFilters(AuthenticateRequest.class)
|
||||
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||
ListenableFuture<Boolean> checkTokenIsValid(@PathParam("token") String token);
|
||||
|
||||
/** @see AdminClient#getEndpointsForToken(String) */
|
||||
@GET
|
||||
@SelectJson("endpoints")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/tokens/{token}/endpoints")
|
||||
@RequestFilters(AuthenticateRequest.class)
|
||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||
ListenableFuture<Set<Endpoint>> getEndpointsForToken(@PathParam("token") String token);
|
||||
|
||||
/** @see AdminClient#getTenant(String) */
|
||||
@GET
|
||||
@SelectJson("tenant")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/tenants/{tenantId}")
|
||||
@RequestFilters(AuthenticateRequest.class)
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<Tenant> getTenant(@PathParam("tenantId") String tenantId);
|
||||
|
||||
/** @see AdminClient#getTenantByName(String) */
|
||||
@GET
|
||||
@SelectJson("tenant")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/tenants")
|
||||
@RequestFilters(AuthenticateRequest.class)
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<Tenant> getTenantByName(@QueryParam("name") String tenantName);
|
||||
|
||||
/** @see AdminClient#listUsers() */
|
||||
@GET
|
||||
@SelectJson("users")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/users")
|
||||
@RequestFilters(AuthenticateRequest.class)
|
||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||
ListenableFuture<Set<User>> listUsers();
|
||||
|
||||
/** @see AdminClient#getUser(String) */
|
||||
@GET
|
||||
@SelectJson("user")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/users/{userId}")
|
||||
@RequestFilters(AuthenticateRequest.class)
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<User> getUser(@PathParam("userId") String userId);
|
||||
|
||||
/** @see AdminClient#getUserByName(String) */
|
||||
@GET
|
||||
@SelectJson("user")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/users")
|
||||
@RequestFilters(AuthenticateRequest.class)
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<User> getUserByName(@QueryParam("name") String userName);
|
||||
|
||||
/** @see AdminClient#listRolesOfUser(String) */
|
||||
@GET
|
||||
@SelectJson("roles")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/users/{userId}/roles")
|
||||
@RequestFilters(AuthenticateRequest.class)
|
||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||
ListenableFuture<Set<Role>> listRolesOfUser(@PathParam("userId") String userId);
|
||||
|
||||
/** @see AdminClient#listRolesOfUserOnTenant(String, String) */
|
||||
@GET
|
||||
@SelectJson("roles")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/tenants/{tenantId}/users/{userId}/roles")
|
||||
@RequestFilters(AuthenticateRequest.class)
|
||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||
ListenableFuture<Set<Role>> listRolesOfUserOnTenant(@PathParam("userId") String userId, @PathParam("tenantId") String tenantId);
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.concurrent.Timeout;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Role;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Token;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.User;
|
||||
|
||||
/**
|
||||
* Provides synchronous access to the KeyStone Admin API.
|
||||
* <p/>
|
||||
*
|
||||
* @author Adam Lowe
|
||||
* @see AdminAsyncClient
|
||||
* @see <a href=
|
||||
* "http://docs.openstack.org/api/openstack-identity-service/2.0/content/Admin_API_Service_Developer_Operations-d1e1356.html"
|
||||
* />
|
||||
*/
|
||||
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
|
||||
public interface AdminClient {
|
||||
|
||||
/**
|
||||
* Discover API version information, links to documentation (PDF, HTML, WADL), and supported media types
|
||||
*
|
||||
* @return the requested information
|
||||
*/
|
||||
ApiMetadata getApiMetadata();
|
||||
|
||||
/**
|
||||
* The operation returns a list of tenants which the current token provides access to.
|
||||
*/
|
||||
Set<Tenant> listTenants();
|
||||
|
||||
/**
|
||||
* Retrieve information about a tenant, by tenant ID
|
||||
*
|
||||
* @return the information about the tenant
|
||||
*/
|
||||
Tenant getTenant(String tenantId);
|
||||
|
||||
/**
|
||||
* Retrieve information about a tenant, by tenant name
|
||||
* <p/>
|
||||
* NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/956687 )
|
||||
*
|
||||
* @return the information about the tenant
|
||||
*/
|
||||
Tenant getTenantByName(String tenantName);
|
||||
|
||||
/**
|
||||
* Validate a token and, if it is valid, return access information regarding the tenant (though not the service catalog)/
|
||||
*
|
||||
* @return the requested information
|
||||
*/
|
||||
Token getToken(String token);
|
||||
|
||||
/**
|
||||
* Validate a token and, if it is valid, return access information regarding the tenant (though not the service catalog)/
|
||||
*
|
||||
* @return the requested information
|
||||
*/
|
||||
User getUserOfToken(String token);
|
||||
|
||||
/**
|
||||
* Validate a token. This is a high-performance variant of the #getToken() call that does not return any further
|
||||
* information.
|
||||
*
|
||||
* @return true if the token is valid
|
||||
*/
|
||||
Boolean checkTokenIsValid(String token);
|
||||
|
||||
/**
|
||||
* List all endpoints for a token
|
||||
* <p/>
|
||||
* NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/988672 )
|
||||
*
|
||||
* @return the set of endpoints
|
||||
*/
|
||||
Set<Endpoint> getEndpointsForToken(String token);
|
||||
|
||||
/**
|
||||
* Retrieve the list of users
|
||||
* <p/>
|
||||
* NOTE: this method is not in API documentation for keystone, but does work
|
||||
*
|
||||
* @return the list of users
|
||||
*/
|
||||
Set<User> listUsers();
|
||||
|
||||
/**
|
||||
* Retrieve information about a user, by user ID
|
||||
*
|
||||
* @return the information about the user
|
||||
*/
|
||||
User getUser(String userId);
|
||||
|
||||
/**
|
||||
* Retrieve information about a user, by user name
|
||||
* <p/>
|
||||
* NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/956687 )
|
||||
*
|
||||
* @return the information about the user
|
||||
*/
|
||||
User getUserByName(String userName);
|
||||
|
||||
/**
|
||||
* Retrieves the list of global roles associated with a specific user (excludes tenant roles).
|
||||
* <p/>
|
||||
* NOTE: Broken in openstack ( https://bugs.launchpad.net/keystone/+bug/933565 )
|
||||
*
|
||||
* @return the set of Roles granted to the user
|
||||
*/
|
||||
Set<Role> listRolesOfUser(String userId);
|
||||
|
||||
/**
|
||||
* List the roles a user has been granted on a specific tenant
|
||||
*
|
||||
* @return the set of roles
|
||||
*/
|
||||
Set<Role> listRolesOfUserOnTenant(String userId, String tenantId);
|
||||
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0;
|
||||
|
||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.apis.ApiMetadata;
|
||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
|
||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneRestClientModule;
|
||||
import org.jclouds.openstack.services.ServiceType;
|
||||
import org.jclouds.rest.RestContext;
|
||||
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
* Implementation of {@link org.jclouds.apis.ApiMetadata} for Keystone 2.0 API
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class KeystoneApiMetadata extends BaseRestApiMetadata {
|
||||
|
||||
/** The serialVersionUID */
|
||||
private static final long serialVersionUID = 6725672099385580694L;
|
||||
|
||||
public static final TypeToken<RestContext<KeystoneClient, KeystoneAsyncClient>> CONTEXT_TOKEN = new TypeToken<RestContext<KeystoneClient, KeystoneAsyncClient>>() {
|
||||
};
|
||||
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
return new Builder().fromApiMetadata(this);
|
||||
}
|
||||
|
||||
public KeystoneApiMetadata() {
|
||||
this(new Builder());
|
||||
}
|
||||
|
||||
protected KeystoneApiMetadata(Builder builder) {
|
||||
super(builder);
|
||||
}
|
||||
|
||||
public static Properties defaultProperties() {
|
||||
Properties properties = BaseRestApiMetadata.defaultProperties();
|
||||
// auth fail can happen while cloud-init applies keypair updates
|
||||
properties.setProperty("jclouds.ssh.max-retries", "7");
|
||||
properties.setProperty("jclouds.ssh.retry-auth", "true");
|
||||
// TODO: this doesn't actually do anything yet.
|
||||
properties.setProperty(KeystoneProperties.VERSION, "2.0");
|
||||
properties.put(SERVICE_TYPE, ServiceType.IDENTITY);
|
||||
return properties;
|
||||
}
|
||||
|
||||
public static class Builder extends BaseRestApiMetadata.Builder {
|
||||
|
||||
protected Builder() {
|
||||
super(KeystoneClient.class, KeystoneAsyncClient.class);
|
||||
id("openstack-keystone")
|
||||
.name("OpenStack Keystone Essex+ API")
|
||||
.identityName("tenantId:user")
|
||||
.credentialName("password")
|
||||
.documentation(URI.create("http://api.openstack.org/"))
|
||||
.version("2.0")
|
||||
.defaultEndpoint("http://localhost:5000")
|
||||
.defaultProperties(KeystoneApiMetadata.defaultProperties())
|
||||
.defaultModules(ImmutableSet.<Class<? extends Module>>of(KeystoneRestClientModule.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeystoneApiMetadata build() {
|
||||
return new KeystoneApiMetadata(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder fromApiMetadata(ApiMetadata in) {
|
||||
super.fromApiMetadata(in);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.Path;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.location.Region;
|
||||
import org.jclouds.location.functions.RegionToEndpoint;
|
||||
import org.jclouds.openstack.keystone.v2_0.functions.RegionToAdminEndpointURI;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Provides access to Openstack keystone resources via their REST API.
|
||||
* <p/>
|
||||
*
|
||||
* @author Adam Lowe
|
||||
* @see <a href="http://keystone.openstack.org/" />
|
||||
* @see KeystoneClient
|
||||
*/
|
||||
@Path("/v{" + Constants.PROPERTY_API_VERSION + "}")
|
||||
public interface KeystoneAsyncClient {
|
||||
/**
|
||||
* @return the Region codes configured
|
||||
*/
|
||||
@Provides
|
||||
@Region
|
||||
Set<String> getConfiguredRegions();
|
||||
|
||||
/** Provides asynchronous access to Identity user-accessible features */
|
||||
@Delegate
|
||||
ServiceAsyncClient getServiceClientForRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region);
|
||||
|
||||
/** Provides asynchronous access to the KeyStone Admin API */
|
||||
@Delegate
|
||||
AdminAsyncClient getAdminClientForRegion(@EndpointParam(parser = RegionToAdminEndpointURI.class) @Nullable String region);
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.concurrent.Timeout;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.location.Region;
|
||||
import org.jclouds.location.functions.RegionToEndpoint;
|
||||
import org.jclouds.openstack.keystone.v2_0.functions.RegionToAdminEndpointURI;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Provides access to Openstack keystone resources via their REST API.
|
||||
* <p/>
|
||||
*
|
||||
* @author Adam Lowe
|
||||
* @see <a href="http://keystone.openstack.org/" />
|
||||
*/
|
||||
@Timeout(duration = 10, timeUnit = TimeUnit.SECONDS)
|
||||
public interface KeystoneClient {
|
||||
/**
|
||||
* @return the Region codes configured
|
||||
*/
|
||||
@Provides
|
||||
@Region
|
||||
Set<String> getConfiguredRegions();
|
||||
|
||||
/** Provides synchronous access to Identity user-accessible features */
|
||||
@Delegate
|
||||
ServiceClient getServiceClientForRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region);
|
||||
|
||||
/** Provides synchronous access to the KeyStone Admin API */
|
||||
@Delegate
|
||||
AdminClient getAdminClientForRegion(@EndpointParam(parser = RegionToAdminEndpointURI.class) @Nullable String region);
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.openstack.filters.AuthenticateRequest;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
|
||||
import org.jclouds.rest.annotations.ExceptionParser;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.annotations.SelectJson;
|
||||
import org.jclouds.rest.annotations.SkipEncoding;
|
||||
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
||||
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to Service via their REST API.
|
||||
* <p/>
|
||||
*
|
||||
* @see ServiceClient
|
||||
* @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Service_API_Client_Operations.html"
|
||||
* />
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
@SkipEncoding({ '/', '=' })
|
||||
public interface ServiceAsyncClient {
|
||||
/**
|
||||
* @see ServiceClient#getApiMetadata()
|
||||
*/
|
||||
@GET
|
||||
@SelectJson("version")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/")
|
||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||
ListenableFuture<ApiMetadata> getApiMetadata();
|
||||
|
||||
/**
|
||||
* @see ServiceClient#listTenants()
|
||||
*/
|
||||
@GET
|
||||
@SelectJson("tenants")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/tenants")
|
||||
@RequestFilters(AuthenticateRequest.class)
|
||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||
ListenableFuture<Set<Tenant>> listTenants();
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.concurrent.Timeout;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
|
||||
|
||||
/**
|
||||
* Provides synchronous access to the KeyStone Service API.
|
||||
* <p/>
|
||||
*
|
||||
* @author Adam Lowe
|
||||
* @see ServiceAsyncClient
|
||||
* @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Service_API_Client_Operations.html"
|
||||
* />
|
||||
*/
|
||||
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
|
||||
public interface ServiceClient {
|
||||
|
||||
/**
|
||||
* Discover API version information, links to documentation (PDF, HTML, WADL), and supported media types
|
||||
*
|
||||
* @return the requested information
|
||||
*/
|
||||
ApiMetadata getApiMetadata();
|
||||
|
||||
/**
|
||||
* The operation returns a list of tenants which the current token provides access to.
|
||||
*/
|
||||
Set<Tenant> listTenants();
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.config;
|
||||
|
||||
import org.jclouds.json.config.GsonModule;
|
||||
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
|
||||
/**
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
public class KeystoneParserModule extends AbstractModule {
|
||||
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(DateAdapter.class).to(GsonModule.Iso8601DateAdapter.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.http.HttpErrorHandler;
|
||||
import org.jclouds.http.annotation.ClientError;
|
||||
import org.jclouds.http.annotation.Redirection;
|
||||
import org.jclouds.http.annotation.ServerError;
|
||||
import org.jclouds.openstack.keystone.v2_0.AdminAsyncClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.AdminClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.KeystoneAsyncClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.KeystoneClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.ServiceAsyncClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.ServiceClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.handlers.KeystoneErrorHandler;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.config.RestClientModule;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* Configures the Keystone connection.
|
||||
*
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
@ConfiguresRestClient
|
||||
public class KeystoneRestClientModule extends RestClientModule<KeystoneClient, KeystoneAsyncClient> {
|
||||
|
||||
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
|
||||
.put(ServiceClient.class, ServiceAsyncClient.class).put(AdminClient.class, AdminAsyncClient.class)
|
||||
.build();
|
||||
|
||||
public KeystoneRestClientModule() {
|
||||
super(DELEGATE_MAP);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new KeystoneParserModule());
|
||||
super.configure();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installLocations() {
|
||||
// TODO: select this from KeystoneProperties.VERSION; note you select from
|
||||
// a guice provided property, so it will have to come from somewhere else, maybe we move
|
||||
// this to the the ContextBuilder
|
||||
install(KeystoneAuthenticationModule.forRegions());
|
||||
super.installLocations();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindErrorHandlers() {
|
||||
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(KeystoneErrorHandler.class);
|
||||
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(KeystoneErrorHandler.class);
|
||||
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(KeystoneErrorHandler.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.handlers;
|
||||
|
||||
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.http.HttpCommand;
|
||||
import org.jclouds.http.HttpErrorHandler;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
import org.jclouds.rest.ResourceNotFoundException;
|
||||
|
||||
/**
|
||||
* This will parse and set an appropriate exception on the command object.
|
||||
*
|
||||
* @author Adam Lowe
|
||||
*
|
||||
*/
|
||||
// TODO: is there error spec someplace? let's type errors, etc.
|
||||
@Singleton
|
||||
public class KeystoneErrorHandler implements HttpErrorHandler {
|
||||
public void handleError(HttpCommand command, HttpResponse response) {
|
||||
// it is important to always read fully and close streams
|
||||
byte[] data = closeClientButKeepContentStream(response);
|
||||
String message = data != null ? new String(data) : null;
|
||||
|
||||
Exception exception = message != null ? new HttpResponseException(command, response, message)
|
||||
: new HttpResponseException(command, response);
|
||||
message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
|
||||
response.getStatusLine());
|
||||
switch (response.getStatusCode()) {
|
||||
case 400:
|
||||
break;
|
||||
case 401:
|
||||
case 403:
|
||||
exception = new AuthorizationException(message, exception);
|
||||
break;
|
||||
case 404:
|
||||
if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
|
||||
exception = new ResourceNotFoundException(message, exception);
|
||||
}
|
||||
break;
|
||||
}
|
||||
command.setException(exception);
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.jclouds.openstack.keystone.v2_0.KeystoneApiMetadata
|
|
@ -0,0 +1,379 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 1.1 (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-1.1
|
||||
*
|
||||
* 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.openstack.keystone.v2_0;
|
||||
|
||||
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
|
||||
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 java.net.URI;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.openstack.domain.Link;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.MediaType;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Role;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Token;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.User;
|
||||
import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneRestClientExpectTest;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* Tests parsing and Guice wiring of UserClient
|
||||
*
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
public class AdminClientExpectTest extends BaseKeystoneRestClientExpectTest<KeystoneClient> {
|
||||
private DateService dateService = new SimpleDateFormatDateService();
|
||||
|
||||
public AdminClientExpectTest() {
|
||||
endpoint = "https://csnode.jclouds.org:35357";
|
||||
}
|
||||
|
||||
public void testGetApiMetaData() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/").
|
||||
headers(ImmutableMultimap.of("Accept", APPLICATION_JSON)).build(),
|
||||
standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/api_metadata.json", APPLICATION_JSON)).build())
|
||||
.getAdminClientForRegion("region-a.geo-1");
|
||||
ApiMetadata metadata = client.getApiMetadata();
|
||||
assertNotNull(metadata);
|
||||
assertEquals(metadata.getId(), "v2.0");
|
||||
|
||||
ApiMetadata expected = ApiMetadata.builder().id("v2.0")
|
||||
.links(ImmutableSet.of(Link.builder().relation(Link.Relation.SELF).href(URI.create("http://172.16.89.140:5000/v2.0/")).build(),
|
||||
Link.builder().relation(Link.Relation.DESCRIBEDBY).type("text/html").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/content/")).build(),
|
||||
Link.builder().relation(Link.Relation.DESCRIBEDBY).type("application/pdf").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf")).build()
|
||||
))
|
||||
.status("beta")
|
||||
.updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-11-19T00:00:00Z"))
|
||||
.mediaTypes(ImmutableSet.of(
|
||||
MediaType.builder().base("application/json").type("application/vnd.openstack.identity-v2.0+json").build(),
|
||||
MediaType.builder().base("application/xml").type("application/vnd.openstack.identity-v2.0+xml").build()
|
||||
))
|
||||
.build();
|
||||
|
||||
assertEquals(metadata, expected);
|
||||
}
|
||||
|
||||
public void testGetApiMetaDataFailNotFound() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/").headers(ImmutableMultimap.of("Accept", APPLICATION_JSON)).build(),
|
||||
standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1");
|
||||
assertNull(client.getApiMetadata());
|
||||
}
|
||||
|
||||
public void testListTenants() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/tenants").build(),
|
||||
standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/tenant_list.json", APPLICATION_JSON)).build())
|
||||
.getAdminClientForRegion("region-a.geo-1");
|
||||
Set<Tenant> tenants = client.listTenants();
|
||||
assertNotNull(tenants);
|
||||
assertFalse(tenants.isEmpty());
|
||||
|
||||
Set<Tenant> expected = ImmutableSet.of(
|
||||
Tenant.builder().name("demo").id("05d1dc7af71646deba64cfc17b81bec0").build(),
|
||||
Tenant.builder().name("admin").id("7aa2e17ec29f44d193c48feaba0852cc").build()
|
||||
);
|
||||
|
||||
assertEquals(tenants, expected);
|
||||
}
|
||||
|
||||
public void testListTenantsFailNotFound() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/tenants").build(),
|
||||
standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1");
|
||||
assertTrue(client.listTenants().isEmpty());
|
||||
}
|
||||
|
||||
public void testGetTenant() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/tenants/013ba41150a14830bec85ffe93353bcc").build(),
|
||||
standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/tenant_details.json", APPLICATION_JSON)).build())
|
||||
.getAdminClientForRegion("region-a.geo-1");
|
||||
Tenant tenant = client.getTenant("013ba41150a14830bec85ffe93353bcc");
|
||||
assertNotNull(tenant);
|
||||
assertEquals(tenant, Tenant.builder().id("013ba41150a14830bec85ffe93353bcc").name("admin").build());
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = AuthorizationException.class)
|
||||
public void testListTenantsFailNotAuthorized() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/tenants/013ba41150a14830bec85ffe93353bcc").build(),
|
||||
standardResponseBuilder(401).build()).getAdminClientForRegion("region-a.geo-1");
|
||||
client.getTenant("013ba41150a14830bec85ffe93353bcc");
|
||||
}
|
||||
|
||||
public void testGetTenantByName() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/tenants?name=admin").build(),
|
||||
standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/tenant_details.json", APPLICATION_JSON)).build())
|
||||
.getAdminClientForRegion("region-a.geo-1");
|
||||
Tenant tenant = client.getTenantByName("admin");
|
||||
assertNotNull(tenant);
|
||||
assertEquals(tenant, Tenant.builder().id("013ba41150a14830bec85ffe93353bcc").name("admin").build());
|
||||
}
|
||||
|
||||
public void testGetTenantByNameFailNotFound() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/tenants?name=admin").build(),
|
||||
standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1");
|
||||
assertNull(client.getTenantByName("admin"));
|
||||
}
|
||||
|
||||
public void testGetToken() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(),
|
||||
standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/token_details.json", APPLICATION_JSON)).build())
|
||||
.getAdminClientForRegion("region-a.geo-1");
|
||||
Token token = client.getToken("sometokenorother");
|
||||
assertNotNull(token);
|
||||
assertEquals(token,
|
||||
Token.builder().id("167eccdc790946969ced473732e8109b").expires(dateService.iso8601SecondsDateParse("2012-04-28T12:42:50Z"))
|
||||
.tenant(Tenant.builder().id("4cea93f5464b4f1c921fb3e0461d72b5").name("demo").build()).build());
|
||||
}
|
||||
|
||||
public void testGetTokenFailNotFound() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(),
|
||||
standardResponseBuilder(404).build())
|
||||
.getAdminClientForRegion("region-a.geo-1");
|
||||
assertNull(client.getToken("sometokenorother"));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = HttpResponseException.class)
|
||||
public void testGetTokenFail500() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(),
|
||||
standardResponseBuilder(500).build()).getAdminClientForRegion("region-a.geo-1");
|
||||
client.getToken("sometokenorother");
|
||||
}
|
||||
|
||||
public void testGetUserOfToken() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(),
|
||||
standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/token_details.json", APPLICATION_JSON)).build())
|
||||
.getAdminClientForRegion("region-a.geo-1");
|
||||
User user = client.getUserOfToken("sometokenorother");
|
||||
assertNotNull(user);
|
||||
assertEquals(user, User.builder().id("2b9b606181634ae9ac86fd95a8bc2cde").name("admin")
|
||||
.roles(ImmutableSet.of(Role.builder().id("79cada5c02814b57a52e0eed4dd388cb").name("admin").build()))
|
||||
.build());
|
||||
}
|
||||
|
||||
public void testGetUserOfTokenFailNotFound() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(),
|
||||
standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1");
|
||||
assertNull(client.getUserOfToken("sometokenorother"));
|
||||
}
|
||||
|
||||
public void testCheckTokenIsValid() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").method("HEAD")
|
||||
.headers(ImmutableMultimap.of("X-Auth-Token", authToken)).build(),
|
||||
standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/token_details.json", APPLICATION_JSON)).build())
|
||||
.getAdminClientForRegion("region-a.geo-1");
|
||||
assertTrue(client.checkTokenIsValid("sometokenorother"));
|
||||
}
|
||||
|
||||
public void testCheckTokenIsValidFailNotValid() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").method("HEAD")
|
||||
.headers(ImmutableMultimap.of("X-Auth-Token", authToken)).build(),
|
||||
standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1");
|
||||
assertFalse(client.checkTokenIsValid("sometokenorother"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEndpointsForToken() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/tokens/XXXXXX/endpoints").build(),
|
||||
standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_endpoints.json", APPLICATION_JSON)).build())
|
||||
.getAdminClientForRegion("region-a.geo-1");
|
||||
Set<Endpoint> endpoints = client.getEndpointsForToken("XXXXXX");
|
||||
|
||||
assertEquals(endpoints, ImmutableSet.of(
|
||||
Endpoint.builder().publicURL(URI.create("https://csnode.jclouds.org/v2.0/"))
|
||||
.adminURL(URI.create("https://csnode.jclouds.org:35357/v2.0/"))
|
||||
.region("region-a.geo-1").versionId("2.0").build()
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEndpointsForTokenFailNotFound() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/tokens/XXXXXX/endpoints").build(),
|
||||
standardResponseBuilder(404).build())
|
||||
.getAdminClientForRegion("region-a.geo-1");
|
||||
assertTrue(client.getEndpointsForToken("XXXXXX").isEmpty());
|
||||
}
|
||||
|
||||
public void testListUsers() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/users").build(),
|
||||
standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_list.json", APPLICATION_JSON)).build())
|
||||
.getAdminClientForRegion("region-a.geo-1");
|
||||
Set<User> users = client.listUsers();
|
||||
assertNotNull(users);
|
||||
assertFalse(users.isEmpty());
|
||||
|
||||
Set<User> expected = ImmutableSet.of(
|
||||
User.builder().name("nova").id("e021dfd758eb44a89f1c57c8ef3be8e2").build(),
|
||||
User.builder().name("glance").id("3f6c1c9ba993495ead7d2eb2192e284f").build(),
|
||||
User.builder().name("demo").id("667b2e1420604df8b67cd8ea57d4ee64").build(),
|
||||
User.builder().name("admin").id("2b9b606181634ae9ac86fd95a8bc2cde").build()
|
||||
);
|
||||
|
||||
assertEquals(users, expected);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = AuthorizationException.class)
|
||||
public void testListUsersFailNotAuth() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/users").build(),
|
||||
standardResponseBuilder(401).build()).getAdminClientForRegion("region-a.geo-1");
|
||||
client.listUsers();
|
||||
}
|
||||
|
||||
public void testGetUser() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/users/e021dfd758eb44a89f1c57c8ef3be8e2").build(),
|
||||
standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_details.json", APPLICATION_JSON)).build())
|
||||
.getAdminClientForRegion("region-a.geo-1");
|
||||
User user = client.getUser("e021dfd758eb44a89f1c57c8ef3be8e2");
|
||||
assertNotNull(user);
|
||||
assertEquals(user, User.builder().name("nova").id("e021dfd758eb44a89f1c57c8ef3be8e2").build());
|
||||
}
|
||||
|
||||
public void testGetUserFailNotFound() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/users/f021dfd758eb44a89f1c57c8ef3be8e2").build(),
|
||||
standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1");
|
||||
assertNull(client.getUser("f021dfd758eb44a89f1c57c8ef3be8e2"));
|
||||
}
|
||||
|
||||
public void testGetUserByName() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/users?name=nova").build(),
|
||||
standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_details.json", APPLICATION_JSON)).build())
|
||||
.getAdminClientForRegion("region-a.geo-1");
|
||||
User user = client.getUserByName("nova");
|
||||
assertNotNull(user);
|
||||
assertEquals(user, User.builder().name("nova").id("e021dfd758eb44a89f1c57c8ef3be8e2").build());
|
||||
}
|
||||
|
||||
public void testGetUserByNameFailNotFound() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/users?name=fred").build(),
|
||||
standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1");
|
||||
assertNull(client.getUserByName("fred"));
|
||||
}
|
||||
|
||||
public void testListRolesOfUser() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/users/3f6c1c9ba993495ead7d2eb2192e284f/roles").build(),
|
||||
standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_role_list.json", APPLICATION_JSON)).build())
|
||||
.getAdminClientForRegion("region-a.geo-1");
|
||||
Set<Role> roles = client.listRolesOfUser("3f6c1c9ba993495ead7d2eb2192e284f");
|
||||
assertNotNull(roles);
|
||||
assertFalse(roles.isEmpty());
|
||||
assertEquals(roles, ImmutableSet.of(
|
||||
Role.builder().id("79cada5c02814b57a52e0eed4dd388cb").name("admin").build()
|
||||
));
|
||||
}
|
||||
|
||||
public void testListRolesOfUserFailNotFound() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/users/4f6c1c9ba993495ead7d2eb2192e284f/roles").build(),
|
||||
standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1");
|
||||
assertTrue(client.listRolesOfUser("4f6c1c9ba993495ead7d2eb2192e284f").isEmpty());
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = HttpResponseException.class)
|
||||
public void testListRolesOfUserFailNotImplemented() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/users/5f6c1c9ba993495ead7d2eb2192e284f/roles").build(),
|
||||
standardResponseBuilder(501).build()).getAdminClientForRegion("region-a.geo-1");
|
||||
assertTrue(client.listRolesOfUser("5f6c1c9ba993495ead7d2eb2192e284f").isEmpty());
|
||||
}
|
||||
|
||||
public void testListRolesOfUserInTenant() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/users/3f6c1c9ba993495ead7d2eb2192e284f/roles").build(),
|
||||
standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_tenant_role_list.json", APPLICATION_JSON)).build())
|
||||
.getAdminClientForRegion("region-a.geo-1");
|
||||
Set<Role> roles = client.listRolesOfUser("3f6c1c9ba993495ead7d2eb2192e284f");
|
||||
assertNotNull(roles);
|
||||
assertFalse(roles.isEmpty());
|
||||
assertEquals(roles, ImmutableSet.of(
|
||||
Role.builder().id("31c451195aac49b386039341e2c92a16").name("KeystoneServiceAdmin").build(),
|
||||
Role.builder().id("79cada5c02814b57a52e0eed4dd388cb").name("admin").build(),
|
||||
Role.builder().id("6ea17ddd37a6447794cb0e164d4db894").name("KeystoneAdmin").build()));
|
||||
}
|
||||
|
||||
public void testListRolesOfUserInTenantFailNotFound() {
|
||||
AdminClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
standardRequestBuilder(endpoint + "/v2.0/users/3f6c1c9ba993495ead7d2eb2192e284f/roles").build(),
|
||||
standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1");
|
||||
assertTrue(client.listRolesOfUser("3f6c1c9ba993495ead7d2eb2192e284f").isEmpty());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,193 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 1.1 (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-1.1
|
||||
*
|
||||
* 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.openstack.keystone.v2_0;
|
||||
|
||||
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.AssertJUnit.assertTrue;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.openstack.filters.AuthenticateRequest;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Role;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Token;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.User;
|
||||
import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneClientLiveTest;
|
||||
import org.jclouds.openstack.reference.AuthHeaders;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* Tests AdminClient
|
||||
*
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
@Test(groups = "live", testName = "AdminClientLiveTest", singleThreaded = true)
|
||||
public class AdminClientLiveTest extends BaseKeystoneClientLiveTest {
|
||||
|
||||
protected String token;
|
||||
|
||||
// Get the token currently in use (there's currently no listTokens())
|
||||
@BeforeMethod
|
||||
public void grabToken() {
|
||||
AuthenticateRequest ar = keystoneContext.getUtils().getInjector().getInstance(AuthenticateRequest.class);
|
||||
HttpRequest test = ar.filter(HttpRequest.builder().method("GET").endpoint(URI.create(endpoint)).build());
|
||||
token = Iterables.getOnlyElement(test.getHeaders().get(AuthHeaders.AUTH_TOKEN));
|
||||
}
|
||||
|
||||
public void testGetApiMetaData() {
|
||||
for (String regionId : keystoneContext.getApi().getConfiguredRegions()) {
|
||||
ApiMetadata result = keystoneContext.getApi().getAdminClientForRegion(regionId).getApiMetadata();
|
||||
assertNotNull(result);
|
||||
assertNotNull(result.getId());
|
||||
assertNotNull(result.getStatus());
|
||||
assertNotNull(result.getUpdated());
|
||||
}
|
||||
}
|
||||
|
||||
public void testTenants() {
|
||||
for (String regionId : keystoneContext.getApi().getConfiguredRegions()) {
|
||||
AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId);
|
||||
Set<Tenant> result = client.listTenants();
|
||||
assertNotNull(result);
|
||||
assertFalse(result.isEmpty());
|
||||
|
||||
for (Tenant tenant : result) {
|
||||
assertNotNull(tenant.getId());
|
||||
|
||||
Tenant aTenant = client.getTenant(tenant.getId());
|
||||
assertEquals(aTenant, tenant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testToken() {
|
||||
for (String regionId : keystoneContext.getApi().getConfiguredRegions()) {
|
||||
AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId);
|
||||
assertTrue(client.checkTokenIsValid(token));
|
||||
Token result = client.getToken(token);
|
||||
assertNotNull(result);
|
||||
assertEquals(result.getId(), token);
|
||||
assertNotNull(result.getTenant());
|
||||
|
||||
User user = client.getUserOfToken(token);
|
||||
assertNotNull(user);
|
||||
assertNotNull(user.getId());
|
||||
assertNotNull(user.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public void testInvalidToken() {
|
||||
for (String regionId : keystoneContext.getApi().getConfiguredRegions()) {
|
||||
AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId);
|
||||
assertFalse(client.checkTokenIsValid("thisisnotarealtoken!"));
|
||||
assertNull(client.getToken("thisisnotarealtoken!"));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO this threw 501 not implemented
|
||||
@Test(enabled = false)
|
||||
public void testTokenEndpoints() {
|
||||
for (String regionId : keystoneContext.getApi().getConfiguredRegions()) {
|
||||
AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId);
|
||||
Set<Endpoint> endpoints = client.getEndpointsForToken(token);
|
||||
assertNotNull(endpoints);
|
||||
assertFalse(endpoints.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO this threw 501 not implemented
|
||||
@Test(enabled = false)
|
||||
public void testInvalidTokenEndpoints() {
|
||||
for (String regionId : keystoneContext.getApi().getConfiguredRegions()) {
|
||||
AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId);
|
||||
assertTrue(client.getEndpointsForToken("thisisnotarealtoken!").isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
public void testUsers() {
|
||||
for (String regionId : keystoneContext.getApi().getConfiguredRegions()) {
|
||||
AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId);
|
||||
Set<User> users = client.listUsers();
|
||||
assertNotNull(users);
|
||||
assertFalse(users.isEmpty());
|
||||
for (User user : users) {
|
||||
User aUser = client.getUser(user.getId());
|
||||
assertEquals(aUser, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = {"testUsers", "testTenants"})
|
||||
public void testUserRolesOnTenant() {
|
||||
for (String regionId : keystoneContext.getApi().getConfiguredRegions()) {
|
||||
AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId);
|
||||
Set<User> users = client.listUsers();
|
||||
Set<Tenant> tenants = client.listTenants();
|
||||
|
||||
for (User user : users) {
|
||||
for (Tenant tenant : tenants) {
|
||||
Set<Role> roles = client.listRolesOfUserOnTenant(user.getId(), tenant.getId());
|
||||
for (Role role : roles) {
|
||||
assertNotNull(role.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO this functionality is currently broken in openstack
|
||||
@Test(enabled = false, dependsOnMethods = "testUsers")
|
||||
public void testListRolesOfUser() {
|
||||
for (String regionId : keystoneContext.getApi().getConfiguredRegions()) {
|
||||
AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId);
|
||||
for (User user : client.listUsers()) {
|
||||
Set<Role> roles = client.listRolesOfUser(user.getId());
|
||||
for (Role role : roles) {
|
||||
assertNotNull(role.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO this functionality is currently broken in openstack (possibly deprecated?)
|
||||
@Test(enabled=false, dependsOnMethods = {"testUsers", "testTenants"})
|
||||
public void testUsersAndTenantsByName() {
|
||||
for (String regionId : keystoneContext.getApi().getConfiguredRegions()) {
|
||||
AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId);
|
||||
for (User user : client.listUsers()) {
|
||||
User aUser = client.getUserByName(user.getName());
|
||||
assertEquals(aUser, user);
|
||||
}
|
||||
for (Tenant tenant : client.listTenants()) {
|
||||
Tenant aTenant = client.getTenantByName(tenant.getName());
|
||||
assertEquals(aTenant, tenant);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 1.1 (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-1.1
|
||||
*
|
||||
* 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.openstack.keystone.v2_0;
|
||||
|
||||
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.openstack.domain.Link;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.MediaType;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
|
||||
import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneRestClientExpectTest;
|
||||
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* Tests parsing and Guice wiring of UserClient
|
||||
*
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
public class UserClientExpectTest extends BaseKeystoneRestClientExpectTest<KeystoneClient> {
|
||||
|
||||
public void testGetApiMetaData() {
|
||||
ServiceClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
HttpRequest.builder().method("GET").endpoint(URI.create(endpoint + "/v2.0/")).
|
||||
headers(ImmutableMultimap.of("Accept", APPLICATION_JSON)).build(),
|
||||
HttpResponse.builder().statusCode(200).
|
||||
payload(payloadFromResourceWithContentType("/api_metadata.json", APPLICATION_JSON)).build())
|
||||
.getServiceClientForRegion("region-a.geo-1");
|
||||
ApiMetadata metadata = client.getApiMetadata();
|
||||
assertNotNull(metadata);
|
||||
assertEquals(metadata.getId(), "v2.0");
|
||||
|
||||
ApiMetadata expected = ApiMetadata.builder().id("v2.0")
|
||||
.links(ImmutableSet.of(Link.builder().relation(Link.Relation.SELF).href(URI.create("http://172.16.89.140:5000/v2.0/")).build(),
|
||||
Link.builder().relation(Link.Relation.DESCRIBEDBY).type("text/html").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/content/")).build(),
|
||||
Link.builder().relation(Link.Relation.DESCRIBEDBY).type("application/pdf").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf")).build()
|
||||
))
|
||||
.status("beta")
|
||||
.updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-11-19T00:00:00Z"))
|
||||
.mediaTypes(ImmutableSet.of(
|
||||
MediaType.builder().base("application/json").type("application/vnd.openstack.identity-v2.0+json").build(),
|
||||
MediaType.builder().base("application/xml").type("application/vnd.openstack.identity-v2.0+xml").build()
|
||||
))
|
||||
.build();
|
||||
|
||||
assertEquals(metadata, expected);
|
||||
}
|
||||
|
||||
public void testListTenants() {
|
||||
ServiceClient client = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
|
||||
HttpRequest.builder().method("GET").endpoint(URI.create(endpoint + "/v2.0/tenants")).
|
||||
headers(ImmutableMultimap.of("Accept", APPLICATION_JSON, "X-Auth-Token", authToken)).build(),
|
||||
HttpResponse.builder().statusCode(200).
|
||||
payload(payloadFromResourceWithContentType("/tenant_list.json", APPLICATION_JSON)).build())
|
||||
.getServiceClientForRegion("region-a.geo-1");
|
||||
Set<Tenant> tenants = client.listTenants();
|
||||
assertNotNull(tenants);
|
||||
assertFalse(tenants.isEmpty());
|
||||
|
||||
Set<Tenant> expected = ImmutableSet.of(
|
||||
Tenant.builder().name("demo").id("05d1dc7af71646deba64cfc17b81bec0").build(),
|
||||
Tenant.builder().name("admin").id("7aa2e17ec29f44d193c48feaba0852cc").build()
|
||||
);
|
||||
|
||||
assertEquals(tenants, expected);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 1.1 (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-1.1
|
||||
*
|
||||
* 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.openstack.keystone.v2_0;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
|
||||
import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneClientLiveTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Tests UserClient
|
||||
*
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
@Test(groups = "live", testName = "UserClientLiveTest")
|
||||
public class UserClientLiveTest extends BaseKeystoneClientLiveTest {
|
||||
|
||||
public void testGetApiMetaData() {
|
||||
for (String regionId : keystoneContext.getApi().getConfiguredRegions()) {
|
||||
ApiMetadata result = keystoneContext.getApi().getServiceClientForRegion(regionId).getApiMetadata();
|
||||
assertNotNull(result);
|
||||
assertNotNull(result.getId());
|
||||
assertNotNull(result.getStatus());
|
||||
assertNotNull(result.getUpdated());
|
||||
}
|
||||
}
|
||||
|
||||
public void testListTenants() {
|
||||
for (String regionId : keystoneContext.getApi().getConfiguredRegions()) {
|
||||
Set<Tenant> result = keystoneContext.getApi().getServiceClientForRegion(regionId).listTenants();
|
||||
assertNotNull(result);
|
||||
assertFalse(result.isEmpty());
|
||||
|
||||
for (Tenant tenant : result) {
|
||||
assertNotNull(tenant.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.internal;
|
||||
|
||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.apis.BaseContextLiveTest;
|
||||
import org.jclouds.openstack.keystone.v2_0.KeystoneApiMetadata;
|
||||
import org.jclouds.openstack.keystone.v2_0.KeystoneAsyncClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.KeystoneClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
|
||||
import org.jclouds.openstack.services.ServiceType;
|
||||
import org.jclouds.rest.RestContext;
|
||||
import org.testng.annotations.AfterGroups;
|
||||
import org.testng.annotations.BeforeGroups;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.reflect.TypeToken;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code KeystoneClient}
|
||||
*
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
@Test(groups = "live")
|
||||
public class BaseKeystoneClientLiveTest extends BaseContextLiveTest<RestContext<KeystoneClient, KeystoneAsyncClient>> {
|
||||
|
||||
public BaseKeystoneClientLiveTest() {
|
||||
provider = "openstack-keystone";
|
||||
}
|
||||
|
||||
protected RestContext<KeystoneClient, KeystoneAsyncClient> keystoneContext;
|
||||
|
||||
@BeforeGroups(groups = { "integration", "live" })
|
||||
@Override
|
||||
public void setupContext() {
|
||||
super.setupContext();
|
||||
keystoneContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Properties setupProperties() {
|
||||
Properties props = super.setupProperties();
|
||||
setIfTestSystemPropertyPresent(props, KeystoneProperties.CREDENTIAL_TYPE);
|
||||
return props;
|
||||
}
|
||||
|
||||
@AfterGroups(groups = "live")
|
||||
protected void tearDown() {
|
||||
if (keystoneContext != null)
|
||||
keystoneContext.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TypeToken<RestContext<KeystoneClient, KeystoneAsyncClient>> contextType() {
|
||||
return KeystoneApiMetadata.CONTEXT_TOKEN;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 1.1 (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-1.1
|
||||
*
|
||||
* 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.openstack.keystone.v2_0.internal;
|
||||
|
||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.openstack.keystone.v1_1.config.AuthenticationServiceModule;
|
||||
import org.jclouds.openstack.services.ServiceType;
|
||||
import org.jclouds.rest.internal.BaseRestClientExpectTest;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
|
||||
/**
|
||||
* Base class for writing KeyStone 2.0 Rest Client Expect tests
|
||||
*
|
||||
* @author Adam Lowe
|
||||
*/
|
||||
public class BaseKeystoneRestClientExpectTest<S> extends BaseRestClientExpectTest<S> {
|
||||
protected HttpRequest keystoneAuthWithUsernameAndPassword;
|
||||
protected HttpRequest keystoneAuthWithAccessKeyAndSecretKey;
|
||||
protected String authToken;
|
||||
protected HttpResponse responseWithKeystoneAccess;
|
||||
protected String endpoint = "https://csnode.jclouds.org";
|
||||
|
||||
public BaseKeystoneRestClientExpectTest() {
|
||||
provider = "openstack-keystone";
|
||||
keystoneAuthWithUsernameAndPassword = KeystoneFixture.INSTANCE.initialAuthWithUsernameAndPassword(identity,
|
||||
credential);
|
||||
keystoneAuthWithAccessKeyAndSecretKey = KeystoneFixture.INSTANCE.initialAuthWithAccessKeyAndSecretKey(identity,
|
||||
credential);
|
||||
|
||||
authToken = KeystoneFixture.INSTANCE.getAuthToken();
|
||||
responseWithKeystoneAccess = KeystoneFixture.INSTANCE.responseWithAccess();
|
||||
// now, createContext arg will need tenant prefix
|
||||
identity = KeystoneFixture.INSTANCE.getTenantName() + ":" + identity;
|
||||
}
|
||||
|
||||
protected HttpRequest.Builder standardRequestBuilder(String endpoint) {
|
||||
return HttpRequest.builder().method("GET")
|
||||
.headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken))
|
||||
.endpoint(URI.create(endpoint));
|
||||
}
|
||||
|
||||
protected HttpResponse.Builder standardResponseBuilder(int status) {
|
||||
return HttpResponse.builder().statusCode(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Properties setupProperties() {
|
||||
Properties props = super.setupProperties();
|
||||
props.put(SERVICE_TYPE, ServiceType.IDENTITY);
|
||||
return props;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpRequestComparisonType compareHttpRequestAsType(HttpRequest input) {
|
||||
return Objects.equal("HEAD", input.getMethod()) ? HttpRequestComparisonType.DEFAULT : HttpRequestComparisonType.JSON;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{"version": {"status": "beta", "updated": "2011-11-19T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}, {"base": "application/xml", "type": "application/vnd.openstack.identity-v2.0+xml"}], "id": "v2.0", "links": [{"href": "http://172.16.89.140:5000/v2.0/", "rel": "self"}, {"href": "http://docs.openstack.org/api/openstack-identity-service/2.0/content/", "type": "text/html", "rel": "describedby"}, {"href": "http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf", "type": "application/pdf", "rel": "describedby"}]}}
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0"?>
|
||||
<configuration scan="false">
|
||||
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
|
||||
<file>target/test-data/jclouds.log</file>
|
||||
|
||||
<encoder>
|
||||
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
|
||||
<file>target/test-data/jclouds-wire.log</file>
|
||||
|
||||
<encoder>
|
||||
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="BLOBSTOREFILE" class="ch.qos.logback.core.FileAppender">
|
||||
<file>target/test-data/jclouds-blobstore.log</file>
|
||||
|
||||
<encoder>
|
||||
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root>
|
||||
<level value="warn" />
|
||||
</root>
|
||||
|
||||
<logger name="org.jclouds">
|
||||
<level value="DEBUG" />
|
||||
<appender-ref ref="FILE" />
|
||||
</logger>
|
||||
|
||||
<logger name="jclouds.wire">
|
||||
<level value="DEBUG" />
|
||||
<appender-ref ref="WIREFILE" />
|
||||
</logger>
|
||||
|
||||
<logger name="jclouds.headers">
|
||||
<level value="DEBUG" />
|
||||
<appender-ref ref="WIREFILE" />
|
||||
</logger>
|
||||
|
||||
<logger name="jclouds.blobstore">
|
||||
<level value="DEBUG" />
|
||||
<appender-ref ref="BLOBSTOREFILE" />
|
||||
</logger>
|
||||
|
||||
</configuration>
|
|
@ -0,0 +1 @@
|
|||
{"tenant": {"enabled": true, "description": null, "name": "admin", "id": "013ba41150a14830bec85ffe93353bcc"}}
|
|
@ -0,0 +1 @@
|
|||
{"tenants_links": [], "tenants": [{"enabled": true, "description": null, "name": "demo", "id": "05d1dc7af71646deba64cfc17b81bec0"}, {"enabled": true, "description": null, "name": "admin", "id": "7aa2e17ec29f44d193c48feaba0852cc"}]}
|
|
@ -0,0 +1 @@
|
|||
{"access": {"token": {"expires": "2012-04-28T12:42:50Z", "id": "167eccdc790946969ced473732e8109b", "tenant": {"id": "4cea93f5464b4f1c921fb3e0461d72b5", "enabled": true, "description": null, "name": "demo"}}, "user": {"username": "admin", "roles_links": [], "id": "2b9b606181634ae9ac86fd95a8bc2cde", "roles": [{"id": "79cada5c02814b57a52e0eed4dd388cb", "name": "admin"}], "name": "admin"}}}
|
|
@ -0,0 +1 @@
|
|||
{"user": {"name": "nova", "enabled": true, "email": "nova@example.com", "id": "e021dfd758eb44a89f1c57c8ef3be8e2", "tenantId": "ab1da202f5774cceb5da2aeff1f0aa87"}}
|
|
@ -0,0 +1,10 @@
|
|||
{"endpoints": [
|
||||
{
|
||||
"adminURL": "https://csnode.jclouds.org:35357/v2.0/",
|
||||
"publicURL": "https://csnode.jclouds.org/v2.0/",
|
||||
"region": "region-a.geo-1",
|
||||
"id": "2.0",
|
||||
"versionId":"2.0",
|
||||
"list": "https://csnode.jclouds.org/extension"
|
||||
}
|
||||
]}
|
|
@ -0,0 +1 @@
|
|||
{"users": [{"name": "admin", "enabled": true, "email": "admin@example.com", "id": "2b9b606181634ae9ac86fd95a8bc2cde", "tenantId": null}, {"name": "demo", "enabled": true, "email": "demo@example.com", "id": "667b2e1420604df8b67cd8ea57d4ee64", "tenantId": null}, {"name": "nova", "enabled": true, "email": "nova@example.com", "id": "e021dfd758eb44a89f1c57c8ef3be8e2", "tenantId": "ab1da202f5774cceb5da2aeff1f0aa87"}, {"name": "glance", "enabled": true, "email": "glance@example.com", "id": "3f6c1c9ba993495ead7d2eb2192e284f", "tenantId": "ab1da202f5774cceb5da2aeff1f0aa87"}]}
|
|
@ -0,0 +1 @@
|
|||
{"roles": [{"id": "79cada5c02814b57a52e0eed4dd388cb", "name": "admin"}]}
|
|
@ -0,0 +1 @@
|
|||
{"roles": [{"id": "31c451195aac49b386039341e2c92a16", "name": "KeystoneServiceAdmin"}, {"id": "79cada5c02814b57a52e0eed4dd388cb", "name": "admin"}, {"id": "6ea17ddd37a6447794cb0e164d4db894", "name": "KeystoneAdmin"}]}
|
|
@ -46,5 +46,6 @@
|
|||
<module>cdmi</module>
|
||||
<module>openstack-glance</module>
|
||||
<module>joyent-sdc</module>
|
||||
<module>openstack-keystone</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.vcloud.director.v1_5.compute.functions;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.collect.Memoized;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.Reference;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
|
||||
/**
|
||||
* @author danikov
|
||||
*/
|
||||
@Singleton
|
||||
public class FindLocationForResource implements Function<Reference, Location> {
|
||||
|
||||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
final Supplier<Set<? extends Location>> locations;
|
||||
|
||||
@Inject
|
||||
public FindLocationForResource(@Memoized Supplier<Set<? extends Location>> locations) {
|
||||
this.locations = locations;
|
||||
}
|
||||
|
||||
/**
|
||||
* searches for a location associated with this resource.
|
||||
*
|
||||
* @throws NoSuchElementException
|
||||
* if not found
|
||||
*/
|
||||
public Location apply(Reference resource) {
|
||||
for (Location input : locations.get()) {
|
||||
do {
|
||||
// The "name" isn't always present, ex inside a vApp we have a rel
|
||||
// link that only includes href and type.
|
||||
if (URI.create(input.getId()).equals(resource.getHref()))
|
||||
return input;
|
||||
} while ((input = input.getParent()) != null);
|
||||
}
|
||||
throw new NoSuchElementException(String.format("resource: %s not found in locations: %s", resource,
|
||||
locations.get()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.vcloud.director.v1_5.compute.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.HardwareBuilder;
|
||||
import org.jclouds.compute.predicates.ImagePredicates;
|
||||
import org.jclouds.dmtf.ovf.VirtualHardwareSection;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.Link;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.dmtf.Envelope;
|
||||
import org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class HardwareForVAppTemplate implements Function<VAppTemplate, Hardware> {
|
||||
|
||||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final Function<VAppTemplate, Envelope> templateToEnvelope;
|
||||
private final FindLocationForResource findLocationForResource;
|
||||
private final VCloudHardwareBuilderFromResourceAllocations rasdToHardwareBuilder;
|
||||
|
||||
@Inject
|
||||
protected HardwareForVAppTemplate(Function<VAppTemplate, Envelope> templateToEnvelope,
|
||||
FindLocationForResource findLocationForResource,
|
||||
VCloudHardwareBuilderFromResourceAllocations rasdToHardwareBuilder) {
|
||||
this.templateToEnvelope = checkNotNull(templateToEnvelope, "templateToEnvelope");
|
||||
this.findLocationForResource = checkNotNull(findLocationForResource, "findLocationForResource");
|
||||
this.rasdToHardwareBuilder = checkNotNull(rasdToHardwareBuilder, "rasdToHardwareBuilder");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hardware apply(VAppTemplate from) {
|
||||
checkNotNull(from, "VAppTemplate");
|
||||
|
||||
Envelope ovf = templateToEnvelope.apply(from);
|
||||
|
||||
if (ovf.getVirtualSystem().getVirtualHardwareSections().size() > 1) {
|
||||
logger.warn("multiple hardware choices found. using first", ovf);
|
||||
}
|
||||
VirtualHardwareSection hardware = Iterables.get(ovf.getVirtualSystem().getVirtualHardwareSections(), 0);
|
||||
HardwareBuilder builder = rasdToHardwareBuilder.apply(hardware.getItems());
|
||||
Link vdc = Iterables.find(checkNotNull(from, "from").getLinks(), LinkPredicates.typeEquals(VCloudDirectorMediaType.VDC));
|
||||
if (vdc != null) {
|
||||
builder.location(findLocationForResource.apply(vdc));
|
||||
} else {
|
||||
// otherwise, it could be in a public catalog, which is not assigned to a VDC
|
||||
}
|
||||
builder.ids(from.getHref().toASCIIString()).name(from.getName()).supportsImage(
|
||||
ImagePredicates.idEquals(from.getHref().toASCIIString()));
|
||||
builder.hypervisor("VMware");
|
||||
return builder.build();
|
||||
|
||||
}
|
||||
|
||||
protected String getName(String name) {
|
||||
return name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.vcloud.director.v1_5.compute.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.HardwareBuilder;
|
||||
import org.jclouds.compute.predicates.ImagePredicates;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.Reference;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.Vm;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.section.VirtualHardwareSection;
|
||||
import org.jclouds.vcloud.director.v1_5.functions.SectionForVApp;
|
||||
import org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class HardwareForVm implements Function<Vm, Hardware> {
|
||||
|
||||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final Function<Reference, Location> findLocationForResource;
|
||||
private final VCloudHardwareBuilderFromResourceAllocations rasdToHardwareBuilder;
|
||||
private final SectionForVApp<VirtualHardwareSection> findVirtualHardwareSectionForVm;
|
||||
|
||||
@Inject
|
||||
protected HardwareForVm(Function<Reference, Location> findLocationForResource,
|
||||
VCloudHardwareBuilderFromResourceAllocations rasdToHardwareBuilder,
|
||||
SectionForVApp<VirtualHardwareSection> findVirtualHardwareSectionForVm) {
|
||||
this.findLocationForResource = checkNotNull(findLocationForResource, "findLocationForResource");
|
||||
this.rasdToHardwareBuilder = checkNotNull(rasdToHardwareBuilder, "rasdToHardwareBuilder");
|
||||
this.findVirtualHardwareSectionForVm = checkNotNull(findVirtualHardwareSectionForVm, "findVirtualHardwareSectionForVm");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hardware apply(Vm from) {
|
||||
checkNotNull(from, "VApp");
|
||||
// TODO make this work with composite vApps
|
||||
if (from == null)
|
||||
return null;
|
||||
|
||||
VirtualHardwareSection hardware = findVirtualHardwareSectionForVm.apply(from);
|
||||
HardwareBuilder builder = rasdToHardwareBuilder.apply(hardware.getItems());
|
||||
builder.location(findLocationForResource.apply(Iterables.find(checkNotNull(from, "from").getLinks(),
|
||||
LinkPredicates.typeEquals(VCloudDirectorMediaType.VDC))));
|
||||
builder.ids(from.getHref().toASCIIString()).name(from.getName()).supportsImage(
|
||||
ImagePredicates.idEquals(from.getHref().toASCIIString()));
|
||||
builder.hypervisor("VMware");
|
||||
return builder.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.vcloud.director.v1_5.compute.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.compute.domain.CIMOperatingSystem;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.ImageBuilder;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.ovf.Envelope;
|
||||
import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.Link;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate;
|
||||
import org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ImageForVAppTemplate implements Function<VAppTemplate, Image> {
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
public Logger logger = Logger.NULL;
|
||||
|
||||
private final Function<VAppTemplate, Envelope> templateToEnvelope;
|
||||
private final FindLocationForResource findLocationForResource;
|
||||
|
||||
@Inject
|
||||
protected ImageForVAppTemplate(Function<VAppTemplate, Envelope> templateToEnvelope,
|
||||
FindLocationForResource findLocationForResource) {
|
||||
this.templateToEnvelope = checkNotNull(templateToEnvelope, "templateToEnvelope");
|
||||
this.findLocationForResource = checkNotNull(findLocationForResource, "findLocationForResource");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image apply(VAppTemplate from) {
|
||||
checkNotNull(from, "VAppTemplate");
|
||||
Envelope ovf = templateToEnvelope.apply(from);
|
||||
|
||||
ImageBuilder builder = new ImageBuilder();
|
||||
builder.ids(from.getHref().toASCIIString());
|
||||
builder.uri(from.getHref());
|
||||
builder.name(from.getName());
|
||||
Link vdc = Iterables.find(checkNotNull(from, "from").getLinks(), LinkPredicates.typeEquals(VCloudDirectorMediaType.VDC));
|
||||
if (vdc != null) {
|
||||
builder.location(findLocationForResource.apply(vdc));
|
||||
} else {
|
||||
// otherwise, it could be in a public catalog, which is not assigned to a VDC
|
||||
}
|
||||
builder.description(from.getDescription() != null ? from.getDescription() : from.getName());
|
||||
builder.operatingSystem(CIMOperatingSystem.toComputeOs(ovf));
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.vcloud.director.v1_5.compute.functions;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.compute.domain.Volume;
|
||||
import org.jclouds.dmtf.cim.ResourceAllocationSettingData;
|
||||
import org.jclouds.dmtf.cim.functions.HardwareBuilderFromResourceAllocations;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class VCloudHardwareBuilderFromResourceAllocations extends HardwareBuilderFromResourceAllocations {
|
||||
@Override
|
||||
public Volume apply(ResourceAllocationSettingData from) {
|
||||
// FIXME: not yet implemented
|
||||
// if (from instanceof VCloudHardDisk) {
|
||||
// VCloudHardDisk vDisk = VCloudHardDisk.class.cast(from);
|
||||
// return new VolumeImpl(from.getAddressOnParent() + "", Volume.Type.LOCAL, vDisk.getCapacity() / 1024f, null,
|
||||
// "0".equals(from.getAddressOnParent()), true);
|
||||
// } else {
|
||||
return super.apply(from);
|
||||
// }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.vcloud.director.v1_5.compute.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.dmtf.ovf.NetworkSection;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.ovf.Envelope;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate;
|
||||
import org.jclouds.vcloud.director.v1_5.functions.SectionForVAppTemplate;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException implements
|
||||
Function<VAppTemplate, Envelope> {
|
||||
|
||||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final LoadingCache<URI, Envelope> envelopes;
|
||||
private final SectionForVAppTemplate<NetworkSection> findNetworkSectionForVAppTemplate;
|
||||
|
||||
@Inject
|
||||
protected ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException(LoadingCache<URI, Envelope> envelopes,
|
||||
SectionForVAppTemplate<NetworkSection> findNetworkSectionForVAppTemplate) {
|
||||
this.envelopes = checkNotNull(envelopes, "envelopes");
|
||||
this.findNetworkSectionForVAppTemplate = checkNotNull(findNetworkSectionForVAppTemplate, "findNetworkSectionForVAppTemplate");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Envelope apply(VAppTemplate from) {
|
||||
checkArgument(from.getChildren().size() == 1, "multiple vms are not supported: %s", from);
|
||||
|
||||
checkArgument(findNetworkSectionForVAppTemplate.apply(from).getNetworks().size() == 1,
|
||||
"multiple network connections are not supported: %s", from);
|
||||
|
||||
checkArgument(from.isOvfDescriptorUploaded(), "ovf descriptor is not uploaded: %s", from);
|
||||
Envelope ovf = getOVFForVAppTemplateAndValidate(from);
|
||||
return ovf;
|
||||
}
|
||||
|
||||
private Envelope getOVFForVAppTemplateAndValidate(VAppTemplate from) throws IllegalArgumentException {
|
||||
Envelope ovf;
|
||||
try {
|
||||
ovf = envelopes.get(from.getHref());
|
||||
checkArgument(ovf.getVirtualSystem().getVirtualHardwareSections().size() > 0,
|
||||
"no hardware sections exist in ovf %s", ovf);
|
||||
} catch (ExecutionException e) {
|
||||
throw new IllegalArgumentException("no ovf envelope found for: " + from, e);
|
||||
}
|
||||
return ovf;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.vcloud.director.v1_5.compute.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Predicates.not;
|
||||
import static com.google.common.collect.Iterables.filter;
|
||||
import static org.jclouds.vcloud.director.v1_5.compute.util.VCloudDirectorComputeUtils.getCredentialsFrom;
|
||||
import static org.jclouds.vcloud.director.v1_5.compute.util.VCloudDirectorComputeUtils.getIpsFromVm;
|
||||
import static org.jclouds.vcloud.director.v1_5.compute.util.VCloudDirectorComputeUtils.toComputeOs;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||
import org.jclouds.compute.domain.NodeState;
|
||||
import org.jclouds.compute.functions.GroupNamingConvention;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.util.InetAddresses2.IsPrivateIPAddress;
|
||||
import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.ResourceEntity.Status;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.Vm;
|
||||
import org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class VmToNodeMetadata implements Function<Vm, NodeMetadata> {
|
||||
@Resource
|
||||
protected static Logger logger = Logger.NULL;
|
||||
|
||||
protected final FindLocationForResource findLocationForResourceInVDC;
|
||||
protected final Function<Vm, Hardware> hardwareForVm;
|
||||
protected final Map<Status, NodeState> vAppStatusToNodeState;
|
||||
protected final Map<String, Credentials> credentialStore;
|
||||
protected final GroupNamingConvention nodeNamingConvention;
|
||||
|
||||
@Inject
|
||||
protected VmToNodeMetadata(Map<Status, NodeState> vAppStatusToNodeState, Map<String, Credentials> credentialStore,
|
||||
FindLocationForResource findLocationForResourceInVDC, Function<Vm, Hardware> hardwareForVm,
|
||||
GroupNamingConvention.Factory namingConvention) {
|
||||
this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
|
||||
this.hardwareForVm = checkNotNull(hardwareForVm, "hardwareForVm");
|
||||
this.findLocationForResourceInVDC = checkNotNull(findLocationForResourceInVDC, "findLocationForResourceInVDC");
|
||||
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
|
||||
this.vAppStatusToNodeState = checkNotNull(vAppStatusToNodeState, "vAppStatusToNodeState");
|
||||
}
|
||||
|
||||
public NodeMetadata apply(Vm from) {
|
||||
NodeMetadataBuilder builder = new NodeMetadataBuilder();
|
||||
builder.ids(from.getHref().toASCIIString());
|
||||
builder.uri(from.getHref());
|
||||
builder.name(from.getName());
|
||||
builder.hostname(from.getName());
|
||||
builder.location(findLocationForResourceInVDC.apply(
|
||||
Iterables.find(from.getLinks(), LinkPredicates.typeEquals(VCloudDirectorMediaType.VDC))));
|
||||
builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getName()));
|
||||
builder.operatingSystem(toComputeOs(from));
|
||||
builder.hardware(hardwareForVm.apply(from));
|
||||
builder.state(vAppStatusToNodeState.get(from.getStatus()));
|
||||
Set<String> addresses = getIpsFromVm(from);
|
||||
builder.publicAddresses(filter(addresses, not(IsPrivateIPAddress.INSTANCE)));
|
||||
builder.privateAddresses(filter(addresses, IsPrivateIPAddress.INSTANCE));
|
||||
|
||||
// normally, we don't affect the credential store when reading vApps.
|
||||
// However, login user, etc, is actually in the metadata, so lets see
|
||||
Credentials fromApi = getCredentialsFrom(from);
|
||||
if (fromApi != null && !credentialStore.containsKey("node#" + from.getHref().toASCIIString()))
|
||||
credentialStore.put("node#" + from.getHref().toASCIIString(), fromApi);
|
||||
return builder.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.vcloud.director.v1_5.compute.util;
|
||||
|
||||
import static com.google.common.collect.Iterables.filter;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.cim.OSType;
|
||||
import org.jclouds.compute.domain.CIMOperatingSystem;
|
||||
import org.jclouds.compute.domain.OperatingSystem;
|
||||
import org.jclouds.dmtf.CIMPredicates;
|
||||
import org.jclouds.dmtf.cim.ResourceAllocationSettingData;
|
||||
import org.jclouds.dmtf.cim.ResourceAllocationSettingData.ResourceType;
|
||||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.VApp;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.Vm;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConnection;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.section.OperatingSystemSection;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.section.VirtualHardwareSection;
|
||||
import org.jclouds.vcloud.director.v1_5.functions.SectionForVApp;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSet.Builder;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author danikov
|
||||
*/
|
||||
public class VCloudDirectorComputeUtils {
|
||||
|
||||
public static OperatingSystem toComputeOs(VApp vApp, OperatingSystem defaultOs) {
|
||||
CIMOperatingSystem cimOs = toComputeOs(vApp);
|
||||
return cimOs != null ? cimOs : defaultOs;
|
||||
}
|
||||
|
||||
public static CIMOperatingSystem toComputeOs(VApp vApp) {
|
||||
// TODO we need to change the design so that it doesn't assume single-vms
|
||||
return vApp.getChildren().getVms().size() > 0 ? toComputeOs(Iterables.get(vApp.getChildren().getVms(), 0)) : null;
|
||||
}
|
||||
|
||||
private static SectionForVApp<OperatingSystemSection> findOperatingSystemSectionForVApp =
|
||||
new SectionForVApp<OperatingSystemSection>(OperatingSystemSection.class);
|
||||
|
||||
public static CIMOperatingSystem toComputeOs(Vm vm) {
|
||||
return toComputeOs(findOperatingSystemSectionForVApp.apply(vm));
|
||||
}
|
||||
|
||||
public static CIMOperatingSystem toComputeOs(OperatingSystemSection os) {
|
||||
return new CIMOperatingSystem(OSType.fromValue(os.getId()), "", null, os.getDescription());
|
||||
}
|
||||
|
||||
public static String getVirtualSystemIdentifierOfFirstVMIn(VApp vApp) {
|
||||
return vApp.getChildren().getVms().size() > 0 ?
|
||||
getVirtualSystemIdentifierOf(Iterables.get(vApp.getChildren().getVms(), 0)) : null;
|
||||
}
|
||||
|
||||
@Inject private static SectionForVApp<VirtualHardwareSection> findVirtualHardwareSectionForVApp =
|
||||
new SectionForVApp<VirtualHardwareSection>(VirtualHardwareSection.class);
|
||||
|
||||
public static String getVirtualSystemIdentifierOf(Vm vm) {
|
||||
VirtualHardwareSection virtualHardwareSection = findVirtualHardwareSectionForVApp.apply(vm);
|
||||
if (virtualHardwareSection != null && virtualHardwareSection != null)
|
||||
return virtualHardwareSection.getSystem().getVirtualSystemIdentifier();
|
||||
return null;
|
||||
}
|
||||
|
||||
public static LoginCredentials getCredentialsFrom(VApp vApp) {
|
||||
return vApp.getChildren().getVms().size() > 0 ?
|
||||
getCredentialsFrom(Iterables.get(vApp.getChildren().getVms(), 0)) : null;
|
||||
}
|
||||
|
||||
public static LoginCredentials getCredentialsFrom(VAppTemplate vApp) {
|
||||
return vApp.getChildren().size() > 0 ? getCredentialsFrom(Iterables.get(vApp.getChildren(), 0)) : null;
|
||||
}
|
||||
|
||||
@Inject private static SectionForVApp<GuestCustomizationSection> findGuestCustomizationSectionForVApp =
|
||||
new SectionForVApp<GuestCustomizationSection>(GuestCustomizationSection.class);
|
||||
|
||||
public static LoginCredentials getCredentialsFrom(Vm vm) {
|
||||
LoginCredentials.Builder builder = LoginCredentials.builder();
|
||||
GuestCustomizationSection guestCustomizationSection = findGuestCustomizationSectionForVApp.apply(vm);
|
||||
if (guestCustomizationSection != null)
|
||||
builder.password(guestCustomizationSection.getAdminPassword());
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Inject private static SectionForVApp<NetworkConnectionSection> findNetworkConnectionSectionForVApp =
|
||||
new SectionForVApp<NetworkConnectionSection>(NetworkConnectionSection.class);
|
||||
|
||||
public static Set<String> getIpsFromVApp(VApp vApp) {
|
||||
// TODO make this work with composite vApps
|
||||
if (vApp.getChildren().getVms().size() == 0)
|
||||
return ImmutableSet.of();
|
||||
return getIpsFromVm(Iterables.get(vApp.getChildren().getVms(), 0));
|
||||
}
|
||||
|
||||
public static Set<String> getIpsFromVm(Vm vm) {
|
||||
Builder<String> ips = ImmutableSet.builder();
|
||||
// TODO: figure out how to differentiate public from private ip addresses
|
||||
// assumption is that we'll do this from the network object, which may
|
||||
// have
|
||||
// enough data to tell whether or not it is a public network without
|
||||
// string
|
||||
// parsing. At worst, we could have properties set per cloud provider to
|
||||
// declare the networks which are public, then check against these in
|
||||
// networkconnection.getNetwork
|
||||
NetworkConnectionSection networkConnectionSection = findNetworkConnectionSectionForVApp.apply(vm);
|
||||
if (networkConnectionSection != null) {
|
||||
for (NetworkConnection connection : networkConnectionSection.getNetworkConnections()) {
|
||||
if (connection.getIpAddress() != null)
|
||||
ips.add(connection.getIpAddress());
|
||||
if (connection.getExternalIpAddress() != null)
|
||||
ips.add(connection.getExternalIpAddress());
|
||||
}
|
||||
} else {
|
||||
for (ResourceAllocationSettingData net : filter(findVirtualHardwareSectionForVApp.apply(vm).getItems(),
|
||||
CIMPredicates.resourceTypeIn(ResourceType.ETHERNET_ADAPTER))) {
|
||||
// FIXME: not yet implemented
|
||||
// if (net instanceof VCloudNetworkAdapter) {
|
||||
// VCloudNetworkAdapter vNet = VCloudNetworkAdapter.class.cast(net);
|
||||
// if (vNet.getIpAddress() != null)
|
||||
// ips.add(vNet.getIpAddress());
|
||||
// }
|
||||
}
|
||||
}
|
||||
return ips.build();
|
||||
}
|
||||
}
|
|
@ -43,6 +43,7 @@ import org.jclouds.rest.internal.RestContextImpl;
|
|||
import org.jclouds.vcloud.director.v1_5.admin.VCloudDirectorAdminAsyncClient;
|
||||
import org.jclouds.vcloud.director.v1_5.admin.VCloudDirectorAdminClient;
|
||||
import org.jclouds.vcloud.director.v1_5.annotations.Login;
|
||||
import org.jclouds.vcloud.director.v1_5.compute.util.VCloudDirectorComputeUtils;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.Session;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.SessionWithToken;
|
||||
import org.jclouds.vcloud.director.v1_5.features.CatalogAsyncClient;
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.vcloud.director.v1_5.functions;
|
||||
|
||||
import org.jclouds.dmtf.ovf.SectionType;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.AbstractVAppType;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
* @author danikov
|
||||
*/
|
||||
public class SectionForVApp<S extends SectionType> implements Function<AbstractVAppType, S> {
|
||||
|
||||
private final Class<? extends SectionType> sectionType;
|
||||
|
||||
public SectionForVApp(Class<S> sectionType) {
|
||||
this.sectionType = sectionType;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public S apply(AbstractVAppType from) {
|
||||
for (SectionType section : from.getSections()) {
|
||||
if (sectionType.isAssignableFrom(section.getClass())) {
|
||||
return (S)section;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -18,8 +18,6 @@
|
|||
*/
|
||||
package org.jclouds.vcloud.director.v1_5.functions;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
|
@ -27,7 +25,6 @@ import org.jclouds.dmtf.ovf.SectionType;
|
|||
import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* @author danikov
|
||||
|
@ -45,7 +42,6 @@ public class SectionForVAppTemplate<S extends SectionType> implements Function<V
|
|||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public S apply(VAppTemplate from) {
|
||||
Set<S> sections = Sets.newLinkedHashSet();
|
||||
for (SectionType section : from.getSections()) {
|
||||
if (sectionType.isAssignableFrom(section.getClass())) {
|
||||
return (S)section;
|
||||
|
|
|
@ -20,9 +20,13 @@ package org.jclouds.vcloud.director.v1_5.predicates;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
|
||||
import org.jclouds.vcloud.director.v1_5.domain.Link;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
|
||||
/**
|
||||
* Predicates handy when working with Links
|
||||
|
@ -31,7 +35,7 @@ import com.google.common.base.Predicate;
|
|||
*/
|
||||
|
||||
public class LinkPredicates {
|
||||
|
||||
|
||||
/**
|
||||
* matches links of the given relation
|
||||
*
|
||||
|
@ -46,32 +50,57 @@ public class LinkPredicates {
|
|||
|
||||
/** @see #relEquals(String) */
|
||||
public static Predicate<Link> relEquals(final Link.Rel rel) {
|
||||
checkNotNull(rel, "rel must be defined");
|
||||
|
||||
return new Predicate<Link>() {
|
||||
@Override
|
||||
public boolean apply(Link link) {
|
||||
return rel == link.getRel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "relEquals(" + rel.value() + ")";
|
||||
}
|
||||
};
|
||||
return LINK_REL_SELECTORS.apply(checkNotNull(rel, "rel must be defined"));
|
||||
}
|
||||
|
||||
private static final LoadingCache<Link.Rel, Predicate<Link>> LINK_REL_SELECTORS = CacheBuilder.newBuilder()
|
||||
.maximumSize(Link.Rel.ALL.size())
|
||||
.build(
|
||||
new CacheLoader<Link.Rel, Predicate<Link>>() {
|
||||
public Predicate<Link> load(final Link.Rel rel) {
|
||||
return new Predicate<Link>() {
|
||||
@Override
|
||||
public boolean apply(Link link) {
|
||||
return rel == link.getRel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "relEquals(" + rel.value() + ")";
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @see ReferenceTypePredicates#nameEquals
|
||||
*/
|
||||
public static Predicate<Link> nameEquals(String name) {
|
||||
return ReferencePredicates.nameEquals(name);
|
||||
return MEDIA_NAME_SELECTORS.apply(name);
|
||||
}
|
||||
|
||||
private static final LoadingCache<String, Predicate<Link>> MEDIA_NAME_SELECTORS = CacheBuilder.newBuilder()
|
||||
.maximumSize(VCloudDirectorMediaType.ALL.size())
|
||||
.build(
|
||||
new CacheLoader<String, Predicate<Link>>() {
|
||||
public Predicate<Link> load(String key) {
|
||||
return ReferencePredicates.nameEquals(key);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @see ReferenceTypePredicates#typeEquals
|
||||
*/
|
||||
public static Predicate<Link> typeEquals(String type) {
|
||||
return ReferencePredicates.typeEquals(type);
|
||||
return MEDIA_TYPE_SELECTORS.apply(type);
|
||||
}
|
||||
|
||||
private static final LoadingCache<String, Predicate<Link>> MEDIA_TYPE_SELECTORS = CacheBuilder.newBuilder()
|
||||
.maximumSize(VCloudDirectorMediaType.ALL.size())
|
||||
.build(
|
||||
new CacheLoader<String, Predicate<Link>>() {
|
||||
public Predicate<Link> load(String key) {
|
||||
return ReferencePredicates.typeEquals(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue