http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/ServiceCatalogModule.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/ServiceCatalogModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/ServiceCatalogModule.java new file mode 100644 index 0000000..9761da0 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/ServiceCatalogModule.java @@ -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.LocationIdToURIFromAccessForTypeAndVersion; +import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURIFromAccessForTypeAndVersion; +import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURISupplier; +import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToURIFromAccessForTypeAndVersion; +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(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<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, + 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); + } + } + +}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/AdminEndpointResolutionStrategy.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/AdminEndpointResolutionStrategy.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/AdminEndpointResolutionStrategy.java new file mode 100644 index 0000000..3ee1d78 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/AdminEndpointResolutionStrategy.java @@ -0,0 +1,27 @@ +/* + * 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 com.google.inject.ImplementedBy; + +/** + * 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 { +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/AdminURL.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/AdminURL.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/AdminURL.java new file mode 100644 index 0000000..b727ca1 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/AdminURL.java @@ -0,0 +1,34 @@ +/* + * 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 javax.inject.Singleton; + +import org.jclouds.openstack.keystone.catalog.ServiceEndpoint; + +import com.google.common.base.Predicate; + +@Singleton +public class AdminURL extends BaseEndpointResolutionStrategy implements AdminEndpointResolutionStrategy { + + @Override + protected Predicate<ServiceEndpoint> filter() { + return withIface(ADMIN); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/BaseEndpointResolutionStrategy.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/BaseEndpointResolutionStrategy.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/BaseEndpointResolutionStrategy.java new file mode 100644 index 0000000..23fe16d --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/BaseEndpointResolutionStrategy.java @@ -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() + ")"; + } + }; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/InternalURL.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/InternalURL.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/InternalURL.java new file mode 100644 index 0000000..dfe44e3 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/InternalURL.java @@ -0,0 +1,34 @@ +/* + * 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 javax.inject.Singleton; + +import org.jclouds.openstack.keystone.catalog.ServiceEndpoint; + +import com.google.common.base.Predicate; + +@Singleton +public class InternalURL extends BaseEndpointResolutionStrategy { + + @Override + protected Predicate<ServiceEndpoint> filter() { + return withIface(INTERNAL); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/PublicURLOrInternal.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/PublicURLOrInternal.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/PublicURLOrInternal.java new file mode 100644 index 0000000..cbf01f9 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/PublicURLOrInternal.java @@ -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; + } + }; + }; +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ReturnRegionOrProvider.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ReturnRegionOrProvider.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ReturnRegionOrProvider.java new file mode 100644 index 0000000..db1d314 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ReturnRegionOrProvider.java @@ -0,0 +1,38 @@ +/* + * 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 javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.location.Provider; +import org.jclouds.openstack.keystone.catalog.ServiceEndpoint; + +@Singleton +public class ReturnRegionOrProvider implements ServiceEndpointToRegion { + private final String provider; + + @Inject + ReturnRegionOrProvider(@Provider String provider) { + this.provider = provider; + } + + @Override + public String apply(ServiceEndpoint input) { + return input.regionId() != null ? input.regionId() : provider; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ServiceEndpointResolutionStrategy.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ServiceEndpointResolutionStrategy.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ServiceEndpointResolutionStrategy.java new file mode 100644 index 0000000..da8b654 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ServiceEndpointResolutionStrategy.java @@ -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.catalog.functions; + +import java.net.URI; +import java.util.Collection; + +import org.jclouds.openstack.keystone.catalog.ServiceEndpoint; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.inject.ImplementedBy; + +/** + * Given a sets of endpoints for a particular service and version, return the + * URL to be used to connect to the service. + */ +@ImplementedBy(PublicURLOrInternal.class) +public interface ServiceEndpointResolutionStrategy extends Function<Collection<ServiceEndpoint>, Supplier<URI>> { + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ServiceEndpointToRegion.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ServiceEndpointToRegion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ServiceEndpointToRegion.java new file mode 100644 index 0000000..c1ed3f1 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ServiceEndpointToRegion.java @@ -0,0 +1,27 @@ +/* + * 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 org.jclouds.openstack.keystone.catalog.ServiceEndpoint; + +import com.google.common.base.Function; +import com.google.inject.ImplementedBy; + +@ImplementedBy(ReturnRegionOrProvider.class) +public interface ServiceEndpointToRegion extends Function<ServiceEndpoint, String> { + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/LocationIdToURIFromAccessForTypeAndVersion.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/LocationIdToURIFromAccessForTypeAndVersion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/LocationIdToURIFromAccessForTypeAndVersion.java new file mode 100644 index 0000000..8adf561 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/LocationIdToURIFromAccessForTypeAndVersion.java @@ -0,0 +1,129 @@ +/* + * 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 LocationIdToURIFromAccessForTypeAndVersion implements Supplier<Map<String, Supplier<URI>>> { + + public interface Factory { + + LocationIdToURIFromAccessForTypeAndVersion 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 + LocationIdToURIFromAccessForTypeAndVersion(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(); + + // 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 "locationIdToURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")"; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java new file mode 100644 index 0000000..740b7a3 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java @@ -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 RegionIdToAdminURIFromAccessForTypeAndVersion extends LocationIdToURIFromAccessForTypeAndVersion implements + RegionIdToAdminURISupplier { + @Inject + public RegionIdToAdminURIFromAccessForTypeAndVersion(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 "regionIdToAdminURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")"; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURISupplier.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURISupplier.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURISupplier.java new file mode 100644 index 0000000..0f70205 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURISupplier.java @@ -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.catalog.suppliers; + +import java.net.URI; +import java.util.Map; +import java.util.NoSuchElementException; + +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.base.Supplier; +import com.google.inject.ImplementedBy; +import com.google.inject.assistedinject.Assisted; + +@ImplementedBy(RegionIdToAdminURIFromAccessForTypeAndVersion.class) +public interface RegionIdToAdminURISupplier extends Supplier<Map<String, Supplier<URI>>> { + + interface Factory { + + RegionIdToAdminURISupplier createForApiTypeAndVersion(@Assisted("apiType") String apiType, + @Nullable @Assisted("apiVersion") String apiVersion) throws NoSuchElementException; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToURIFromAccessForTypeAndVersion.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToURIFromAccessForTypeAndVersion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToURIFromAccessForTypeAndVersion.java new file mode 100644 index 0000000..d40b4af --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToURIFromAccessForTypeAndVersion.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.keystone.catalog.suppliers; + +import java.util.List; + +import javax.inject.Inject; + +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.location.suppliers.RegionIdToURISupplier; +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.Supplier; +import com.google.inject.assistedinject.Assisted; + +public class RegionIdToURIFromAccessForTypeAndVersion extends LocationIdToURIFromAccessForTypeAndVersion implements + RegionIdToURISupplier { + + @Inject + public RegionIdToURIFromAccessForTypeAndVersion(Supplier<List<ServiceEndpoint>> serviceEndpoints, + ServiceEndpointResolutionStrategy resolveServiceEndpointURI, ServiceEndpointToRegion serviceEndpointToRegion, + @Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) { + super(serviceEndpoints, resolveServiceEndpointURI, serviceEndpointToRegion, apiType, apiVersion); + } + + @Override + public String toString() { + return "regionIdToURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")"; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/config/KeystoneProperties.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/config/KeystoneProperties.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/config/KeystoneProperties.java new file mode 100644 index 0000000..ece0129 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/config/KeystoneProperties.java @@ -0,0 +1,83 @@ +/* + * 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.config; + +import org.jclouds.openstack.keystone.auth.config.CredentialTypes; + +/** + * Configuration properties and constants used in Keystone connections. + */ +public final class KeystoneProperties { + + /** + * Type of credentials used to log into the auth service. + * + * <h3>valid values</h3> + * <ul> + * <li>apiAccessKeyCredentials</li> + * <li>passwordCredentials</li> + * <li>tokenCredentials</li> + * </ul> + * + * @see CredentialTypes + * @see <a href= + * "http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_authenticate_v2.0_tokens_Service_API_Api_Operations.html" + * /> + */ + public static final String CREDENTIAL_TYPE = "jclouds.keystone.credential-type"; + + /** + * set this property to specify the tenant id of the authenticated user. + * Cannot be used simultaneously with {@link #TENANT_NAME} + * + * @see <a href="http://wiki.openstack.org/CLIAuth">openstack docs</a> + */ + public static final String TENANT_ID = "jclouds.keystone.tenant-id"; + + /** + * set this property to specify the tenant name of the authenticated user. + * Cannot be used simultaneously with {@link #TENANT_ID} + * + * @see <a href="http://wiki.openstack.org/CLIAuth">openstack docs</a> + */ + public static final String TENANT_NAME = "jclouds.keystone.tenant-name"; + + /** + * set this property to {@code true} to designate that the service requires + * explicit specification of either {@link #TENANT_NAME} or + * {@link #TENANT_ID} + * + * @see <a href="http://wiki.openstack.org/CLIAuth">openstack docs</a> + */ + public static final String REQUIRES_TENANT = "jclouds.keystone.requires-tenant"; + + /** + * type of the keystone service. ex. {@code compute} + * + * @see ServiceType + */ + 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() { + throw new AssertionError("intentionally unimplemented"); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationApi.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationApi.java deleted file mode 100644 index 0ac8a6c..0000000 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationApi.java +++ /dev/null @@ -1,91 +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; - -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.javax.annotation.Nullable; -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.ApiAccessKeyCredentials; -import org.jclouds.openstack.keystone.v2_0.domain.PasswordCredentials; -import org.jclouds.rest.annotations.MapBinder; -import org.jclouds.rest.annotations.PayloadParam; -import org.jclouds.rest.annotations.SelectJson; - -import com.google.inject.name.Named; - -/** - * Provides access to the OpenStack Keystone Service API. - */ -@Consumes(MediaType.APPLICATION_JSON) -@Path("/tokens") -public interface AuthenticationApi extends Closeable { - - /** - * Authenticate to generate a token. - * - * @return access with token - */ - @Named("authenticate") - @POST - @SelectJson("access") - @MapBinder(BindAuthToJsonPayload.class) - Access authenticateWithTenantNameAndCredentials(@Nullable @PayloadParam("tenantName") String tenantName, - PasswordCredentials passwordCredentials); - - /** - * Authenticate to generate a token. - * - * @return access with token - */ - @Named("authenticate") - @POST - @SelectJson("access") - @MapBinder(BindAuthToJsonPayload.class) - Access authenticateWithTenantIdAndCredentials(@Nullable @PayloadParam("tenantId") String tenantId, - PasswordCredentials passwordCredentials); - - /** - * 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); -} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java index a06ea13..b8dbbcf 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java @@ -16,18 +16,19 @@ */ 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.v2_0.config.KeystoneProperties.SERVICE_TYPE; +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.v2_0.config.AuthenticationApiModule; -import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes; -import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule; +import org.jclouds.openstack.keystone.auth.config.AuthenticationModule; +import org.jclouds.openstack.keystone.auth.config.CredentialTypes; +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.KeystoneAdminURLModule; import org.jclouds.openstack.keystone.v2_0.config.KeystoneParserModule; import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.rest.internal.BaseHttpApiMetadata; @@ -59,6 +60,7 @@ public class KeystoneApiMetadata extends BaseHttpApiMetadata<KeystoneApi> { Properties properties = BaseHttpApiMetadata.defaultProperties(); properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS); properties.setProperty(SERVICE_TYPE, ServiceType.IDENTITY); + properties.setProperty(KEYSTONE_VERSION, "2"); return properties; } @@ -75,8 +77,8 @@ public class KeystoneApiMetadata extends BaseHttpApiMetadata<KeystoneApi> { .defaultEndpoint("http://localhost:5000/v${jclouds.api-version}/") .defaultProperties(KeystoneApiMetadata.defaultProperties()) .defaultModules(ImmutableSet.<Class<? extends Module>>builder() - .add(AuthenticationApiModule.class) - .add(KeystoneAuthenticationModule.class) + .add(AuthenticationModule.class) + .add(ServiceCatalogModule.class) .add(KeystoneAdminURLModule.class) .add(KeystoneParserModule.class) .add(KeystoneHttpApiModule.class).build()); http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/auth/V2AuthenticationApi.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/auth/V2AuthenticationApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/auth/V2AuthenticationApi.java new file mode 100644 index 0000000..3efe4f8 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/auth/V2AuthenticationApi.java @@ -0,0 +1,68 @@ +/* + * 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.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.ApiAccessKeyCredentials; +import org.jclouds.openstack.keystone.auth.domain.PasswordCredentials; +import org.jclouds.openstack.keystone.auth.domain.TenantAndCredentials; +import org.jclouds.openstack.keystone.v2_0.binders.BindAuthToJsonPayload; +import org.jclouds.openstack.keystone.v2_0.domain.Access; +import org.jclouds.rest.annotations.MapBinder; +import org.jclouds.rest.annotations.SelectJson; + +import com.google.inject.name.Named; + +/** + * Provides access to the OpenStack Keystone Service API. + */ +@Consumes(MediaType.APPLICATION_JSON) +@Path("/tokens") +public interface V2AuthenticationApi extends AuthenticationApi, Closeable { + + /** + * Authenticate to generate a token. + * + * @return access with token + */ + @Named("authenticate") + @POST + @SelectJson("access") + @MapBinder(BindAuthToJsonPayload.class) + @Override + Access authenticatePassword(TenantAndCredentials<PasswordCredentials> credentials); + + /** + * Authenticate to generate a token. + * + * @return access with token + */ + @Named("authenticate") + @POST + @SelectJson("access") + @MapBinder(BindAuthToJsonPayload.class) + @Override + Access authenticateAccessKey(TenantAndCredentials<ApiAccessKeyCredentials> credentials); + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/binders/BindAuthToJsonPayload.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/binders/BindAuthToJsonPayload.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/binders/BindAuthToJsonPayload.java index 71ef63d..5661947 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/binders/BindAuthToJsonPayload.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/binders/BindAuthToJsonPayload.java @@ -16,24 +16,29 @@ */ package org.jclouds.openstack.keystone.v2_0.binders; -import com.google.common.base.Predicates; -import com.google.common.base.Strings; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableMap.Builder; -import com.google.common.collect.Iterables; +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.auth.config.CredentialTypes.findCredentialType; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + import org.jclouds.http.HttpRequest; 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.TenantAndCredentials; import org.jclouds.rest.MapBinder; import org.jclouds.rest.binders.BindToJsonPayload; import org.jclouds.rest.internal.GeneratedHttpRequest; -import javax.inject.Inject; -import javax.inject.Singleton; -import java.util.Map; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.base.Optional; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; @Singleton public class BindAuthToJsonPayload extends BindToJsonPayload implements MapBinder { @@ -42,28 +47,35 @@ public class BindAuthToJsonPayload extends BindToJsonPayload implements MapBinde super(jsonBinder); } - protected void addCredentialsInArgsOrNull(GeneratedHttpRequest gRequest, Builder<String, Object> builder) { - for (Object arg : Iterables.filter(gRequest.getInvocation().getArgs(), Predicates.notNull())) { - if (arg.getClass().isAnnotationPresent(CredentialType.class)) { - builder.put(arg.getClass().getAnnotation(CredentialType.class).value(), arg); - } - } + protected TenantAndCredentials<?> findCredentialsInArgs(GeneratedHttpRequest gRequest) { + Optional<Object> credentials = tryFind(gRequest.getInvocation().getArgs(), instanceOf(TenantAndCredentials.class)); + return credentials.isPresent() ? (TenantAndCredentials<?>) credentials.get() : null; } @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!"); + "this binder is only valid for GeneratedHttpRequests!"); GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request; - 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 - // still use tenantName - if (!Strings.isNullOrEmpty((String) postParams.get("tenantName"))) - builder.put("tenantName", postParams.get("tenantName")); - else if (!Strings.isNullOrEmpty((String) postParams.get("tenantId"))) - builder.put("tenantId", postParams.get("tenantId")); + + TenantAndCredentials<?> credentials = findCredentialsInArgs(gRequest); + if (credentials != null) { + CredentialType credentialType = findCredentialType(credentials.credentials().getClass()); + checkArgument(credentialType != null, "the given credentials must be annotated with @CredentialType"); + + 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.tenantId())) + builder.put("tenantId", credentials.tenantId()); + else if (!Strings.isNullOrEmpty(credentials.tenantName())) + builder.put("tenantName", credentials.tenantName()); + } + } + R authRequest = super.bindToRequest(request, ImmutableMap.of("auth", builder.build())); authRequest.getPayload().setSensitive(true); return authRequest; http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/catalog/V2ServiceCatalog.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/catalog/V2ServiceCatalog.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/catalog/V2ServiceCatalog.java new file mode 100644 index 0000000..913b0b5 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/catalog/V2ServiceCatalog.java @@ -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(); + } + }; + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/Authentication.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/Authentication.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/Authentication.java deleted file mode 100644 index d6e5381..0000000 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/Authentication.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jclouds.openstack.keystone.v2_0.config; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import javax.inject.Qualifier; - -@Retention(value = RetentionPolicy.RUNTIME) -@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) -@Qualifier -public @interface Authentication { - -} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/AuthenticationApiModule.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/AuthenticationApiModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/AuthenticationApiModule.java deleted file mode 100644 index 2537d63..0000000 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/AuthenticationApiModule.java +++ /dev/null @@ -1,33 +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 org.jclouds.rest.config.BinderUtils.bindHttpApi; - -import org.jclouds.openstack.keystone.v2_0.AuthenticationApi; - -import com.google.inject.AbstractModule; - -public class AuthenticationApiModule extends AbstractModule { - - @Override - protected void configure() { - // AuthenticationApi is used directly for filters and retry handlers, so let's bind it explicitly - bindHttpApi(binder(), AuthenticationApi.class); - } - -} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialType.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialType.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialType.java deleted file mode 100644 index b0d67cc..0000000 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialType.java +++ /dev/null @@ -1,38 +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 java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import javax.inject.Qualifier; - -/** - * @see CredentialTypes - */ -@Retention(value = RetentionPolicy.RUNTIME) -@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) -@Qualifier -public @interface CredentialType { - /** - * @see CredentialTypes - * - */ - String value(); -} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialTypes.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialTypes.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialTypes.java deleted file mode 100644 index c774ae1..0000000 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialTypes.java +++ /dev/null @@ -1,52 +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 java.util.Map; - -import com.google.common.base.Function; -import com.google.common.collect.Maps; - -/** - * Configuration properties and constants used in Keystone connections. - */ -public class CredentialTypes { - - public static final String API_ACCESS_KEY_CREDENTIALS = "apiAccessKeyCredentials"; - - public static final String PASSWORD_CREDENTIALS = "passwordCredentials"; - - public static <T> String credentialTypeOf(T input) { - Class<?> authenticationType = input.getClass(); - checkArgument(authenticationType.isAnnotationPresent(CredentialType.class), - "programming error: %s should have annotation %s", authenticationType, CredentialType.class.getName()); - return authenticationType.getAnnotation(CredentialType.class).value(); - } - - public static <T> Map<String, T> indexByCredentialType(Iterable<T> iterable) { - return Maps.uniqueIndex(iterable, new Function<T, String>() { - - @Override - public String apply(T input) { - return credentialTypeOf(input); - } - - }); - } -} http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java ---------------------------------------------------------------------- diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java deleted file mode 100644 index 4d540fd..0000000 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java +++ /dev/null @@ -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()); - } - }; - } - -}
