http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/KeystoneApiMetadata.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/KeystoneApiMetadata.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/KeystoneApiMetadata.java new file mode 100644 index 0000000..d649563 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/KeystoneApiMetadata.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.v3; + +import static org.jclouds.openstack.keystone.config.KeystoneProperties.CREDENTIAL_TYPE; +import static org.jclouds.openstack.keystone.config.KeystoneProperties.KEYSTONE_VERSION; +import static org.jclouds.openstack.keystone.config.KeystoneProperties.SERVICE_TYPE; + +import java.net.URI; +import java.util.Properties; + +import org.jclouds.apis.ApiMetadata; +import org.jclouds.openstack.keystone.auth.config.AuthenticationModule; +import org.jclouds.openstack.keystone.catalog.config.KeystoneAdminURLModule; +import org.jclouds.openstack.keystone.catalog.config.ServiceCatalogModule; +import org.jclouds.openstack.keystone.v2_0.config.KeystoneHttpApiModule; +import org.jclouds.openstack.keystone.v2_0.config.KeystoneParserModule; +import org.jclouds.openstack.v2_0.ServiceType; +import org.jclouds.rest.internal.BaseHttpApiMetadata; + +import com.google.auto.service.AutoService; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Module; + +/** + * Implementation of {@link ApiMetadata} for Keystone 3.0 API + */ +@AutoService(ApiMetadata.class) +public class KeystoneApiMetadata extends BaseHttpApiMetadata<KeystoneApi> { + + @Override + public Builder<?> toBuilder() { + return new ConcreteBuilder().fromApiMetadata(this); + } + + public KeystoneApiMetadata() { + this(new ConcreteBuilder()); + } + + protected KeystoneApiMetadata(Builder<?> builder) { + super(builder); + } + + public static Properties defaultProperties() { + Properties properties = BaseHttpApiMetadata.defaultProperties(); + properties.setProperty(CREDENTIAL_TYPE, org.jclouds.openstack.keystone.auth.config.CredentialTypes.PASSWORD_CREDENTIALS); + properties.setProperty(SERVICE_TYPE, ServiceType.IDENTITY); + properties.setProperty(KEYSTONE_VERSION, "2"); + return properties; + } + + public abstract static class Builder<T extends Builder<T>> extends BaseHttpApiMetadata.Builder<KeystoneApi, T> { + + protected Builder() { + id("openstack-keystone-3") + .name("OpenStack Keystone 3.x API") + .identityName("${tenantName}:${userName} or ${userName}, if your keystone supports a default tenant") + .credentialName("${password}") + .endpointName("Keystone base url ending in /v${jclouds.api-version}/") + .documentation(URI.create("http://api.openstack.org/")) + .version("3") + .defaultEndpoint("http://localhost:5000/v${jclouds.api-version}/") + .defaultProperties(KeystoneApiMetadata.defaultProperties()) + .defaultModules(ImmutableSet.<Class<? extends Module>>builder() + .add(AuthenticationModule.class) + .add(ServiceCatalogModule.class) + .add(KeystoneAdminURLModule.class) + .add(KeystoneParserModule.class) + .add(KeystoneHttpApiModule.class).build()); + } + + @Override + public KeystoneApiMetadata build() { + return new KeystoneApiMetadata(this); + } + } + + private static class ConcreteBuilder extends Builder<ConcreteBuilder> { + @Override + protected ConcreteBuilder self() { + return this; + } + } +}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/auth/V3AuthenticationApi.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/auth/V3AuthenticationApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/auth/V3AuthenticationApi.java new file mode 100644 index 0000000..7a84c21 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/auth/V3AuthenticationApi.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.v3.auth; + +import java.io.Closeable; + +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.core.MediaType; + +import org.jclouds.openstack.keystone.auth.AuthenticationApi; +import org.jclouds.openstack.keystone.auth.domain.PasswordCredentials; +import org.jclouds.openstack.keystone.auth.domain.TenantAndCredentials; +import org.jclouds.openstack.keystone.auth.domain.TokenCredentials; +import org.jclouds.openstack.keystone.v3.binders.BindPasswordAuthToJsonPayload; +import org.jclouds.openstack.keystone.v3.binders.BindTokenAuthToJsonPayload; +import org.jclouds.openstack.keystone.v3.domain.Token; +import org.jclouds.openstack.keystone.v3.parsers.ParseToken; +import org.jclouds.rest.annotations.MapBinder; +import org.jclouds.rest.annotations.ResponseParser; + +import com.google.inject.name.Named; + +/** + * Provides access to the OpenStack Keystone Authentication API. + */ +@Consumes(MediaType.APPLICATION_JSON) +@Path("/auth/tokens") +public interface V3AuthenticationApi extends AuthenticationApi, Closeable { + + @Named("token:create") + @POST + @ResponseParser(ParseToken.class) + @MapBinder(BindPasswordAuthToJsonPayload.class) + @Override + Token authenticatePassword(TenantAndCredentials<PasswordCredentials> credentials); + + @Named("token:create") + @POST + @ResponseParser(ParseToken.class) + @MapBinder(BindTokenAuthToJsonPayload.class) + @Override + Token authenticateToken(TenantAndCredentials<TokenCredentials> credentials); + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindAuthToJsonPayload.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindAuthToJsonPayload.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindAuthToJsonPayload.java new file mode 100644 index 0000000..f100988 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindAuthToJsonPayload.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.v3.binders; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.instanceOf; +import static com.google.common.collect.Iterables.tryFind; + +import java.util.Map; + +import org.jclouds.http.HttpRequest; +import org.jclouds.json.Json; +import org.jclouds.openstack.keystone.auth.domain.TenantAndCredentials; +import org.jclouds.openstack.keystone.v3.domain.Auth; +import org.jclouds.rest.MapBinder; +import org.jclouds.rest.binders.BindToJsonPayload; +import org.jclouds.rest.internal.GeneratedHttpRequest; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableMap; + +public abstract class BindAuthToJsonPayload<T> extends BindToJsonPayload implements MapBinder { + + protected BindAuthToJsonPayload(Json jsonBinder) { + super(jsonBinder); + } + + protected abstract Auth buildAuth(TenantAndCredentials<T> credentials); + + @Override + public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) { + checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest, + "this binder is only valid for GeneratedHttpRequests!"); + GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request; + + Optional<Object> authentication = tryFind(gRequest.getInvocation().getArgs(), + instanceOf(TenantAndCredentials.class)); + checkArgument(authentication.isPresent(), "no credentials found in the api call arguments"); + + @SuppressWarnings("unchecked") + Auth auth = buildAuth((TenantAndCredentials<T>) authentication.get()); + + R authRequest = super.bindToRequest(request, ImmutableMap.of("auth", auth)); + authRequest.getPayload().setSensitive(true); + + return authRequest; + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindPasswordAuthToJsonPayload.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindPasswordAuthToJsonPayload.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindPasswordAuthToJsonPayload.java new file mode 100644 index 0000000..41f64bc --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindPasswordAuthToJsonPayload.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.v3.binders; + +import static java.util.Collections.singletonList; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.json.Json; +import org.jclouds.openstack.keystone.auth.domain.PasswordCredentials; +import org.jclouds.openstack.keystone.auth.domain.TenantAndCredentials; +import org.jclouds.openstack.keystone.v3.domain.Auth; +import org.jclouds.openstack.keystone.v3.domain.Auth.Identity; +import org.jclouds.openstack.keystone.v3.domain.Auth.Identity.PasswordAuth; +import org.jclouds.openstack.keystone.v3.domain.Auth.Identity.PasswordAuth.UserAuth; +import org.jclouds.openstack.keystone.v3.domain.Auth.Identity.PasswordAuth.UserAuth.DomainAuth; + +@Singleton +public class BindPasswordAuthToJsonPayload extends BindAuthToJsonPayload<PasswordCredentials> { + + @Inject + BindPasswordAuthToJsonPayload(Json jsonBinder) { + super(jsonBinder); + } + + @Override + protected Auth buildAuth(TenantAndCredentials<PasswordCredentials> credentials) { + return Auth.create(Identity.create( + singletonList("password"), + null, + PasswordAuth.create(UserAuth.create(credentials.credentials().username(), + DomainAuth.create(credentials.tenantName()), credentials.credentials().password())))); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindTokenAuthToJsonPayload.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindTokenAuthToJsonPayload.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindTokenAuthToJsonPayload.java new file mode 100644 index 0000000..9d60fad --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindTokenAuthToJsonPayload.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.v3.binders; + +import static java.util.Collections.singletonList; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.json.Json; +import org.jclouds.openstack.keystone.auth.domain.TenantAndCredentials; +import org.jclouds.openstack.keystone.auth.domain.TokenCredentials; +import org.jclouds.openstack.keystone.v3.domain.Auth; +import org.jclouds.openstack.keystone.v3.domain.Auth.Identity; +import org.jclouds.openstack.keystone.v3.domain.Auth.Identity.TokenAuth; + +@Singleton +public class BindTokenAuthToJsonPayload extends BindAuthToJsonPayload<TokenCredentials> { + + @Inject + BindTokenAuthToJsonPayload(Json jsonBinder) { + super(jsonBinder); + } + + @Override + protected Auth buildAuth(TenantAndCredentials<TokenCredentials> credentials) { + return Auth + .create(Identity.create(singletonList("token"), TokenAuth.create(credentials.credentials().id()), null)); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/catalog/V3ServiceCatalog.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/catalog/V3ServiceCatalog.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/catalog/V3ServiceCatalog.java new file mode 100644 index 0000000..0e86f2b --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/catalog/V3ServiceCatalog.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.v3.catalog; + +import java.util.List; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.logging.Logger; +import org.jclouds.openstack.keystone.auth.domain.AuthInfo; +import org.jclouds.openstack.keystone.catalog.ServiceEndpoint; +import org.jclouds.openstack.keystone.v3.domain.Catalog; +import org.jclouds.openstack.keystone.v3.domain.Endpoint; +import org.jclouds.openstack.keystone.v3.domain.Token; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; + +@Singleton +public class V3ServiceCatalog implements Supplier<List<ServiceEndpoint>> { + + @Resource + private Logger logger = Logger.NULL; + + private final Supplier<AuthInfo> authInfo; + + @Inject + V3ServiceCatalog(Supplier<AuthInfo> authInfo) { + this.authInfo = authInfo; + } + + @Override + public List<ServiceEndpoint> get() { + Token token = (Token) authInfo.get(); + + ImmutableList.Builder<ServiceEndpoint> serviceEndpoints = ImmutableList.builder(); + for (Catalog catalog : token.catalog()) { + for (Endpoint endpoint : catalog.endpoints()) { + serviceEndpoints.add(ServiceEndpoint.builder().id(endpoint.id()).iface(endpoint.iface()) + .regionId(endpoint.regionId()).type(catalog.type()).url(endpoint.url()).build()); + } + } + + return serviceEndpoints.build(); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Auth.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Auth.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Auth.java new file mode 100644 index 0000000..13c3753 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Auth.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.v3.domain; + +import java.util.List; + +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.json.SerializedNames; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class Auth { + + public abstract Identity identity(); + + @SerializedNames({ "identity" }) + public static Auth create(Identity identity) { + return new AutoValue_Auth(identity); + } + + @AutoValue + public abstract static class Identity { + + public abstract List<String> methods(); + public abstract TokenAuth token(); + public abstract PasswordAuth password(); + + @SerializedNames({ "methods", "token", "password" }) + public static Identity create(List<String> methods, TokenAuth token, PasswordAuth password) { + return new AutoValue_Auth_Identity(methods, token, password); + } + + @AutoValue + public abstract static class TokenAuth { + + public abstract String id(); + + @SerializedNames({ "id" }) + public static TokenAuth create(String id) { + return new AutoValue_Auth_Identity_TokenAuth(id); + } + } + + @AutoValue + public abstract static class PasswordAuth { + + public abstract UserAuth user(); + + @SerializedNames({ "user" }) + public static PasswordAuth create(UserAuth user) { + return new AutoValue_Auth_Identity_PasswordAuth(user); + } + + @AutoValue + public abstract static class UserAuth { + + public abstract String name(); + public abstract DomainAuth domain(); + public abstract String password(); + + @SerializedNames({ "name", "domain", "password" }) + public static UserAuth create(String name, DomainAuth domain, String password) { + return new AutoValue_Auth_Identity_PasswordAuth_UserAuth(name, domain, password); + } + + @AutoValue + public abstract static class DomainAuth { + + @Nullable public abstract String name(); + + @SerializedNames({ "name" }) + public static DomainAuth create(String name) { + return new AutoValue_Auth_Identity_PasswordAuth_UserAuth_DomainAuth(name); + } + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Catalog.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Catalog.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Catalog.java new file mode 100644 index 0000000..e5977f9 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Catalog.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.v3.domain; + +import java.util.List; + +import org.jclouds.json.SerializedNames; + +import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableList; + +@AutoValue +public abstract class Catalog { + + public abstract String id(); + + public abstract String name(); + + public abstract String type(); + + public abstract List<Endpoint> endpoints(); + + @SerializedNames({"id", "name", "type", "endpoints"}) + public static Catalog create(String id, + String name, + String type, + List<Endpoint> endpoints + ) { + return new AutoValue_Catalog(id, name, type, endpoints == null ? ImmutableList.<Endpoint>of() : ImmutableList.copyOf(endpoints)); + } + + Catalog() { + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Endpoint.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Endpoint.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Endpoint.java new file mode 100644 index 0000000..5de3d11 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Endpoint.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.v3.domain; + +import java.net.URI; +import java.util.List; + +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.json.SerializedNames; +import org.jclouds.openstack.v2_0.domain.Link; + +import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableList; + +@AutoValue +public abstract class Endpoint { + + public abstract String id(); + public abstract String region(); + public abstract String regionId(); + + @Nullable public abstract String serviceId(); + public abstract URI url(); + @Nullable public abstract Boolean enabled(); + @Nullable public abstract List<Link> links(); + public abstract String iface(); + + @SerializedNames({ "id", "region", "region_id", "service_id", "url", "enabled", "links", "interface" }) + public static Endpoint create(String id, String region, String regionId, String serviceId, URI url, Boolean enabled, + List<Link> links, String iface) { + return new AutoValue_Endpoint(id, region, regionId, serviceId, url, enabled, + links == null ? ImmutableList.<Link> of() : ImmutableList.copyOf(links), iface); + } + + Endpoint() { + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Link.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Link.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Link.java new file mode 100644 index 0000000..0d86069 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Link.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.v3.domain; + +import org.jclouds.json.SerializedNames; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class Link { + + public abstract String self(); + + @SerializedNames({"self"}) + public static Link create(String self) { + return new AutoValue_Link(self); + } + + Link() { + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Region.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Region.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Region.java new file mode 100644 index 0000000..22e5d1c --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Region.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.v3.domain; + +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.json.SerializedNames; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class Region { + + public abstract String id(); + + public abstract String name(); + + public abstract Link link(); + + @Nullable public abstract String parentRegionId(); + + @SerializedNames({"id", "description", "links", "parent_region_id"}) + public static Region create(String id, + String name, + Link link, + String parentRegionId + ) { + return new AutoValue_Region(id, name, link, parentRegionId); + } + + Region() { + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Token.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Token.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Token.java new file mode 100644 index 0000000..4c43dd2 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Token.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.v3.domain; + +import java.util.Date; +import java.util.List; + +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.json.SerializedNames; +import org.jclouds.openstack.keystone.auth.domain.AuthInfo; + +import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableList; + +@AutoValue +public abstract class Token implements AuthInfo { + + @Nullable + public abstract String id(); + public abstract List<String> methods(); + @Nullable + public abstract Date expiresAt(); + @Nullable + public abstract Object extras(); + @Nullable + public abstract List<Catalog> catalog(); + public abstract List<String> auditIds(); + public abstract User user(); + public abstract Date issuedAt(); + + @Override + public String getAuthToken() { + return id(); + } + @SerializedNames({"id", "methods", "expires_at", "extras", "catalog", "audit_ids", "user", "issued_at"}) + private static Token create( + String id, + List<String> methods, + Date expiresAt, + Object extras, + List<Catalog> catalog, + List<String> auditIds, + User user, + Date issuedAt + ) { + return builder() + .id(id) + .methods(methods) + .expiresAt(expiresAt) + .extras(extras) + .catalog(catalog) + .auditIds(auditIds) + .user(user) + .issuedAt(issuedAt) + .build(); + } + + public abstract Builder toBuilder(); + + public static Builder builder() { + return new AutoValue_Token.Builder(); + } + + @AutoValue.Builder + public abstract static class Builder { + + public abstract Builder id(String id); + public abstract Builder methods(List<String> methods); + public abstract Builder expiresAt(Date expiresAt); + public abstract Builder extras(Object extras); + public abstract Builder catalog(List<Catalog> catalog); + public abstract Builder auditIds(List<String> auditIds); + public abstract Builder user(User user); + public abstract Builder issuedAt(Date issuedAt); + + abstract List<Catalog> catalog(); + abstract List<String> methods(); + abstract List<String> auditIds(); + + abstract Token autoBuild(); + + public Token build() { + return catalog(catalog() != null ? ImmutableList.copyOf(catalog()) : ImmutableList.<Catalog>of()) + .methods(methods() != null ? ImmutableList.copyOf(methods()) : ImmutableList.<String>of()) + .auditIds(auditIds() != null ? ImmutableList.copyOf(auditIds()) : ImmutableList.<String>of()) + .autoBuild(); + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/User.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/User.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/User.java new file mode 100644 index 0000000..33702a9 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/User.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.v3.domain; + +import java.util.Date; + +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.json.SerializedNames; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class User { + + @AutoValue + public abstract static class Domain { + + public abstract String id(); + public abstract String name(); + + @SerializedNames({ "id", "name" }) + public static Domain create(String id, String name) { + return new AutoValue_User_Domain(id, name); + } + } + + public abstract String id(); + public abstract String name(); + @Nullable public abstract Date passwordExpiresAt(); + public abstract Domain domain(); + + @SerializedNames({"id", "name", "password_expires_at", "domain"}) + public static User create(String id, + String name, + Date passwordExpiresAt, + Domain domain + ) { + return new AutoValue_User(id, name, passwordExpiresAt, domain); + } + + User() { + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/TokenApi.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/TokenApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/TokenApi.java new file mode 100644 index 0000000..bba190a --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/TokenApi.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.v3.features; + +import java.util.List; +import java.util.Set; + +import javax.inject.Named; +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.core.MediaType; + +import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404; +import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404; +import org.jclouds.Fallbacks.FalseOnNotFoundOr404; +import org.jclouds.Fallbacks.NullOnNotFoundOr404; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest; +import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; +import org.jclouds.openstack.keystone.v2_0.domain.User; +import org.jclouds.openstack.keystone.v3.domain.Region; +import org.jclouds.openstack.keystone.v3.domain.Token; +import org.jclouds.openstack.v2_0.services.Identity; +import org.jclouds.rest.annotations.Fallback; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SelectJson; + +/** + * Provides access to the Keystone Admin API. + */ +@Consumes(MediaType.APPLICATION_JSON) +@RequestFilters(AuthenticateRequest.class) [email protected](Identity.class) +public interface TokenApi { + + /** + * Validate a token and, if it is valid, return access information regarding the tenant (though not the service catalog)/ + * + * @return the requested information + */ + @Named("token:get") + @GET + @SelectJson("token") + @Path("/auth/tokens/{token}") + @Fallback(NullOnNotFoundOr404.class) + @Nullable + Token get(@PathParam("token") 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 + */ + @Named("token:getuser") + @GET + @SelectJson("user") + @Path("/auth/tokens/{token}") + @Fallback(NullOnNotFoundOr404.class) + @Nullable + User getUserOfToken(@PathParam("token") 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 + */ + @Named("token:valid") + @HEAD + @Path("/auth/tokens/{token}") + @Fallback(FalseOnNotFoundOr404.class) + boolean isValid(@PathParam("token") 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 + */ + @Named("token:listEndpoints") + @GET + @SelectJson("endpoints") + @Path("/{token}/endpoints") + @Fallback(EmptySetOnNotFoundOr404.class) + Set<Endpoint> listEndpointsForToken(@PathParam("token") String token); + + + /** + * List all endpoints for a token + * <p/> + * NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/988672 ) + * + * @return the list of endpoints + */ + @Named("token:endpoints") + @GET + @SelectJson("endpoints") + @Path("/endpoints") + @Fallback(EmptyListOnNotFoundOr404.class) + List<Endpoint> endpoints(); + + /** + * List all regions for a token + * <p/> + * + * @return the list of regions + */ + @Named("token:regions") + @GET + @SelectJson("regions") + @Path("/regions") + @Fallback(EmptyListOnNotFoundOr404.class) + List<Region> regions(); +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/parsers/ParseToken.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/parsers/ParseToken.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/parsers/ParseToken.java new file mode 100644 index 0000000..1fd633f --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/parsers/ParseToken.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.v3.parsers; + +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ParseFirstJsonValueNamed; +import org.jclouds.json.internal.GsonWrapper; +import org.jclouds.openstack.keystone.v3.domain.Token; + +import com.google.common.collect.Iterables; +import com.google.inject.Inject; +import com.google.inject.TypeLiteral; + +public class ParseToken extends ParseFirstJsonValueNamed<Token> { + + @Inject + ParseToken(GsonWrapper json, TypeLiteral<Token> type, String... nameChoices) { + super(json, type, nameChoices); + } + + @Override + public Token apply(HttpResponse from) { + Token token = super.apply(from); + String xSubjectToken = Iterables.getOnlyElement(from.getHeaders().get("X-Subject-Token")); + return token.toBuilder().id(xSubjectToken).build(); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/config/InternalUrlModule.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/config/InternalUrlModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/config/InternalUrlModule.java deleted file mode 100644 index 71b36cb..0000000 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/config/InternalUrlModule.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jclouds.openstack.v2_0.config; - -import org.jclouds.openstack.keystone.v2_0.functions.EndpointToSupplierURI; -import org.jclouds.openstack.keystone.v2_0.functions.InternalURL; - -import com.google.inject.AbstractModule; -import com.google.inject.Singleton; - -/** - * Guice module to configure JClouds in order to use the internal urls to - * communicate with the services. - */ -@Singleton -public class InternalUrlModule extends AbstractModule { - @Override - protected void configure() { - bind(EndpointToSupplierURI.class).to(InternalURL.class); - } -} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/features/ExtensionApi.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/features/ExtensionApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/features/ExtensionApi.java index 633b327..466bcc9 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/features/ExtensionApi.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/features/ExtensionApi.java @@ -28,7 +28,7 @@ import javax.ws.rs.core.MediaType; import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404; import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.javax.annotation.Nullable; -import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; +import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest; import org.jclouds.openstack.v2_0.domain.Extension; import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.RequestFilters; http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/reference/AuthHeaders.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/reference/AuthHeaders.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/reference/AuthHeaders.java deleted file mode 100644 index 88ea817..0000000 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/reference/AuthHeaders.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jclouds.openstack.v2_0.reference; - -public final class AuthHeaders { - - public static final String AUTH_USER = "X-Auth-User"; - public static final String AUTH_KEY = "X-Auth-Key"; - public static final String AUTH_TOKEN = "X-Auth-Token"; - - private AuthHeaders() { - throw new AssertionError("intentionally unimplemented"); - } -} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/config/CredentialTypesTest.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/config/CredentialTypesTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/config/CredentialTypesTest.java new file mode 100644 index 0000000..93af93c --- /dev/null +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/config/CredentialTypesTest.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.auth.config; + +import static org.testng.Assert.assertEquals; + +import org.jclouds.openstack.keystone.auth.domain.PasswordCredentials; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +@Test(groups = "unit", testName = "CredentialTypesTest") +public class CredentialTypesTest { + + public void testCredentialTypeOfWhenValid() { + assertEquals( + CredentialTypes.credentialTypeOf(PasswordCredentials.builder().username("username").password("password") + .build()), CredentialTypes.PASSWORD_CREDENTIALS); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testCredentialTypeOfWithoutAnnotation() { + CredentialTypes.credentialTypeOf(""); + } + + public void testIndexByCredentialTypeWhenValid() { + assertEquals( + CredentialTypes.indexByCredentialType( + ImmutableSet.of(PasswordCredentials.builder().username("username").password("password").build())) + .keySet(), ImmutableSet.of(CredentialTypes.PASSWORD_CREDENTIALS)); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testIndexByCredentialTypeWithoutAnnotation() { + CredentialTypes.indexByCredentialType(ImmutableSet.of("")); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/config/ProviderModuleExpectTest.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/config/ProviderModuleExpectTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/config/ProviderModuleExpectTest.java new file mode 100644 index 0000000..a11c7de --- /dev/null +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/config/ProviderModuleExpectTest.java @@ -0,0 +1,180 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.auth.config; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static org.jclouds.openstack.keystone.config.KeystoneProperties.CREDENTIAL_TYPE; +import static org.jclouds.openstack.keystone.config.KeystoneProperties.KEYSTONE_VERSION; +import static org.jclouds.openstack.keystone.config.KeystoneProperties.SERVICE_TYPE; +import static org.jclouds.util.Suppliers2.getLastValueInMap; +import static org.testng.Assert.assertTrue; + +import java.io.Closeable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.net.URI; +import java.util.Properties; + +import javax.inject.Qualifier; +import javax.inject.Singleton; +import javax.ws.rs.HEAD; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +import org.jclouds.Fallbacks.FalseOnNotFoundOr404; +import org.jclouds.apis.ApiMetadata; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.json.config.GsonModule.DateAdapter; +import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; +import org.jclouds.location.suppliers.RegionIdToURISupplier; +import org.jclouds.openstack.keystone.catalog.config.ServiceCatalogModule; +import org.jclouds.openstack.keystone.catalog.config.ServiceCatalogModule.ProviderModule; +import org.jclouds.openstack.keystone.catalog.config.ServiceCatalogModule.RegionModule; +import org.jclouds.openstack.keystone.v2_0.KeystoneApi; +import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneRestApiExpectTest; +import org.jclouds.rest.ConfiguresHttpApi; +import org.jclouds.rest.annotations.ApiVersion; +import org.jclouds.rest.annotations.Fallback; +import org.jclouds.rest.config.HttpApiModule; +import org.jclouds.rest.internal.BaseHttpApiMetadata; +import org.jclouds.rest.internal.BaseRestApiExpectTest; +import org.testng.annotations.Test; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Module; +import com.google.inject.Provides; + +/** + * Tests configuration via {@link ProviderModule} + */ +@Test(groups = "unit", testName = "ProviderModuleExpectTest") +public class ProviderModuleExpectTest extends BaseRestApiExpectTest<ProviderModuleExpectTest.DNSApi> { + + @Retention(RUNTIME) + @Target(METHOD) + @Qualifier + static @interface DNS { + } + + @ConfiguresHttpApi + public static class DNSHttpApiModule extends HttpApiModule<DNSApi> { + + @Override + public void configure() { + bind(DateAdapter.class).to(Iso8601DateAdapter.class); + super.configure(); + } + + @Provides + @Singleton + @DNS + protected final Supplier<URI> provideCDNUrl(RegionIdToURISupplier.Factory factory, @ApiVersion String apiVersion) { + return getLastValueInMap(factory.createForApiTypeAndVersion("dns", apiVersion)); + } + } + + @org.jclouds.rest.annotations.Endpoint(DNS.class) + interface DNSApi extends Closeable { + @HEAD + @Path("/zones/{zoneName}") + @Fallback(FalseOnNotFoundOr404.class) + boolean zoneExists(@PathParam("zoneName") String zoneName); + } + + public void testDNSEndpointApplied() { + KeystoneAuth keystoneAuth = new KeystoneAuth(); + + DNSApi api = requestsSendResponses( + keystoneAuth.getKeystoneAuthWithUsernameAndPassword(), + keystoneAuth.getResponseWithKeystoneAccess(), + HttpRequest.builder().method("HEAD").endpoint("http://172.16.0.1:8776/v1/3456/zones/foo.com").build(), + HttpResponse.builder().statusCode(200).build()); + assertTrue(api.zoneExists("foo.com")); + } + + private static class DNSApiMetadata extends BaseHttpApiMetadata<DNSApi> { + + @Override + public Builder toBuilder() { + return new Builder().fromApiMetadata(this); + } + + public DNSApiMetadata() { + this(new Builder()); + } + + protected DNSApiMetadata(Builder builder) { + super(builder); + } + + public static Properties defaultProperties() { + Properties properties = BaseHttpApiMetadata.defaultProperties(); + properties.setProperty(SERVICE_TYPE, "dns"); + properties.setProperty(KEYSTONE_VERSION, "2"); + properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS); + return properties; + } + + public static class Builder extends BaseHttpApiMetadata.Builder<DNSApi, Builder> { + + protected Builder() { + id("dns") + .name("DNS API") + .identityName("${tenantName}:${userName} or ${userName}, if your keystone supports a default tenant") + .credentialName("${password}") + .endpointName("Keystone base url ending in /v2.0/") + .documentation(URI.create("http://dns")) + .version("1.0") + .defaultEndpoint("http://localhost:5000/v2.0/") + .defaultProperties(DNSApiMetadata.defaultProperties()) + .defaultModules(ImmutableSet.<Class<? extends Module>>builder() + .add(AuthenticationModule.class) + .add(ServiceCatalogModule.class) + .add(RegionModule.class) + .add(DNSHttpApiModule.class).build()); + } + + @Override + public DNSApiMetadata build() { + return new DNSApiMetadata(this); + } + + @Override + protected Builder self() { + return this; + } + } + } + + @Override + public ApiMetadata createApiMetadata() { + return new DNSApiMetadata(); + } + + public static class KeystoneAuth extends BaseKeystoneRestApiExpectTest<KeystoneApi> { + public HttpRequest getKeystoneAuthWithUsernameAndPassword() { + return keystoneAuthWithUsernameAndPassword; + } + + public HttpResponse getResponseWithKeystoneAccess() { + return responseWithKeystoneAccess; + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/handlers/RetryOnRenewTest.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/handlers/RetryOnRenewTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/handlers/RetryOnRenewTest.java new file mode 100644 index 0000000..01611ff --- /dev/null +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/handlers/RetryOnRenewTest.java @@ -0,0 +1,131 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.auth.handlers; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import org.jclouds.domain.Credentials; +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.handlers.BackoffLimitedRetryHandler; +import org.jclouds.io.Payloads; +import org.jclouds.openstack.keystone.auth.domain.AuthInfo; +import org.testng.annotations.Test; + +import com.google.common.cache.LoadingCache; + +/** + * Tests behavior of {@code RetryOnRenew} handler + */ +@Test(groups = "unit", testName = "RetryOnRenewTest") +public class RetryOnRenewTest { + @Test + public void test401ShouldRetry() { + HttpCommand command = createMock(HttpCommand.class); + HttpRequest request = createMock(HttpRequest.class); + HttpResponse response = createMock(HttpResponse.class); + @SuppressWarnings("unchecked") + LoadingCache<Credentials, AuthInfo> cache = createMock(LoadingCache.class); + BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class); + + expect(command.getCurrentRequest()).andReturn(request); + + cache.invalidateAll(); + expectLastCall(); + + expect(response.getPayload()).andReturn(Payloads.newStringPayload("")).anyTimes(); + expect(response.getStatusCode()).andReturn(401).atLeastOnce(); + + replay(command); + replay(response); + replay(cache); + replay(backoffHandler); + + RetryOnRenew retry = new RetryOnRenew(cache, backoffHandler); + + assertTrue(retry.shouldRetryRequest(command, response)); + + verify(command); + verify(response); + verify(cache); + } + + @Test + public void test401ShouldRetry4Times() { + HttpCommand command = createMock(HttpCommand.class); + HttpRequest request = createMock(HttpRequest.class); + HttpResponse response = createMock(HttpResponse.class); + + @SuppressWarnings("unchecked") + LoadingCache<Credentials, AuthInfo> cache = createMock(LoadingCache.class); + BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class); + + expect(command.getCurrentRequest()).andReturn(request).anyTimes(); + expect(request.getHeaders()).andStubReturn(null); + + cache.invalidateAll(); + expectLastCall().anyTimes(); + + expect(response.getPayload()).andReturn(Payloads.newStringPayload("")).anyTimes(); + expect(response.getStatusCode()).andReturn(401).anyTimes(); + + replay(command, request, response, cache); + + RetryOnRenew retry = new RetryOnRenew(cache, backoffHandler); + + for (int i = 0; i < RetryOnRenew.NUM_RETRIES - 1; ++i) { + assertTrue(retry.shouldRetryRequest(command, response), "Expected retry to succeed"); + } + + assertFalse(retry.shouldRetryRequest(command, response), "Expected retry to fail on attempt " + RetryOnRenew.NUM_RETRIES); + + verify(command, response, cache); + } + + @Test + public void test408ShouldRetry() { + HttpCommand command = createMock(HttpCommand.class); + HttpResponse response = createMock(HttpResponse.class); + @SuppressWarnings("unchecked") + LoadingCache<Credentials, AuthInfo> cache = createMock(LoadingCache.class); + BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class); + + expect(backoffHandler.shouldRetryRequest(command, response)).andReturn(true).once(); + expect(response.getStatusCode()).andReturn(408).once(); + + replay(command); + replay(response); + replay(cache); + replay(backoffHandler); + + RetryOnRenew retry = new RetryOnRenew(cache, backoffHandler); + + assertTrue(retry.shouldRetryRequest(command, response)); + + verify(command); + verify(response); + verify(cache); + verify(backoffHandler); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/LocationIdToURIFromAccessForTypeAndVersionTest.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/LocationIdToURIFromAccessForTypeAndVersionTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/LocationIdToURIFromAccessForTypeAndVersionTest.java new file mode 100644 index 0000000..91146b0 --- /dev/null +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/LocationIdToURIFromAccessForTypeAndVersionTest.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.auth.suppliers; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + +import javax.inject.Singleton; + +import org.jclouds.location.Provider; +import org.jclouds.openstack.keystone.auth.domain.AuthInfo; +import org.jclouds.openstack.keystone.catalog.ServiceEndpoint; +import org.jclouds.openstack.keystone.catalog.suppliers.LocationIdToURIFromAccessForTypeAndVersion; +import org.jclouds.openstack.keystone.v2_0.catalog.V2ServiceCatalog; +import org.jclouds.openstack.keystone.v2_0.parse.ParseAccessTest; +import org.jclouds.openstack.keystone.v2_0.parse.ParseRackspaceAccessTest; +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.Scopes; +import com.google.inject.TypeLiteral; +import com.google.inject.assistedinject.FactoryModuleBuilder; + +@Test(groups = "unit", testName = "LocationIdToURIFromAccessForTypeAndVersionTest") +public class LocationIdToURIFromAccessForTypeAndVersionTest { + private final LocationIdToURIFromAccessForTypeAndVersion.Factory factory = Guice.createInjector( + new AbstractModule() { + + @Override + protected void configure() { + bindConstant().annotatedWith(Provider.class).to("openstack-keystone"); + bind(new TypeLiteral<Supplier<URI>>() { + }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity"))); + install(new FactoryModuleBuilder().implement(LocationIdToURIFromAccessForTypeAndVersion.class, + LocationIdToURIFromAccessForTypeAndVersion.class).build( + LocationIdToURIFromAccessForTypeAndVersion.Factory.class)); + // We test against a 2.0 service catalog but it is OK for the purpose of this test + bind(new TypeLiteral<Supplier<List<ServiceEndpoint>>>() { + }).to(V2ServiceCatalog.class).in(Scopes.SINGLETON); + } + + @Provides + @Singleton + public Supplier<AuthInfo> provide() { + return Suppliers.<AuthInfo> ofInstance(new ParseAccessTest().expected()); + } + + }).getInstance(LocationIdToURIFromAccessForTypeAndVersion.Factory.class); + + public void testRegionUnmatchesOkWhenNoVersionIdSet() { + assertEquals( + Maps.transformValues(factory.createForApiTypeAndVersion("compute", "2").get(), + Suppliers.<URI> supplierFunction()), + ImmutableMap.of("az-1.region-a.geo-1", + URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v2/3456"), "az-2.region-a.geo-1", + URI.create("https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v2/3456"), "az-3.region-a.geo-1", + URI.create("https://az-3.region-a.geo-1.compute.hpcloudsvc.com/v2/3456"))); + } + + public void testRegionMatches() { + assertEquals( + Maps.transformValues(factory.createForApiTypeAndVersion("compute", "2").get(), + Suppliers.<URI> supplierFunction()), + ImmutableMap.of("az-1.region-a.geo-1", + URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v2/3456"), "az-2.region-a.geo-1", + URI.create("https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v2/3456"), "az-3.region-a.geo-1", + URI.create("https://az-3.region-a.geo-1.compute.hpcloudsvc.com/v2/3456"))); + } + + private final LocationIdToURIFromAccessForTypeAndVersion.Factory raxFactory = Guice.createInjector( + new AbstractModule() { + + @Override + protected void configure() { + bindConstant().annotatedWith(Provider.class).to("rackspace"); + bind(new TypeLiteral<Supplier<URI>>() { + }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity"))); + install(new FactoryModuleBuilder().implement(LocationIdToURIFromAccessForTypeAndVersion.class, + LocationIdToURIFromAccessForTypeAndVersion.class).build( + LocationIdToURIFromAccessForTypeAndVersion.Factory.class)); + // We test against a 2.0 service catalog but it is OK for the purpose of this test + bind(new TypeLiteral<Supplier<List<ServiceEndpoint>>>() { + }).to(V2ServiceCatalog.class).in(Scopes.SINGLETON); + } + + @Provides + @Singleton + public Supplier<AuthInfo> provide() { + return Suppliers.<AuthInfo> ofInstance(new ParseRackspaceAccessTest().expected()); + } + }).getInstance(LocationIdToURIFromAccessForTypeAndVersion.Factory.class); + + @Test(expectedExceptions = NoSuchElementException.class) + public void testWhenNotInList() { + assertEquals( + Maps.transformValues(raxFactory.createForApiTypeAndVersion("goo", "1.0").get(), + Suppliers.<URI> supplierFunction()), + ImmutableMap.of("rackspace", URI.create("https://servers.api.rackspacecloud.com/v1.0/40806637803162"))); + } + + public void testProviderWhenNoRegions() { + Map<String, URI> withNoRegions = Maps.transformValues(raxFactory.createForApiTypeAndVersion("compute", "1.0") + .get(), Suppliers.<URI> supplierFunction()); + assertEquals(withNoRegions, + ImmutableMap.of("rackspace", URI.create("https://servers.api.rackspacecloud.com/v1.0/40806637803162"))); + } + + public void testOkWithNoVersions() { + assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("rax:database", null).get(), + Suppliers.<URI> supplierFunction()), ImmutableMap.of("DFW", + URI.create("https://dfw.databases.api.rackspacecloud.com/v1.0/40806637803162"), "ORD", + URI.create("https://ord.databases.api.rackspacecloud.com/v1.0/40806637803162"))); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionTest.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionTest.java new file mode 100644 index 0000000..0ed35a4 --- /dev/null +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionTest.java @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.auth.suppliers; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + +import javax.inject.Singleton; + +import org.jclouds.location.Provider; +import org.jclouds.openstack.keystone.auth.domain.AuthInfo; +import org.jclouds.openstack.keystone.catalog.ServiceEndpoint; +import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURIFromAccessForTypeAndVersion; +import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURISupplier; +import org.jclouds.openstack.keystone.v2_0.catalog.V2ServiceCatalog; +import org.jclouds.openstack.keystone.v2_0.parse.ParseAccessTest; +import org.jclouds.openstack.keystone.v2_0.parse.ParseRackspaceAccessTest; +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.Scopes; +import com.google.inject.TypeLiteral; +import com.google.inject.assistedinject.FactoryModuleBuilder; + +@Test(groups = "unit", testName = "RegionIdToAdminURIFromAccessForTypeAndVersionTest") +public class RegionIdToAdminURIFromAccessForTypeAndVersionTest { + private final RegionIdToAdminURISupplier.Factory factory = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bindConstant().annotatedWith(Provider.class).to("openstack-keystone"); + bind(new TypeLiteral<Supplier<URI>>() { + }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity"))); + install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class, + RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class)); + // We test against a 2.0 service catalog but it is OK for the purpose of this test + bind(new TypeLiteral<Supplier<List<ServiceEndpoint>>>() { + }).to(V2ServiceCatalog.class).in(Scopes.SINGLETON); + } + + @Provides + @Singleton + public Supplier<AuthInfo> provide() { + return Suppliers.<AuthInfo> 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); + map.put("region-b.geo-1", null); + map.put("region-c.geo-1", null); + assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "2").get(), Suppliers + .<URI> supplierFunction()), map); + } + + private final RegionIdToAdminURISupplier.Factory raxFactory = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bindConstant().annotatedWith(Provider.class).to("rackspace"); + bind(new TypeLiteral<Supplier<URI>>() { + }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity"))); + install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class, + RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class)); + // We test against a 2.0 service catalog but it is OK for the purpose of this test + bind(new TypeLiteral<Supplier<List<ServiceEndpoint>>>() { + }).to(V2ServiceCatalog.class).in(Scopes.SINGLETON); + } + + @Provides + @Singleton + public Supplier<AuthInfo> provide() { + return Suppliers.<AuthInfo> ofInstance(new ParseRackspaceAccessTest().expected()); + } + }).getInstance(RegionIdToAdminURISupplier.Factory.class); + + @Test(expectedExceptions = NoSuchElementException.class) + public void testWhenNotInList() { + assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("goo", "1.0").get(), Suppliers + .<URI> supplierFunction()), ImmutableMap.of("rackspace", URI + .create("https://servers.api.rackspacecloud.com/v1.0/40806637803162"))); + } + + public void testProviderWhenNoRegions() { + Map<String, URI> map = Maps.newLinkedHashMap(); + map.put("rackspace", null); + assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("compute", "1.0").get(), Suppliers + .<URI> supplierFunction()), map); + } + + public void testOkWithNoVersions() { + Map<String, URI> map = Maps.newLinkedHashMap(); + map.put("DFW", null); + map.put("ORD", null); + assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("rax:database", null).get(), Suppliers + .<URI> supplierFunction()), map); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToURIFromAccessForTypeAndVersionTest.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToURIFromAccessForTypeAndVersionTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToURIFromAccessForTypeAndVersionTest.java new file mode 100644 index 0000000..cbdaf21 --- /dev/null +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToURIFromAccessForTypeAndVersionTest.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.auth.suppliers; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; +import java.util.List; +import java.util.NoSuchElementException; + +import javax.inject.Singleton; + +import org.jclouds.location.Provider; +import org.jclouds.location.suppliers.RegionIdToURISupplier; +import org.jclouds.openstack.keystone.auth.domain.AuthInfo; +import org.jclouds.openstack.keystone.catalog.ServiceEndpoint; +import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToURIFromAccessForTypeAndVersion; +import org.jclouds.openstack.keystone.v2_0.catalog.V2ServiceCatalog; +import org.jclouds.openstack.keystone.v2_0.parse.ParseAccessTest; +import org.jclouds.openstack.keystone.v2_0.parse.ParseRackspaceAccessTest; +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.Scopes; +import com.google.inject.TypeLiteral; +import com.google.inject.assistedinject.FactoryModuleBuilder; + +@Test(groups = "unit", testName = "RegionIdToURIFromAccessForTypeAndVersionTest") +public class RegionIdToURIFromAccessForTypeAndVersionTest { + private final RegionIdToURISupplier.Factory factory = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bindConstant().annotatedWith(Provider.class).to("openstack-keystone"); + bind(new TypeLiteral<Supplier<URI>>() { + }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity"))); + install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class, + RegionIdToURIFromAccessForTypeAndVersion.class).build( + RegionIdToURISupplier.Factory.class)); + // We test against a 2.0 service catalog but it is OK for the purpose of this test + bind(new TypeLiteral<Supplier<List<ServiceEndpoint>>>() { + }).to(V2ServiceCatalog.class).in(Scopes.SINGLETON); + } + + @Provides + @Singleton + public Supplier<AuthInfo> provide() { + return Suppliers.<AuthInfo> ofInstance(new ParseAccessTest().expected()); + } + }).getInstance(RegionIdToURISupplier.Factory.class); + + @Test(expectedExceptions = NoSuchElementException.class) + public void testRegionUnmatches() { + Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.0").get(), + Suppliers.<URI> supplierFunction()); + } + + public void testRegionMatches() { + assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "2").get(), Suppliers + .<URI> supplierFunction()), ImmutableMap.of("az-1.region-a.geo-1", URI + .create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v2/3456"), "az-2.region-a.geo-1", URI + .create("https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v2/3456"), "az-3.region-a.geo-1", URI + .create("https://az-3.region-a.geo-1.compute.hpcloudsvc.com/v2/3456"))); + } + + private final RegionIdToURISupplier.Factory raxFactory = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bindConstant().annotatedWith(Provider.class).to("rackspace"); + bind(new TypeLiteral<Supplier<URI>>() { + }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity"))); + install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class, + RegionIdToURIFromAccessForTypeAndVersion.class).build( + RegionIdToURISupplier.Factory.class)); + // We test against a 2.0 service catalog but it is OK for the purpose of this test + bind(new TypeLiteral<Supplier<List<ServiceEndpoint>>>() { + }).to(V2ServiceCatalog.class).in(Scopes.SINGLETON); + } + + @Provides + @Singleton + public Supplier<AuthInfo> provide() { + return Suppliers.<AuthInfo> ofInstance(new ParseRackspaceAccessTest().expected()); + } + }).getInstance(RegionIdToURISupplier.Factory.class); + + @Test(expectedExceptions = NoSuchElementException.class) + public void testWhenNotInList() { + assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("goo", "1.0").get(), Suppliers + .<URI> supplierFunction()), ImmutableMap.of("rackspace", URI + .create("https://servers.api.rackspacecloud.com/v1.0/40806637803162"))); + } + + public void testProviderWhenNoRegions() { + assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("compute", "1.0").get(), Suppliers + .<URI> supplierFunction()), ImmutableMap.of("rackspace", URI + .create("https://servers.api.rackspacecloud.com/v1.0/40806637803162"))); + } + + public void testOkWithNoVersions() { + assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("rax:database", null).get(), Suppliers + .<URI> supplierFunction()), ImmutableMap.of("DFW", URI + .create("https://dfw.databases.api.rackspacecloud.com/v1.0/40806637803162"), "ORD", URI + .create("https://ord.databases.api.rackspacecloud.com/v1.0/40806637803162"))); + } + +}
