You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by za...@apache.org on 2016/02/16 22:19:08 UTC

jclouds git commit: Enhance the way openstack extensions are resolved. Needed for new openstack versions.

Repository: jclouds
Updated Branches:
  refs/heads/master 27b3a844f -> c8bbb44f3


Enhance the way openstack extensions are resolved. Needed for new openstack versions.


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/c8bbb44f
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/c8bbb44f
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/c8bbb44f

Branch: refs/heads/master
Commit: c8bbb44f372677af2c7f60c7535a33d4c26b69c2
Parents: 27b3a84
Author: Zack Shoylev <za...@rackspace.com>
Authored: Thu Feb 11 16:49:59 2016 -0600
Committer: Zack Shoylev <za...@rackspace.com>
Committed: Tue Feb 16 15:18:39 2016 -0600

----------------------------------------------------------------------
 .../v2_0/config/KeystoneHttpApiModule.java      |   4 +-
 ...nExtensionAnnotationMatchesExtensionSet.java | 123 +++++++++++++++++++
 ...espaceEqualsAnyNamespaceInExtensionsSet.java | 102 ---------------
 ...ceEqualsAnyNamespaceInExtensionsSetTest.java |  39 +++---
 .../nova/v2_0/config/NovaHttpApiModule.java     |   4 +-
 5 files changed, 145 insertions(+), 127 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/c8bbb44f/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneHttpApiModule.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneHttpApiModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneHttpApiModule.java
index 149edd0..fc8aca3 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneHttpApiModule.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneHttpApiModule.java
@@ -36,7 +36,7 @@ import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURIFromAcces
 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.functions.PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet;
+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.annotations.ApiVersion;
@@ -98,7 +98,7 @@ public class KeystoneHttpApiModule extends HttpApiModule<KeystoneApi> {
 
    @Override
    protected void configure() {
-      bind(ImplicitOptionalConverter.class).to(PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.class);
+      bind(ImplicitOptionalConverter.class).to(PresentWhenExtensionAnnotationMatchesExtensionSet.class);
       super.configure();
       namespaceAliasBinder(binder());
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/c8bbb44f/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/functions/PresentWhenExtensionAnnotationMatchesExtensionSet.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/functions/PresentWhenExtensionAnnotationMatchesExtensionSet.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/functions/PresentWhenExtensionAnnotationMatchesExtensionSet.java
new file mode 100644
index 0000000..7507067
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/functions/PresentWhenExtensionAnnotationMatchesExtensionSet.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.v2_0.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.any;
+import static org.jclouds.openstack.v2_0.predicates.ExtensionPredicates.aliasEquals;
+import static org.jclouds.openstack.v2_0.predicates.ExtensionPredicates.nameEquals;
+import static org.jclouds.openstack.v2_0.predicates.ExtensionPredicates.namespaceOrAliasEquals;
+import static org.jclouds.util.Optionals2.unwrapIfOptional;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Inject;
+
+import org.jclouds.openstack.keystone.v2_0.config.NamespaceAliases;
+import org.jclouds.openstack.v2_0.domain.Extension;
+import org.jclouds.reflect.InvocationSuccess;
+import org.jclouds.rest.functions.ImplicitOptionalConverter;
+
+import com.google.common.base.Optional;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
+
+/**
+ * We use the annotation {@link Extension} to bind a class that implements an extension
+ * API to an {@link Extension}.
+ *
+ * Match in the following order:
+ *
+ * 1. Match by namespace
+ * 2. Match by namespace aliases
+ * 3. Match by alias
+ * 4. Match by name
+ *
+ * New versions of openstack have no namespaces anymore.
+ * Alias is different than a namespace alias - it's an alternative namespace URL to match against.
+ */
+public class PresentWhenExtensionAnnotationMatchesExtensionSet implements
+      ImplicitOptionalConverter {
+   private final LoadingCache<String, Set<? extends Extension>> extensions;
+   private final Map<URI, Set<URI>> aliases;
+
+   @Inject
+   PresentWhenExtensionAnnotationMatchesExtensionSet(
+         LoadingCache<String, Set<? extends Extension>> extensions, @NamespaceAliases Map<URI, Set<URI>> aliases) {
+      this.extensions = extensions;
+      this.aliases = aliases == null ? ImmutableMap.<URI, Set<URI>> of() : ImmutableMap.copyOf(aliases);
+   }
+
+   private boolean checkExtension(String invocationArg, URI namespace,
+         Set<URI> aliasesForNamespace, String alias, String name) {
+      if (any(extensions.getUnchecked(invocationArg), namespaceOrAliasEquals(namespace, aliasesForNamespace)))
+         return true;
+      // Could not find extension by namespace or namespace alias. Try to find it by alias next:
+      if ( !"".equals(alias)) {
+         if (any(extensions.getUnchecked(invocationArg), aliasEquals(alias)))
+            return true;
+      }
+      // Could not find extension by namespace or namespace alias or alias. Try to find it by name next:
+      if ( !"".equals(name)) {
+         if (any(extensions.getUnchecked(invocationArg), nameEquals(name)))
+            return true;
+      }
+      return false;
+   }
+
+   @Override
+   public Optional<Object> apply(InvocationSuccess input) {
+      Class<?> target = unwrapIfOptional(input.getInvocation().getInvokable().getReturnType());
+      Optional<org.jclouds.openstack.v2_0.services.Extension> ext = Optional.fromNullable(target
+            .getAnnotation(org.jclouds.openstack.v2_0.services.Extension.class));
+      if (ext.isPresent()) {
+         URI namespace = URI.create(ext.get().namespace());
+         List<Object> args = input.getInvocation().getArgs();
+         Set<URI> aliasesForNamespace = aliases.containsKey(namespace) ? aliases.get(namespace) : Sets.<URI> newHashSet();
+         String name = ext.get().name();
+         String alias = ext.get().alias();
+
+         if (args.isEmpty()) {
+            if (checkExtension("", namespace, aliasesForNamespace, alias, name)) {
+               return input.getResult();
+            }
+         } else if (args.size() == 1) {
+            String arg0 = checkNotNull(args.get(0), "arg[0] in %s", input).toString();
+            if (checkExtension(arg0, namespace, aliasesForNamespace, alias, name)) {
+               return input.getResult();
+            }
+         } else {
+            throw new RuntimeException(String.format("expecting zero or one args %s", input));
+         }
+
+         return Optional.absent();
+      } else {
+         // No extension annotation, should check whether to return absent
+         return input.getResult();
+      }
+   }
+
+   @Override
+   public String toString() {
+      return "PresentWhenExtensionAnnotationMatchesExtensionSet()";
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/c8bbb44f/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.java
deleted file mode 100644
index 101f06b..0000000
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.openstack.v2_0.functions;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Iterables.any;
-import static org.jclouds.openstack.v2_0.predicates.ExtensionPredicates.nameEquals;
-import static org.jclouds.openstack.v2_0.predicates.ExtensionPredicates.namespaceOrAliasEquals;
-import static org.jclouds.util.Optionals2.unwrapIfOptional;
-
-import java.net.URI;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.inject.Inject;
-
-import org.jclouds.openstack.keystone.v2_0.config.NamespaceAliases;
-import org.jclouds.openstack.v2_0.domain.Extension;
-import org.jclouds.reflect.InvocationSuccess;
-import org.jclouds.rest.functions.ImplicitOptionalConverter;
-
-import com.google.common.base.Optional;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Sets;
-
-/**
- * We use the annotation {@link Extension} to bind a class that implements an extension
- * API to an {@link Extension}.
- */
-public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet implements
-      ImplicitOptionalConverter {
-   private final LoadingCache<String, Set<? extends Extension>> extensions;
-   private final Map<URI, Set<URI>> aliases;
-
-   @Inject
-   PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet(
-         LoadingCache<String, Set<? extends Extension>> extensions, @NamespaceAliases Map<URI, Set<URI>> aliases) {
-      this.extensions = extensions;
-      this.aliases = aliases == null ? ImmutableMap.<URI, Set<URI>> of() : ImmutableMap.copyOf(aliases);
-   }
-
-   @Override
-   public Optional<Object> apply(InvocationSuccess input) {
-      Class<?> target = unwrapIfOptional(input.getInvocation().getInvokable().getReturnType());
-      Optional<org.jclouds.openstack.v2_0.services.Extension> ext = Optional.fromNullable(target
-            .getAnnotation(org.jclouds.openstack.v2_0.services.Extension.class));
-      if (ext.isPresent()) {
-         URI namespace = URI.create(ext.get().namespace());
-         List<Object> args = input.getInvocation().getArgs();
-         Set<URI> aliasesForNamespace = aliases.containsKey(namespace) ? aliases.get(namespace) : Sets.<URI> newHashSet();
-         String name = ext.get().name();
-
-         if (args.isEmpty()) {
-            if (any(extensions.getUnchecked(""), namespaceOrAliasEquals(namespace, aliasesForNamespace)))
-               return input.getResult();
-            // Could not find extension by namespace or namespace alias. Try to find it by name next:
-            if ( !"".equals(name)) {
-               if (any(extensions.getUnchecked(""), nameEquals(name)))
-                  return input.getResult();
-            }
-         } else if (args.size() == 1) {
-            String arg0 = checkNotNull(args.get(0), "arg[0] in %s", input).toString();
-            if (any(extensions.getUnchecked(arg0), namespaceOrAliasEquals(namespace, aliasesForNamespace)))
-               return input.getResult();
-            // Could not find extension by namespace or namespace alias. Try to find it by name next:
-            if (!"".equals(name)) {
-               if (any(extensions.getUnchecked(arg0), nameEquals(name)))
-                  return input.getResult();
-            }
-         } else {
-            throw new RuntimeException(String.format("expecting zero or one args %s", input));
-         }
-
-         return Optional.absent();
-      } else {
-         // No extension annotation, should check whether to return absent
-         return input.getResult();
-      }
-   }
-
-   @Override
-   public String toString() {
-      return "presentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet()";
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/c8bbb44f/apis/openstack-keystone/src/test/java/org/jclouds/openstack/v2_0/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSetTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/v2_0/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSetTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/v2_0/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSetTest.java
index 4b6d479..7836140 100644
--- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/v2_0/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSetTest.java
+++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/v2_0/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSetTest.java
@@ -65,25 +65,17 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
             new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-06-16T00:00:00+00:00")).description(
             "Floating IPs support").build();
 
-   @org.jclouds.openstack.v2_0.services.Extension(of = ServiceType.COMPUTE, namespace = "http://docs.openstack.org/ext/floating_ips/api/v1.1")
+   @org.jclouds.openstack.v2_0.services.Extension(of = ServiceType.COMPUTE, name = "Floating_ips", alias = "os-floating-ips", namespace = "http://docs.openstack.org/ext/floating_ips/api/v1.1")
    interface FloatingIPApi {
 
    }
 
-   @org.jclouds.openstack.v2_0.services.Extension(of = ServiceType.COMPUTE, name = "Floating_ips", namespace = "http://docs.openstack.org/fake")
-   interface FloatingIPNamedApi {
-
-   }
-
    interface NovaApi {
 
       @Delegate
       Optional<FloatingIPApi> getFloatingIPExtensionApi(String region);
 
       @Delegate
-      Optional<FloatingIPNamedApi> getFloatingIPNamedExtensionApi(String region);
-
-      @Delegate
       Optional<KeyPairApi> getKeyPairExtensionApi(String region);
 
    }
@@ -93,11 +85,6 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
             Invocation.create(method(NovaApi.class, "getFloatingIPExtensionApi", String.class), args), "foo");
    }
 
-   InvocationSuccess getFloatingIPNamedExtension(List<Object> args) throws SecurityException, NoSuchMethodException {
-      return InvocationSuccess.create(
-            Invocation.create(method(NovaApi.class, "getFloatingIPNamedExtensionApi", String.class), args), "foo");
-   }
-
    InvocationSuccess getKeyPairExtension(List<Object> args) throws SecurityException, NoSuchMethodException {
       return InvocationSuccess.create(
             Invocation.create(method(NovaApi.class, "getKeyPairExtensionApi", String.class), args), "foo");
@@ -144,28 +131,38 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
     *
     */
    public void testPresentWhenNameSpaceIsMissingAndMatchByNameOrAlias() throws SecurityException, NoSuchMethodException {
-      Extension floatingIpsWithFakeNamespace = floatingIps.toBuilder()
+      // Revert to alias
+      Extension floatingIpsWithMissingNamespace = floatingIps.toBuilder()
+            .namespace(URI.create("http://docs.openstack.org/ext/fake"))
+            .build();
+
+      // Revert to name
+      Extension floatingIpsWithMissingNamespaceAndAlias = floatingIps.toBuilder()
             .namespace(URI.create("http://docs.openstack.org/ext/fake"))
+            .alias("fake")
             .build();
 
       Multimap<URI, URI> aliases = ImmutableMultimap.of();
 
-      assertEquals(whenExtensionsAndAliasesInRegionInclude("region", ImmutableSet.of(floatingIpsWithFakeNamespace), aliases).apply(
-            getFloatingIPNamedExtension(ImmutableList.<Object> of("region"))), Optional.of("foo"));
+      assertEquals(whenExtensionsAndAliasesInRegionInclude("region", ImmutableSet.of(floatingIpsWithMissingNamespace), aliases).apply(
+            getFloatingIPExtension(ImmutableList.<Object> of("region"))), Optional.of("foo"));
+
+      assertEquals(whenExtensionsAndAliasesInRegionInclude("region", ImmutableSet.of(floatingIpsWithMissingNamespaceAndAlias), aliases).apply(
+            getFloatingIPExtension(ImmutableList.<Object> of("region"))), Optional.of("foo"));
    }
 
-   private PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet whenExtensionsInRegionInclude(
+   private PresentWhenExtensionAnnotationMatchesExtensionSet whenExtensionsInRegionInclude(
             String region, Extension... extensions) {
       return whenExtensionsAndAliasesInRegionInclude(region, ImmutableSet.copyOf(extensions), ImmutableMultimap.<URI, URI> of());
    }
 
-   private PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet whenExtensionsAndAliasesInRegionInclude(
+   private PresentWhenExtensionAnnotationMatchesExtensionSet whenExtensionsAndAliasesInRegionInclude(
             String region, final Set<Extension> extensions, final Multimap<URI, URI> aliases) {
       final LoadingCache<String, Set<? extends Extension>> extensionsForRegion = CacheBuilder.newBuilder().build(
                CacheLoader.from(Functions.forMap(ImmutableMap.<String, Set<? extends Extension>>of(region, extensions, "differentregion",
                         ImmutableSet.<Extension> of()))));
 
-      PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet fn = Guice.createInjector(
+      PresentWhenExtensionAnnotationMatchesExtensionSet fn = Guice.createInjector(
                new AbstractModule() {
                   @Override
                   protected void configure() {
@@ -183,7 +180,7 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
                      return extensionsForRegion;
                   }
 
-               }).getInstance(PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.class);
+               }).getInstance(PresentWhenExtensionAnnotationMatchesExtensionSet.class);
 
       return fn;
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/c8bbb44f/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/config/NovaHttpApiModule.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/config/NovaHttpApiModule.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/config/NovaHttpApiModule.java
index dcbb519..c6d99ef 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/config/NovaHttpApiModule.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/config/NovaHttpApiModule.java
@@ -29,7 +29,7 @@ import org.jclouds.openstack.nova.v2_0.NovaApi;
 import org.jclouds.openstack.nova.v2_0.extensions.ExtensionNamespaces;
 import org.jclouds.openstack.nova.v2_0.handlers.NovaErrorHandler;
 import org.jclouds.openstack.v2_0.domain.Extension;
-import org.jclouds.openstack.v2_0.functions.PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet;
+import org.jclouds.openstack.v2_0.functions.PresentWhenExtensionAnnotationMatchesExtensionSet;
 import org.jclouds.rest.ConfiguresHttpApi;
 import org.jclouds.rest.config.HttpApiModule;
 import org.jclouds.rest.functions.ImplicitOptionalConverter;
@@ -54,7 +54,7 @@ public class NovaHttpApiModule extends HttpApiModule<NovaApi> {
 
    @Override
    protected void configure() {
-      bind(ImplicitOptionalConverter.class).to(PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.class);
+      bind(ImplicitOptionalConverter.class).to(PresentWhenExtensionAnnotationMatchesExtensionSet.class);
       super.configure();
       bindDefaultAliases();
    }