From 30ba71796929591e1abf7dc176b1a7ce6b91cec3 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Fri, 15 Jun 2012 19:20:13 -0400 Subject: [PATCH] Issue 977:ec2 zones are not mapping to endpoints --- .../ec2/config/EC2RestClientModule.java | 12 ++- .../java/org/jclouds/ec2/domain/Volume.java | 2 +- ...java => DescribeRegionsForRegionURIs.java} | 11 +-- .../config/EC2RestClientModuleExpectTest.java | 9 +- .../ec2/internal/BaseEC2ExpectTest.java | 99 +++++++++++++++++++ .../EC2ElasticBlockStoreClientExpectTest.java | 71 +++++++++++++ .../availabilityZones-ap-northeast-1.xml | 17 ++++ .../availabilityZones-ap-southeast-1.xml | 17 ++++ .../resources/availabilityZones-eu-west-1.xml | 23 +++++ .../resources/availabilityZones-sa-east-1.xml | 17 ++++ .../resources/availabilityZones-us-east-1.xml | 35 +++++++ .../resources/availabilityZones-us-west-1.xml | 23 +++++ .../resources/availabilityZones-us-west-2.xml | 23 +++++ .../test/resources/regionEndpoints-all.xml | 34 +++++++ .../ZoneIdToURIFromJoinOnRegionIdToURI.java | 64 ++++++++++++ 15 files changed, 441 insertions(+), 16 deletions(-) rename apis/ec2/src/main/java/org/jclouds/ec2/suppliers/{DescribeRegionsForConfiguredRegions.java => DescribeRegionsForRegionURIs.java} (76%) create mode 100644 apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ExpectTest.java create mode 100644 apis/ec2/src/test/java/org/jclouds/ec2/services/EC2ElasticBlockStoreClientExpectTest.java create mode 100644 apis/ec2/src/test/resources/availabilityZones-ap-northeast-1.xml create mode 100644 apis/ec2/src/test/resources/availabilityZones-ap-southeast-1.xml create mode 100644 apis/ec2/src/test/resources/availabilityZones-eu-west-1.xml create mode 100644 apis/ec2/src/test/resources/availabilityZones-sa-east-1.xml create mode 100644 apis/ec2/src/test/resources/availabilityZones-us-east-1.xml create mode 100644 apis/ec2/src/test/resources/availabilityZones-us-west-1.xml create mode 100644 apis/ec2/src/test/resources/availabilityZones-us-west-2.xml create mode 100644 apis/ec2/src/test/resources/regionEndpoints-all.xml create mode 100644 core/src/main/java/org/jclouds/location/suppliers/derived/ZoneIdToURIFromJoinOnRegionIdToURI.java diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/config/EC2RestClientModule.java b/apis/ec2/src/main/java/org/jclouds/ec2/config/EC2RestClientModule.java index 48047b3aaf..264b0126ca 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/config/EC2RestClientModule.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/config/EC2RestClientModule.java @@ -40,11 +40,15 @@ import org.jclouds.ec2.services.SecurityGroupClient; import org.jclouds.ec2.services.WindowsAsyncClient; import org.jclouds.ec2.services.WindowsClient; import org.jclouds.ec2.suppliers.DescribeAvailabilityZonesInRegion; -import org.jclouds.ec2.suppliers.DescribeRegionsForConfiguredRegions; +import org.jclouds.ec2.suppliers.DescribeRegionsForRegionURIs; import org.jclouds.location.config.LocationModule; import org.jclouds.location.suppliers.RegionIdToURISupplier; import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier; +import org.jclouds.location.suppliers.RegionIdsSupplier; +import org.jclouds.location.suppliers.ZoneIdToURISupplier; import org.jclouds.location.suppliers.ZoneIdsSupplier; +import org.jclouds.location.suppliers.derived.RegionIdsFromRegionIdToURIKeySet; +import org.jclouds.location.suppliers.derived.ZoneIdToURIFromJoinOnRegionIdToURI; import org.jclouds.location.suppliers.derived.ZoneIdsFromRegionIdToZoneIdsValues; import org.jclouds.rest.ConfiguresRestClient; @@ -81,13 +85,13 @@ public class EC2RestClientModule super(syncClientType, asyncClientType, sync2Async); } - - @Override protected void installLocations() { install(new LocationModule()); bind(RegionIdToZoneIdsSupplier.class).to(DescribeAvailabilityZonesInRegion.class).in(Scopes.SINGLETON); - bind(RegionIdToURISupplier.class).to(DescribeRegionsForConfiguredRegions.class).in(Scopes.SINGLETON); + bind(RegionIdToURISupplier.class).to(DescribeRegionsForRegionURIs.class).in(Scopes.SINGLETON); bind(ZoneIdsSupplier.class).to(ZoneIdsFromRegionIdToZoneIdsValues.class).in(Scopes.SINGLETON); + bind(RegionIdsSupplier.class).to(RegionIdsFromRegionIdToURIKeySet.class).in(Scopes.SINGLETON); + bind(ZoneIdToURISupplier.class).to(ZoneIdToURIFromJoinOnRegionIdToURI.class).in(Scopes.SINGLETON); } } diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/domain/Volume.java b/apis/ec2/src/main/java/org/jclouds/ec2/domain/Volume.java index 14f003fb31..427560be3f 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/domain/Volume.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/domain/Volume.java @@ -97,7 +97,7 @@ public class Volume implements Comparable { private String availabilityZone; private Status status; private Date createTime; - private Set attachments; + private Set attachments = ImmutableSet.of(); public Builder region(String region) { this.region = region; diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForConfiguredRegions.java b/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForRegionURIs.java similarity index 76% rename from apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForConfiguredRegions.java rename to apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForRegionURIs.java index 6e3d7ab9e7..b802aebaf6 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForConfiguredRegions.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForRegionURIs.java @@ -20,7 +20,6 @@ package org.jclouds.ec2.suppliers; import java.net.URI; import java.util.Map; -import java.util.Set; import javax.inject.Inject; import javax.inject.Singleton; @@ -31,29 +30,23 @@ import org.jclouds.location.Region; import org.jclouds.location.suppliers.RegionIdToURISupplier; import org.jclouds.util.Suppliers2; -import com.google.common.base.Predicates; import com.google.common.base.Supplier; import com.google.common.collect.Maps; @Singleton -public class DescribeRegionsForConfiguredRegions implements RegionIdToURISupplier { +public class DescribeRegionsForRegionURIs implements RegionIdToURISupplier { private final AvailabilityZoneAndRegionClient client; - private final Supplier> regions; @Inject - public DescribeRegionsForConfiguredRegions(EC2Client client, @Region Supplier> regions) { + public DescribeRegionsForRegionURIs(EC2Client client) { this.client = client.getAvailabilityZoneAndRegionServices(); - this.regions = regions; } @Singleton @Region @Override public Map> get() { - Set regionWhiteList = regions.get(); Map regionToUris = client.describeRegions(); - if (regionWhiteList.size() > 0) - regionToUris = Maps.filterKeys(regionToUris, Predicates.in(regionWhiteList)); return Maps.transformValues(regionToUris, Suppliers2. ofInstanceFunction()); } } \ No newline at end of file diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/config/EC2RestClientModuleExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/config/EC2RestClientModuleExpectTest.java index c1f589cc65..cee0074d32 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/config/EC2RestClientModuleExpectTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/config/EC2RestClientModuleExpectTest.java @@ -30,6 +30,7 @@ import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.location.Region; import org.jclouds.location.Zone; +import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull; import org.jclouds.location.functions.ZoneToEndpoint; import org.testng.annotations.Test; @@ -127,9 +128,13 @@ public class EC2RestClientModuleExpectTest extends BaseEC2ExpectTest { public void testZoneToEndpoint() { assertEquals(injector.getInstance(ZoneToEndpoint.class).apply("us-west-2a"), URI.create("https://ec2.us-west-2.amazonaws.com")); - } - + + public void testRegionToEndpointOrProviderIfNull() { + assertEquals(injector.getInstance(RegionToEndpointOrProviderIfNull.class).apply("us-west-2"), + URI.create("https://ec2.us-west-2.amazonaws.com")); + } + @Override public Injector createClient(Function fn, Module module, Properties props) { return createInjector(fn, module, props); diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ExpectTest.java new file mode 100644 index 0000000000..be74eacb03 --- /dev/null +++ b/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ExpectTest.java @@ -0,0 +1,99 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.ec2.internal; + +import java.net.URI; +import java.util.Map; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.aws.filters.FormSigner; +import org.jclouds.date.DateService; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.ec2.EC2AsyncClient; +import org.jclouds.ec2.EC2Client; +import org.jclouds.ec2.config.EC2RestClientModule; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.internal.BaseRestClientExpectTest; + +import com.google.common.base.Functions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Module; +import com.google.inject.Provides; + +public abstract class BaseEC2ExpectTest extends BaseRestClientExpectTest { + protected static final String CONSTANT_DATE = "2012-04-16T15:54:08.897Z"; + + protected DateService dateService = new SimpleDateFormatDateService(); + + protected HttpRequest describeRegionsRequest = HttpRequest + .builder() + .method("POST") + .endpoint(URI.create("https://ec2.us-east-1.amazonaws.com/")) + .headers(ImmutableMultimap.of("Host", "ec2.us-east-1.amazonaws.com")) + .payload(payloadFromStringWithContentType( + "Action=DescribeRegions&Signature=s5OXKqaaeKhJW5FVrRntuMsUL4Ed5fjzgUWeukU96ko%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2010-06-15&AWSAccessKeyId=identity", + MediaType.APPLICATION_FORM_URLENCODED)).build(); + protected HttpResponse describeRegionsResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/regionEndpoints-all.xml", MediaType.APPLICATION_XML)) + .build(); + + protected final Map describeAvailabilityZonesRequestResponse; + + public BaseEC2ExpectTest() { + provider = "ec2"; + FormSigner formSigner = createInjector(Functions.forMap(ImmutableMap. of()), + createModule(), setupProperties()).getInstance(FormSigner.class); + Builder builder = ImmutableMap. builder(); + for (String region : ImmutableSet.of("ap-northeast-1", "ap-southeast-1", "eu-west-1", "sa-east-1", "us-east-1", "us-west-1", "us-west-2")){ + builder.put( + formSigner.filter(HttpRequest.builder() + .method("POST") + .endpoint(URI.create("https://ec2." + region + ".amazonaws.com/")) + .headers(ImmutableMultimap.of("Host", "ec2." + region + ".amazonaws.com")) + .payload(payloadFromStringWithContentType( + "Action=DescribeAvailabilityZones&Version=2010-06-15", + MediaType.APPLICATION_FORM_URLENCODED)).build()), + HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType( + "/availabilityZones-" + region + ".xml", MediaType.APPLICATION_XML)).build()); + + } + describeAvailabilityZonesRequestResponse = builder.build(); + } + + @ConfiguresRestClient + private static final class TestEC2RestClientModule extends EC2RestClientModule { + @Override + @Provides + protected String provideTimeStamp(DateService dateService) { + return CONSTANT_DATE; + } + } + + @Override + protected Module createModule() { + return new TestEC2RestClientModule(); + } +} diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/EC2ElasticBlockStoreClientExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/EC2ElasticBlockStoreClientExpectTest.java new file mode 100644 index 0000000000..c032187782 --- /dev/null +++ b/apis/ec2/src/test/java/org/jclouds/ec2/services/EC2ElasticBlockStoreClientExpectTest.java @@ -0,0 +1,71 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.ec2.services; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import org.jclouds.ec2.EC2Client; +import org.jclouds.ec2.domain.Volume; +import org.jclouds.ec2.internal.BaseEC2ExpectTest; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; +import com.google.common.collect.ImmutableMultimap; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "EC2ElasticBlockStoreClientExpectTest") +public class EC2ElasticBlockStoreClientExpectTest extends BaseEC2ExpectTest { + + public void testCreateVolumeInAvailabilityZone() { + Builder builder = ImmutableMap.builder(); + builder.put(describeRegionsRequest, describeRegionsResponse); + builder.putAll(describeAvailabilityZonesRequestResponse); + builder.put( + HttpRequest.builder() + .method("POST") + .endpoint(URI.create("https://ec2.us-east-1.amazonaws.com/")) + .headers(ImmutableMultimap.of("Host", "ec2.us-east-1.amazonaws.com")) + .payload(payloadFromStringWithContentType("Action=CreateVolume&AvailabilityZone=us-east-1a&Signature=FB5hTZHKSAuiygoafIdJh1EnfTu0ogC2VfRQOar85mg%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Size=4&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2010-06-15&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/created_volume.xml")).build()); + + ElasticBlockStoreClient client = requestsSendResponses(builder.build()).getElasticBlockStoreServices(); + Volume expected = Volume + .builder() + .id("vol-2a21e543") + .status(Volume.Status.CREATING) + .availabilityZone("us-east-1a") + .region("us-east-1") + .id("vol-2a21e543") + .size(1) + .createTime(dateService.iso8601DateParse("2009-12-28T05:42:53.000Z")) + .build(); + + assertEquals(client.createVolumeInAvailabilityZone("us-east-1a", 4), expected); + } + +} diff --git a/apis/ec2/src/test/resources/availabilityZones-ap-northeast-1.xml b/apis/ec2/src/test/resources/availabilityZones-ap-northeast-1.xml new file mode 100644 index 0000000000..129daf59ef --- /dev/null +++ b/apis/ec2/src/test/resources/availabilityZones-ap-northeast-1.xml @@ -0,0 +1,17 @@ + + 24251909-7fb6-4080-8ca3-fbb5a1ddb02d + + + ap-northeast-1a + available + ap-northeast-1 + + + + ap-northeast-1b + available + ap-northeast-1 + + + + \ No newline at end of file diff --git a/apis/ec2/src/test/resources/availabilityZones-ap-southeast-1.xml b/apis/ec2/src/test/resources/availabilityZones-ap-southeast-1.xml new file mode 100644 index 0000000000..47b33ec747 --- /dev/null +++ b/apis/ec2/src/test/resources/availabilityZones-ap-southeast-1.xml @@ -0,0 +1,17 @@ + + 22c5332d-c331-4310-b695-e21e76c3fdb0 + + + ap-southeast-1a + available + ap-southeast-1 + + + + ap-southeast-1b + available + ap-southeast-1 + + + + \ No newline at end of file diff --git a/apis/ec2/src/test/resources/availabilityZones-eu-west-1.xml b/apis/ec2/src/test/resources/availabilityZones-eu-west-1.xml new file mode 100644 index 0000000000..921216c9f3 --- /dev/null +++ b/apis/ec2/src/test/resources/availabilityZones-eu-west-1.xml @@ -0,0 +1,23 @@ + + 386c8215-6ec8-4495-aaa6-8c4175688093 + + + eu-west-1a + available + eu-west-1 + + + + eu-west-1b + available + eu-west-1 + + + + eu-west-1c + available + eu-west-1 + + + + \ No newline at end of file diff --git a/apis/ec2/src/test/resources/availabilityZones-sa-east-1.xml b/apis/ec2/src/test/resources/availabilityZones-sa-east-1.xml new file mode 100644 index 0000000000..d6f97c6c3c --- /dev/null +++ b/apis/ec2/src/test/resources/availabilityZones-sa-east-1.xml @@ -0,0 +1,17 @@ + + d2e09bd5-b2ec-4c6b-aac9-6bf1fa217cb5 + + + sa-east-1a + available + sa-east-1 + + + + sa-east-1b + available + sa-east-1 + + + + \ No newline at end of file diff --git a/apis/ec2/src/test/resources/availabilityZones-us-east-1.xml b/apis/ec2/src/test/resources/availabilityZones-us-east-1.xml new file mode 100644 index 0000000000..52b521e823 --- /dev/null +++ b/apis/ec2/src/test/resources/availabilityZones-us-east-1.xml @@ -0,0 +1,35 @@ + + ed825abf-edbb-4677-83d5-0fbd86ce5a5d + + + us-east-1a + available + us-east-1 + + + + us-east-1b + available + us-east-1 + + + + us-east-1c + available + us-east-1 + + + + us-east-1d + available + us-east-1 + + + + us-east-1e + available + us-east-1 + + + + \ No newline at end of file diff --git a/apis/ec2/src/test/resources/availabilityZones-us-west-1.xml b/apis/ec2/src/test/resources/availabilityZones-us-west-1.xml new file mode 100644 index 0000000000..c74ce18d12 --- /dev/null +++ b/apis/ec2/src/test/resources/availabilityZones-us-west-1.xml @@ -0,0 +1,23 @@ + + dbfb2a5f-ce75-49fb-846b-e2cf2fc5cdbb + + + us-west-1a + available + us-west-1 + + + + us-west-1b + available + us-west-1 + + + + us-west-1c + available + us-west-1 + + + + \ No newline at end of file diff --git a/apis/ec2/src/test/resources/availabilityZones-us-west-2.xml b/apis/ec2/src/test/resources/availabilityZones-us-west-2.xml new file mode 100644 index 0000000000..a782705ec5 --- /dev/null +++ b/apis/ec2/src/test/resources/availabilityZones-us-west-2.xml @@ -0,0 +1,23 @@ + + e40c2bc4-7231-4df1-a604-202bb8333332 + + + us-west-2a + available + us-west-2 + + + + us-west-2b + available + us-west-2 + + + + us-west-2c + available + us-west-2 + + + + \ No newline at end of file diff --git a/apis/ec2/src/test/resources/regionEndpoints-all.xml b/apis/ec2/src/test/resources/regionEndpoints-all.xml new file mode 100644 index 0000000000..d577f72b8f --- /dev/null +++ b/apis/ec2/src/test/resources/regionEndpoints-all.xml @@ -0,0 +1,34 @@ + + + 8392a998-c7bb-41fc-be15-045f528d7627 + + + eu-west-1 + ec2.eu-west-1.amazonaws.com + + + sa-east-1 + ec2.sa-east-1.amazonaws.com + + + us-east-1 + ec2.us-east-1.amazonaws.com + + + ap-northeast-1 + ec2.ap-northeast-1.amazonaws.com + + + us-west-2 + ec2.us-west-2.amazonaws.com + + + us-west-1 + ec2.us-west-1.amazonaws.com + + + ap-southeast-1 + ec2.ap-southeast-1.amazonaws.com + + + \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/location/suppliers/derived/ZoneIdToURIFromJoinOnRegionIdToURI.java b/core/src/main/java/org/jclouds/location/suppliers/derived/ZoneIdToURIFromJoinOnRegionIdToURI.java new file mode 100644 index 0000000000..7bbde01200 --- /dev/null +++ b/core/src/main/java/org/jclouds/location/suppliers/derived/ZoneIdToURIFromJoinOnRegionIdToURI.java @@ -0,0 +1,64 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.location.suppliers.derived; + +import java.net.URI; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.location.Region; +import org.jclouds.location.Zone; +import org.jclouds.location.suppliers.ZoneIdToURISupplier; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; + +/** + * + */ +@Singleton +public class ZoneIdToURIFromJoinOnRegionIdToURI implements ZoneIdToURISupplier { + + private final Supplier>> regionIdToURISupplier; + private final Supplier>>> regionIdToZoneIdsSupplier; + + @Inject + protected ZoneIdToURIFromJoinOnRegionIdToURI(@Region Supplier>> regionIdToURISupplier, + @Zone Supplier>>> regionIdToZoneIdsSupplier) { + this.regionIdToURISupplier = regionIdToURISupplier; + this.regionIdToZoneIdsSupplier = regionIdToZoneIdsSupplier; + } + + @Override + public Map> get() { + Builder> builder = ImmutableMap.> builder(); + for (Entry> regionToURI : regionIdToURISupplier.get().entrySet()) { + for (String zone : regionIdToZoneIdsSupplier.get().get(regionToURI.getKey()).get()) { + builder.put(zone, regionToURI.getValue()); + } + } + return builder.build(); + } + +} \ No newline at end of file