mirror of https://github.com/apache/jclouds.git
Add support for OpenStack Keystone V3
Refactors the Keystone Authentication and Service Catalog classes to a common model that can be used by V2 and V3 of Keystone. Each version will have their own Authentication APIs and Service Catalog Suppliers, and the higher level Keystone Authentication will transparently delegate to the right API based on the keystone-version property. OpenStack APIs will just have to define the default keystone-version property they work with, and declare the generic Keystone Authentication and Service Catalog modules. Co-authored-by: Andrea Turli <andreaturli@apache.org>
This commit is contained in:
parent
18eb7f3d38
commit
dd73410d12
|
@ -16,8 +16,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.cinder.v1;
|
package org.jclouds.openstack.cinder.v1;
|
||||||
|
|
||||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
|
import static org.jclouds.openstack.keystone.config.KeystoneProperties.CREDENTIAL_TYPE;
|
||||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
|
import static org.jclouds.openstack.keystone.config.KeystoneProperties.SERVICE_TYPE;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
@ -25,10 +25,11 @@ import java.util.Properties;
|
||||||
import org.jclouds.apis.ApiMetadata;
|
import org.jclouds.apis.ApiMetadata;
|
||||||
import org.jclouds.openstack.cinder.v1.config.CinderHttpApiModule;
|
import org.jclouds.openstack.cinder.v1.config.CinderHttpApiModule;
|
||||||
import org.jclouds.openstack.cinder.v1.config.CinderParserModule;
|
import org.jclouds.openstack.cinder.v1.config.CinderParserModule;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.AuthenticationApiModule;
|
import org.jclouds.openstack.keystone.auth.config.AuthenticationModule;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
|
import org.jclouds.openstack.keystone.auth.config.CredentialTypes;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
|
import org.jclouds.openstack.keystone.catalog.config.ServiceCatalogModule;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.RegionModule;
|
import org.jclouds.openstack.keystone.catalog.config.ServiceCatalogModule.RegionModule;
|
||||||
|
import org.jclouds.openstack.keystone.config.KeystoneProperties;
|
||||||
import org.jclouds.openstack.v2_0.ServiceType;
|
import org.jclouds.openstack.v2_0.ServiceType;
|
||||||
import org.jclouds.rest.internal.BaseHttpApiMetadata;
|
import org.jclouds.rest.internal.BaseHttpApiMetadata;
|
||||||
|
|
||||||
|
@ -58,6 +59,7 @@ public class CinderApiMetadata extends BaseHttpApiMetadata<CinderApi> {
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseHttpApiMetadata.defaultProperties();
|
Properties properties = BaseHttpApiMetadata.defaultProperties();
|
||||||
properties.setProperty(SERVICE_TYPE, ServiceType.BLOCK_STORAGE);
|
properties.setProperty(SERVICE_TYPE, ServiceType.BLOCK_STORAGE);
|
||||||
|
properties.setProperty(KeystoneProperties.KEYSTONE_VERSION, "2");
|
||||||
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
|
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -75,8 +77,8 @@ public class CinderApiMetadata extends BaseHttpApiMetadata<CinderApi> {
|
||||||
.defaultEndpoint("http://localhost:5000/v2.0/")
|
.defaultEndpoint("http://localhost:5000/v2.0/")
|
||||||
.defaultProperties(CinderApiMetadata.defaultProperties())
|
.defaultProperties(CinderApiMetadata.defaultProperties())
|
||||||
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
|
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
|
||||||
.add(AuthenticationApiModule.class)
|
.add(AuthenticationModule.class)
|
||||||
.add(KeystoneAuthenticationModule.class)
|
.add(ServiceCatalogModule.class)
|
||||||
.add(RegionModule.class)
|
.add(RegionModule.class)
|
||||||
.add(CinderParserModule.class)
|
.add(CinderParserModule.class)
|
||||||
.add(CinderHttpApiModule.class)
|
.add(CinderHttpApiModule.class)
|
||||||
|
|
|
@ -21,7 +21,7 @@ import com.google.common.annotations.Beta;
|
||||||
import com.google.common.collect.FluentIterable;
|
import com.google.common.collect.FluentIterable;
|
||||||
import org.jclouds.Fallbacks;
|
import org.jclouds.Fallbacks;
|
||||||
import org.jclouds.openstack.cinder.v1.domain.AvailabilityZone;
|
import org.jclouds.openstack.cinder.v1.domain.AvailabilityZone;
|
||||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
|
||||||
import org.jclouds.openstack.v2_0.ServiceType;
|
import org.jclouds.openstack.v2_0.ServiceType;
|
||||||
import org.jclouds.openstack.v2_0.services.Extension;
|
import org.jclouds.openstack.v2_0.services.Extension;
|
||||||
import org.jclouds.rest.annotations.Fallback;
|
import org.jclouds.rest.annotations.Fallback;
|
||||||
|
|
|
@ -26,7 +26,7 @@ import javax.ws.rs.core.MediaType;
|
||||||
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.openstack.cinder.v1.domain.VolumeQuota;
|
import org.jclouds.openstack.cinder.v1.domain.VolumeQuota;
|
||||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
|
||||||
import org.jclouds.rest.annotations.Fallback;
|
import org.jclouds.rest.annotations.Fallback;
|
||||||
import org.jclouds.rest.annotations.RequestFilters;
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
import org.jclouds.rest.annotations.SelectJson;
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
|
|
@ -32,7 +32,7 @@ import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.openstack.cinder.v1.domain.Snapshot;
|
import org.jclouds.openstack.cinder.v1.domain.Snapshot;
|
||||||
import org.jclouds.openstack.cinder.v1.options.CreateSnapshotOptions;
|
import org.jclouds.openstack.cinder.v1.options.CreateSnapshotOptions;
|
||||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
|
||||||
import org.jclouds.rest.annotations.Fallback;
|
import org.jclouds.rest.annotations.Fallback;
|
||||||
import org.jclouds.rest.annotations.MapBinder;
|
import org.jclouds.rest.annotations.MapBinder;
|
||||||
import org.jclouds.rest.annotations.PayloadParam;
|
import org.jclouds.rest.annotations.PayloadParam;
|
||||||
|
|
|
@ -32,7 +32,7 @@ import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.openstack.cinder.v1.domain.Volume;
|
import org.jclouds.openstack.cinder.v1.domain.Volume;
|
||||||
import org.jclouds.openstack.cinder.v1.options.CreateVolumeOptions;
|
import org.jclouds.openstack.cinder.v1.options.CreateVolumeOptions;
|
||||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
|
||||||
import org.jclouds.rest.annotations.Fallback;
|
import org.jclouds.rest.annotations.Fallback;
|
||||||
import org.jclouds.rest.annotations.MapBinder;
|
import org.jclouds.rest.annotations.MapBinder;
|
||||||
import org.jclouds.rest.annotations.PayloadParam;
|
import org.jclouds.rest.annotations.PayloadParam;
|
||||||
|
|
|
@ -27,7 +27,7 @@ import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
|
||||||
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.openstack.cinder.v1.domain.VolumeType;
|
import org.jclouds.openstack.cinder.v1.domain.VolumeType;
|
||||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
|
||||||
import org.jclouds.rest.annotations.Fallback;
|
import org.jclouds.rest.annotations.Fallback;
|
||||||
import org.jclouds.rest.annotations.RequestFilters;
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
import org.jclouds.rest.annotations.SelectJson;
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
|
|
@ -20,7 +20,7 @@ import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.apis.BaseApiLiveTest;
|
import org.jclouds.apis.BaseApiLiveTest;
|
||||||
import org.jclouds.openstack.cinder.v1.CinderApi;
|
import org.jclouds.openstack.cinder.v1.CinderApi;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
|
import org.jclouds.openstack.keystone.config.KeystoneProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests behavior of CinderApi
|
* Tests behavior of CinderApi
|
||||||
|
|
|
@ -32,13 +32,18 @@
|
||||||
<packaging>bundle</packaging>
|
<packaging>bundle</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<!-- keystone endpoint -->
|
<!-- keystone version 2 -->
|
||||||
<test.openstack-keystone.endpoint>http://localhost:5000/v${jclouds.api-version}/</test.openstack-keystone.endpoint>
|
<test.openstack-keystone.endpoint>http://localhost:5000/v${jclouds.api-version}/</test.openstack-keystone.endpoint>
|
||||||
<!-- keystone version -->
|
|
||||||
<test.openstack-keystone.api-version>2.0</test.openstack-keystone.api-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.identity>FIXME_TENANT:FIXME_USER</test.openstack-keystone.identity>
|
||||||
<test.openstack-keystone.credential>FIXME_CREDENTIALS</test.openstack-keystone.credential>
|
<test.openstack-keystone.credential>FIXME_PASSWORD</test.openstack-keystone.credential>
|
||||||
|
<!-- keystone version 3 -->
|
||||||
|
<test.openstack-keystone-3.endpoint>http://localhost/identity/v3</test.openstack-keystone-3.endpoint>
|
||||||
|
<test.openstack-keystone-3.api-version>3</test.openstack-keystone-3.api-version>
|
||||||
|
<test.openstack-keystone-3.build-version />
|
||||||
|
<test.openstack-keystone-3.identity>FIXME_DOMAIN:FIXME_USER</test.openstack-keystone-3.identity>
|
||||||
|
<test.openstack-keystone-3.credential>FIXME_PASSWORD</test.openstack-keystone-3.credential>
|
||||||
<test.jclouds.keystone.credential-type>passwordCredentials</test.jclouds.keystone.credential-type>
|
<test.jclouds.keystone.credential-type>passwordCredentials</test.jclouds.keystone.credential-type>
|
||||||
|
|
||||||
<jclouds.osgi.export>org.jclouds.openstack*;version="${project.version}"</jclouds.osgi.export>
|
<jclouds.osgi.export>org.jclouds.openstack*;version="${project.version}"</jclouds.osgi.export>
|
||||||
|
@ -69,6 +74,13 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- A driver that supports the PATCH verb is needed for tests -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.jclouds.driver</groupId>
|
||||||
|
<artifactId>jclouds-okhttp</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ch.qos.logback</groupId>
|
<groupId>ch.qos.logback</groupId>
|
||||||
<artifactId>logback-classic</artifactId>
|
<artifactId>logback-classic</artifactId>
|
||||||
|
@ -84,8 +96,29 @@
|
||||||
<artifactId>auto-service</artifactId>
|
<artifactId>auto-service</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.auto.value</groupId>
|
||||||
|
<artifactId>auto-value</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- Disabling error-prone compiler due to: https://github.com/google/error-prone/issues/711
|
||||||
|
The fix is only available in error-prone versions that do not support Java 7 -->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<inherited>false</inherited>
|
||||||
|
<configuration>
|
||||||
|
<source>${maven.compile.source}</source>
|
||||||
|
<target>${maven.compile.target}</target>
|
||||||
|
<encoding>${project.build.sourceEncoding}</encoding>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
<profile>
|
||||||
<id>live</id>
|
<id>live</id>
|
||||||
|
@ -102,6 +135,13 @@
|
||||||
<goal>test</goal>
|
<goal>test</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>none</exclude>
|
||||||
|
</excludes>
|
||||||
|
<includes>
|
||||||
|
<include>**/keystone/v2_0/**/*IntegrationTest.java</include>
|
||||||
|
<include>**/keystone/v2_0/**/*LiveTest.java</include>
|
||||||
|
</includes>
|
||||||
<systemPropertyVariables>
|
<systemPropertyVariables>
|
||||||
<test.openstack-keystone.endpoint>${test.openstack-keystone.endpoint}</test.openstack-keystone.endpoint>
|
<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.api-version>${test.openstack-keystone.api-version}</test.openstack-keystone.api-version>
|
||||||
|
@ -117,6 +157,43 @@
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>live-v3</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>
|
||||||
|
<excludes>
|
||||||
|
<exclude>none</exclude>
|
||||||
|
</excludes>
|
||||||
|
<includes>
|
||||||
|
<include>**/keystone/v3/**/*IntegrationTest.java</include>
|
||||||
|
<include>**/keystone/v3/**/*LiveTest.java</include>
|
||||||
|
</includes>
|
||||||
|
<systemPropertyVariables>
|
||||||
|
<test.openstack-keystone-3.endpoint>${test.openstack-keystone.endpoint}</test.openstack-keystone-3.endpoint>
|
||||||
|
<test.openstack-keystone-3.api-version>${test.openstack-keystone.api-version}</test.openstack-keystone-3.api-version>
|
||||||
|
<test.openstack-keystone-3.build-version>${test.openstack-keystone.build-version}</test.openstack-keystone-3.build-version>
|
||||||
|
<test.openstack-keystone-3.identity>${test.openstack-keystone-3.identity}</test.openstack-keystone-3.identity>
|
||||||
|
<test.openstack-keystone-3.credential>${test.openstack-keystone-3.credential}</test.openstack-keystone-3.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>
|
</profiles>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.v2_0.reference;
|
package org.jclouds.openstack.keystone.auth;
|
||||||
|
|
||||||
public final class AuthHeaders {
|
public final class AuthHeaders {
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.ApiAccessKeyCredentials;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.TenantOrDomainAndCredentials;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.PasswordCredentials;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.TokenCredentials;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authentication methods to be implemented to all Keystone authentication APIs.
|
||||||
|
*/
|
||||||
|
public interface AuthenticationApi {
|
||||||
|
|
||||||
|
AuthInfo authenticatePassword(TenantOrDomainAndCredentials<PasswordCredentials> credentials);
|
||||||
|
|
||||||
|
AuthInfo authenticateAccessKey(TenantOrDomainAndCredentials<ApiAccessKeyCredentials> credentials);
|
||||||
|
|
||||||
|
AuthInfo authenticateToken(TenantOrDomainAndCredentials<TokenCredentials> credentials);
|
||||||
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.config;
|
package org.jclouds.openstack.keystone.auth.config;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
|
@ -0,0 +1,142 @@
|
||||||
|
/*
|
||||||
|
* 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 com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.jclouds.http.HttpRetryHandler;
|
||||||
|
import org.jclouds.http.annotation.ClientError;
|
||||||
|
import org.jclouds.location.Provider;
|
||||||
|
import org.jclouds.openstack.keystone.auth.AuthenticationApi;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
|
||||||
|
import org.jclouds.openstack.keystone.auth.functions.AuthenticateApiAccessKeyCredentials;
|
||||||
|
import org.jclouds.openstack.keystone.auth.functions.AuthenticatePasswordCredentials;
|
||||||
|
import org.jclouds.openstack.keystone.auth.functions.AuthenticateTokenCredentials;
|
||||||
|
import org.jclouds.openstack.keystone.auth.handlers.RetryOnRenew;
|
||||||
|
import org.jclouds.openstack.keystone.config.KeystoneProperties;
|
||||||
|
import org.jclouds.openstack.keystone.v2_0.auth.V2AuthenticationApi;
|
||||||
|
import org.jclouds.openstack.keystone.v3.auth.V3AuthenticationApi;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.ImmutableSet.Builder;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
|
public class AuthenticationModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class);
|
||||||
|
bindHttpApi(binder(), V2AuthenticationApi.class);
|
||||||
|
bindHttpApi(binder(), V3AuthenticationApi.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected final AuthenticationApi provideAuthenticationApi(Injector i,
|
||||||
|
@Named(KeystoneProperties.KEYSTONE_VERSION) String keystoneVersion) {
|
||||||
|
return authenticationApis(i).get(keystoneVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map<String, AuthenticationApi> authenticationApis(Injector i) {
|
||||||
|
Map<String, AuthenticationApi> authenticationApis = Maps.newHashMap();
|
||||||
|
authenticationApis.put("2", i.getInstance(V2AuthenticationApi.class));
|
||||||
|
authenticationApis.put("3", i.getInstance(V3AuthenticationApi.class));
|
||||||
|
return authenticationApis;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* borrowing concurrency code to ensure that caching takes place properly
|
||||||
|
*/
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@Authentication
|
||||||
|
protected final Supplier<String> provideAuthenticationTokenCache(final Supplier<AuthInfo> supplier)
|
||||||
|
throws InterruptedException, ExecutionException, TimeoutException {
|
||||||
|
return new Supplier<String>() {
|
||||||
|
@Override
|
||||||
|
public String get() {
|
||||||
|
return supplier.get().getAuthToken();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected final Map<String, Function<Credentials, AuthInfo>> provideAuthenticationMethods(Injector i) {
|
||||||
|
return authenticationMethods(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map<String, Function<Credentials, AuthInfo>> authenticationMethods(Injector i) {
|
||||||
|
Builder<Function<Credentials, AuthInfo>> fns = ImmutableSet.builder();
|
||||||
|
fns.add(i.getInstance(AuthenticatePasswordCredentials.class));
|
||||||
|
fns.add(i.getInstance(AuthenticateApiAccessKeyCredentials.class));
|
||||||
|
fns.add(i.getInstance(AuthenticateTokenCredentials.class));
|
||||||
|
return CredentialTypes.indexByCredentialType(fns.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected final Function<Credentials, AuthInfo> authenticationMethodForCredentialType(
|
||||||
|
@Named(KeystoneProperties.CREDENTIAL_TYPE) String credentialType,
|
||||||
|
Map<String, Function<Credentials, AuthInfo>> authenticationMethods) {
|
||||||
|
checkArgument(authenticationMethods.containsKey(credentialType), "credential type %s not in supported list: %s",
|
||||||
|
credentialType, authenticationMethods.keySet());
|
||||||
|
return authenticationMethods.get(credentialType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: what is the timeout of the session token? modify default accordingly
|
||||||
|
// PROPERTY_SESSION_INTERVAL is default to 60 seconds, but we have this here
|
||||||
|
// at 11 hours for now.
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
public final LoadingCache<Credentials, AuthInfo> provideAuthInfoCache(Function<Credentials, AuthInfo> getAccess) {
|
||||||
|
return CacheBuilder.newBuilder().expireAfterWrite(11, TimeUnit.HOURS).build(CacheLoader.from(getAccess));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temporary conversion of a cache to a supplier until there is a
|
||||||
|
// single-element cache
|
||||||
|
// http://code.google.com/p/guava-libraries/issues/detail?id=872
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected final Supplier<AuthInfo> provideAuthInfoSupplier(final LoadingCache<Credentials, AuthInfo> cache,
|
||||||
|
@Provider final Supplier<Credentials> creds) {
|
||||||
|
return new Supplier<AuthInfo>() {
|
||||||
|
@Override
|
||||||
|
public AuthInfo get() {
|
||||||
|
return cache.getUnchecked(creds.get());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.config;
|
package org.jclouds.openstack.keystone.auth.config;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
|
@ -32,7 +32,6 @@ import javax.inject.Qualifier;
|
||||||
public @interface CredentialType {
|
public @interface CredentialType {
|
||||||
/**
|
/**
|
||||||
* @see CredentialTypes
|
* @see CredentialTypes
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
String value();
|
String value();
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.config;
|
package org.jclouds.openstack.keystone.auth.config;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
|
||||||
|
@ -32,21 +32,33 @@ public class CredentialTypes {
|
||||||
|
|
||||||
public static final String PASSWORD_CREDENTIALS = "passwordCredentials";
|
public static final String PASSWORD_CREDENTIALS = "passwordCredentials";
|
||||||
|
|
||||||
|
public static final String TOKEN_CREDENTIALS = "tokenCredentials";
|
||||||
|
|
||||||
public static <T> String credentialTypeOf(T input) {
|
public static <T> String credentialTypeOf(T input) {
|
||||||
Class<?> authenticationType = input.getClass();
|
Class<?> authenticationType = input.getClass();
|
||||||
checkArgument(authenticationType.isAnnotationPresent(CredentialType.class),
|
CredentialType credentialType = findCredentialType(authenticationType);
|
||||||
"programming error: %s should have annotation %s", authenticationType, CredentialType.class.getName());
|
checkArgument(credentialType != null, "programming error: %s should have annotation %s", authenticationType,
|
||||||
return authenticationType.getAnnotation(CredentialType.class).value();
|
CredentialType.class.getName());
|
||||||
|
return credentialType.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> Map<String, T> indexByCredentialType(Iterable<T> iterable) {
|
public static <T> Map<String, T> indexByCredentialType(Iterable<T> iterable) {
|
||||||
return Maps.uniqueIndex(iterable, new Function<T, String>() {
|
return Maps.uniqueIndex(iterable, new Function<T, String>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String apply(T input) {
|
public String apply(T input) {
|
||||||
return credentialTypeOf(input);
|
return credentialTypeOf(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find an annotation in teh given class or their parents. We need this since
|
||||||
|
* AutoValue classes inherit the classes we define.
|
||||||
|
*/
|
||||||
|
public static CredentialType findCredentialType(Class<?> input) {
|
||||||
|
if (input == null)
|
||||||
|
return null;
|
||||||
|
CredentialType ann = input.getAnnotation(CredentialType.class);
|
||||||
|
return ann != null ? ann : findCredentialType(input.getSuperclass());
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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.domain;
|
||||||
|
|
||||||
|
import static org.jclouds.openstack.keystone.auth.config.CredentialTypes.API_ACCESS_KEY_CREDENTIALS;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.keystone.auth.config.CredentialType;
|
||||||
|
|
||||||
|
import com.google.auto.value.AutoValue;
|
||||||
|
|
||||||
|
@CredentialType(API_ACCESS_KEY_CREDENTIALS)
|
||||||
|
@AutoValue
|
||||||
|
public abstract class ApiAccessKeyCredentials {
|
||||||
|
|
||||||
|
public abstract String accessKey();
|
||||||
|
public abstract String secretKey();
|
||||||
|
|
||||||
|
public static ApiAccessKeyCredentials create(String accessKey, String secretKey) {
|
||||||
|
return builder().accessKey(accessKey).secretKey(secretKey).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiAccessKeyCredentials() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new AutoValue_ApiAccessKeyCredentials.Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue.Builder
|
||||||
|
public abstract static class Builder {
|
||||||
|
public abstract Builder accessKey(String accessKey);
|
||||||
|
public abstract Builder secretKey(String secretKey);
|
||||||
|
|
||||||
|
public abstract ApiAccessKeyCredentials build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,10 +14,12 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
package org.jclouds.openstack.keystone.auth.domain;
|
||||||
|
|
||||||
import com.google.inject.ImplementedBy;
|
/**
|
||||||
|
* Common interface for authentication objects.
|
||||||
|
*/
|
||||||
|
public interface AuthInfo {
|
||||||
|
|
||||||
@ImplementedBy(AdminURL.class)
|
String getAuthToken();
|
||||||
public interface EndpointToSupplierAdminURI extends EndpointToSupplierURI {
|
|
||||||
}
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* 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.domain;
|
||||||
|
|
||||||
|
import static org.jclouds.openstack.keystone.auth.config.CredentialTypes.PASSWORD_CREDENTIALS;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.keystone.auth.config.CredentialType;
|
||||||
|
|
||||||
|
import com.google.auto.value.AutoValue;
|
||||||
|
import com.google.common.base.MoreObjects;
|
||||||
|
|
||||||
|
@CredentialType(PASSWORD_CREDENTIALS)
|
||||||
|
@AutoValue
|
||||||
|
public abstract class PasswordCredentials {
|
||||||
|
|
||||||
|
public abstract String username();
|
||||||
|
public abstract String password();
|
||||||
|
|
||||||
|
public static PasswordCredentials create(String username, String password) {
|
||||||
|
return builder().username(username).password(password).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
PasswordCredentials() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return MoreObjects.toStringHelper(this).add("username", username())
|
||||||
|
.add("password", password() == null ? null : "*****").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new AutoValue_PasswordCredentials.Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue.Builder
|
||||||
|
public abstract static class Builder {
|
||||||
|
public abstract Builder username(String username);
|
||||||
|
public abstract Builder password(String password);
|
||||||
|
|
||||||
|
public abstract PasswordCredentials build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.auth.domain;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.auto.value.AutoValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keystone credentials with tenant. Configure the tenant properties to the
|
||||||
|
* configured context credentials.
|
||||||
|
*/
|
||||||
|
@AutoValue
|
||||||
|
public abstract class TenantOrDomainAndCredentials<T> {
|
||||||
|
|
||||||
|
@Nullable public abstract String tenantOrDomainId();
|
||||||
|
@Nullable public abstract String tenantOrDomainName();
|
||||||
|
@Nullable public abstract String scope();
|
||||||
|
public abstract T credentials();
|
||||||
|
|
||||||
|
TenantOrDomainAndCredentials() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Builder<T> builder() {
|
||||||
|
return new AutoValue_TenantOrDomainAndCredentials.Builder<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue.Builder
|
||||||
|
public abstract static class Builder<T> {
|
||||||
|
public abstract Builder<T> tenantOrDomainId(String tenantId);
|
||||||
|
public abstract Builder<T> tenantOrDomainName(String tenantName);
|
||||||
|
public abstract Builder<T> scope(String scope);
|
||||||
|
public abstract Builder<T> credentials(T credentials);
|
||||||
|
|
||||||
|
public abstract TenantOrDomainAndCredentials<T> build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,26 +14,37 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
package org.jclouds.openstack.keystone.auth.domain;
|
||||||
|
|
||||||
import java.net.URI;
|
import static org.jclouds.openstack.keystone.auth.config.CredentialTypes.TOKEN_CREDENTIALS;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import org.jclouds.openstack.keystone.auth.config.CredentialType;
|
||||||
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
import com.google.auto.value.AutoValue;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
@CredentialType(TOKEN_CREDENTIALS)
|
||||||
import com.google.common.base.Suppliers;
|
@AutoValue
|
||||||
|
public abstract class TokenCredentials {
|
||||||
|
|
||||||
@Singleton
|
public abstract String id();
|
||||||
public class PublicURLOrInternalIfNull implements EndpointToSupplierURI {
|
|
||||||
// TODO: check accessibility and prioritize private first
|
public static TokenCredentials create(String id) {
|
||||||
@Override
|
return builder().id(id).build();
|
||||||
public Supplier<URI> apply(Endpoint input) {
|
|
||||||
return Suppliers.ofInstance(input.getPublicURL() != null ? input.getPublicURL() : input.getInternalURL());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
TokenCredentials() {
|
||||||
return "supplyPublicURL()";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new AutoValue_TokenCredentials.Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue.Builder
|
||||||
|
public abstract static class Builder {
|
||||||
|
public abstract Builder id(String id);
|
||||||
|
|
||||||
|
public abstract TokenCredentials build();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.filters;
|
package org.jclouds.openstack.keystone.auth.filters;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
@ -22,8 +22,8 @@ import javax.inject.Singleton;
|
||||||
import org.jclouds.http.HttpException;
|
import org.jclouds.http.HttpException;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpRequestFilter;
|
import org.jclouds.http.HttpRequestFilter;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.Authentication;
|
import org.jclouds.openstack.keystone.auth.AuthHeaders;
|
||||||
import org.jclouds.openstack.v2_0.reference.AuthHeaders;
|
import org.jclouds.openstack.keystone.auth.config.Authentication;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ public class AuthenticateRequest implements HttpRequestFilter {
|
||||||
private final Supplier<String> authTokenProvider;
|
private final Supplier<String> authTokenProvider;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AuthenticateRequest(@Authentication Supplier<String> authTokenProvider) {
|
AuthenticateRequest(@Authentication Supplier<String> authTokenProvider) {
|
||||||
this.authTokenProvider = authTokenProvider;
|
this.authTokenProvider = authTokenProvider;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.functions;
|
||||||
|
|
||||||
|
import static org.jclouds.openstack.keystone.auth.config.CredentialTypes.API_ACCESS_KEY_CREDENTIALS;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.keystone.auth.AuthenticationApi;
|
||||||
|
import org.jclouds.openstack.keystone.auth.config.CredentialType;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.ApiAccessKeyCredentials;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.TenantOrDomainAndCredentials;
|
||||||
|
|
||||||
|
@CredentialType(API_ACCESS_KEY_CREDENTIALS)
|
||||||
|
@Singleton
|
||||||
|
public class AuthenticateApiAccessKeyCredentials extends BaseAuthenticator<ApiAccessKeyCredentials> {
|
||||||
|
|
||||||
|
private final AuthenticationApi auth;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AuthenticateApiAccessKeyCredentials(AuthenticationApi auth) {
|
||||||
|
this.auth = auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApiAccessKeyCredentials createCredentials(String identity, String credential) {
|
||||||
|
return ApiAccessKeyCredentials.builder().accessKey(identity).secretKey(credential).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthInfo authenticate(TenantOrDomainAndCredentials<ApiAccessKeyCredentials> credentials) {
|
||||||
|
return auth.authenticateAccessKey(credentials);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.auth.functions;
|
||||||
|
|
||||||
|
import static org.jclouds.openstack.keystone.auth.config.CredentialTypes.PASSWORD_CREDENTIALS;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.keystone.auth.AuthenticationApi;
|
||||||
|
import org.jclouds.openstack.keystone.auth.config.CredentialType;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.TenantOrDomainAndCredentials;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.PasswordCredentials;
|
||||||
|
|
||||||
|
@CredentialType(PASSWORD_CREDENTIALS)
|
||||||
|
@Singleton
|
||||||
|
public class AuthenticatePasswordCredentials extends BaseAuthenticator<PasswordCredentials> {
|
||||||
|
|
||||||
|
private final AuthenticationApi auth;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AuthenticatePasswordCredentials(AuthenticationApi auth) {
|
||||||
|
this.auth = auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PasswordCredentials createCredentials(String identity, String credential) {
|
||||||
|
return PasswordCredentials.builder().username(identity).password(credential).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthInfo authenticate(TenantOrDomainAndCredentials<PasswordCredentials> credentials) {
|
||||||
|
return auth.authenticatePassword(credentials);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.auth.functions;
|
||||||
|
|
||||||
|
import static org.jclouds.openstack.keystone.auth.config.CredentialTypes.TOKEN_CREDENTIALS;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.keystone.auth.AuthenticationApi;
|
||||||
|
import org.jclouds.openstack.keystone.auth.config.CredentialType;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.TenantOrDomainAndCredentials;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.TokenCredentials;
|
||||||
|
|
||||||
|
@CredentialType(TOKEN_CREDENTIALS)
|
||||||
|
@Singleton
|
||||||
|
public class AuthenticateTokenCredentials extends BaseAuthenticator<TokenCredentials> {
|
||||||
|
|
||||||
|
private final AuthenticationApi auth;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AuthenticateTokenCredentials(AuthenticationApi auth) {
|
||||||
|
this.auth = auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TokenCredentials createCredentials(String identity, String credential) {
|
||||||
|
return TokenCredentials.builder().id(credential).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthInfo authenticate(TenantOrDomainAndCredentials<TokenCredentials> credentials) {
|
||||||
|
return auth.authenticateToken(credentials);
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,26 +14,28 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.functions.internal;
|
package org.jclouds.openstack.keystone.auth.functions;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.REQUIRES_TENANT;
|
import static org.jclouds.openstack.keystone.config.KeystoneProperties.REQUIRES_TENANT;
|
||||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.TENANT_ID;
|
import static org.jclouds.openstack.keystone.config.KeystoneProperties.SCOPE;
|
||||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.TENANT_NAME;
|
import static org.jclouds.openstack.keystone.config.KeystoneProperties.TENANT_ID;
|
||||||
|
import static org.jclouds.openstack.keystone.config.KeystoneProperties.TENANT_NAME;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.TenantOrDomainAndCredentials;
|
||||||
|
import org.jclouds.openstack.keystone.v3.domain.Auth.Scope;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Optional;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.name.Named;
|
import com.google.inject.name.Named;
|
||||||
|
|
||||||
public abstract class BaseAuthenticator<C> implements Function<Credentials, Access> {
|
public abstract class BaseAuthenticator<C> implements Function<Credentials, AuthInfo> {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
@ -50,6 +52,10 @@ public abstract class BaseAuthenticator<C> implements Function<Credentials, Acce
|
||||||
@Named(REQUIRES_TENANT)
|
@Named(REQUIRES_TENANT)
|
||||||
protected boolean requiresTenant;
|
protected boolean requiresTenant;
|
||||||
|
|
||||||
|
@Inject(optional = true)
|
||||||
|
@Named(SCOPE)
|
||||||
|
protected String scope = Scope.UNSCOPED;
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void checkPropertiesAreCompatible() {
|
public void checkPropertiesAreCompatible() {
|
||||||
checkState(defaultTenantName == null || defaultTenantId == null, "you cannot specify both %s and %s",
|
checkState(defaultTenantName == null || defaultTenantId == null, "you cannot specify both %s and %s",
|
||||||
|
@ -57,41 +63,32 @@ public abstract class BaseAuthenticator<C> implements Function<Credentials, Acce
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Access apply(Credentials input) {
|
public AuthInfo apply(Credentials input) {
|
||||||
Optional<String> tenantName = Optional.fromNullable(defaultTenantName);
|
String tenantName = defaultTenantName;
|
||||||
Optional<String> tenantId = Optional.fromNullable(defaultTenantId);
|
|
||||||
|
|
||||||
String usernameOrAccessKey = input.identity;
|
String usernameOrAccessKey = input.identity;
|
||||||
|
String passwordOrSecretKeyOrToken = input.credential;
|
||||||
|
|
||||||
if (!tenantName.isPresent() && input.identity.indexOf(':') != -1) {
|
if (defaultTenantName == null && input.identity.indexOf(':') != -1) {
|
||||||
tenantName = Optional.of(input.identity.substring(0, input.identity.lastIndexOf(':')));
|
tenantName = input.identity.substring(0, input.identity.lastIndexOf(':'));
|
||||||
usernameOrAccessKey = input.identity.substring(input.identity.lastIndexOf(':') + 1);
|
usernameOrAccessKey = input.identity.substring(input.identity.lastIndexOf(':') + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
String passwordOrSecretKey = input.credential;
|
if (defaultTenantId == null && tenantName == null && requiresTenant) {
|
||||||
|
|
||||||
C creds = createCredentials(usernameOrAccessKey, passwordOrSecretKey);
|
|
||||||
|
|
||||||
Access access;
|
|
||||||
if (tenantId.isPresent()) {
|
|
||||||
access = authenticateWithTenantId(tenantId, creds);
|
|
||||||
} else if (tenantName.isPresent()) {
|
|
||||||
access = authenticateWithTenantName(tenantName, creds);
|
|
||||||
} else if (!requiresTenant) {
|
|
||||||
access = authenticateWithTenantName(tenantName, creds);
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
String.format(
|
String.format(
|
||||||
"current configuration is set to [%s]. Unless you set [%s] or [%s], you must prefix your identity with 'tenantName:'",
|
"current configuration is set to [%s]. Unless you set [%s] or [%s], you must prefix your identity with 'tenantName:'",
|
||||||
REQUIRES_TENANT, TENANT_NAME, TENANT_ID));
|
REQUIRES_TENANT, TENANT_NAME, TENANT_ID));
|
||||||
}
|
}
|
||||||
return access;
|
|
||||||
|
C creds = createCredentials(usernameOrAccessKey, passwordOrSecretKeyOrToken);
|
||||||
|
TenantOrDomainAndCredentials<C> credsWithTenant = TenantOrDomainAndCredentials.<C> builder().tenantOrDomainId(defaultTenantId)
|
||||||
|
.tenantOrDomainName(tenantName).scope(scope).credentials(creds).build();
|
||||||
|
|
||||||
|
return authenticate(credsWithTenant);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract C createCredentials(String identity, String credential);
|
public abstract C createCredentials(String identity, String credential);
|
||||||
|
|
||||||
protected abstract Access authenticateWithTenantId(Optional<String> tenantId, C apiAccessKeyCredentials);
|
public abstract AuthInfo authenticate(TenantOrDomainAndCredentials<C> credentials);
|
||||||
|
|
||||||
protected abstract Access authenticateWithTenantName(Optional<String> tenantId, C apiAccessKeyCredentials);
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.handlers;
|
package org.jclouds.openstack.keystone.auth.handlers;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -28,8 +28,8 @@ import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.http.HttpRetryHandler;
|
import org.jclouds.http.HttpRetryHandler;
|
||||||
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
import org.jclouds.openstack.keystone.auth.AuthHeaders;
|
||||||
import org.jclouds.openstack.v2_0.reference.AuthHeaders;
|
import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.cache.Cache;
|
import com.google.common.cache.Cache;
|
||||||
|
@ -53,12 +53,12 @@ public class RetryOnRenew implements HttpRetryHandler {
|
||||||
@Named(Constants.PROPERTY_MAX_RETRIES)
|
@Named(Constants.PROPERTY_MAX_RETRIES)
|
||||||
static int NUM_RETRIES = 5;
|
static int NUM_RETRIES = 5;
|
||||||
|
|
||||||
private final LoadingCache<Credentials, Access> authenticationResponseCache;
|
private final LoadingCache<Credentials, AuthInfo> authenticationResponseCache;
|
||||||
|
|
||||||
private final BackoffLimitedRetryHandler backoffHandler;
|
private final BackoffLimitedRetryHandler backoffHandler;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected RetryOnRenew(LoadingCache<Credentials, Access> authenticationResponseCache,
|
RetryOnRenew(LoadingCache<Credentials, AuthInfo> authenticationResponseCache,
|
||||||
BackoffLimitedRetryHandler backoffHandler) {
|
BackoffLimitedRetryHandler backoffHandler) {
|
||||||
this.authenticationResponseCache = authenticationResponseCache;
|
this.authenticationResponseCache = authenticationResponseCache;
|
||||||
this.backoffHandler = backoffHandler;
|
this.backoffHandler = backoffHandler;
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* 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.catalog;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.auto.value.AutoValue;
|
||||||
|
import com.google.common.base.Enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common properties for OpenStack service endpoints.
|
||||||
|
* <p>
|
||||||
|
* This class provides a common view on the service catalog endpoints so it can
|
||||||
|
* be parsed in a generic way for Keystone v2 and v3.
|
||||||
|
*/
|
||||||
|
@AutoValue
|
||||||
|
public abstract class ServiceEndpoint {
|
||||||
|
|
||||||
|
public enum Interface {
|
||||||
|
PUBLIC, ADMIN, INTERNAL, UNRECOGNIZED;
|
||||||
|
|
||||||
|
public static Interface fromValue(String iface) {
|
||||||
|
return Enums.getIfPresent(Interface.class, iface.toUpperCase()).or(UNRECOGNIZED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable public abstract String id();
|
||||||
|
@Nullable public abstract String regionId();
|
||||||
|
public abstract URI url();
|
||||||
|
public abstract Interface iface();
|
||||||
|
public abstract String type();
|
||||||
|
@Nullable public abstract String version();
|
||||||
|
|
||||||
|
ServiceEndpoint() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new AutoValue_ServiceEndpoint.Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue.Builder
|
||||||
|
public abstract static class Builder {
|
||||||
|
public abstract Builder id(String id);
|
||||||
|
public abstract Builder regionId(String regionId);
|
||||||
|
public abstract Builder url(URI url);
|
||||||
|
public abstract Builder iface(Interface iface);
|
||||||
|
public abstract Builder type(String type);
|
||||||
|
public abstract Builder version(String version);
|
||||||
|
|
||||||
|
public Builder iface(String iface) {
|
||||||
|
return iface(Interface.fromValue(iface));
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract ServiceEndpoint build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,10 +14,10 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.v2_0.config;
|
package org.jclouds.openstack.keystone.catalog.config;
|
||||||
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.functions.EndpointToSupplierURI;
|
import org.jclouds.openstack.keystone.catalog.functions.InternalURL;
|
||||||
import org.jclouds.openstack.keystone.v2_0.functions.InternalURL;
|
import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointResolutionStrategy;
|
||||||
|
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
@ -30,6 +30,6 @@ import com.google.inject.Singleton;
|
||||||
public class InternalUrlModule extends AbstractModule {
|
public class InternalUrlModule extends AbstractModule {
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(EndpointToSupplierURI.class).to(InternalURL.class);
|
bind(ServiceEndpointResolutionStrategy.class).to(InternalURL.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* 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.catalog.config;
|
||||||
|
|
||||||
|
import static org.jclouds.openstack.keystone.config.KeystoneProperties.KEYSTONE_VERSION;
|
||||||
|
import static org.jclouds.util.Suppliers2.getLastValueInMap;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.location.Provider;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURISupplier;
|
||||||
|
import org.jclouds.openstack.v2_0.ServiceType;
|
||||||
|
import org.jclouds.openstack.v2_0.services.Identity;
|
||||||
|
import org.jclouds.rest.annotations.ApiVersion;
|
||||||
|
import org.jclouds.util.Suppliers2;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||||
|
|
||||||
|
public class KeystoneAdminURLModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
|
||||||
|
RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* in some cases, there is no {@link ServiceType#IDENTITY} entry in the service catalog. In
|
||||||
|
* other cases, there's no adminURL entry present. Fallback to the provider in this case.
|
||||||
|
*/
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@Identity
|
||||||
|
protected final Supplier<URI> provideIdentityAdminUrl(final RegionIdToAdminURISupplier.Factory factory,
|
||||||
|
@ApiVersion final String version, @Named(KEYSTONE_VERSION) String keystoneVersion,
|
||||||
|
@Provider final Supplier<URI> providerURI) {
|
||||||
|
// There is a convention to use service types such as "identityv3" for specific endpoints. let's look first for
|
||||||
|
// those endpoints, and fallback to the default "identity" one or the project URL.
|
||||||
|
Supplier<URI> identityServiceForSpecificVersionInType = getLastValueInMap(factory.createForApiTypeAndVersion(
|
||||||
|
ServiceType.IDENTITY + "v" + keystoneVersion, version));
|
||||||
|
Supplier<URI> identityServiceForVersion = Suppliers2.onThrowable(identityServiceForSpecificVersionInType,
|
||||||
|
NoSuchElementException.class,
|
||||||
|
getLastValueInMap(factory.createForApiTypeAndVersion(ServiceType.IDENTITY, version)));
|
||||||
|
Supplier<URI> whenIdentityServiceIsntListedFallbackToProviderURI = Suppliers2.onThrowable(
|
||||||
|
identityServiceForVersion, NoSuchElementException.class, providerURI);
|
||||||
|
Supplier<URI> whenIdentityServiceHasNoAdminURLFallbackToProviderURI = Suppliers2.or(
|
||||||
|
whenIdentityServiceIsntListedFallbackToProviderURI, providerURI);
|
||||||
|
return whenIdentityServiceHasNoAdminURLFallbackToProviderURI;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,160 @@
|
||||||
|
/*
|
||||||
|
* 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.catalog.config;
|
||||||
|
|
||||||
|
import static org.jclouds.util.Suppliers2.getLastValueInMap;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.location.Provider;
|
||||||
|
import org.jclouds.location.suppliers.ImplicitLocationSupplier;
|
||||||
|
import org.jclouds.location.suppliers.LocationsSupplier;
|
||||||
|
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
||||||
|
import org.jclouds.location.suppliers.RegionIdsSupplier;
|
||||||
|
import org.jclouds.location.suppliers.all.RegionToProvider;
|
||||||
|
import org.jclouds.location.suppliers.derived.RegionIdsFromRegionIdToURIKeySet;
|
||||||
|
import org.jclouds.location.suppliers.implicit.FirstRegion;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.suppliers.LocationIdToURIFromServiceEndpointsForTypeAndVersion;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURISupplier;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToURIFromServiceEndpointsForTypeAndVersion;
|
||||||
|
import org.jclouds.openstack.keystone.config.KeystoneProperties;
|
||||||
|
import org.jclouds.openstack.keystone.v2_0.catalog.V2ServiceCatalog;
|
||||||
|
import org.jclouds.openstack.keystone.v3.catalog.V3ServiceCatalog;
|
||||||
|
import org.jclouds.rest.annotations.ApiVersion;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
import com.google.inject.Scopes;
|
||||||
|
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||||
|
|
||||||
|
public class ServiceCatalogModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected final Supplier<List<ServiceEndpoint>> provideServiceCatalog(Injector i,
|
||||||
|
@Named(KeystoneProperties.KEYSTONE_VERSION) String keystoneVersion) {
|
||||||
|
Map<String, Supplier<List<ServiceEndpoint>>> serviceCatalogs = Maps.newHashMap();
|
||||||
|
serviceCatalogs.put("2", i.getInstance(V2ServiceCatalog.class));
|
||||||
|
serviceCatalogs.put("3", i.getInstance(V3ServiceCatalog.class));
|
||||||
|
return serviceCatalogs.get(keystoneVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For global services who have no regions, such as DNS. To use, do the following
|
||||||
|
* <ol>
|
||||||
|
* <li>add this module to your {@link org.jclouds.apis.ApiMetadata#getDefaultModules()}</li>
|
||||||
|
* <li>create a service-specific annotation, such as {@code @CloudDNS}, and make sure that has the meta-annotation
|
||||||
|
* {@link javax.inject.Qualifier}</li>
|
||||||
|
* <li>add the above annotation to any {@code Api} classes by placing it on the type. ex.
|
||||||
|
* {@code @Endpoint(CloudDNS.class)}</li>
|
||||||
|
* <li>add the following to your {@link org.jclouds.rest.config.RestClientModule}</li>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* bind(new TypeLiteral<Supplier<URI>>() {
|
||||||
|
* }).annotatedWith(CloudDNS.class).to(new TypeLiteral<Supplier<URI>>() {
|
||||||
|
* });
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public static class ProviderModule extends AbstractModule {
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
install(new FactoryModuleBuilder().build(LocationIdToURIFromServiceEndpointsForTypeAndVersion.Factory.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected final Supplier<URI> provideZoneIdToURISupplierForApiVersion(
|
||||||
|
@Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
|
||||||
|
LocationIdToURIFromServiceEndpointsForTypeAndVersion.Factory factory) {
|
||||||
|
return getLastValueInMap(factory.createForApiTypeAndVersion(serviceType, apiVersion));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
final Function<ServiceEndpoint, String> provideProvider(@Provider final String provider) {
|
||||||
|
return new Function<ServiceEndpoint, String>() {
|
||||||
|
@Override
|
||||||
|
public String apply(ServiceEndpoint in) {
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RegionModule extends AbstractModule {
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
|
||||||
|
RegionIdToURIFromServiceEndpointsForTypeAndVersion.class).build(RegionIdToURISupplier.Factory.class));
|
||||||
|
install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
|
||||||
|
RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
|
||||||
|
// Dynamically build the region list as opposed to from properties
|
||||||
|
bind(RegionIdsSupplier.class).to(RegionIdsFromRegionIdToURIKeySet.class);
|
||||||
|
bind(ImplicitLocationSupplier.class).to(FirstRegion.class).in(Scopes.SINGLETON);
|
||||||
|
bind(LocationsSupplier.class).to(RegionToProvider.class).in(Scopes.SINGLETON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected final RegionIdToURISupplier guiceProvideRegionIdToURISupplierForApiVersion(
|
||||||
|
@Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
|
||||||
|
RegionIdToURISupplier.Factory factory) {
|
||||||
|
return provideRegionIdToURISupplierForApiVersion(serviceType, apiVersion, factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Supply the region to id map from keystone, based on the servicetype and
|
||||||
|
// api version in config
|
||||||
|
protected RegionIdToURISupplier provideRegionIdToURISupplierForApiVersion(
|
||||||
|
@Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
|
||||||
|
RegionIdToURISupplier.Factory factory) {
|
||||||
|
return factory.createForApiTypeAndVersion(serviceType, apiVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected final RegionIdToAdminURISupplier guiceProvideRegionIdToAdminURISupplierForApiVersion(
|
||||||
|
@Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
|
||||||
|
RegionIdToAdminURISupplier.Factory factory) {
|
||||||
|
return provideRegionIdToAdminURISupplierForApiVersion(serviceType, apiVersion, factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Supply the region to id to AdminURL map from keystone, based on the
|
||||||
|
// servicetype and api version in config
|
||||||
|
protected RegionIdToAdminURISupplier provideRegionIdToAdminURISupplierForApiVersion(
|
||||||
|
@Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
|
||||||
|
RegionIdToAdminURISupplier.Factory factory) {
|
||||||
|
return factory.createForApiTypeAndVersion(serviceType, apiVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,16 +14,14 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
package org.jclouds.openstack.keystone.catalog.functions;
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.base.Supplier;
|
|
||||||
import com.google.inject.ImplementedBy;
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
@ImplementedBy(PublicURLOrInternalIfNull.class)
|
/**
|
||||||
public interface EndpointToSupplierURI extends Function<Endpoint, Supplier<URI>> {
|
* Given a sets of endpoints for a particular service and version, return the
|
||||||
|
* URL of the admin endpoint to be used to connect to the service.
|
||||||
|
*/
|
||||||
|
@ImplementedBy(AdminURL.class)
|
||||||
|
public interface AdminEndpointResolutionStrategy extends ServiceEndpointResolutionStrategy {
|
||||||
}
|
}
|
|
@ -14,25 +14,21 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
package org.jclouds.openstack.keystone.catalog.functions;
|
||||||
|
|
||||||
import java.net.URI;
|
import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.ADMIN;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Suppliers;
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class AdminURL implements EndpointToSupplierAdminURI {
|
public class AdminURL extends BaseEndpointResolutionStrategy implements AdminEndpointResolutionStrategy {
|
||||||
@Override
|
|
||||||
public Supplier<URI> apply(Endpoint input) {
|
|
||||||
return Suppliers.ofInstance(input.getAdminURL());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
@Override
|
||||||
return "supplyAdminURL()";
|
protected Predicate<ServiceEndpoint> filter() {
|
||||||
|
return withIface(ADMIN);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* 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.catalog.functions;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Iterables.tryFind;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.base.Suppliers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the endpoint to be used to connect to a service based on a given
|
||||||
|
* predicate.
|
||||||
|
*/
|
||||||
|
public abstract class BaseEndpointResolutionStrategy implements ServiceEndpointResolutionStrategy {
|
||||||
|
|
||||||
|
protected abstract Predicate<ServiceEndpoint> filter();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Supplier<URI> apply(Collection<ServiceEndpoint> input) {
|
||||||
|
Predicate<ServiceEndpoint> filter = filter();
|
||||||
|
Optional<ServiceEndpoint> serviceEndpoint = tryFind(input, filter);
|
||||||
|
return Suppliers.ofInstance(serviceEndpoint.isPresent() ? serviceEndpoint.get().url() : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Predicate<ServiceEndpoint> withIface(final Interface iface) {
|
||||||
|
return new Predicate<ServiceEndpoint>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(ServiceEndpoint input) {
|
||||||
|
return input.iface().equals(iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "interface(" + iface.name().toLowerCase() + ")";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,20 +14,21 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.config;
|
package org.jclouds.openstack.keystone.catalog.functions;
|
||||||
|
|
||||||
import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
|
import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.INTERNAL;
|
||||||
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.AuthenticationApi;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import com.google.inject.AbstractModule;
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
|
|
||||||
public class AuthenticationApiModule extends AbstractModule {
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class InternalURL extends BaseEndpointResolutionStrategy {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected Predicate<ServiceEndpoint> filter() {
|
||||||
// AuthenticationApi is used directly for filters and retry handlers, so let's bind it explicitly
|
return withIface(INTERNAL);
|
||||||
bindHttpApi(binder(), AuthenticationApi.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* 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.catalog.functions;
|
||||||
|
|
||||||
|
import static com.google.common.base.Predicates.or;
|
||||||
|
import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.INTERNAL;
|
||||||
|
import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.PUBLIC;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class PublicURLOrInternal extends BaseEndpointResolutionStrategy {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Supplier<URI> apply(Collection<ServiceEndpoint> input) {
|
||||||
|
List<ServiceEndpoint> publicEndpointsFirst = new ArrayList<ServiceEndpoint>(input);
|
||||||
|
Collections.sort(publicEndpointsFirst, PublicInterfacesFirst);
|
||||||
|
return super.apply(publicEndpointsFirst);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Predicate<ServiceEndpoint> filter() {
|
||||||
|
return or(withIface(PUBLIC), withIface(INTERNAL));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Comparator<ServiceEndpoint> PublicInterfacesFirst = new Comparator<ServiceEndpoint>() {
|
||||||
|
@Override
|
||||||
|
public int compare(ServiceEndpoint left, ServiceEndpoint right) {
|
||||||
|
// We only care about public interfaces, since the collection will be
|
||||||
|
// filtered only by public or internal ones
|
||||||
|
if (PUBLIC.equals(left.iface())) {
|
||||||
|
return -1;
|
||||||
|
} else if (PUBLIC.equals(right.iface())) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -14,27 +14,25 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
package org.jclouds.openstack.keystone.catalog.functions;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.location.Provider;
|
import org.jclouds.location.Provider;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class ReturnRegionOrProvider implements EndpointToRegion {
|
public class ReturnRegionOrProvider implements ServiceEndpointToRegion {
|
||||||
private String provider;
|
private final String provider;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ReturnRegionOrProvider(@Provider String provider) {
|
ReturnRegionOrProvider(@Provider String provider) {
|
||||||
this.provider = checkNotNull(provider, "provider");
|
this.provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String apply(Endpoint input) {
|
public String apply(ServiceEndpoint input) {
|
||||||
return input.getRegion() != null ? input.getRegion() : provider;
|
return input.regionId() != null ? input.regionId() : provider;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,30 +14,22 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
package org.jclouds.openstack.keystone.catalog.functions;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Suppliers;
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select internal URL endpoints services
|
* Given a sets of endpoints for a particular service and version, return the
|
||||||
*
|
* URL to be used to connect to the service.
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@ImplementedBy(PublicURLOrInternal.class)
|
||||||
public class InternalURL implements EndpointToSupplierURI {
|
public interface ServiceEndpointResolutionStrategy extends Function<Collection<ServiceEndpoint>, Supplier<URI>> {
|
||||||
@Override
|
|
||||||
public Supplier<URI> apply(Endpoint input) {
|
|
||||||
return Suppliers.ofInstance(input.getInternalURL());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "supplyInternalURL()";
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -14,14 +14,14 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
package org.jclouds.openstack.keystone.catalog.functions;
|
||||||
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.inject.ImplementedBy;
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
@ImplementedBy(ReturnRegionOrProvider.class)
|
@ImplementedBy(ReturnRegionOrProvider.class)
|
||||||
public interface EndpointToRegion extends Function<Endpoint, String> {
|
public interface ServiceEndpointToRegion extends Function<ServiceEndpoint, String> {
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* 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.catalog.suppliers;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Iterables.any;
|
||||||
|
import static com.google.common.collect.Iterables.filter;
|
||||||
|
import static com.google.common.collect.Iterables.isEmpty;
|
||||||
|
import static com.google.common.collect.Maps.transformValues;
|
||||||
|
import static com.google.common.collect.Multimaps.asMap;
|
||||||
|
import static com.google.common.collect.Multimaps.index;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointResolutionStrategy;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointToRegion;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
|
||||||
|
public class LocationIdToURIFromServiceEndpointsForTypeAndVersion implements Supplier<Map<String, Supplier<URI>>> {
|
||||||
|
|
||||||
|
public interface Factory {
|
||||||
|
|
||||||
|
LocationIdToURIFromServiceEndpointsForTypeAndVersion createForApiTypeAndVersion(@Assisted("apiType") String apiType,
|
||||||
|
@Nullable @Assisted("apiVersion") String apiVersion) throws NoSuchElementException;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
protected final Supplier<List<ServiceEndpoint>> serviceEndpoints;
|
||||||
|
protected final ServiceEndpointResolutionStrategy resolveServiceEndpointURI;
|
||||||
|
protected final ServiceEndpointToRegion serviceEndpointToRegion;
|
||||||
|
protected final String apiType;
|
||||||
|
protected final String apiVersion;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
LocationIdToURIFromServiceEndpointsForTypeAndVersion(Supplier<List<ServiceEndpoint>> serviceEndpoints,
|
||||||
|
ServiceEndpointResolutionStrategy resolveServiceEndpointURI, ServiceEndpointToRegion serviceEndpointToRegion,
|
||||||
|
@Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
|
||||||
|
this.serviceEndpoints = serviceEndpoints;
|
||||||
|
this.resolveServiceEndpointURI = resolveServiceEndpointURI;
|
||||||
|
this.serviceEndpointToRegion = serviceEndpointToRegion;
|
||||||
|
this.apiType = apiType;
|
||||||
|
this.apiVersion = apiVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Supplier<URI>> get() {
|
||||||
|
List<ServiceEndpoint> endpoints = serviceEndpoints.get();
|
||||||
|
if (endpoints.isEmpty()) {
|
||||||
|
throw new NoSuchElementException(
|
||||||
|
"No endpoints were found in the service catalog. Make sure your authentication token has the right scopes and permissions");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter endpoints by service type
|
||||||
|
Iterable<ServiceEndpoint> endpointsForType = filter(endpoints, apiTypeEquals);
|
||||||
|
if (isEmpty(endpointsForType)) {
|
||||||
|
throw new NoSuchElementException(String.format("no endpoints for apiType %s in service endpoints %s", apiType,
|
||||||
|
endpoints));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there are endpoints for a particular version, if specified and
|
||||||
|
// there are versioned endpoints
|
||||||
|
boolean checkVersionId = apiVersion != null && any(endpointsForType, versionAware);
|
||||||
|
Predicate<ServiceEndpoint> versionFilter = checkVersionId ? apiVersionEqualsVersionId : Predicates.<ServiceEndpoint> alwaysTrue();
|
||||||
|
Iterable<ServiceEndpoint> endpointsForTypeAndVersion = filter(endpointsForType, versionFilter);
|
||||||
|
if (isEmpty(endpointsForTypeAndVersion)) {
|
||||||
|
throw new NoSuchElementException(String.format(
|
||||||
|
"no service endpoints for apiType %s are of version %s, or version agnostic: %s", apiType, apiVersion,
|
||||||
|
endpointsForType));
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("service endpoints for apiType %s and version %s: %s", apiType, apiVersion,
|
||||||
|
endpointsForTypeAndVersion);
|
||||||
|
|
||||||
|
Multimap<String, ServiceEndpoint> locationToServiceEndpoints = index(endpointsForTypeAndVersion,
|
||||||
|
serviceEndpointToRegion);
|
||||||
|
return transformValues(asMap(locationToServiceEndpoints), resolveServiceEndpointURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Predicate<ServiceEndpoint> apiVersionEqualsVersionId = new Predicate<ServiceEndpoint>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(ServiceEndpoint input) {
|
||||||
|
return input.version().equals(apiVersion);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Predicate<ServiceEndpoint> versionAware = new Predicate<ServiceEndpoint>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(ServiceEndpoint input) {
|
||||||
|
return input.version() != null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Predicate<ServiceEndpoint> apiTypeEquals = new Predicate<ServiceEndpoint>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(ServiceEndpoint input) {
|
||||||
|
return input.type().equals(apiType);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "locationIdToURIFromServiceEndpointsForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* 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.catalog.suppliers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.functions.AdminEndpointResolutionStrategy;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointToRegion;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
|
||||||
|
public class RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion extends LocationIdToURIFromServiceEndpointsForTypeAndVersion implements
|
||||||
|
RegionIdToAdminURISupplier {
|
||||||
|
@Inject
|
||||||
|
public RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion(Supplier<List<ServiceEndpoint>> serviceEndpoints,
|
||||||
|
AdminEndpointResolutionStrategy resolveServiceEndpointURI, ServiceEndpointToRegion serviceEndpointToRegion,
|
||||||
|
@Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
|
||||||
|
super(serviceEndpoints, resolveServiceEndpointURI, serviceEndpointToRegion, apiType, apiVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "regionIdToAdminURIFromServiceEndpointsForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.suppliers;
|
package org.jclouds.openstack.keystone.catalog.suppliers;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -26,19 +26,11 @@ import com.google.common.base.Supplier;
|
||||||
import com.google.inject.ImplementedBy;
|
import com.google.inject.ImplementedBy;
|
||||||
import com.google.inject.assistedinject.Assisted;
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
|
||||||
@ImplementedBy(RegionIdToAdminURIFromAccessForTypeAndVersion.class)
|
@ImplementedBy(RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion.class)
|
||||||
public interface RegionIdToAdminURISupplier extends Supplier<Map<String, Supplier<URI>>> {
|
public interface RegionIdToAdminURISupplier extends Supplier<Map<String, Supplier<URI>>> {
|
||||||
|
|
||||||
interface Factory {
|
interface Factory {
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param apiType
|
|
||||||
* type of the api, according to the provider. ex. {@code compute}
|
|
||||||
* {@code object-store}
|
|
||||||
* @param apiVersion
|
|
||||||
* version of the api, or null
|
|
||||||
* @return regions mapped to default uri
|
|
||||||
* @throws NoSuchElementException if the {@code apiType} is not present in the catalog
|
|
||||||
*/
|
|
||||||
RegionIdToAdminURISupplier createForApiTypeAndVersion(@Assisted("apiType") String apiType,
|
RegionIdToAdminURISupplier createForApiTypeAndVersion(@Assisted("apiType") String apiType,
|
||||||
@Nullable @Assisted("apiVersion") String apiVersion) throws NoSuchElementException;
|
@Nullable @Assisted("apiVersion") String apiVersion) throws NoSuchElementException;
|
||||||
}
|
}
|
|
@ -14,27 +14,29 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.suppliers;
|
package org.jclouds.openstack.keystone.catalog.suppliers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
import org.jclouds.openstack.keystone.v2_0.functions.EndpointToRegion;
|
import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointResolutionStrategy;
|
||||||
import org.jclouds.openstack.keystone.v2_0.functions.EndpointToSupplierURI;
|
import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointToRegion;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.inject.assistedinject.Assisted;
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
|
||||||
public class RegionIdToURIFromAccessForTypeAndVersion extends LocationIdToURIFromAccessForTypeAndVersion implements
|
public class RegionIdToURIFromServiceEndpointsForTypeAndVersion extends LocationIdToURIFromServiceEndpointsForTypeAndVersion implements
|
||||||
RegionIdToURISupplier {
|
RegionIdToURISupplier {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public RegionIdToURIFromAccessForTypeAndVersion(Supplier<Access> access,
|
public RegionIdToURIFromServiceEndpointsForTypeAndVersion(Supplier<List<ServiceEndpoint>> serviceEndpoints,
|
||||||
EndpointToSupplierURI endpointToSupplierURI, EndpointToRegion endpointToRegion,
|
ServiceEndpointResolutionStrategy resolveServiceEndpointURI, ServiceEndpointToRegion serviceEndpointToRegion,
|
||||||
@Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
|
@Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
|
||||||
super(access, endpointToSupplierURI, endpointToRegion, apiType, apiVersion);
|
super(serviceEndpoints, resolveServiceEndpointURI, serviceEndpointToRegion, apiType, apiVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
|
@ -14,7 +14,10 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.config;
|
package org.jclouds.openstack.keystone.config;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.keystone.auth.config.CredentialTypes;
|
||||||
|
import org.jclouds.rest.annotations.SinceApiVersion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration properties and constants used in Keystone connections.
|
* Configuration properties and constants used in Keystone connections.
|
||||||
|
@ -28,6 +31,7 @@ public final class KeystoneProperties {
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>apiAccessKeyCredentials</li>
|
* <li>apiAccessKeyCredentials</li>
|
||||||
* <li>passwordCredentials</li>
|
* <li>passwordCredentials</li>
|
||||||
|
* <li>tokenCredentials</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @see CredentialTypes
|
* @see CredentialTypes
|
||||||
|
@ -62,6 +66,20 @@ public final class KeystoneProperties {
|
||||||
*/
|
*/
|
||||||
public static final String REQUIRES_TENANT = "jclouds.keystone.requires-tenant";
|
public static final String REQUIRES_TENANT = "jclouds.keystone.requires-tenant";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set this property to specify for scoped authentication.
|
||||||
|
* <p>
|
||||||
|
* The format is one of the following:
|
||||||
|
* <ul>
|
||||||
|
* <li>project:<project-id></li>
|
||||||
|
* <li>domain:<domain-name></li>
|
||||||
|
* <li></li>
|
||||||
|
* </ul>
|
||||||
|
* For example: <code>project:457841231597451534</code>
|
||||||
|
*/
|
||||||
|
@SinceApiVersion("3")
|
||||||
|
public static final String SCOPE = "jclouds.keystone.scope";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* type of the keystone service. ex. {@code compute}
|
* type of the keystone service. ex. {@code compute}
|
||||||
*
|
*
|
||||||
|
@ -69,6 +87,11 @@ public final class KeystoneProperties {
|
||||||
*/
|
*/
|
||||||
public static final String SERVICE_TYPE = "jclouds.keystone.service-type";
|
public static final String SERVICE_TYPE = "jclouds.keystone.service-type";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Version of keystone to be used by services. Default: 3.
|
||||||
|
*/
|
||||||
|
public static final String KEYSTONE_VERSION = "jclouds.keystone.version";
|
||||||
|
|
||||||
private KeystoneProperties() {
|
private KeystoneProperties() {
|
||||||
throw new AssertionError("intentionally unimplemented");
|
throw new AssertionError("intentionally unimplemented");
|
||||||
}
|
}
|
|
@ -16,18 +16,19 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0;
|
package org.jclouds.openstack.keystone.v2_0;
|
||||||
|
|
||||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
|
import static org.jclouds.openstack.keystone.config.KeystoneProperties.CREDENTIAL_TYPE;
|
||||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_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.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.apis.ApiMetadata;
|
import org.jclouds.apis.ApiMetadata;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.AuthenticationApiModule;
|
import org.jclouds.openstack.keystone.auth.config.AuthenticationModule;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
|
import org.jclouds.openstack.keystone.auth.config.CredentialTypes;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
|
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.KeystoneHttpApiModule;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneHttpApiModule.KeystoneAdminURLModule;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneParserModule;
|
import org.jclouds.openstack.keystone.v2_0.config.KeystoneParserModule;
|
||||||
import org.jclouds.openstack.v2_0.ServiceType;
|
import org.jclouds.openstack.v2_0.ServiceType;
|
||||||
import org.jclouds.rest.internal.BaseHttpApiMetadata;
|
import org.jclouds.rest.internal.BaseHttpApiMetadata;
|
||||||
|
@ -59,6 +60,7 @@ public class KeystoneApiMetadata extends BaseHttpApiMetadata<KeystoneApi> {
|
||||||
Properties properties = BaseHttpApiMetadata.defaultProperties();
|
Properties properties = BaseHttpApiMetadata.defaultProperties();
|
||||||
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
|
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
|
||||||
properties.setProperty(SERVICE_TYPE, ServiceType.IDENTITY);
|
properties.setProperty(SERVICE_TYPE, ServiceType.IDENTITY);
|
||||||
|
properties.setProperty(KEYSTONE_VERSION, "2");
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,8 +77,8 @@ public class KeystoneApiMetadata extends BaseHttpApiMetadata<KeystoneApi> {
|
||||||
.defaultEndpoint("http://localhost:5000/v${jclouds.api-version}/")
|
.defaultEndpoint("http://localhost:5000/v${jclouds.api-version}/")
|
||||||
.defaultProperties(KeystoneApiMetadata.defaultProperties())
|
.defaultProperties(KeystoneApiMetadata.defaultProperties())
|
||||||
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
|
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
|
||||||
.add(AuthenticationApiModule.class)
|
.add(AuthenticationModule.class)
|
||||||
.add(KeystoneAuthenticationModule.class)
|
.add(ServiceCatalogModule.class)
|
||||||
.add(KeystoneAdminURLModule.class)
|
.add(KeystoneAdminURLModule.class)
|
||||||
.add(KeystoneParserModule.class)
|
.add(KeystoneParserModule.class)
|
||||||
.add(KeystoneHttpApiModule.class).build());
|
.add(KeystoneHttpApiModule.class).build());
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0;
|
package org.jclouds.openstack.keystone.v2_0.auth;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
|
||||||
|
@ -23,13 +23,13 @@ import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.openstack.keystone.auth.AuthenticationApi;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.ApiAccessKeyCredentials;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.PasswordCredentials;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.TenantOrDomainAndCredentials;
|
||||||
import org.jclouds.openstack.keystone.v2_0.binders.BindAuthToJsonPayload;
|
import org.jclouds.openstack.keystone.v2_0.binders.BindAuthToJsonPayload;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.ApiAccessKeyCredentials;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.PasswordCredentials;
|
|
||||||
import org.jclouds.rest.annotations.MapBinder;
|
import org.jclouds.rest.annotations.MapBinder;
|
||||||
import org.jclouds.rest.annotations.PayloadParam;
|
|
||||||
import org.jclouds.rest.annotations.SelectJson;
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
|
||||||
import com.google.inject.name.Named;
|
import com.google.inject.name.Named;
|
||||||
|
@ -39,7 +39,7 @@ import com.google.inject.name.Named;
|
||||||
*/
|
*/
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Path("/tokens")
|
@Path("/tokens")
|
||||||
public interface AuthenticationApi extends Closeable {
|
public interface V2AuthenticationApi extends AuthenticationApi, Closeable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticate to generate a token.
|
* Authenticate to generate a token.
|
||||||
|
@ -50,8 +50,8 @@ public interface AuthenticationApi extends Closeable {
|
||||||
@POST
|
@POST
|
||||||
@SelectJson("access")
|
@SelectJson("access")
|
||||||
@MapBinder(BindAuthToJsonPayload.class)
|
@MapBinder(BindAuthToJsonPayload.class)
|
||||||
Access authenticateWithTenantNameAndCredentials(@Nullable @PayloadParam("tenantName") String tenantName,
|
@Override
|
||||||
PasswordCredentials passwordCredentials);
|
Access authenticatePassword(TenantOrDomainAndCredentials<PasswordCredentials> credentials);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticate to generate a token.
|
* Authenticate to generate a token.
|
||||||
|
@ -62,30 +62,7 @@ public interface AuthenticationApi extends Closeable {
|
||||||
@POST
|
@POST
|
||||||
@SelectJson("access")
|
@SelectJson("access")
|
||||||
@MapBinder(BindAuthToJsonPayload.class)
|
@MapBinder(BindAuthToJsonPayload.class)
|
||||||
Access authenticateWithTenantIdAndCredentials(@Nullable @PayloadParam("tenantId") String tenantId,
|
@Override
|
||||||
PasswordCredentials passwordCredentials);
|
Access authenticateAccessKey(TenantOrDomainAndCredentials<ApiAccessKeyCredentials> credentials);
|
||||||
|
|
||||||
/**
|
|
||||||
* Authenticate to generate a token.
|
|
||||||
*
|
|
||||||
* @return access with token
|
|
||||||
*/
|
|
||||||
@Named("authenticate")
|
|
||||||
@POST
|
|
||||||
@SelectJson("access")
|
|
||||||
@MapBinder(BindAuthToJsonPayload.class)
|
|
||||||
Access authenticateWithTenantNameAndCredentials(@Nullable @PayloadParam("tenantName") String tenantName,
|
|
||||||
ApiAccessKeyCredentials apiAccessKeyCredentials);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authenticate to generate a token.
|
|
||||||
*
|
|
||||||
* @return access with token
|
|
||||||
*/
|
|
||||||
@Named("authenticate")
|
|
||||||
@POST
|
|
||||||
@SelectJson("access")
|
|
||||||
@MapBinder(BindAuthToJsonPayload.class)
|
|
||||||
Access authenticateWithTenantIdAndCredentials(@Nullable @PayloadParam("tenantId") String tenantId,
|
|
||||||
ApiAccessKeyCredentials apiAccessKeyCredentials);
|
|
||||||
}
|
}
|
|
@ -16,24 +16,29 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.binders;
|
package org.jclouds.openstack.keystone.v2_0.binders;
|
||||||
|
|
||||||
import com.google.common.base.Predicates;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import com.google.common.base.Strings;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import static com.google.common.base.Predicates.instanceOf;
|
||||||
import com.google.common.collect.ImmutableMap.Builder;
|
import static com.google.common.collect.Iterables.tryFind;
|
||||||
import com.google.common.collect.Iterables;
|
import static org.jclouds.openstack.keystone.auth.config.CredentialTypes.findCredentialType;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.json.Json;
|
import org.jclouds.json.Json;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.CredentialType;
|
import org.jclouds.openstack.keystone.auth.config.CredentialType;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.TenantOrDomainAndCredentials;
|
||||||
import org.jclouds.rest.MapBinder;
|
import org.jclouds.rest.MapBinder;
|
||||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import com.google.common.base.Optional;
|
||||||
import javax.inject.Singleton;
|
import com.google.common.base.Strings;
|
||||||
import java.util.Map;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableMap.Builder;
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindAuthToJsonPayload extends BindToJsonPayload implements MapBinder {
|
public class BindAuthToJsonPayload extends BindToJsonPayload implements MapBinder {
|
||||||
|
@ -42,12 +47,9 @@ public class BindAuthToJsonPayload extends BindToJsonPayload implements MapBinde
|
||||||
super(jsonBinder);
|
super(jsonBinder);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addCredentialsInArgsOrNull(GeneratedHttpRequest gRequest, Builder<String, Object> builder) {
|
protected TenantOrDomainAndCredentials<?> findCredentialsInArgs(GeneratedHttpRequest gRequest) {
|
||||||
for (Object arg : Iterables.filter(gRequest.getInvocation().getArgs(), Predicates.notNull())) {
|
Optional<Object> credentials = tryFind(gRequest.getInvocation().getArgs(), instanceOf(TenantOrDomainAndCredentials.class));
|
||||||
if (arg.getClass().isAnnotationPresent(CredentialType.class)) {
|
return credentials.isPresent() ? (TenantOrDomainAndCredentials<?>) credentials.get() : null;
|
||||||
builder.put(arg.getClass().getAnnotation(CredentialType.class).value(), arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -55,15 +57,25 @@ public class BindAuthToJsonPayload extends BindToJsonPayload implements MapBinde
|
||||||
checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest,
|
checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest,
|
||||||
"this binder is only valid for GeneratedHttpRequests!");
|
"this binder is only valid for GeneratedHttpRequests!");
|
||||||
GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request;
|
GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request;
|
||||||
|
|
||||||
Builder<String, Object> builder = ImmutableMap.builder();
|
Builder<String, Object> builder = ImmutableMap.builder();
|
||||||
addCredentialsInArgsOrNull(gRequest, builder);
|
|
||||||
// TODO: is tenantName permanent? or should we switch to tenantId at some point. seems most tools
|
TenantOrDomainAndCredentials<?> credentials = findCredentialsInArgs(gRequest);
|
||||||
// still use tenantName
|
if (credentials != null) {
|
||||||
if (!Strings.isNullOrEmpty((String) postParams.get("tenantName")))
|
CredentialType credentialType = findCredentialType(credentials.credentials().getClass());
|
||||||
builder.put("tenantName", postParams.get("tenantName"));
|
checkArgument(credentialType != null, "the given credentials must be annotated with @CredentialType");
|
||||||
else if (!Strings.isNullOrEmpty((String) postParams.get("tenantId")))
|
|
||||||
builder.put("tenantId", postParams.get("tenantId"));
|
builder.put(credentialType.value(), credentials.credentials());
|
||||||
|
|
||||||
|
// TODO: is tenantName permanent? or should we switch to tenantId at
|
||||||
|
// some point. seems most tools still use tenantName
|
||||||
|
if (credentials != null) {
|
||||||
|
if (!Strings.isNullOrEmpty(credentials.tenantOrDomainId()))
|
||||||
|
builder.put("tenantId", credentials.tenantOrDomainId());
|
||||||
|
else if (!Strings.isNullOrEmpty(credentials.tenantOrDomainName()))
|
||||||
|
builder.put("tenantName", credentials.tenantOrDomainName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
R authRequest = super.bindToRequest(request, ImmutableMap.of("auth", builder.build()));
|
R authRequest = super.bindToRequest(request, ImmutableMap.of("auth", builder.build()));
|
||||||
authRequest.getPayload().setSensitive(true);
|
authRequest.getPayload().setSensitive(true);
|
||||||
return authRequest;
|
return authRequest;
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* 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.v2_0.catalog;
|
||||||
|
|
||||||
|
import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.ADMIN;
|
||||||
|
import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.INTERNAL;
|
||||||
|
import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.PUBLIC;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
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.catalog.ServiceEndpoint.Interface;
|
||||||
|
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
||||||
|
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
||||||
|
import org.jclouds.openstack.keystone.v2_0.domain.Service;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class V2ServiceCatalog implements Supplier<List<ServiceEndpoint>> {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
private final Supplier<AuthInfo> authInfo;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
V2ServiceCatalog(Supplier<AuthInfo> authInfo) {
|
||||||
|
this.authInfo = authInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ServiceEndpoint> get() {
|
||||||
|
Access access = (Access) authInfo.get();
|
||||||
|
ImmutableList.Builder<ServiceEndpoint> serviceEndpoints = ImmutableList.builder();
|
||||||
|
for (Service service : access) {
|
||||||
|
for (Endpoint endpoint : service) {
|
||||||
|
if (endpoint.getAdminURL() != null) {
|
||||||
|
serviceEndpoints.add(toServiceEndpoint(service.getType(), ADMIN).apply(endpoint));
|
||||||
|
}
|
||||||
|
if (endpoint.getInternalURL() != null) {
|
||||||
|
serviceEndpoints.add(toServiceEndpoint(service.getType(), INTERNAL).apply(endpoint));
|
||||||
|
}
|
||||||
|
if (endpoint.getPublicURL() != null) {
|
||||||
|
serviceEndpoints.add(toServiceEndpoint(service.getType(), PUBLIC).apply(endpoint));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return serviceEndpoints.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Function<Endpoint, ServiceEndpoint> toServiceEndpoint(final String type, final Interface iface) {
|
||||||
|
return new Function<Endpoint, ServiceEndpoint>() {
|
||||||
|
@Override
|
||||||
|
public ServiceEndpoint apply(Endpoint input) {
|
||||||
|
ServiceEndpoint.Builder builder = ServiceEndpoint.builder().id(input.getId()).iface(iface)
|
||||||
|
.regionId(input.getRegion()).type(type).version(input.getVersionId());
|
||||||
|
|
||||||
|
switch (iface) {
|
||||||
|
case ADMIN:
|
||||||
|
builder.url(input.getAdminURL());
|
||||||
|
break;
|
||||||
|
case INTERNAL:
|
||||||
|
builder.url(input.getInternalURL());
|
||||||
|
break;
|
||||||
|
case PUBLIC:
|
||||||
|
builder.url(input.getPublicURL());
|
||||||
|
break;
|
||||||
|
case UNRECOGNIZED:
|
||||||
|
URI url = input.getPublicURL() != null ? input.getPublicURL() : input.getInternalURL();
|
||||||
|
logger.warn("Unrecognized endpoint interface for %s. Using URL: %s", input, url);
|
||||||
|
builder.url(url);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,257 +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.keystone.v2_0.config;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
import static org.jclouds.util.Suppliers2.getLastValueInMap;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
|
|
||||||
import javax.inject.Named;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.jclouds.domain.Credentials;
|
|
||||||
import org.jclouds.http.HttpRetryHandler;
|
|
||||||
import org.jclouds.http.annotation.ClientError;
|
|
||||||
import org.jclouds.location.Provider;
|
|
||||||
import org.jclouds.location.suppliers.ImplicitLocationSupplier;
|
|
||||||
import org.jclouds.location.suppliers.LocationsSupplier;
|
|
||||||
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
|
||||||
import org.jclouds.location.suppliers.RegionIdsSupplier;
|
|
||||||
import org.jclouds.location.suppliers.ZoneIdToURISupplier;
|
|
||||||
import org.jclouds.location.suppliers.ZoneIdsSupplier;
|
|
||||||
import org.jclouds.location.suppliers.all.RegionToProvider;
|
|
||||||
import org.jclouds.location.suppliers.all.ZoneToProvider;
|
|
||||||
import org.jclouds.location.suppliers.derived.RegionIdsFromRegionIdToURIKeySet;
|
|
||||||
import org.jclouds.location.suppliers.derived.ZoneIdsFromZoneIdToURIKeySet;
|
|
||||||
import org.jclouds.location.suppliers.implicit.FirstRegion;
|
|
||||||
import org.jclouds.location.suppliers.implicit.FirstZone;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
|
||||||
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.LocationIdToURIFromAccessForTypeAndVersion;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURIFromAccessForTypeAndVersion;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURISupplier;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToURIFromAccessForTypeAndVersion;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.suppliers.ZoneIdToURIFromAccessForTypeAndVersion;
|
|
||||||
import org.jclouds.rest.annotations.ApiVersion;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.base.Supplier;
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
|
||||||
import com.google.common.cache.CacheLoader;
|
|
||||||
import com.google.common.cache.LoadingCache;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.common.collect.ImmutableSet.Builder;
|
|
||||||
import com.google.inject.AbstractModule;
|
|
||||||
import com.google.inject.Injector;
|
|
||||||
import com.google.inject.Provides;
|
|
||||||
import com.google.inject.Scopes;
|
|
||||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
|
||||||
|
|
||||||
public class KeystoneAuthenticationModule extends AbstractModule {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For global services who have no regions, such as DNS. To use, do the following
|
|
||||||
* <ol>
|
|
||||||
* <li>add this module to your {@link org.jclouds.apis.ApiMetadata#getDefaultModules()}</li>
|
|
||||||
* <li>create a service-specific annotation, such as {@code @CloudDNS}, and make sure that has the meta-annotation
|
|
||||||
* {@link javax.inject.Qualifier}</li>
|
|
||||||
* <li>add the above annotation to any {@code Api} classes by placing it on the type. ex.
|
|
||||||
* {@code @Endpoint(CloudDNS.class)}</li>
|
|
||||||
* <li>add the following to your {@link org.jclouds.rest.config.RestClientModule}</li>
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* bind(new TypeLiteral<Supplier<URI>>() {
|
|
||||||
* }).annotatedWith(CloudDNS.class).to(new TypeLiteral<Supplier<URI>>() {
|
|
||||||
* });
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
public static class ProviderModule extends AbstractModule {
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
install(new FactoryModuleBuilder().build(LocationIdToURIFromAccessForTypeAndVersion.Factory.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
protected final Supplier<URI> provideZoneIdToURISupplierForApiVersion(
|
|
||||||
@Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
|
|
||||||
LocationIdToURIFromAccessForTypeAndVersion.Factory factory) {
|
|
||||||
return getLastValueInMap(factory.createForApiTypeAndVersion(serviceType, apiVersion));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
final Function<Endpoint, String> provideProvider(@Provider final String provider) {
|
|
||||||
return new Function<Endpoint, String>() {
|
|
||||||
@Override
|
|
||||||
public String apply(Endpoint in) {
|
|
||||||
return provider;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class RegionModule extends AbstractModule {
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
|
|
||||||
RegionIdToURIFromAccessForTypeAndVersion.class).build(RegionIdToURISupplier.Factory.class));
|
|
||||||
install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
|
|
||||||
RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
|
|
||||||
// dynamically build the region list as opposed to from properties
|
|
||||||
bind(RegionIdsSupplier.class).to(RegionIdsFromRegionIdToURIKeySet.class);
|
|
||||||
bind(ImplicitLocationSupplier.class).to(FirstRegion.class).in(Scopes.SINGLETON);
|
|
||||||
bind(LocationsSupplier.class).to(RegionToProvider.class).in(Scopes.SINGLETON);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
protected final RegionIdToURISupplier guiceProvideRegionIdToURISupplierForApiVersion(
|
|
||||||
@Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
|
|
||||||
RegionIdToURISupplier.Factory factory) {
|
|
||||||
return provideRegionIdToURISupplierForApiVersion(serviceType, apiVersion, factory);
|
|
||||||
}
|
|
||||||
|
|
||||||
// supply the region to id map from keystone, based on the servicetype and api version in
|
|
||||||
// config
|
|
||||||
protected RegionIdToURISupplier provideRegionIdToURISupplierForApiVersion(
|
|
||||||
@Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
|
|
||||||
RegionIdToURISupplier.Factory factory) {
|
|
||||||
return factory.createForApiTypeAndVersion(serviceType, apiVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
protected final RegionIdToAdminURISupplier guiceProvideRegionIdToAdminURISupplierForApiVersion(
|
|
||||||
@Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
|
|
||||||
RegionIdToAdminURISupplier.Factory factory) {
|
|
||||||
return provideRegionIdToAdminURISupplierForApiVersion(serviceType, apiVersion, factory);
|
|
||||||
}
|
|
||||||
|
|
||||||
// supply the region to id to AdminURL map from keystone, based on the servicetype and api
|
|
||||||
// version in
|
|
||||||
// config
|
|
||||||
protected RegionIdToAdminURISupplier provideRegionIdToAdminURISupplierForApiVersion(
|
|
||||||
@Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
|
|
||||||
RegionIdToAdminURISupplier.Factory factory) {
|
|
||||||
return factory.createForApiTypeAndVersion(serviceType, apiVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated All OpenStack APIs rely on regions in jclouds 2.0. To be removed in jclouds 2.0.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static class ZoneModule extends AbstractModule {
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
install(new FactoryModuleBuilder().implement(ZoneIdToURISupplier.class,
|
|
||||||
ZoneIdToURIFromAccessForTypeAndVersion.class).build(ZoneIdToURISupplier.Factory.class));
|
|
||||||
// dynamically build the zone list as opposed to from properties
|
|
||||||
bind(ZoneIdsSupplier.class).to(ZoneIdsFromZoneIdToURIKeySet.class);
|
|
||||||
bind(ImplicitLocationSupplier.class).to(FirstZone.class).in(Scopes.SINGLETON);
|
|
||||||
bind(LocationsSupplier.class).to(ZoneToProvider.class).in(Scopes.SINGLETON);
|
|
||||||
}
|
|
||||||
|
|
||||||
// supply the zone to id map from keystone, based on the servicetype and api version in
|
|
||||||
// config
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
protected final ZoneIdToURISupplier provideZoneIdToURISupplierForApiVersion(
|
|
||||||
@Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
|
|
||||||
ZoneIdToURISupplier.Factory factory) {
|
|
||||||
return factory.createForApiTypeAndVersion(serviceType, apiVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* borrowing concurrency code to ensure that caching takes place properly
|
|
||||||
*/
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
@Authentication
|
|
||||||
protected final Supplier<String> provideAuthenticationTokenCache(final Supplier<Access> supplier)
|
|
||||||
throws InterruptedException, ExecutionException, TimeoutException {
|
|
||||||
return new Supplier<String>() {
|
|
||||||
@Override
|
|
||||||
public String get() {
|
|
||||||
return supplier.get().getToken().getId();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
protected final Map<String, Function<Credentials, Access>> provideAuthenticationMethods(Injector i) {
|
|
||||||
return authenticationMethods(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Map<String, Function<Credentials, Access>> authenticationMethods(Injector i) {
|
|
||||||
Builder<Function<Credentials, Access>> fns = ImmutableSet.<Function<Credentials, Access>> builder();
|
|
||||||
fns.add(i.getInstance(AuthenticatePasswordCredentials.class));
|
|
||||||
fns.add(i.getInstance(AuthenticateApiAccessKeyCredentials.class));
|
|
||||||
return CredentialTypes.indexByCredentialType(fns.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
protected final Function<Credentials, Access> authenticationMethodForCredentialType(
|
|
||||||
@Named(KeystoneProperties.CREDENTIAL_TYPE) String credentialType,
|
|
||||||
Map<String, Function<Credentials, Access>> authenticationMethods) {
|
|
||||||
checkArgument(authenticationMethods.containsKey(credentialType), "credential type %s not in supported list: %s",
|
|
||||||
credentialType, authenticationMethods.keySet());
|
|
||||||
return authenticationMethods.get(credentialType);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: what is the timeout of the session token? modify default accordingly
|
|
||||||
// PROPERTY_SESSION_INTERVAL is default to 60 seconds, but we have this here at 11 hours for now.
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
public final LoadingCache<Credentials, Access> provideAccessCache(Function<Credentials, Access> getAccess) {
|
|
||||||
return CacheBuilder.newBuilder().expireAfterWrite(11, TimeUnit.HOURS).build(CacheLoader.from(getAccess));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Temporary conversion of a cache to a supplier until there is a single-element cache
|
|
||||||
// http://code.google.com/p/guava-libraries/issues/detail?id=872
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
protected final Supplier<Access> provideAccessSupplier(final LoadingCache<Credentials, Access> cache,
|
|
||||||
@Provider final Supplier<Credentials> creds) {
|
|
||||||
return new Supplier<Access>() {
|
|
||||||
@Override
|
|
||||||
public Access get() {
|
|
||||||
return cache.getUnchecked(creds.get());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -16,10 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.config;
|
package org.jclouds.openstack.keystone.v2_0.config;
|
||||||
|
|
||||||
import static org.jclouds.util.Suppliers2.getLastValueInMap;
|
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -29,30 +26,21 @@ import org.jclouds.http.HttpErrorHandler;
|
||||||
import org.jclouds.http.annotation.ClientError;
|
import org.jclouds.http.annotation.ClientError;
|
||||||
import org.jclouds.http.annotation.Redirection;
|
import org.jclouds.http.annotation.Redirection;
|
||||||
import org.jclouds.http.annotation.ServerError;
|
import org.jclouds.http.annotation.ServerError;
|
||||||
import org.jclouds.location.Provider;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.KeystoneApi;
|
import org.jclouds.openstack.keystone.v2_0.KeystoneApi;
|
||||||
import org.jclouds.openstack.keystone.v2_0.handlers.KeystoneErrorHandler;
|
import org.jclouds.openstack.keystone.v2_0.handlers.KeystoneErrorHandler;
|
||||||
import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURIFromAccessForTypeAndVersion;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURISupplier;
|
|
||||||
import org.jclouds.openstack.v2_0.ServiceType;
|
|
||||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||||
import org.jclouds.openstack.v2_0.functions.PresentWhenExtensionAnnotationMatchesExtensionSet;
|
import org.jclouds.openstack.v2_0.functions.PresentWhenExtensionAnnotationMatchesExtensionSet;
|
||||||
import org.jclouds.openstack.v2_0.services.Identity;
|
|
||||||
import org.jclouds.rest.ConfiguresHttpApi;
|
import org.jclouds.rest.ConfiguresHttpApi;
|
||||||
import org.jclouds.rest.annotations.ApiVersion;
|
|
||||||
import org.jclouds.rest.config.HttpApiModule;
|
import org.jclouds.rest.config.HttpApiModule;
|
||||||
import org.jclouds.rest.functions.ImplicitOptionalConverter;
|
import org.jclouds.rest.functions.ImplicitOptionalConverter;
|
||||||
import org.jclouds.util.Suppliers2;
|
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Suppliers;
|
import com.google.common.base.Suppliers;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.google.common.cache.CacheLoader;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
import com.google.inject.AbstractModule;
|
|
||||||
import com.google.inject.Binder;
|
import com.google.inject.Binder;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
|
||||||
import com.google.inject.multibindings.MapBinder;
|
import com.google.inject.multibindings.MapBinder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,33 +52,6 @@ public class KeystoneHttpApiModule extends HttpApiModule<KeystoneApi> {
|
||||||
public KeystoneHttpApiModule() {
|
public KeystoneHttpApiModule() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class KeystoneAdminURLModule extends AbstractModule {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
|
|
||||||
RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* in some cases, there is no {@link ServiceType#IDENTITY} entry in the service catalog. In
|
|
||||||
* other cases, there's no adminURL entry present. Fallback to the provider in this case.
|
|
||||||
*/
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
@Identity
|
|
||||||
protected final Supplier<URI> provideStorageUrl(final RegionIdToAdminURISupplier.Factory factory,
|
|
||||||
@ApiVersion final String version, @Provider final Supplier<URI> providerURI) {
|
|
||||||
Supplier<URI> identityServiceForVersion = getLastValueInMap(factory.createForApiTypeAndVersion(
|
|
||||||
ServiceType.IDENTITY, version));
|
|
||||||
Supplier<URI> whenIdentityServiceIsntListedFallbackToProviderURI = Suppliers2.onThrowable(
|
|
||||||
identityServiceForVersion, NoSuchElementException.class, providerURI);
|
|
||||||
Supplier<URI> whenIdentityServiceHasNoAdminURLFallbackToProviderURI = Suppliers2.or(
|
|
||||||
whenIdentityServiceIsntListedFallbackToProviderURI, providerURI);
|
|
||||||
return whenIdentityServiceHasNoAdminURLFallbackToProviderURI;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow providers to cleanly contribute their own aliases
|
// Allow providers to cleanly contribute their own aliases
|
||||||
public static MapBinder<URI, URI> namespaceAliasBinder(Binder binder) {
|
public static MapBinder<URI, URI> namespaceAliasBinder(Binder binder) {
|
||||||
return MapBinder.newMapBinder(binder, URI.class, URI.class, NamespaceAliases.class).permitDuplicates();
|
return MapBinder.newMapBinder(binder, URI.class, URI.class, NamespaceAliases.class).permitDuplicates();
|
||||||
|
|
|
@ -22,6 +22,7 @@ import java.beans.ConstructorProperties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
@ -36,7 +37,7 @@ import com.google.common.collect.ImmutableSet;
|
||||||
* "http://docs.openstack.org/api/openstack-identity-service/2.0/content/Identity-Service-Concepts-e1362.html"
|
* "http://docs.openstack.org/api/openstack-identity-service/2.0/content/Identity-Service-Concepts-e1362.html"
|
||||||
* />
|
* />
|
||||||
*/
|
*/
|
||||||
public class Access extends ForwardingSet<Service> implements Comparable<Access> {
|
public class Access extends ForwardingSet<Service> implements Comparable<Access>, AuthInfo {
|
||||||
|
|
||||||
public static Builder<?> builder() {
|
public static Builder<?> builder() {
|
||||||
return new ConcreteBuilder();
|
return new ConcreteBuilder();
|
||||||
|
@ -166,4 +167,9 @@ public class Access extends ForwardingSet<Service> implements Comparable<Access>
|
||||||
return serviceCatalog;
|
return serviceCatalog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthToken() {
|
||||||
|
return token.getId();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,140 +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.keystone.v2_0.domain;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
import java.beans.ConstructorProperties;
|
|
||||||
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.CredentialType;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
|
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
|
||||||
import com.google.common.base.Objects;
|
|
||||||
import com.google.common.base.MoreObjects.ToStringHelper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Api AccessKey Credentials
|
|
||||||
*
|
|
||||||
* @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_authenticate_v2.0_tokens_Service_API_Api_Operations.html#d662e583"
|
|
||||||
/>
|
|
||||||
*/
|
|
||||||
@CredentialType(CredentialTypes.API_ACCESS_KEY_CREDENTIALS)
|
|
||||||
public class ApiAccessKeyCredentials {
|
|
||||||
|
|
||||||
public static Builder<?> builder() {
|
|
||||||
return new ConcreteBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<?> toBuilder() {
|
|
||||||
return new ConcreteBuilder().fromApiAccessKeyCredentials(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ApiAccessKeyCredentials createWithAccessKeyAndSecretKey(String accessKey, String secretKey) {
|
|
||||||
return new ApiAccessKeyCredentials(accessKey, secretKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract static class Builder<T extends Builder<T>> {
|
|
||||||
protected abstract T self();
|
|
||||||
|
|
||||||
protected String accessKey;
|
|
||||||
protected String secretKey;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ApiAccessKeyCredentials#getAccessKey()
|
|
||||||
*/
|
|
||||||
public T accessKey(String accessKey) {
|
|
||||||
this.accessKey = accessKey;
|
|
||||||
return self();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ApiAccessKeyCredentials#getSecretKey()
|
|
||||||
*/
|
|
||||||
public T secretKey(String secretKey) {
|
|
||||||
this.secretKey = secretKey;
|
|
||||||
return self();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ApiAccessKeyCredentials build() {
|
|
||||||
return new ApiAccessKeyCredentials(accessKey, secretKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T fromApiAccessKeyCredentials(ApiAccessKeyCredentials in) {
|
|
||||||
return this
|
|
||||||
.accessKey(in.getAccessKey())
|
|
||||||
.secretKey(in.getSecretKey());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
|
||||||
@Override
|
|
||||||
protected ConcreteBuilder self() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final String accessKey;
|
|
||||||
private final String secretKey;
|
|
||||||
|
|
||||||
@ConstructorProperties({
|
|
||||||
"accessKey", "secretKey"
|
|
||||||
})
|
|
||||||
protected ApiAccessKeyCredentials(String accessKey, String secretKey) {
|
|
||||||
this.accessKey = checkNotNull(accessKey, "accessKey");
|
|
||||||
this.secretKey = checkNotNull(secretKey, "secretKey");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the accessKey
|
|
||||||
*/
|
|
||||||
public String getAccessKey() {
|
|
||||||
return this.accessKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the secretKey
|
|
||||||
*/
|
|
||||||
public String getSecretKey() {
|
|
||||||
return this.secretKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hashCode(accessKey, secretKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) return true;
|
|
||||||
if (obj == null || getClass() != obj.getClass()) return false;
|
|
||||||
ApiAccessKeyCredentials that = ApiAccessKeyCredentials.class.cast(obj);
|
|
||||||
return Objects.equal(this.accessKey, that.accessKey)
|
|
||||||
&& Objects.equal(this.secretKey, that.secretKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ToStringHelper string() {
|
|
||||||
return MoreObjects.toStringHelper(this)
|
|
||||||
.add("accessKey", accessKey).add("secretKey", secretKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return string().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -22,8 +22,8 @@ import java.net.URI;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.google.common.base.Objects;
|
|
||||||
import com.google.common.base.MoreObjects.ToStringHelper;
|
import com.google.common.base.MoreObjects.ToStringHelper;
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An network-accessible address, usually described by URL, where a service may
|
* An network-accessible address, usually described by URL, where a service may
|
||||||
|
|
|
@ -1,140 +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.keystone.v2_0.domain;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
import java.beans.ConstructorProperties;
|
|
||||||
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.CredentialType;
|
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
|
||||||
import com.google.common.base.Objects;
|
|
||||||
import com.google.common.base.MoreObjects.ToStringHelper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Password Credentials
|
|
||||||
*
|
|
||||||
* @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_authenticate_v2.0_tokens_Service_API_Api_Operations.html#d662e583"
|
|
||||||
/>
|
|
||||||
*/
|
|
||||||
@CredentialType("passwordCredentials")
|
|
||||||
public class PasswordCredentials {
|
|
||||||
|
|
||||||
public static Builder<?> builder() {
|
|
||||||
return new ConcreteBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<?> toBuilder() {
|
|
||||||
return new ConcreteBuilder().fromPasswordCredentials(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PasswordCredentials createWithUsernameAndPassword(String username, String password) {
|
|
||||||
return new PasswordCredentials(username, password);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract static class Builder<T extends Builder<T>> {
|
|
||||||
protected abstract T self();
|
|
||||||
|
|
||||||
protected String username;
|
|
||||||
protected String password;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see PasswordCredentials#getUsername()
|
|
||||||
*/
|
|
||||||
public T username(String username) {
|
|
||||||
this.username = username;
|
|
||||||
return self();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see PasswordCredentials#getPassword()
|
|
||||||
*/
|
|
||||||
public T password(String password) {
|
|
||||||
this.password = password;
|
|
||||||
return self();
|
|
||||||
}
|
|
||||||
|
|
||||||
public PasswordCredentials build() {
|
|
||||||
return new PasswordCredentials(username, password);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T fromPasswordCredentials(PasswordCredentials in) {
|
|
||||||
return this
|
|
||||||
.username(in.getUsername())
|
|
||||||
.password(in.getPassword());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
|
||||||
@Override
|
|
||||||
protected ConcreteBuilder self() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final String username;
|
|
||||||
private final String password;
|
|
||||||
|
|
||||||
@ConstructorProperties({
|
|
||||||
"username", "password"
|
|
||||||
})
|
|
||||||
protected PasswordCredentials(String username, String password) {
|
|
||||||
this.username = checkNotNull(username, "username");
|
|
||||||
this.password = checkNotNull(password, "password");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the username
|
|
||||||
*/
|
|
||||||
public String getUsername() {
|
|
||||||
return this.username;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the password
|
|
||||||
*/
|
|
||||||
public String getPassword() {
|
|
||||||
return this.password;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hashCode(username, password);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) return true;
|
|
||||||
if (obj == null || getClass() != obj.getClass()) return false;
|
|
||||||
PasswordCredentials that = PasswordCredentials.class.cast(obj);
|
|
||||||
return Objects.equal(this.username, that.username)
|
|
||||||
&& Objects.equal(this.password, that.password);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ToStringHelper string() {
|
|
||||||
return MoreObjects.toStringHelper(this)
|
|
||||||
.add("username", username)
|
|
||||||
.add("password", password == null ? null : "*****");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return string().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -30,8 +30,8 @@ import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
|
||||||
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
|
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
|
||||||
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Role;
|
import org.jclouds.openstack.keystone.v2_0.domain.Role;
|
||||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
|
||||||
import org.jclouds.openstack.v2_0.ServiceType;
|
import org.jclouds.openstack.v2_0.ServiceType;
|
||||||
import org.jclouds.openstack.v2_0.services.Extension;
|
import org.jclouds.openstack.v2_0.services.Extension;
|
||||||
import org.jclouds.rest.annotations.Fallback;
|
import org.jclouds.rest.annotations.Fallback;
|
||||||
|
|
|
@ -30,9 +30,9 @@ import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
|
||||||
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||||
import org.jclouds.collect.PagedIterable;
|
import org.jclouds.collect.PagedIterable;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
|
||||||
import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
|
import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Service;
|
import org.jclouds.openstack.keystone.v2_0.domain.Service;
|
||||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.functions.internal.ParseServices;
|
import org.jclouds.openstack.keystone.v2_0.functions.internal.ParseServices;
|
||||||
import org.jclouds.openstack.keystone.v2_0.functions.internal.ParseServices.ToPagedIterable;
|
import org.jclouds.openstack.keystone.v2_0.functions.internal.ParseServices.ToPagedIterable;
|
||||||
import org.jclouds.openstack.v2_0.ServiceType;
|
import org.jclouds.openstack.v2_0.ServiceType;
|
||||||
|
|
|
@ -28,8 +28,8 @@ import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
|
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
|
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
|
||||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.options.CreateTenantOptions;
|
import org.jclouds.openstack.keystone.v2_0.options.CreateTenantOptions;
|
||||||
import org.jclouds.openstack.keystone.v2_0.options.UpdateTenantOptions;
|
import org.jclouds.openstack.keystone.v2_0.options.UpdateTenantOptions;
|
||||||
import org.jclouds.openstack.v2_0.ServiceType;
|
import org.jclouds.openstack.v2_0.ServiceType;
|
||||||
|
|
|
@ -27,8 +27,8 @@ import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
|
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.User;
|
import org.jclouds.openstack.keystone.v2_0.domain.User;
|
||||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.options.CreateUserOptions;
|
import org.jclouds.openstack.keystone.v2_0.options.CreateUserOptions;
|
||||||
import org.jclouds.openstack.keystone.v2_0.options.UpdateUserOptions;
|
import org.jclouds.openstack.keystone.v2_0.options.UpdateUserOptions;
|
||||||
import org.jclouds.openstack.v2_0.ServiceType;
|
import org.jclouds.openstack.v2_0.ServiceType;
|
||||||
|
|
|
@ -25,8 +25,8 @@ import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
|
import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
|
||||||
|
import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
|
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
|
||||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
|
||||||
import org.jclouds.rest.annotations.Fallback;
|
import org.jclouds.rest.annotations.Fallback;
|
||||||
import org.jclouds.rest.annotations.RequestFilters;
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
import org.jclouds.rest.annotations.SelectJson;
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
|
|
@ -27,9 +27,9 @@ import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
|
||||||
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||||
import org.jclouds.collect.PagedIterable;
|
import org.jclouds.collect.PagedIterable;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
|
||||||
import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
|
import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
|
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
|
||||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.functions.internal.ParseTenants;
|
import org.jclouds.openstack.keystone.v2_0.functions.internal.ParseTenants;
|
||||||
import org.jclouds.openstack.keystone.v2_0.functions.internal.ParseTenants.ToPagedIterable;
|
import org.jclouds.openstack.keystone.v2_0.functions.internal.ParseTenants.ToPagedIterable;
|
||||||
import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
|
import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
|
||||||
|
|
|
@ -30,10 +30,10 @@ import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
|
||||||
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
|
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
|
||||||
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
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.Endpoint;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Token;
|
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.domain.User;
|
||||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
|
||||||
import org.jclouds.openstack.v2_0.services.Identity;
|
import org.jclouds.openstack.v2_0.services.Identity;
|
||||||
import org.jclouds.rest.annotations.Fallback;
|
import org.jclouds.rest.annotations.Fallback;
|
||||||
import org.jclouds.rest.annotations.RequestFilters;
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
|
|
|
@ -31,10 +31,10 @@ import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
|
||||||
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||||
import org.jclouds.collect.PagedIterable;
|
import org.jclouds.collect.PagedIterable;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
|
||||||
import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
|
import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Role;
|
import org.jclouds.openstack.keystone.v2_0.domain.Role;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.User;
|
import org.jclouds.openstack.keystone.v2_0.domain.User;
|
||||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.functions.internal.ParseUsers;
|
import org.jclouds.openstack.keystone.v2_0.functions.internal.ParseUsers;
|
||||||
import org.jclouds.openstack.keystone.v2_0.functions.internal.ParseUsers.ToPagedIterable;
|
import org.jclouds.openstack.keystone.v2_0.functions.internal.ParseUsers.ToPagedIterable;
|
||||||
import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
|
import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
* (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.AuthenticationApi;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.CredentialType;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.ApiAccessKeyCredentials;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.functions.internal.BaseAuthenticator;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
@CredentialType(CredentialTypes.API_ACCESS_KEY_CREDENTIALS)
|
|
||||||
@Singleton
|
|
||||||
public class AuthenticateApiAccessKeyCredentials extends BaseAuthenticator<ApiAccessKeyCredentials> {
|
|
||||||
protected final AuthenticationApi api;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public AuthenticateApiAccessKeyCredentials(AuthenticationApi api) {
|
|
||||||
this.api = api;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Access authenticateWithTenantName(Optional<String> tenantName, ApiAccessKeyCredentials apiAccessKeyCredentials) {
|
|
||||||
return api.authenticateWithTenantNameAndCredentials(tenantName.orNull(), apiAccessKeyCredentials);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Access authenticateWithTenantId(Optional<String> tenantId, ApiAccessKeyCredentials apiAccessKeyCredentials) {
|
|
||||||
return api.authenticateWithTenantIdAndCredentials(tenantId.orNull(), apiAccessKeyCredentials);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ApiAccessKeyCredentials createCredentials(String identity, String credential) {
|
|
||||||
return ApiAccessKeyCredentials.createWithAccessKeyAndSecretKey(identity, credential);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "authenticateApiAccessKeyCredentials()";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
* (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.AuthenticationApi;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.CredentialType;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.PasswordCredentials;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.functions.internal.BaseAuthenticator;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
|
|
||||||
@CredentialType(CredentialTypes.PASSWORD_CREDENTIALS)
|
|
||||||
@Singleton
|
|
||||||
public class AuthenticatePasswordCredentials extends BaseAuthenticator<PasswordCredentials> {
|
|
||||||
protected final AuthenticationApi api;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public AuthenticatePasswordCredentials(AuthenticationApi api) {
|
|
||||||
this.api = api;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Access authenticateWithTenantName(Optional<String> tenantName, PasswordCredentials apiAccessKeyCredentials) {
|
|
||||||
return api.authenticateWithTenantNameAndCredentials(tenantName.orNull(), apiAccessKeyCredentials);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Access authenticateWithTenantId(Optional<String> tenantId, PasswordCredentials apiAccessKeyCredentials) {
|
|
||||||
return api.authenticateWithTenantIdAndCredentials(tenantId.orNull(), apiAccessKeyCredentials);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PasswordCredentials createCredentials(String identity, String credential) {
|
|
||||||
return PasswordCredentials.createWithUsernameAndPassword(identity, credential);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "authenticatePasswordCredentials()";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,49 +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.keystone.v2_0.functions;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURISupplier;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.base.Supplier;
|
|
||||||
|
|
||||||
public final class RegionToAdminEndpointURI implements Function<Object, URI> {
|
|
||||||
|
|
||||||
private final RegionIdToAdminURISupplier regionToAdminEndpoints;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
RegionToAdminEndpointURI(RegionIdToAdminURISupplier regionToAdminEndpoints) {
|
|
||||||
this.regionToAdminEndpoints = regionToAdminEndpoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public URI apply(Object from) {
|
|
||||||
Map<String, Supplier<URI>> regionToAdminEndpoint = regionToAdminEndpoints.get();
|
|
||||||
checkState(!regionToAdminEndpoint.isEmpty(), "no region name to admin endpoint mappings in keystone!");
|
|
||||||
checkArgument(regionToAdminEndpoint.containsKey(from),
|
|
||||||
"requested location %s, which is not in the keystone admin endpoints: %s", from, regionToAdminEndpoint);
|
|
||||||
return regionToAdminEndpoint.get(from).get();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,208 +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.keystone.v2_0.suppliers;
|
|
||||||
|
|
||||||
import static com.google.common.collect.Iterables.any;
|
|
||||||
import static com.google.common.collect.Iterables.concat;
|
|
||||||
import static com.google.common.collect.Iterables.isEmpty;
|
|
||||||
import static com.google.common.collect.Iterables.tryFind;
|
|
||||||
import static com.google.common.collect.Multimaps.index;
|
|
||||||
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
|
||||||
import org.jclouds.logging.Logger;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Service;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.functions.EndpointToSupplierURI;
|
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
import com.google.common.base.Predicate;
|
|
||||||
import com.google.common.base.Supplier;
|
|
||||||
import com.google.common.collect.FluentIterable;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.ImmutableMap.Builder;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
import com.google.inject.assistedinject.Assisted;
|
|
||||||
|
|
||||||
public class LocationIdToURIFromAccessForTypeAndVersion implements Supplier<Map<String, Supplier<URI>>> {
|
|
||||||
|
|
||||||
public interface Factory {
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param apiType
|
|
||||||
* type of the api, according to the provider. ex.
|
|
||||||
* {@code compute} {@code object-store}
|
|
||||||
* @param apiVersion
|
|
||||||
* version of the api, or null if not available
|
|
||||||
* @return locations mapped to default uri
|
|
||||||
* @throws NoSuchElementException
|
|
||||||
* if the {@code apiType} is not present in the catalog
|
|
||||||
*/
|
|
||||||
LocationIdToURIFromAccessForTypeAndVersion createForApiTypeAndVersion(@Assisted("apiType") String apiType,
|
|
||||||
@Nullable @Assisted("apiVersion") String apiVersion) throws NoSuchElementException;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
protected Logger logger = Logger.NULL;
|
|
||||||
|
|
||||||
protected final Supplier<Access> access;
|
|
||||||
protected final EndpointToSupplierURI endpointToSupplierURI;
|
|
||||||
protected final Function<Endpoint, String> endpointToLocationId;
|
|
||||||
protected final String apiType;
|
|
||||||
protected final String apiVersion;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public LocationIdToURIFromAccessForTypeAndVersion(Supplier<Access> access,
|
|
||||||
EndpointToSupplierURI endpointToSupplierURI, Function<Endpoint, String> endpointToLocationId,
|
|
||||||
@Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
|
|
||||||
this.access = access;
|
|
||||||
this.endpointToSupplierURI = endpointToSupplierURI;
|
|
||||||
this.endpointToLocationId = endpointToLocationId;
|
|
||||||
this.apiType = apiType;
|
|
||||||
this.apiVersion = apiVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Supplier<URI>> get() {
|
|
||||||
FluentIterable<Service> services = FluentIterable.from(access.get()).filter(apiTypeEquals);
|
|
||||||
if (services.isEmpty())
|
|
||||||
throw new NoSuchElementException(String.format("apiType %s not found in catalog %s", apiType, services));
|
|
||||||
|
|
||||||
Iterable<Endpoint> endpoints = concat(services);
|
|
||||||
|
|
||||||
if (isEmpty(endpoints))
|
|
||||||
throw new NoSuchElementException(
|
|
||||||
String.format("no endpoints for apiType %s in services %s", apiType, services));
|
|
||||||
|
|
||||||
boolean checkVersionId = any(endpoints, versionAware);
|
|
||||||
|
|
||||||
Multimap<String, Endpoint> locationToEndpoints = index(endpoints, endpointToLocationId);
|
|
||||||
Map<String, Endpoint> locationToEndpoint;
|
|
||||||
if (checkVersionId && apiVersion != null) {
|
|
||||||
locationToEndpoint = refineToVersionSpecificEndpoint(locationToEndpoints);
|
|
||||||
if (locationToEndpoint.size() == 0)
|
|
||||||
throw new NoSuchElementException(String.format(
|
|
||||||
"no endpoints for apiType %s are of version %s, or version agnostic: %s", apiType, apiVersion,
|
|
||||||
locationToEndpoints));
|
|
||||||
} else {
|
|
||||||
locationToEndpoint = firstEndpointInLocation(locationToEndpoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug("endpoints for apiType %s and version %s: %s", apiType, apiVersion, locationToEndpoints);
|
|
||||||
return Maps.transformValues(locationToEndpoint, endpointToSupplierURI);
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
Map<String, Endpoint> firstEndpointInLocation(Multimap<String, Endpoint> locationToEndpoints) {
|
|
||||||
Builder<String, Endpoint> locationToEndpointBuilder = ImmutableMap.<String, Endpoint> builder();
|
|
||||||
for (Map.Entry<String, Collection<Endpoint>> entry : locationToEndpoints.asMap().entrySet()) {
|
|
||||||
String locationId = entry.getKey();
|
|
||||||
Collection<Endpoint> endpoints = entry.getValue();
|
|
||||||
switch (endpoints.size()) {
|
|
||||||
case 0:
|
|
||||||
logNoEndpointsInLocation(locationId);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
locationToEndpointBuilder.put(locationId, Iterables.get(endpoints, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return locationToEndpointBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
Map<String, Endpoint> refineToVersionSpecificEndpoint(Multimap<String, Endpoint> locationToEndpoints) {
|
|
||||||
Builder<String, Endpoint> locationToEndpointBuilder = ImmutableMap.<String, Endpoint> builder();
|
|
||||||
for (Map.Entry<String, Collection<Endpoint>> entry : locationToEndpoints.asMap().entrySet()) {
|
|
||||||
String locationId = entry.getKey();
|
|
||||||
Collection<Endpoint> endpoints = entry.getValue();
|
|
||||||
switch (endpoints.size()) {
|
|
||||||
case 0:
|
|
||||||
logNoEndpointsInLocation(locationId);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
putIfPresent(locationId, strictMatchEndpointVersion(endpoints, locationId), locationToEndpointBuilder);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return locationToEndpointBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prioritizes endpoint.versionId over endpoint.id when matching
|
|
||||||
*/
|
|
||||||
private Optional<Endpoint> strictMatchEndpointVersion(Iterable<Endpoint> endpoints, String locationId) {
|
|
||||||
Optional<Endpoint> endpointOfVersion = tryFind(endpoints, apiVersionEqualsVersionId);
|
|
||||||
if (!endpointOfVersion.isPresent())
|
|
||||||
logger.debug("no endpoints of apiType %s matched expected version %s in location %s: %s", apiType, apiVersion,
|
|
||||||
locationId, endpoints);
|
|
||||||
return endpointOfVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logNoEndpointsInLocation(String locationId) {
|
|
||||||
logger.debug("no endpoints found for apiType %s in location %s", apiType, locationId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Predicate<Endpoint> apiVersionEqualsVersionId = new Predicate<Endpoint>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Endpoint input) {
|
|
||||||
return input.getVersionId().equals(apiVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
private final Predicate<Endpoint> versionAware = new Predicate<Endpoint>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Endpoint input) {
|
|
||||||
return input.getVersionId() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
private final Predicate<Service> apiTypeEquals = new Predicate<Service>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Service input) {
|
|
||||||
return input.getType().equals(apiType);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
private static <K, V> void putIfPresent(K key, Optional<V> value, Builder<K, V> builder) {
|
|
||||||
if (value.isPresent())
|
|
||||||
builder.put(key, value.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "locationIdToURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +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.keystone.v2_0.suppliers;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
|
||||||
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;
|
|
||||||
|
|
||||||
public class RegionIdToAdminURIFromAccessForTypeAndVersion extends LocationIdToURIFromAccessForTypeAndVersion implements
|
|
||||||
RegionIdToAdminURISupplier {
|
|
||||||
@Inject
|
|
||||||
public RegionIdToAdminURIFromAccessForTypeAndVersion(Supplier<Access> access,
|
|
||||||
EndpointToSupplierAdminURI endpointToSupplierURI, EndpointToRegion endpointToRegion,
|
|
||||||
@Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
|
|
||||||
super(access, endpointToSupplierURI, endpointToRegion, apiType, apiVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "regionIdToAdminURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +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.keystone.v2_0.suppliers;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
|
||||||
import org.jclouds.location.suppliers.ZoneIdToURISupplier;
|
|
||||||
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.EndpointToSupplierURI;
|
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
|
||||||
import com.google.inject.assistedinject.Assisted;
|
|
||||||
|
|
||||||
public class ZoneIdToURIFromAccessForTypeAndVersion extends LocationIdToURIFromAccessForTypeAndVersion implements
|
|
||||||
ZoneIdToURISupplier {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public ZoneIdToURIFromAccessForTypeAndVersion(
|
|
||||||
Supplier<Access> access,
|
|
||||||
// NOTE that in some services, the region is in fact the zone. temporarily, we need
|
|
||||||
// to use the region field, in this case.
|
|
||||||
EndpointToSupplierURI endpointToSupplierURI, EndpointToRegion endpointToZone,
|
|
||||||
@Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
|
|
||||||
super(access, endpointToSupplierURI, endpointToZone, apiType, apiVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "zoneIdToURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* 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 java.io.Closeable;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.keystone.v3.features.AuthApi;
|
||||||
|
import org.jclouds.openstack.keystone.v3.features.CatalogApi;
|
||||||
|
import org.jclouds.openstack.keystone.v3.features.ProjectApi;
|
||||||
|
import org.jclouds.openstack.keystone.v3.features.RegionApi;
|
||||||
|
import org.jclouds.openstack.keystone.v3.features.UserApi;
|
||||||
|
import org.jclouds.rest.annotations.Delegate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to the OpenStack Identity (Keystone) REST API.
|
||||||
|
*/
|
||||||
|
public interface KeystoneApi extends Closeable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to authentication and token management features.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
AuthApi getAuthApi();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to service catalog features.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
CatalogApi getCatalogApi();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to region features.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
RegionApi getRegionApi();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to project features.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
ProjectApi getProjectApi();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to user features.
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
UserApi getUserApi();
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* 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.v3.config.KeystoneHttpApiModule;
|
||||||
|
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, "3");
|
||||||
|
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("${domain}:${userName} or ${userName}, if your keystone supports a default project")
|
||||||
|
.credentialName("${password}")
|
||||||
|
.endpointName("Keystone V3 base URL")
|
||||||
|
.documentation(URI.create("http://api.openstack.org/"))
|
||||||
|
.version("3")
|
||||||
|
.defaultEndpoint("http://localhost/identity/v3")
|
||||||
|
.defaultProperties(KeystoneApiMetadata.defaultProperties())
|
||||||
|
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
|
||||||
|
.add(AuthenticationModule.class)
|
||||||
|
.add(ServiceCatalogModule.class)
|
||||||
|
.add(KeystoneAdminURLModule.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.TenantOrDomainAndCredentials;
|
||||||
|
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.ParseTokenFromHttpResponse;
|
||||||
|
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(ParseTokenFromHttpResponse.class)
|
||||||
|
@MapBinder(BindPasswordAuthToJsonPayload.class)
|
||||||
|
@Override
|
||||||
|
Token authenticatePassword(TenantOrDomainAndCredentials<PasswordCredentials> credentials);
|
||||||
|
|
||||||
|
@Named("token:create")
|
||||||
|
@POST
|
||||||
|
@ResponseParser(ParseTokenFromHttpResponse.class)
|
||||||
|
@MapBinder(BindTokenAuthToJsonPayload.class)
|
||||||
|
@Override
|
||||||
|
Token authenticateToken(TenantOrDomainAndCredentials<TokenCredentials> credentials);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* 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 static org.jclouds.openstack.keystone.v3.domain.Auth.Scope.DOMAIN;
|
||||||
|
import static org.jclouds.openstack.keystone.v3.domain.Auth.Scope.DOMAIN_ID;
|
||||||
|
import static org.jclouds.openstack.keystone.v3.domain.Auth.Scope.PROJECT;
|
||||||
|
import static org.jclouds.openstack.keystone.v3.domain.Auth.Scope.PROJECT_ID;
|
||||||
|
import static org.jclouds.openstack.keystone.v3.domain.Auth.Scope.UNSCOPED;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.json.Json;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.TenantOrDomainAndCredentials;
|
||||||
|
import org.jclouds.openstack.keystone.v3.domain.Auth;
|
||||||
|
import org.jclouds.openstack.keystone.v3.domain.Auth.DomainIdScope;
|
||||||
|
import org.jclouds.openstack.keystone.v3.domain.Auth.DomainScope;
|
||||||
|
import org.jclouds.openstack.keystone.v3.domain.Auth.Id;
|
||||||
|
import org.jclouds.openstack.keystone.v3.domain.Auth.Name;
|
||||||
|
import org.jclouds.openstack.keystone.v3.domain.Auth.ProjectIdScope;
|
||||||
|
import org.jclouds.openstack.keystone.v3.domain.Auth.ProjectScope;
|
||||||
|
import org.jclouds.openstack.keystone.v3.domain.Auth.ProjectScope.ProjectName;
|
||||||
|
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;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
public abstract class BindAuthToJsonPayload<T> extends BindToJsonPayload implements MapBinder {
|
||||||
|
|
||||||
|
private static final Set<String> SCOPE_PREFIXES = ImmutableSet
|
||||||
|
.of(PROJECT, PROJECT_ID, DOMAIN, DOMAIN_ID);
|
||||||
|
|
||||||
|
protected BindAuthToJsonPayload(Json jsonBinder) {
|
||||||
|
super(jsonBinder);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Auth buildAuth(TenantOrDomainAndCredentials<T> credentials, Object scope);
|
||||||
|
|
||||||
|
@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(TenantOrDomainAndCredentials.class));
|
||||||
|
checkArgument(authentication.isPresent(), "no credentials found in the api call arguments");
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
TenantOrDomainAndCredentials<T> credentials = (TenantOrDomainAndCredentials<T>) authentication.get();
|
||||||
|
Object scope = parseScope(credentials);
|
||||||
|
Auth auth = buildAuth(credentials, scope);
|
||||||
|
|
||||||
|
R authRequest = super.bindToRequest(request, ImmutableMap.of("auth", auth));
|
||||||
|
authRequest.getPayload().setSensitive(true);
|
||||||
|
|
||||||
|
return authRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object parseScope(TenantOrDomainAndCredentials<T> credentials) {
|
||||||
|
String scope = credentials.scope();
|
||||||
|
// If there is no prefix, assume an unscoped authentication
|
||||||
|
if (!scope.contains(":")) {
|
||||||
|
checkArgument(scope.equals(UNSCOPED), "Invalid scope: %s", scope);
|
||||||
|
return UNSCOPED;
|
||||||
|
}
|
||||||
|
// Otherwise, parse if it is a project or domain scope
|
||||||
|
String[] parts = scope.split(":");
|
||||||
|
checkArgument(parts.length == 2, "Invalid scope: %s", scope);
|
||||||
|
checkArgument(SCOPE_PREFIXES.contains(parts[0]), "Scope prefix should be: %s", SCOPE_PREFIXES);
|
||||||
|
|
||||||
|
if (PROJECT.equals(parts[0])) {
|
||||||
|
Object domainScope = credentials.tenantOrDomainId() != null ? Id.create(credentials.tenantOrDomainId()) : Name
|
||||||
|
.create(credentials.tenantOrDomainName());
|
||||||
|
return ProjectScope.create(ProjectName.create(parts[1], domainScope));
|
||||||
|
} else if (PROJECT_ID.equals(parts[0])) {
|
||||||
|
return ProjectIdScope.create(Id.create(parts[1]));
|
||||||
|
} else if (DOMAIN.equals(parts[0])) {
|
||||||
|
return DomainScope.create(Name.create(parts[1]));
|
||||||
|
} else {
|
||||||
|
return DomainIdScope.create(Id.create(parts[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.TenantOrDomainAndCredentials;
|
||||||
|
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(TenantOrDomainAndCredentials<PasswordCredentials> credentials, Object scope) {
|
||||||
|
PasswordCredentials creds = credentials.credentials();
|
||||||
|
DomainAuth domain = DomainAuth.create(credentials.tenantOrDomainName());
|
||||||
|
UserAuth user = UserAuth.create(creds.username(), domain, creds.password());
|
||||||
|
|
||||||
|
return Auth.create(Identity.create(singletonList("password"), null, PasswordAuth.create(user)), scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.TenantOrDomainAndCredentials;
|
||||||
|
import org.jclouds.openstack.keystone.auth.domain.TokenCredentials;
|
||||||
|
import org.jclouds.openstack.keystone.v3.domain.Auth;
|
||||||
|
import org.jclouds.openstack.keystone.v3.domain.Auth.Id;
|
||||||
|
import org.jclouds.openstack.keystone.v3.domain.Auth.Identity;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class BindTokenAuthToJsonPayload extends BindAuthToJsonPayload<TokenCredentials> {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
BindTokenAuthToJsonPayload(Json jsonBinder) {
|
||||||
|
super(jsonBinder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Auth buildAuth(TenantOrDomainAndCredentials<TokenCredentials> credentials, Object scope) {
|
||||||
|
Id token = Id.create(credentials.credentials().id());
|
||||||
|
return Auth.create(Identity.create(singletonList("token"), token, null), scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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.config;
|
||||||
|
|
||||||
|
import org.jclouds.json.config.GsonModule;
|
||||||
|
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||||
|
import org.jclouds.openstack.keystone.v3.KeystoneApi;
|
||||||
|
import org.jclouds.rest.ConfiguresHttpApi;
|
||||||
|
import org.jclouds.rest.config.HttpApiModule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the Keystone API.
|
||||||
|
*/
|
||||||
|
@ConfiguresHttpApi
|
||||||
|
public class KeystoneHttpApiModule extends HttpApiModule<KeystoneApi> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
super.configure();
|
||||||
|
bind(DateAdapter.class).to(GsonModule.Iso8601DateAdapter.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
* 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();
|
||||||
|
@Nullable public abstract Object scope();
|
||||||
|
|
||||||
|
@SerializedNames({ "identity", "scope" })
|
||||||
|
public static Auth create(Identity identity, Object scope) {
|
||||||
|
return new AutoValue_Auth(identity, scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue
|
||||||
|
public abstract static class Identity {
|
||||||
|
public abstract List<String> methods();
|
||||||
|
@Nullable public abstract Id token();
|
||||||
|
@Nullable public abstract PasswordAuth password();
|
||||||
|
|
||||||
|
@SerializedNames({ "methods", "token", "password" })
|
||||||
|
public static Identity create(List<String> methods, Id token, PasswordAuth password) {
|
||||||
|
return new AutoValue_Auth_Identity(methods, token, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue
|
||||||
|
public abstract static class Id {
|
||||||
|
public abstract String id();
|
||||||
|
|
||||||
|
@SerializedNames({ "id" })
|
||||||
|
public static Id create(String id) {
|
||||||
|
return new AutoValue_Auth_Id(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue
|
||||||
|
public abstract static class Name {
|
||||||
|
@Nullable public abstract String name();
|
||||||
|
|
||||||
|
@SerializedNames({ "name" })
|
||||||
|
public static Name create(String name) {
|
||||||
|
return new AutoValue_Auth_Name(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Scope {
|
||||||
|
public static final String PROJECT = "project";
|
||||||
|
public static final String PROJECT_ID = "projectId";
|
||||||
|
public static final String DOMAIN = "domain";
|
||||||
|
public static final String DOMAIN_ID = "domainId";
|
||||||
|
public static final String UNSCOPED = "unscoped";
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue
|
||||||
|
public abstract static class ProjectScope {
|
||||||
|
public abstract ProjectName project();
|
||||||
|
|
||||||
|
@SerializedNames({ Scope.PROJECT })
|
||||||
|
public static ProjectScope create(ProjectName project) {
|
||||||
|
return new AutoValue_Auth_ProjectScope(project);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue
|
||||||
|
public abstract static class ProjectName {
|
||||||
|
public abstract String name();
|
||||||
|
@Nullable public abstract Object domain();
|
||||||
|
|
||||||
|
@SerializedNames({ "name", Scope.DOMAIN })
|
||||||
|
public static ProjectName create(String name, Object domain) {
|
||||||
|
return new AutoValue_Auth_ProjectScope_ProjectName(name, domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProjectName create(String name, Name domain) {
|
||||||
|
return new AutoValue_Auth_ProjectScope_ProjectName(name, domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProjectName create(String name, Id domain) {
|
||||||
|
return new AutoValue_Auth_ProjectScope_ProjectName(name, domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue
|
||||||
|
public abstract static class ProjectIdScope {
|
||||||
|
public abstract Id project();
|
||||||
|
|
||||||
|
@SerializedNames({ Scope.PROJECT })
|
||||||
|
public static ProjectIdScope create(Id id) {
|
||||||
|
return new AutoValue_Auth_ProjectIdScope(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue
|
||||||
|
public abstract static class DomainIdScope {
|
||||||
|
public abstract Id domain();
|
||||||
|
|
||||||
|
@SerializedNames({ Scope.DOMAIN })
|
||||||
|
public static DomainIdScope create(Id id) {
|
||||||
|
return new AutoValue_Auth_DomainIdScope(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue
|
||||||
|
public abstract static class DomainScope {
|
||||||
|
public abstract Name domain();
|
||||||
|
|
||||||
|
@SerializedNames({ Scope.DOMAIN })
|
||||||
|
public static DomainScope create(Name name) {
|
||||||
|
return new AutoValue_Auth_DomainScope(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.domain;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
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();
|
||||||
|
@Nullable 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 builder().id(id).name(name).type(type).endpoints(endpoints).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
Catalog() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Builder toBuilder();
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new AutoValue_Catalog.Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue.Builder
|
||||||
|
public abstract static class Builder {
|
||||||
|
public abstract Builder id(String id);
|
||||||
|
public abstract Builder name(String name);
|
||||||
|
public abstract Builder type(String type);
|
||||||
|
public abstract Builder endpoints(List<Endpoint> endpoints);
|
||||||
|
|
||||||
|
abstract List<Endpoint> endpoints();
|
||||||
|
abstract Catalog autoBuild();
|
||||||
|
|
||||||
|
public Catalog build() {
|
||||||
|
endpoints(endpoints() == null ? ImmutableList.<Endpoint> of() : ImmutableList.copyOf(endpoints()));
|
||||||
|
return autoBuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.domain;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
import org.jclouds.json.SerializedNames;
|
||||||
|
|
||||||
|
import com.google.auto.value.AutoValue;
|
||||||
|
|
||||||
|
@AutoValue
|
||||||
|
public abstract class Endpoint {
|
||||||
|
|
||||||
|
@Nullable public abstract String id();
|
||||||
|
@Nullable public abstract String region();
|
||||||
|
@Nullable public abstract String regionId();
|
||||||
|
@Nullable public abstract String serviceId();
|
||||||
|
public abstract URI url();
|
||||||
|
@Nullable public abstract Boolean enabled();
|
||||||
|
public abstract String iface();
|
||||||
|
|
||||||
|
@SerializedNames({ "id", "region", "region_id", "service_id", "url", "enabled", "interface" })
|
||||||
|
public static Endpoint create(String id, String region, String regionId, String serviceId, URI url, Boolean enabled,
|
||||||
|
String iface) {
|
||||||
|
return builder().id(serviceId).region(region).regionId(regionId).serviceId(serviceId).url(url).enabled(enabled)
|
||||||
|
.iface(iface).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
Endpoint() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Builder toBuilder();
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new AutoValue_Endpoint.Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue.Builder
|
||||||
|
public abstract static class Builder {
|
||||||
|
public abstract Builder id(String id);
|
||||||
|
public abstract Builder region(String region);
|
||||||
|
public abstract Builder regionId(String regionId);
|
||||||
|
public abstract Builder serviceId(String serviceId);
|
||||||
|
public abstract Builder url(URI url);
|
||||||
|
public abstract Builder enabled(Boolean enabled);
|
||||||
|
public abstract Builder iface(String iface);
|
||||||
|
public abstract Endpoint build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* 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 Group {
|
||||||
|
|
||||||
|
public abstract String id();
|
||||||
|
public abstract String name();
|
||||||
|
@Nullable public abstract String description();
|
||||||
|
@Nullable public abstract String domainId();
|
||||||
|
@Nullable public abstract Link link();
|
||||||
|
|
||||||
|
@SerializedNames({ "id", "name", "description", "domain_id", "links" })
|
||||||
|
public static Group create(String id, String name, String description, String domainId, Link link) {
|
||||||
|
return builder().id(id).name(name).description(description).domainId(domainId).link(link).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
Group() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Builder toBuilder();
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new AutoValue_Group.Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue.Builder
|
||||||
|
public abstract static class Builder {
|
||||||
|
public abstract Builder id(String id);
|
||||||
|
public abstract Builder name(String String);
|
||||||
|
public abstract Builder description(String description);
|
||||||
|
public abstract Builder domainId(String domainId);
|
||||||
|
public abstract Builder link(Link link);
|
||||||
|
public abstract Group build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
@AutoValue
|
||||||
|
public abstract class Project {
|
||||||
|
|
||||||
|
public abstract boolean isDomain();
|
||||||
|
@Nullable public abstract String description();
|
||||||
|
@Nullable public abstract String domainId();
|
||||||
|
@Nullable public abstract String domainName();
|
||||||
|
public abstract boolean enabled();
|
||||||
|
@Nullable public abstract String id();
|
||||||
|
public abstract String name();
|
||||||
|
@Nullable public abstract String parentId();
|
||||||
|
@Nullable public abstract List<String> tags();
|
||||||
|
@Nullable public abstract Link link();
|
||||||
|
|
||||||
|
@SerializedNames({ "is_domain", "description", "domain_id", "domain_name", "enabled", "id", "name", "parent_id",
|
||||||
|
"tags", "links" })
|
||||||
|
public static Project create(boolean isDomain, String description, String domainId, String domainName,
|
||||||
|
boolean enabled, String id, String name, String parentId, List<String> tags, Link link) {
|
||||||
|
return builder().isDomain(isDomain).description(description).domainId(domainId).domainName(domainName)
|
||||||
|
.enabled(enabled).id(id).name(name).parentId(parentId).tags(tags).link(link).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
Project() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Builder toBuilder();
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new AutoValue_Project.Builder().isDomain(false).enabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue.Builder
|
||||||
|
public abstract static class Builder {
|
||||||
|
public abstract Builder isDomain(boolean isDomain);
|
||||||
|
public abstract Builder description(String description);
|
||||||
|
public abstract Builder domainId(String domainId);
|
||||||
|
public abstract Builder domainName(String domainName);
|
||||||
|
public abstract Builder enabled(boolean enabled);
|
||||||
|
public abstract Builder id(String id);
|
||||||
|
public abstract Builder name(String name);
|
||||||
|
public abstract Builder parentId(String parentId);
|
||||||
|
public abstract Builder tags(List<String> tags);
|
||||||
|
public abstract Builder link(Link link);
|
||||||
|
|
||||||
|
abstract List<String> tags();
|
||||||
|
abstract Project autoBuild();
|
||||||
|
|
||||||
|
public Project build() {
|
||||||
|
tags(tags() == null ? null : ImmutableList.copyOf(tags()));
|
||||||
|
return autoBuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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 description();
|
||||||
|
@Nullable public abstract Link link();
|
||||||
|
@Nullable public abstract String parentRegionId();
|
||||||
|
|
||||||
|
@SerializedNames({ "id", "description", "links", "parent_region_id" })
|
||||||
|
public static Region create(String id, String description, Link link, String parentRegionId) {
|
||||||
|
return builder().id(id).description(description).link(link).parentRegionId(parentRegionId).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
Region() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Builder toBuilder();
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new AutoValue_Region.Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue.Builder
|
||||||
|
public abstract static class Builder {
|
||||||
|
public abstract Builder id(String id);
|
||||||
|
public abstract Builder description(String name);
|
||||||
|
public abstract Builder link(Link link);
|
||||||
|
public abstract Builder parentRegionId(String parentRegionId);
|
||||||
|
public abstract Region build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* 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();
|
||||||
|
@Nullable 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
Token() {
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* 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();
|
||||||
|
@Nullable public abstract Domain domain();
|
||||||
|
@Nullable public abstract String domainId();
|
||||||
|
@Nullable public abstract String defaultProjectId();
|
||||||
|
@Nullable public abstract Boolean enabled();
|
||||||
|
@Nullable public abstract Link link();
|
||||||
|
|
||||||
|
@SerializedNames({ "id", "name", "password_expires_at", "domain", "domain_id", "default_project_id", "enabled", "links" })
|
||||||
|
public static User create(String id, String name, Date passwordExpiresAt, Domain domain, String domainId,
|
||||||
|
String defaultProjectId, Boolean enabled, Link link) {
|
||||||
|
return builder().id(id).name(name).passwordExpiresAt(passwordExpiresAt).domain(domain).domainId(domainId)
|
||||||
|
.defaultProjectId(defaultProjectId).enabled(enabled).link(link).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
User() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Builder toBuilder();
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new AutoValue_User.Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue.Builder
|
||||||
|
public abstract static class Builder {
|
||||||
|
public abstract Builder id(String id);
|
||||||
|
public abstract Builder name(String name);
|
||||||
|
public abstract Builder passwordExpiresAt(Date passwordExpiresAt);
|
||||||
|
public abstract Builder domain(Domain domain);
|
||||||
|
public abstract Builder domainId(String domainId);
|
||||||
|
public abstract Builder defaultProjectId(String defaultProjectId);
|
||||||
|
public abstract Builder enabled(Boolean enabled);
|
||||||
|
public abstract Builder link(Link link);
|
||||||
|
public abstract User build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* 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 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.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.v3.domain.Token;
|
||||||
|
import org.jclouds.openstack.keystone.v3.domain.User;
|
||||||
|
import org.jclouds.openstack.v2_0.services.Identity;
|
||||||
|
import org.jclouds.rest.annotations.Endpoint;
|
||||||
|
import org.jclouds.rest.annotations.Fallback;
|
||||||
|
import org.jclouds.rest.annotations.Headers;
|
||||||
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to the Keystone Authentication API.
|
||||||
|
*/
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@RequestFilters(AuthenticateRequest.class)
|
||||||
|
@Endpoint(Identity.class)
|
||||||
|
@Path("/auth")
|
||||||
|
public interface AuthApi {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate a token and, if it is valid, return access information regarding the tenant (though not the service catalog).
|
||||||
|
*/
|
||||||
|
@Named("token:get")
|
||||||
|
@GET
|
||||||
|
@SelectJson("token")
|
||||||
|
@Path("/tokens")
|
||||||
|
@Fallback(NullOnNotFoundOr404.class)
|
||||||
|
@Nullable
|
||||||
|
@Headers(keys = "X-Subject-Token", values = "{token}")
|
||||||
|
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).
|
||||||
|
*/
|
||||||
|
@Named("token:getuser")
|
||||||
|
@GET
|
||||||
|
@SelectJson("user")
|
||||||
|
@Path("/tokens")
|
||||||
|
@Fallback(NullOnNotFoundOr404.class)
|
||||||
|
@Nullable
|
||||||
|
@Headers(keys = "X-Subject-Token", values = "{token}")
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
@Named("token:check")
|
||||||
|
@HEAD
|
||||||
|
@Path("/tokens")
|
||||||
|
@Headers(keys = "X-Subject-Token", values = "{token}")
|
||||||
|
@Fallback(FalseOnNotFoundOr404.class)
|
||||||
|
boolean isValid(@PathParam("token") String token);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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 javax.inject.Named;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
|
||||||
|
import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
|
||||||
|
import org.jclouds.openstack.keystone.v3.domain.Endpoint;
|
||||||
|
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)
|
||||||
|
@org.jclouds.rest.annotations.Endpoint(Identity.class)
|
||||||
|
public interface CatalogApi {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List all endpoints for a token.
|
||||||
|
* <p>
|
||||||
|
* NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/988672 )
|
||||||
|
*/
|
||||||
|
@Named("endpoints:list")
|
||||||
|
@GET
|
||||||
|
@SelectJson("endpoints")
|
||||||
|
@Path("/endpoints")
|
||||||
|
@Fallback(EmptyListOnNotFoundOr404.class)
|
||||||
|
List<Endpoint> endpoints();
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
* 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.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.HEAD;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
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.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.v3.domain.Project;
|
||||||
|
import org.jclouds.openstack.v2_0.services.Identity;
|
||||||
|
import org.jclouds.rest.annotations.Endpoint;
|
||||||
|
import org.jclouds.rest.annotations.Fallback;
|
||||||
|
import org.jclouds.rest.annotations.MapBinder;
|
||||||
|
import org.jclouds.rest.annotations.PATCH;
|
||||||
|
import org.jclouds.rest.annotations.PayloadParam;
|
||||||
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
import org.jclouds.rest.annotations.WrapWith;
|
||||||
|
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to the Keystone Projects API.
|
||||||
|
*/
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@RequestFilters(AuthenticateRequest.class)
|
||||||
|
@Endpoint(Identity.class)
|
||||||
|
@Path("/projects")
|
||||||
|
public interface ProjectApi {
|
||||||
|
|
||||||
|
@Named("projects:list")
|
||||||
|
@GET
|
||||||
|
@SelectJson("projects")
|
||||||
|
@Fallback(EmptyListOnNotFoundOr404.class)
|
||||||
|
List<Project> list();
|
||||||
|
|
||||||
|
@Named("projects:get")
|
||||||
|
@GET
|
||||||
|
@Path("/{id}")
|
||||||
|
@SelectJson("project")
|
||||||
|
@Fallback(NullOnNotFoundOr404.class)
|
||||||
|
Project get(@PathParam("id") String id);
|
||||||
|
|
||||||
|
@Named("projects:create")
|
||||||
|
@POST
|
||||||
|
@SelectJson("project")
|
||||||
|
@WrapWith("project")
|
||||||
|
Project create(@PayloadParam("name") String name, @Nullable @PayloadParam("description") String description,
|
||||||
|
@PayloadParam("enabled") boolean enabled, @PayloadParam("is_domain") boolean isDomain,
|
||||||
|
@Nullable @PayloadParam("domain_id") String domainId, @Nullable @PayloadParam("parent_id") String parentId);
|
||||||
|
|
||||||
|
@Named("projects:update")
|
||||||
|
@PATCH
|
||||||
|
@Path("/{id}")
|
||||||
|
@SelectJson("project")
|
||||||
|
Project update(@PathParam("id") String id, @WrapWith("project") Project project);
|
||||||
|
|
||||||
|
@Named("projects:delete")
|
||||||
|
@DELETE
|
||||||
|
@Path("/{id}")
|
||||||
|
@Fallback(FalseOnNotFoundOr404.class)
|
||||||
|
boolean delete(@PathParam("id") String id);
|
||||||
|
|
||||||
|
@Named("projects:listTags")
|
||||||
|
@GET
|
||||||
|
@Path("/{projectId}/tags")
|
||||||
|
@SelectJson("tags")
|
||||||
|
Set<String> listTags(@PathParam("projectId") String projectId);
|
||||||
|
|
||||||
|
@Named("projects:hasTag")
|
||||||
|
@HEAD
|
||||||
|
@Path("/{projectId}/tags/{tag}")
|
||||||
|
@Fallback(FalseOnNotFoundOr404.class)
|
||||||
|
boolean hasTag(@PathParam("projectId") String projectId, @PathParam("tag") String tag);
|
||||||
|
|
||||||
|
@Named("projects:addTag")
|
||||||
|
@PUT
|
||||||
|
@Path("/{projectId}/tags/{tag}")
|
||||||
|
void addTag(@PathParam("projectId") String projectId, @PathParam("tag") String tag);
|
||||||
|
|
||||||
|
@Named("projects:removeTag")
|
||||||
|
@DELETE
|
||||||
|
@Path("/{projectId}/tags/{tag}")
|
||||||
|
void removeTag(@PathParam("projectId") String projectId, @PathParam("tag") String tag);
|
||||||
|
|
||||||
|
@Named("projects:setTags")
|
||||||
|
@PUT
|
||||||
|
@Path("/{projectId}/tags")
|
||||||
|
@MapBinder(BindToJsonPayload.class)
|
||||||
|
void setTags(@PathParam("projectId") String projectId, @PayloadParam("tags") Set<String> tags);
|
||||||
|
|
||||||
|
@Named("projects:removeTags")
|
||||||
|
@DELETE
|
||||||
|
@Path("/{projectId}/tags")
|
||||||
|
void removeAllTags(@PathParam("projectId") String projectId);
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* 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 javax.inject.Named;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
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.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.v3.domain.Region;
|
||||||
|
import org.jclouds.openstack.v2_0.services.Identity;
|
||||||
|
import org.jclouds.rest.annotations.Endpoint;
|
||||||
|
import org.jclouds.rest.annotations.Fallback;
|
||||||
|
import org.jclouds.rest.annotations.PATCH;
|
||||||
|
import org.jclouds.rest.annotations.PayloadParam;
|
||||||
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
import org.jclouds.rest.annotations.WrapWith;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to the Keystone Region API.
|
||||||
|
*/
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@RequestFilters(AuthenticateRequest.class)
|
||||||
|
@Endpoint(Identity.class)
|
||||||
|
@Path("/regions")
|
||||||
|
public interface RegionApi {
|
||||||
|
|
||||||
|
@Named("regions:list")
|
||||||
|
@GET
|
||||||
|
@SelectJson("regions")
|
||||||
|
@Fallback(EmptyListOnNotFoundOr404.class)
|
||||||
|
List<Region> list();
|
||||||
|
|
||||||
|
@Named("regions:get")
|
||||||
|
@GET
|
||||||
|
@Path("/{id}")
|
||||||
|
@SelectJson("region")
|
||||||
|
@Fallback(NullOnNotFoundOr404.class)
|
||||||
|
Region get(@PathParam("id") String id);
|
||||||
|
|
||||||
|
@Named("regions:create")
|
||||||
|
@POST
|
||||||
|
@SelectJson("region")
|
||||||
|
@WrapWith("region")
|
||||||
|
Region create(@PayloadParam("id") String id, @Nullable @PayloadParam("description") String description,
|
||||||
|
@Nullable @PayloadParam("parent_region_id") String parentId);
|
||||||
|
|
||||||
|
@Named("regions:update")
|
||||||
|
@PATCH
|
||||||
|
@Path("/{id}")
|
||||||
|
@SelectJson("region")
|
||||||
|
@WrapWith("region")
|
||||||
|
Region update(@PathParam("id") String id, @Nullable @PayloadParam("description") String description,
|
||||||
|
@Nullable @PayloadParam("parent_region_id") String parentId);
|
||||||
|
|
||||||
|
@Named("regions:delete")
|
||||||
|
@DELETE
|
||||||
|
@Path("/{id}")
|
||||||
|
@Fallback(FalseOnNotFoundOr404.class)
|
||||||
|
boolean delete(@PathParam("id") String id);
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* 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 javax.inject.Named;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
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.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.v3.domain.Group;
|
||||||
|
import org.jclouds.openstack.keystone.v3.domain.Project;
|
||||||
|
import org.jclouds.openstack.keystone.v3.domain.User;
|
||||||
|
import org.jclouds.openstack.v2_0.services.Identity;
|
||||||
|
import org.jclouds.rest.annotations.Endpoint;
|
||||||
|
import org.jclouds.rest.annotations.Fallback;
|
||||||
|
import org.jclouds.rest.annotations.PATCH;
|
||||||
|
import org.jclouds.rest.annotations.PayloadParam;
|
||||||
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
import org.jclouds.rest.annotations.WrapWith;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to the Keystone User API.
|
||||||
|
*/
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@RequestFilters(AuthenticateRequest.class)
|
||||||
|
@Endpoint(Identity.class)
|
||||||
|
@Path("/users")
|
||||||
|
public interface UserApi {
|
||||||
|
|
||||||
|
@Named("users:list")
|
||||||
|
@GET
|
||||||
|
@SelectJson("users")
|
||||||
|
@Fallback(EmptyListOnNotFoundOr404.class)
|
||||||
|
List<User> list();
|
||||||
|
|
||||||
|
@Named("users:get")
|
||||||
|
@GET
|
||||||
|
@Path("/{id}")
|
||||||
|
@SelectJson("user")
|
||||||
|
@Fallback(NullOnNotFoundOr404.class)
|
||||||
|
User get(@PathParam("id") String id);
|
||||||
|
|
||||||
|
@Named("users:create")
|
||||||
|
@POST
|
||||||
|
@SelectJson("user")
|
||||||
|
@WrapWith("user")
|
||||||
|
User create(@PayloadParam("name") String name, @Nullable @PayloadParam("password") String password,
|
||||||
|
@Nullable @PayloadParam("enabled") Boolean enabled, @Nullable @PayloadParam("domain_id") String domainId,
|
||||||
|
@Nullable @PayloadParam("default_project_id") String defaultProjectId);
|
||||||
|
|
||||||
|
@Named("users:update")
|
||||||
|
@PATCH
|
||||||
|
@Path("/{id}")
|
||||||
|
@SelectJson("user")
|
||||||
|
@WrapWith("user")
|
||||||
|
User update(@PathParam("id") String id, @PayloadParam("name") String name,
|
||||||
|
@Nullable @PayloadParam("password") String password, @Nullable @PayloadParam("enabled") Boolean enabled,
|
||||||
|
@Nullable @PayloadParam("domain_id") String domainId,
|
||||||
|
@Nullable @PayloadParam("default_project_id") String defaultProjectId);
|
||||||
|
|
||||||
|
@Named("users:delete")
|
||||||
|
@DELETE
|
||||||
|
@Path("/{id}")
|
||||||
|
@Fallback(FalseOnNotFoundOr404.class)
|
||||||
|
boolean delete(@PathParam("id") String id);
|
||||||
|
|
||||||
|
@Named("users:groups")
|
||||||
|
@GET
|
||||||
|
@Path("/{id}/groups")
|
||||||
|
@SelectJson("groups")
|
||||||
|
List<Group> listGroups(@PathParam("id") String id);
|
||||||
|
|
||||||
|
@Named("users:projects")
|
||||||
|
@GET
|
||||||
|
@Path("/{id}/projects")
|
||||||
|
@SelectJson("projects")
|
||||||
|
List<Project> listProjects(@PathParam("id") String id);
|
||||||
|
|
||||||
|
@Named("users:password")
|
||||||
|
@POST
|
||||||
|
@Path("/{id}/password")
|
||||||
|
@WrapWith("user")
|
||||||
|
void changePassword(@PathParam("id") String id, @PayloadParam("original_password") String originalPassword,
|
||||||
|
@PayloadParam("password") String newPassword);
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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 static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
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.base.Function;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ParseTokenFromHttpResponse implements Function<HttpResponse, Token> {
|
||||||
|
private final ParseFirstJsonValueNamed<Token> parser;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseTokenFromHttpResponse(GsonWrapper gsonView) {
|
||||||
|
this.parser = new ParseFirstJsonValueNamed<Token>(gsonView, TypeLiteral.get(Token.class), "token");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Token apply(HttpResponse response) {
|
||||||
|
checkNotNull(response, "response");
|
||||||
|
Token toParse = parser.apply(response);
|
||||||
|
checkNotNull(toParse, "parsed result from %s", response);
|
||||||
|
String xSubjectToken = response.getFirstHeaderOrNull("X-Subject-Token");
|
||||||
|
return toParse.toBuilder().id(xSubjectToken).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -28,7 +28,7 @@ import javax.ws.rs.core.MediaType;
|
||||||
import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
|
import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
|
||||||
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
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.openstack.v2_0.domain.Extension;
|
||||||
import org.jclouds.rest.annotations.Fallback;
|
import org.jclouds.rest.annotations.Fallback;
|
||||||
import org.jclouds.rest.annotations.RequestFilters;
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
|
|
|
@ -14,11 +14,11 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.config;
|
package org.jclouds.openstack.keystone.auth.config;
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.PasswordCredentials;
|
import org.jclouds.openstack.keystone.auth.domain.PasswordCredentials;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
@ -27,8 +27,9 @@ import com.google.common.collect.ImmutableSet;
|
||||||
public class CredentialTypesTest {
|
public class CredentialTypesTest {
|
||||||
|
|
||||||
public void testCredentialTypeOfWhenValid() {
|
public void testCredentialTypeOfWhenValid() {
|
||||||
assertEquals(CredentialTypes.credentialTypeOf(PasswordCredentials.createWithUsernameAndPassword("username",
|
assertEquals(
|
||||||
"password")), CredentialTypes.PASSWORD_CREDENTIALS);
|
CredentialTypes.credentialTypeOf(PasswordCredentials.builder().username("username").password("password")
|
||||||
|
.build()), CredentialTypes.PASSWORD_CREDENTIALS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
|
@ -37,9 +38,10 @@ public class CredentialTypesTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIndexByCredentialTypeWhenValid() {
|
public void testIndexByCredentialTypeWhenValid() {
|
||||||
assertEquals(CredentialTypes.indexByCredentialType(
|
assertEquals(
|
||||||
ImmutableSet.of(PasswordCredentials.createWithUsernameAndPassword("username", "password"))).keySet(),
|
CredentialTypes.indexByCredentialType(
|
||||||
ImmutableSet.of(CredentialTypes.PASSWORD_CREDENTIALS));
|
ImmutableSet.of(PasswordCredentials.builder().username("username").password("password").build()))
|
||||||
|
.keySet(), ImmutableSet.of(CredentialTypes.PASSWORD_CREDENTIALS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
|
@ -14,12 +14,13 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.config;
|
package org.jclouds.openstack.keystone.auth.config;
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.METHOD;
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
|
import static org.jclouds.openstack.keystone.config.KeystoneProperties.CREDENTIAL_TYPE;
|
||||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_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.jclouds.util.Suppliers2.getLastValueInMap;
|
||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
@ -42,8 +43,10 @@ import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.json.config.GsonModule.DateAdapter;
|
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||||
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
||||||
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
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.KeystoneApi;
|
||||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.RegionModule;
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneRestApiExpectTest;
|
import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneRestApiExpectTest;
|
||||||
import org.jclouds.rest.ConfiguresHttpApi;
|
import org.jclouds.rest.ConfiguresHttpApi;
|
||||||
import org.jclouds.rest.annotations.ApiVersion;
|
import org.jclouds.rest.annotations.ApiVersion;
|
||||||
|
@ -124,6 +127,7 @@ public class ProviderModuleExpectTest extends BaseRestApiExpectTest<ProviderModu
|
||||||
public static Properties defaultProperties() {
|
public static Properties defaultProperties() {
|
||||||
Properties properties = BaseHttpApiMetadata.defaultProperties();
|
Properties properties = BaseHttpApiMetadata.defaultProperties();
|
||||||
properties.setProperty(SERVICE_TYPE, "dns");
|
properties.setProperty(SERVICE_TYPE, "dns");
|
||||||
|
properties.setProperty(KEYSTONE_VERSION, "2");
|
||||||
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
|
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -141,8 +145,8 @@ public class ProviderModuleExpectTest extends BaseRestApiExpectTest<ProviderModu
|
||||||
.defaultEndpoint("http://localhost:5000/v2.0/")
|
.defaultEndpoint("http://localhost:5000/v2.0/")
|
||||||
.defaultProperties(DNSApiMetadata.defaultProperties())
|
.defaultProperties(DNSApiMetadata.defaultProperties())
|
||||||
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
|
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
|
||||||
.add(AuthenticationApiModule.class)
|
.add(AuthenticationModule.class)
|
||||||
.add(KeystoneAuthenticationModule.class)
|
.add(ServiceCatalogModule.class)
|
||||||
.add(RegionModule.class)
|
.add(RegionModule.class)
|
||||||
.add(DNSHttpApiModule.class).build());
|
.add(DNSHttpApiModule.class).build());
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.handlers;
|
package org.jclouds.openstack.keystone.auth.handlers;
|
||||||
|
|
||||||
import static org.easymock.EasyMock.createMock;
|
import static org.easymock.EasyMock.createMock;
|
||||||
import static org.easymock.EasyMock.expect;
|
import static org.easymock.EasyMock.expect;
|
||||||
|
@ -30,7 +30,7 @@ import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
||||||
import org.jclouds.io.Payloads;
|
import org.jclouds.io.Payloads;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
|
@ -46,7 +46,7 @@ public class RetryOnRenewTest {
|
||||||
HttpRequest request = createMock(HttpRequest.class);
|
HttpRequest request = createMock(HttpRequest.class);
|
||||||
HttpResponse response = createMock(HttpResponse.class);
|
HttpResponse response = createMock(HttpResponse.class);
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
LoadingCache<Credentials, Access> cache = createMock(LoadingCache.class);
|
LoadingCache<Credentials, AuthInfo> cache = createMock(LoadingCache.class);
|
||||||
BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class);
|
BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class);
|
||||||
|
|
||||||
expect(command.getCurrentRequest()).andReturn(request);
|
expect(command.getCurrentRequest()).andReturn(request);
|
||||||
|
@ -78,7 +78,7 @@ public class RetryOnRenewTest {
|
||||||
HttpResponse response = createMock(HttpResponse.class);
|
HttpResponse response = createMock(HttpResponse.class);
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
LoadingCache<Credentials, Access> cache = createMock(LoadingCache.class);
|
LoadingCache<Credentials, AuthInfo> cache = createMock(LoadingCache.class);
|
||||||
BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class);
|
BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class);
|
||||||
|
|
||||||
expect(command.getCurrentRequest()).andReturn(request).anyTimes();
|
expect(command.getCurrentRequest()).andReturn(request).anyTimes();
|
||||||
|
@ -108,7 +108,7 @@ public class RetryOnRenewTest {
|
||||||
HttpCommand command = createMock(HttpCommand.class);
|
HttpCommand command = createMock(HttpCommand.class);
|
||||||
HttpResponse response = createMock(HttpResponse.class);
|
HttpResponse response = createMock(HttpResponse.class);
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
LoadingCache<Credentials, Access> cache = createMock(LoadingCache.class);
|
LoadingCache<Credentials, AuthInfo> cache = createMock(LoadingCache.class);
|
||||||
BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class);
|
BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class);
|
||||||
|
|
||||||
expect(backoffHandler.shouldRetryRequest(command, response)).andReturn(true).once();
|
expect(backoffHandler.shouldRetryRequest(command, response)).andReturn(true).once();
|
|
@ -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.LocationIdToURIFromServiceEndpointsForTypeAndVersion;
|
||||||
|
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 LocationIdToURIFromServiceEndpointsForTypeAndVersion.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(LocationIdToURIFromServiceEndpointsForTypeAndVersion.class,
|
||||||
|
LocationIdToURIFromServiceEndpointsForTypeAndVersion.class).build(
|
||||||
|
LocationIdToURIFromServiceEndpointsForTypeAndVersion.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(LocationIdToURIFromServiceEndpointsForTypeAndVersion.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 LocationIdToURIFromServiceEndpointsForTypeAndVersion.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(LocationIdToURIFromServiceEndpointsForTypeAndVersion.class,
|
||||||
|
LocationIdToURIFromServiceEndpointsForTypeAndVersion.class).build(
|
||||||
|
LocationIdToURIFromServiceEndpointsForTypeAndVersion.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(LocationIdToURIFromServiceEndpointsForTypeAndVersion.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")));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,18 +14,23 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.suppliers;
|
package org.jclouds.openstack.keystone.auth.suppliers;
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.location.Provider;
|
import org.jclouds.location.Provider;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion;
|
||||||
|
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.ParseAccessTest;
|
||||||
import org.jclouds.openstack.keystone.v2_0.parse.ParseRackspaceAccessTest;
|
import org.jclouds.openstack.keystone.v2_0.parse.ParseRackspaceAccessTest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
@ -37,6 +42,7 @@ import com.google.common.collect.Maps;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
import com.google.inject.Scopes;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.TypeLiteral;
|
||||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||||
|
|
||||||
|
@ -50,13 +56,16 @@ public class RegionIdToAdminURIFromAccessForTypeAndVersionTest {
|
||||||
bind(new TypeLiteral<Supplier<URI>>() {
|
bind(new TypeLiteral<Supplier<URI>>() {
|
||||||
}).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
|
}).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
|
||||||
install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
|
install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
|
||||||
RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
|
RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion.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
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public Supplier<Access> provide() {
|
public Supplier<AuthInfo> provide() {
|
||||||
return Suppliers.ofInstance(new ParseAccessTest().expected());
|
return Suppliers.<AuthInfo> ofInstance(new ParseAccessTest().expected());
|
||||||
}
|
}
|
||||||
}).getInstance(RegionIdToAdminURISupplier.Factory.class);
|
}).getInstance(RegionIdToAdminURISupplier.Factory.class);
|
||||||
|
|
||||||
|
@ -79,13 +88,16 @@ public class RegionIdToAdminURIFromAccessForTypeAndVersionTest {
|
||||||
bind(new TypeLiteral<Supplier<URI>>() {
|
bind(new TypeLiteral<Supplier<URI>>() {
|
||||||
}).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
|
}).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
|
||||||
install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
|
install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
|
||||||
RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
|
RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion.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
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public Supplier<Access> provide() {
|
public Supplier<AuthInfo> provide() {
|
||||||
return Suppliers.ofInstance(new ParseRackspaceAccessTest().expected());
|
return Suppliers.<AuthInfo> ofInstance(new ParseRackspaceAccessTest().expected());
|
||||||
}
|
}
|
||||||
}).getInstance(RegionIdToAdminURISupplier.Factory.class);
|
}).getInstance(RegionIdToAdminURISupplier.Factory.class);
|
||||||
|
|
|
@ -14,18 +14,22 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.suppliers;
|
package org.jclouds.openstack.keystone.auth.suppliers;
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.util.List;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.location.Provider;
|
import org.jclouds.location.Provider;
|
||||||
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
|
import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToURIFromServiceEndpointsForTypeAndVersion;
|
||||||
|
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.ParseAccessTest;
|
||||||
import org.jclouds.openstack.keystone.v2_0.parse.ParseRackspaceAccessTest;
|
import org.jclouds.openstack.keystone.v2_0.parse.ParseRackspaceAccessTest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
@ -37,6 +41,7 @@ import com.google.common.collect.Maps;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
import com.google.inject.Scopes;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.TypeLiteral;
|
||||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||||
|
|
||||||
|
@ -50,18 +55,20 @@ public class RegionIdToURIFromAccessForTypeAndVersionTest {
|
||||||
bind(new TypeLiteral<Supplier<URI>>() {
|
bind(new TypeLiteral<Supplier<URI>>() {
|
||||||
}).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
|
}).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
|
||||||
install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
|
install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
|
||||||
RegionIdToURIFromAccessForTypeAndVersion.class).build(
|
RegionIdToURIFromServiceEndpointsForTypeAndVersion.class).build(
|
||||||
RegionIdToURISupplier.Factory.class));
|
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
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public Supplier<Access> provide() {
|
public Supplier<AuthInfo> provide() {
|
||||||
return Suppliers.ofInstance(new ParseAccessTest().expected());
|
return Suppliers.<AuthInfo> ofInstance(new ParseAccessTest().expected());
|
||||||
}
|
}
|
||||||
}).getInstance(RegionIdToURISupplier.Factory.class);
|
}).getInstance(RegionIdToURISupplier.Factory.class);
|
||||||
|
|
||||||
@SuppressWarnings("CheckReturnValue")
|
|
||||||
@Test(expectedExceptions = NoSuchElementException.class)
|
@Test(expectedExceptions = NoSuchElementException.class)
|
||||||
public void testRegionUnmatches() {
|
public void testRegionUnmatches() {
|
||||||
Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.0").get(),
|
Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.0").get(),
|
||||||
|
@ -84,14 +91,17 @@ public class RegionIdToURIFromAccessForTypeAndVersionTest {
|
||||||
bind(new TypeLiteral<Supplier<URI>>() {
|
bind(new TypeLiteral<Supplier<URI>>() {
|
||||||
}).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
|
}).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
|
||||||
install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
|
install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
|
||||||
RegionIdToURIFromAccessForTypeAndVersion.class).build(
|
RegionIdToURIFromServiceEndpointsForTypeAndVersion.class).build(
|
||||||
RegionIdToURISupplier.Factory.class));
|
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
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public Supplier<Access> provide() {
|
public Supplier<AuthInfo> provide() {
|
||||||
return Suppliers.ofInstance(new ParseRackspaceAccessTest().expected());
|
return Suppliers.<AuthInfo> ofInstance(new ParseRackspaceAccessTest().expected());
|
||||||
}
|
}
|
||||||
}).getInstance(RegionIdToURISupplier.Factory.class);
|
}).getInstance(RegionIdToURISupplier.Factory.class);
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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.catalog.functions;
|
||||||
|
|
||||||
|
import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.ADMIN;
|
||||||
|
import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.PUBLIC;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@Test(groups = "unit", testName = "AdminURLTest")
|
||||||
|
public class AdminURLTest {
|
||||||
|
private final AdminURL fn = new AdminURL();
|
||||||
|
|
||||||
|
public void testAdminURL() {
|
||||||
|
assertEquals(
|
||||||
|
fn.apply(
|
||||||
|
Collections.singletonList(ServiceEndpoint
|
||||||
|
.builder()
|
||||||
|
.type("cdn")
|
||||||
|
.regionId("LON")
|
||||||
|
.version("1.0")
|
||||||
|
.url(URI
|
||||||
|
.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
|
||||||
|
.iface(ADMIN).build())).get(),
|
||||||
|
URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReturnsNullIfNotAdminURI() {
|
||||||
|
assertEquals(
|
||||||
|
fn.apply(
|
||||||
|
Collections.singletonList(ServiceEndpoint.builder().type("cdn").regionId("LON").version("1.0")
|
||||||
|
.url(URI.create("https://192.168.1.1")).iface(PUBLIC).build())).get(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,13 +14,15 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
package org.jclouds.openstack.keystone.catalog.functions;
|
||||||
|
|
||||||
|
import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.INTERNAL;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,9 +33,10 @@ public class InternalURLTest {
|
||||||
|
|
||||||
public void testInternalURL() {
|
public void testInternalURL() {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
fn.apply(
|
fn.apply(Collections.singletonList(ServiceEndpoint.builder().type("cdn").regionId("regionOne")
|
||||||
Endpoint.builder().region("regionOne").versionId("2.0")
|
.version("2.0")
|
||||||
.internalURL(URI.create("https://ericsson.com/v2/1900e98b-7272-4cbd-8e95-0b8c2a9266c0"))
|
.url(URI.create("https://ericsson.com/v2/1900e98b-7272-4cbd-8e95-0b8c2a9266c0"))
|
||||||
.build()).get(), URI.create("https://ericsson.com/v2/1900e98b-7272-4cbd-8e95-0b8c2a9266c0"));
|
.iface(INTERNAL).build())).get(),
|
||||||
|
URI.create("https://ericsson.com/v2/1900e98b-7272-4cbd-8e95-0b8c2a9266c0"));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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.catalog.functions;
|
||||||
|
|
||||||
|
import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.INTERNAL;
|
||||||
|
import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.PUBLIC;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@Test(groups = "unit", testName = "PublicURLOrInternalTest")
|
||||||
|
public class PublicURLOrInternalTest {
|
||||||
|
private final PublicURLOrInternal fn = new PublicURLOrInternal();
|
||||||
|
|
||||||
|
public void testPublicURLNotNullReturnsPublicURL() {
|
||||||
|
assertEquals(
|
||||||
|
fn.apply(
|
||||||
|
Collections.singletonList(ServiceEndpoint
|
||||||
|
.builder()
|
||||||
|
.type("cdn")
|
||||||
|
.regionId("LON")
|
||||||
|
.version("1.0")
|
||||||
|
.url(URI
|
||||||
|
.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
|
||||||
|
.iface(PUBLIC).build())).get(),
|
||||||
|
URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPublicURLNullReturnsInternalURL() {
|
||||||
|
assertEquals(
|
||||||
|
fn.apply(
|
||||||
|
Collections.singletonList(ServiceEndpoint.builder().type("cdn").regionId("LON").version("1.0")
|
||||||
|
.url(URI.create("https://192.168.1.1")).iface(INTERNAL).build())).get(),
|
||||||
|
URI.create("https://192.168.1.1"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,13 +14,14 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
package org.jclouds.openstack.keystone.catalog.functions;
|
||||||
|
|
||||||
|
import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.PUBLIC;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
@Test(groups = "unit", testName = "ReturnRegionOrProviderTest")
|
@Test(groups = "unit", testName = "ReturnRegionOrProviderTest")
|
||||||
|
@ -29,16 +30,16 @@ public class ReturnRegionOrProviderTest {
|
||||||
|
|
||||||
public void testRegionNotNullReturnsRegion() {
|
public void testRegionNotNullReturnsRegion() {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
fn.apply(Endpoint.builder().region("LON").versionId("1.0").publicURL(
|
fn.apply(ServiceEndpoint.builder().type("cdn").regionId("LON").version("1.0")
|
||||||
URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
|
.url(URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
|
||||||
.build()), "LON");
|
.iface(PUBLIC).build()), "LON");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRegionNullReturnsProvider() {
|
public void testRegionNullReturnsProvider() {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
fn.apply(Endpoint.builder().versionId("1.0").publicURL(
|
fn.apply(ServiceEndpoint.builder().type("cdn").version("1.0")
|
||||||
URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
|
.url(URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
|
||||||
.build()), "openstack-keystone");
|
.iface(PUBLIC).build()), "openstack-keystone");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue