diff --git a/apis/ec2/pom.xml b/apis/ec2/pom.xml index 4818c575a3d..fafde835d84 100644 --- a/apis/ec2/pom.xml +++ b/apis/ec2/pom.xml @@ -33,7 +33,7 @@ https://ec2.us-east-1.amazonaws.com - 2010-06-15 + 2010-08-31 ${test.aws.identity} ${test.aws.credential} diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/EC2ApiMetadata.java b/apis/ec2/src/main/java/org/jclouds/ec2/EC2ApiMetadata.java index 8d544a36fff..2b081c51158 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/EC2ApiMetadata.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/EC2ApiMetadata.java @@ -72,7 +72,7 @@ public Builder() { .credentialName("Secret Access Key") .defaultEndpoint("https://ec2.us-east-1.amazonaws.com") .documentation(URI.create("http://docs.amazonwebservices.com/AWSEC2/latest/APIReference")) - .version("2010-06-15") + .version("2010-08-31") .defaultProperties(EC2ApiMetadata.defaultProperties()) .view(EC2ComputeServiceContext.class) .defaultModules(ImmutableSet.>of(EC2HttpApiModule.class, EC2ResolveImagesModule.class, EC2ComputeServiceContextModule.class)); diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/EC2ComputeService.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/EC2ComputeService.java index 7bfa4bd7934..248102e5f99 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/EC2ComputeService.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/EC2ComputeService.java @@ -15,10 +15,10 @@ * limitations under the License. */ package org.jclouds.ec2.compute; + import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Strings.emptyToNull; import static com.google.common.collect.Iterables.concat; -import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.transform; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; @@ -77,11 +77,13 @@ import org.jclouds.ec2.compute.domain.RegionAndName; import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules; import org.jclouds.ec2.compute.options.EC2TemplateOptions; +import org.jclouds.ec2.domain.InstanceState; import org.jclouds.ec2.domain.KeyPair; import org.jclouds.ec2.domain.RunningInstance; import org.jclouds.ec2.domain.Tag; import org.jclouds.ec2.util.TagFilterBuilder; import org.jclouds.scriptbuilder.functions.InitAdminAccess; +import org.jclouds.util.Strings2; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; @@ -224,15 +226,23 @@ void deleteSecurityGroup(String region, String group) { @VisibleForTesting void deleteKeyPair(String region, String group) { - for (KeyPair keyPair : client.getKeyPairApi().get().describeKeyPairsInRegion(region)) { + for (KeyPair keyPair : client.getKeyPairApi().get().describeKeyPairsInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("key-name", Strings2.urlEncode( + String.format("jclouds#%s#%s*", group, region).replace('#', delimiter))) + .build())) { String keyName = keyPair.getKeyName(); Predicate keyNameMatcher = namingConvention.create().containsGroup(group); String oldKeyNameRegex = String.format("jclouds#%s#%s#%s", group, region, "[0-9a-f]+").replace('#', delimiter); // old keypair pattern too verbose as it has an unnecessary region qualifier if (keyNameMatcher.apply(keyName) || keyName.matches(oldKeyNameRegex)) { - Set instancesUsingKeyPair = extractIdsFromInstances(filter(concat(client.getInstanceApi().get() - .describeInstancesInRegion(region)), usingKeyPairAndNotDead(keyPair))); + Set instancesUsingKeyPair = extractIdsFromInstances(concat(client.getInstanceApi().get() + .describeInstancesInRegionWithFilter(region, ImmutableMultimap.builder() + .put("instance-state-name", InstanceState.TERMINATED.toString()) + .put("instance-state-name", InstanceState.SHUTTING_DOWN.toString()) + .put("key-name", keyPair.getKeyName()).build()))); + if (instancesUsingKeyPair.size() > 0) { logger.debug("<< inUse keyPair(%s), by (%s)", keyPair.getKeyName(), instancesUsingKeyPair); } else { @@ -258,20 +268,6 @@ public String apply(RunningInstance input) { })); } - protected Predicate usingKeyPairAndNotDead(final KeyPair keyPair) { - return new Predicate() { - @Override - public boolean apply(RunningInstance input) { - switch (input.getInstanceState()) { - case TERMINATED: - case SHUTTING_DOWN: - return false; - } - return keyPair.getKeyName().equals(input.getKeyName()); - } - }; - } - /** * Cleans implicit keypairs and security groups. */ diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/domain/RunningInstance.java b/apis/ec2/src/main/java/org/jclouds/ec2/domain/RunningInstance.java index 9b502d6bf9e..725165acdfb 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/domain/RunningInstance.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/domain/RunningInstance.java @@ -330,7 +330,7 @@ public String getRegion() { * more information, go to the Metadata section of the Amazon Elastic Compute Cloud Developer * Guide. * - * @see + * @see */ public String getAmiLaunchIndex() { return amiLaunchIndex; diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/AMIApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/AMIApi.java index 40540aaf255..bdc77563221 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/features/AMIApi.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/AMIApi.java @@ -28,6 +28,7 @@ import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404; import org.jclouds.aws.filters.FormSigner; +import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams; import org.jclouds.ec2.binders.BindUserGroupsToIndexedFormParams; import org.jclouds.ec2.binders.BindUserIdsToIndexedFormParams; import org.jclouds.ec2.domain.Image; @@ -51,6 +52,8 @@ import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; +import com.google.common.collect.Multimap; + /** * Provides access to AMI Services. *

@@ -85,6 +88,33 @@ Set describeImagesInRegion( @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, DescribeImagesOptions... options); + /** + * Returns information about AMIs, AKIs, and ARIs. This includes image type, product codes, + * architecture, and kernel and RAM disk IDs. Images available to you include public images, + * private images that you own, and private images owned by other users for which you have + * explicit launch permissions. + * + * @param region + * AMIs are tied to the Region where its files are located within Amazon S3. + * @param filter + * Multimap of filter key/values. + * @see InstanceApi#describeInstances + * @see #describeImageAttribute + * @see + * @see DescribeImagesOptions + */ + @Named("DescribeImages") + @POST + @Path("/") + @FormParams(keys = ACTION, values = "DescribeImages") + @XMLResponseParser(DescribeImagesResponseHandler.class) + @Fallback(EmptySetOnNotFoundOr404.class) + Set describeImagesInRegionWithFilter( + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, + @BinderParam(BindFiltersToIndexedFormParams.class) Multimap filter, + DescribeImagesOptions... options); + /** * Creates an AMI that uses an Amazon EBS root device from a "running" or "stopped" instance. * diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticBlockStoreApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticBlockStoreApi.java index 8e56f7711ed..69c92bf07c3 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticBlockStoreApi.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticBlockStoreApi.java @@ -28,6 +28,7 @@ import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404; import org.jclouds.aws.filters.FormSigner; import org.jclouds.ec2.EC2Fallbacks.VoidOnVolumeAvailable; +import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams; import org.jclouds.ec2.binders.BindUserGroupsToIndexedFormParams; import org.jclouds.ec2.binders.BindUserIdsToIndexedFormParams; import org.jclouds.ec2.binders.BindVolumeIdsToIndexedFormParams; @@ -55,6 +56,8 @@ import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; +import com.google.common.collect.Multimap; + /** * Provides access to EC2 Elastic Block Store services via their REST API. *

@@ -168,25 +171,50 @@ Volume createVolumeInAvailabilityZone( * volume IDs, Amazon EBS describes all volumes that you own. For more information about Amazon * EBS, go to the Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud * User Guide. - * + * * @param region * region where the volume is defined * @param volumeIds * The ID of the volume to list. Defaults to describe all volumes that you own. - * + * * @see #createSnapshotInRegion * @see #describeSnapshotInRegion * @see */ @POST - @Named("DescribeVolumes") + @Named("DescribeVolumes") @Path("/") @FormParams(keys = ACTION, values = "DescribeVolumes") @XMLResponseParser(DescribeVolumesResponseHandler.class) Set describeVolumesInRegion( - @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, - @BinderParam(BindVolumeIdsToIndexedFormParams.class) String... volumeIds); + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, + @BinderParam(BindVolumeIdsToIndexedFormParams.class) String... volumeIds); + + /** + * Describes the specified Amazon EBS volumes that you own and match the given filters. If you + * do not specify any filters, Amazon EBS describes all volumes that you own. For more + * information about Amazon EBS, go to the Amazon Elastic Compute Cloud Developer Guide or + * Amazon Elastic Compute Cloud User Guide. + * + * @param region + * region where the volume is defined + * @param filter + * Multimap of filter key/values + * + * @see #createSnapshotInRegion + * @see #describeSnapshotInRegion + * @see + */ + @POST + @Named("DescribeVolumes") + @Path("/") + @FormParams(keys = ACTION, values = "DescribeVolumes") + @XMLResponseParser(DescribeVolumesResponseHandler.class) + Set describeVolumesInRegionWithFilter( + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, + @BinderParam(BindFiltersToIndexedFormParams.class) Multimap filter); /** * Deletes an Amazon EBS volume that you own. For more information about Amazon EBS, go to the @@ -413,6 +441,35 @@ Set describeSnapshotsInRegion( @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, DescribeSnapshotsOptions... options); + /** + * Returns information about EBS snapshots matching the given filters. + * + * @param region + * Snapshots are tied to Regions and can only be used for volumes within the same + * Region. + * @param filter + * Multimap of filter key/values. + * @param options + * specify the snapshot ids or other parameters to clarify the list. + * @return matching snapshots. + * + * @see #describeSnapshotsInRegion + * @see #createSnapshotsInRegion + * @see #deleteSnapshotInRegion + * @see + */ + @Named("DescribeSnapshots") + @POST + @Path("/") + @FormParams(keys = ACTION, values = "DescribeSnapshots") + @XMLResponseParser(DescribeSnapshotsResponseHandler.class) + @Fallback(EmptySetOnNotFoundOr404.class) + Set describeSnapshotsInRegionWithFilter( + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, + @BinderParam(BindFiltersToIndexedFormParams.class) Multimap filter, + DescribeSnapshotsOptions... options); + /** * Deletes a snapshot of an Amazon EBS volume that you own. For more information, go to the * Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide. diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticIPAddressApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticIPAddressApi.java index 47d93a7a635..3401cde1d0e 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticIPAddressApi.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticIPAddressApi.java @@ -27,6 +27,7 @@ import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404; import org.jclouds.aws.filters.FormSigner; +import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams; import org.jclouds.ec2.binders.BindPublicIpsToIndexedFormParams; import org.jclouds.ec2.domain.PublicIpInstanceIdPair; import org.jclouds.ec2.xml.AllocateAddressResponseHandler; @@ -38,9 +39,12 @@ import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.FormParams; import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SinceApiVersion; import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; +import com.google.common.collect.Multimap; + /** * Provides access to EC2 Elastic IP Addresses via REST API. *

@@ -168,4 +172,29 @@ Set describeAddressesInRegion( @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, @BinderParam(BindPublicIpsToIndexedFormParams.class) String... publicIps); + /** + * Lists elastic IP addresses assigned to your identity or provides information on addresses + * matching a given filter. + * + * @param region + * Elastic IP addresses are tied to a Region and cannot be mapped across Regions. + * @param filter + * + * @throws AWSResponseException + * if the requested publicIp is not found + * @see #allocateAddress + * @see #releaseAddress + * @see + */ + @SinceApiVersion("2010-08-31") + @Named("DescribeAddresses") + @POST + @Path("/") + @FormParams(keys = ACTION, values = "DescribeAddresses") + @XMLResponseParser(DescribeAddressesResponseHandler.class) + @Fallback(EmptySetOnNotFoundOr404.class) + Set describeAddressesInRegionWithFilter( + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, + @BinderParam(BindFiltersToIndexedFormParams.class) Multimap filter); } diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/InstanceApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/InstanceApi.java index 2b56324ffa3..5d7a5913baf 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/features/InstanceApi.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/InstanceApi.java @@ -29,6 +29,7 @@ import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404; import org.jclouds.aws.filters.FormSigner; import org.jclouds.ec2.binders.BindBlockDeviceMappingToIndexedFormParams; +import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams; import org.jclouds.ec2.binders.BindInstanceIdsToIndexedFormParams; import org.jclouds.ec2.binders.IfNotNullBindAvailabilityZoneToFormParam; import org.jclouds.ec2.domain.BlockDevice; @@ -56,9 +57,12 @@ import org.jclouds.rest.annotations.FormParams; import org.jclouds.rest.annotations.ParamParser; import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SinceApiVersion; import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; +import com.google.common.collect.Multimap; + /** * Provides access to EC2 Instance Services via their REST API. *

@@ -101,6 +105,40 @@ Set> describeInstancesInRegion( @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds); + /** + * Returns information about instances that you own. + *

+ * + * If you specify one or filters, Amazon EC2 returns information for instances + * matching those filters. If you do not specify any filters, Amazon EC2 + * returns information for all relevant instances. If you specify an invalid + * filter, a fault is returned. Only instances you own will be included in the + * results. + *

+ * Recently terminated instances might appear in the returned results. This + * interval is usually less than one hour. + * + * @param region + * Instances are tied to Availability Zones. However, the instance + * ID is tied to the Region. + * @param filter + * + * @see #runInstancesInRegion + * @see #terminateInstancesInRegion + * @see + */ + @SinceApiVersion("2010-08-31") + @Named("DescribeInstances") + @POST + @Path("/") + @FormParams(keys = ACTION, values = "DescribeInstances") + @XMLResponseParser(DescribeInstancesResponseHandler.class) + @Fallback(EmptySetOnNotFoundOr404.class) + Set> describeInstancesInRegionWithFilter( + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, + @BinderParam(BindFiltersToIndexedFormParams.class) Multimap filter); + /** * Launches a specified number of instances of an AMI for which you have * permissions. diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/KeyPairApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/KeyPairApi.java index b09406e2117..c10f3eb342e 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/features/KeyPairApi.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/KeyPairApi.java @@ -27,6 +27,7 @@ import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404; import org.jclouds.aws.filters.FormSigner; +import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams; import org.jclouds.ec2.binders.BindKeyNamesToIndexedFormParams; import org.jclouds.ec2.domain.KeyPair; import org.jclouds.ec2.xml.DescribeKeyPairsResponseHandler; @@ -41,6 +42,8 @@ import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; +import com.google.common.collect.Multimap; + /** * Provides access to EC2 via their REST API. *

@@ -104,6 +107,31 @@ Set describeKeyPairsInRegion( @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, @BinderParam(BindKeyNamesToIndexedFormParams.class) String... keyPairNames); + /** + * Returns information about key pairs available to you. If you specify filters, + * information about keypairs matching those filters is returned. Otherwise, all + * keypairs you have access to are returned. + * + * @param region + * Key pairs (to connect to instances) are Region-specific. + * @param filter + * Multimap of filter key/values. + * + * @see #runInstances + * @see #describeAvailabilityZones + * @see + */ + @Named("DescribeKeyPairs") + @POST + @Path("/") + @FormParams(keys = ACTION, values = "DescribeKeyPairs") + @XMLResponseParser(DescribeKeyPairsResponseHandler.class) + @Fallback(EmptySetOnNotFoundOr404.class) + Set describeKeyPairsInRegionWithFilter( + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, + @BinderParam(BindFiltersToIndexedFormParams.class) Multimap filter); + /** * Deletes the specified key pair, by removing the public key from Amazon EC2. You must own the * key pair diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/SecurityGroupApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/SecurityGroupApi.java index 70cbdac557d..c082bd0f2c7 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/features/SecurityGroupApi.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/SecurityGroupApi.java @@ -28,6 +28,7 @@ import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404; import org.jclouds.Fallbacks.VoidOnNotFoundOr404; import org.jclouds.aws.filters.FormSigner; +import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams; import org.jclouds.ec2.binders.BindGroupNamesToIndexedFormParams; import org.jclouds.ec2.binders.BindUserIdGroupPairToSourceSecurityGroupFormParams; import org.jclouds.ec2.domain.SecurityGroup; @@ -44,6 +45,8 @@ import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; +import com.google.common.collect.Multimap; + /** * Provides access to EC2 via their REST API. *

@@ -113,19 +116,19 @@ void deleteSecurityGroupInRegion( /** * Returns information about security groups that you own. - * + * * @param region * Security groups are not copied across Regions. Instances within the Region cannot * communicate with instances outside the Region using group-based firewall rules. * Traffic from instances in another Region is seen as WAN bandwidth. * @param securityGroupNames * Name of the security groups - * + * * @see #createSecurityGroup * @see #authorizeSecurityGroupIngress * @see #revokeSecurityGroupIngress * @see #deleteSecurityGroup - * + * * @see */ @@ -136,8 +139,36 @@ void deleteSecurityGroupInRegion( @XMLResponseParser(DescribeSecurityGroupsResponseHandler.class) @Fallback(EmptySetOnNotFoundOr404.class) Set describeSecurityGroupsInRegion( - @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, - @BinderParam(BindGroupNamesToIndexedFormParams.class) String... securityGroupNames); + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, + @BinderParam(BindGroupNamesToIndexedFormParams.class) String... securityGroupNames); + + /** + * Returns information about security groups that you own. + * + * @param region + * Security groups are not copied across Regions. Instances within the Region cannot + * communicate with instances outside the Region using group-based firewall rules. + * Traffic from instances in another Region is seen as WAN bandwidth. + * @param filter + * Multimap of filter key/values. + * + * @see #createSecurityGroup + * @see #authorizeSecurityGroupIngress + * @see #revokeSecurityGroupIngress + * @see #deleteSecurityGroup + * + * @see + */ + @Named("DescribeSecurityGroups") + @POST + @Path("/") + @FormParams(keys = ACTION, values = "DescribeSecurityGroups") + @XMLResponseParser(DescribeSecurityGroupsResponseHandler.class) + @Fallback(EmptySetOnNotFoundOr404.class) + Set describeSecurityGroupsInRegionWithFilter( + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, + @BinderParam(BindFiltersToIndexedFormParams.class) Multimap filter); /** * diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/WindowsApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/WindowsApi.java index b895d0bdae6..5461b2331d0 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/features/WindowsApi.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/WindowsApi.java @@ -29,6 +29,7 @@ import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.aws.filters.FormSigner; import org.jclouds.ec2.binders.BindBundleIdsToIndexedFormParams; +import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams; import org.jclouds.ec2.binders.BindS3UploadPolicyAndSignature; import org.jclouds.ec2.domain.BundleTask; import org.jclouds.ec2.domain.PasswordData; @@ -47,6 +48,8 @@ import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; +import com.google.common.collect.Multimap; + /** * Provides access to EC2 Windows Features via the Query API *

@@ -136,12 +139,12 @@ BundleTask cancelBundleTaskInRegion( @FormParam("BundleId") String bundleId); /** - * + * * Describes current bundling tasks. - * + * * @param region * The bundleTask ID is tied to the Region. - * + * * @see #cancelBundleTaskInRegion * @see #bundleInstanceInRegion * @see describeBundleTasksInRegion( - @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, - @BinderParam(BindBundleIdsToIndexedFormParams.class) String... bundleTaskIds); + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, + @BinderParam(BindBundleIdsToIndexedFormParams.class) String... bundleTaskIds); + + /** + * + * Describes current bundling tasks. + * + * @param region + * The bundleTask ID is tied to the Region. + * @param filter + * Filter multimap + * + * @see #cancelBundleTaskInRegion + * @see #bundleInstanceInRegion + * @see + */ + @Named("DescribeBundleTasks") + @POST + @Path("/") + @FormParams(keys = ACTION, values = "DescribeBundleTasks") + @XMLResponseParser(DescribeBundleTasksResponseHandler.class) + @Fallback(EmptySetOnNotFoundOr404.class) + Set describeBundleTasksInRegionWithFilter( + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, + @BinderParam(BindFiltersToIndexedFormParams.class) Multimap filter); /** * diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java index 8e9a656b65c..b55875a539c 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java @@ -46,7 +46,7 @@ /** * Parses the following XML document: *

- * DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/2010-06-15/" + * DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/2010-08-31/" * * @author Adrian Cole * @see diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeSecurityGroupsResponseHandler.java b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeSecurityGroupsResponseHandler.java index aed7ee005bf..8a00ac4a94f 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeSecurityGroupsResponseHandler.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeSecurityGroupsResponseHandler.java @@ -34,7 +34,7 @@ /** * Parses: DescribeSecurityGroupsResponse - * xmlns="http://ec2.amazonaws.com/doc/2010-06-15/" + * xmlns="http://ec2.amazonaws.com/doc/2010-08-31/" * * @see - * TerminateInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-06-15/" - * StartInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-06-15/" StopInstancesResponse - * xmlns="http://ec2.amazonaws.com/doc/2010-06-15/" + * TerminateInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-08-31/" + * StartInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-08-31/" StopInstancesResponse + * xmlns="http://ec2.amazonaws.com/doc/2010-08-31/" * * @author Adrian Cole * @see { + + HttpRequest filter = HttpRequest.builder().method("POST") + .endpoint("https://ec2.us-east-1.amazonaws.com/") + .addHeader("Host", "ec2.us-east-1.amazonaws.com") + .addFormParam("Action", "DescribeImages") + .addFormParam("Filter.1.Name", "owner-id") + .addFormParam("Filter.1.Value.1", "206029621532") + .addFormParam("Signature", "BxOCrCYJujtaUqSPagRvv1ki76veVBiKK3yWHvRWgR0%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-08-31") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testFilterWhenResponseIs2xx() { + HttpResponse filterResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/describe_images.xml", "text/xml")).build(); + + EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse); + + Image image = getOnlyElement(apiWhenExist.getAMIApi().get().describeImagesInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("owner-id", "206029621532") + .build())); + + assertEquals(image.getId(), "ami-be3adfd7"); + } + + public void testFilterWhenResponseIs404() { + HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build(); + + EC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse); + + assertEquals(apiWhenNotExist.getAMIApi().get().describeImagesInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("owner-id", "206029621532") + .build()), + ImmutableSet.of()); + } +} \ No newline at end of file diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java index 3eee3976370..2b56e0a380f 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java @@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Iterables.concat; +import static com.google.common.collect.Iterables.getFirst; import static com.google.common.collect.Iterables.getOnlyElement; import static com.google.common.collect.Sets.newHashSet; import static java.util.concurrent.TimeUnit.SECONDS; @@ -32,12 +33,12 @@ import java.util.Properties; import java.util.Set; +import org.jclouds.aws.AWSResponseException; import org.jclouds.compute.RunNodesException; import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.TemplateBuilderSpec; import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; import org.jclouds.ec2.EC2Api; -import org.jclouds.ec2.EC2ApiMetadata; import org.jclouds.ec2.domain.BlockDevice; import org.jclouds.ec2.domain.Image; import org.jclouds.ec2.domain.Image.ImageType; @@ -51,6 +52,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; /** * Tests behavior of {@code AMIApi} @@ -98,7 +100,9 @@ public void setupContext() { Template template = view.getComputeService().templateBuilder().from(ebsTemplate).build(); regionId = template.getLocation().getId(); imageId = template.getImage().getProviderId(); - for (Image image : client.describeImagesInRegion(regionId)) { + for (Image image : client.describeImagesInRegionWithFilter(regionId, + ImmutableMultimap.builder() + .put("name", ebsBackedImageName).build())) { if (ebsBackedImageName.equals(image.getName())) client.deregisterImageInRegion(regionId, image.getId()); } @@ -115,20 +119,58 @@ public void testDescribeImageBadId() { } public void testDescribeImages() { - for (String region : ec2Api.getConfiguredRegions()) { - Set allResults = client.describeImagesInRegion(region); - assertNotNull(allResults); - assert allResults.size() >= 2 : allResults.size(); - Iterator iterator = allResults.iterator(); - String id1 = iterator.next().getId(); - String id2 = iterator.next().getId(); - Set twoResults = client.describeImagesInRegion(region, imageIds(id1, id2)); - assertNotNull(twoResults); - assertEquals(twoResults.size(), 2); - iterator = twoResults.iterator(); - assertEquals(iterator.next().getId(), id1); - assertEquals(iterator.next().getId(), id2); - } + // Just run in the first region - no need to take the time on all of them. + String region = getFirst(ec2Api.getConfiguredRegions(), null); + assertNotNull(region, "region should not be null"); + Set allResults = client.describeImagesInRegion(region); + assertNotNull(allResults); + assertTrue(allResults.size() >= 2); + Iterator iterator = allResults.iterator(); + String id1 = iterator.next().getId(); + String id2 = iterator.next().getId(); + Set twoResults = client.describeImagesInRegion(region, imageIds(id1, id2)); + assertNotNull(twoResults); + assertEquals(twoResults.size(), 2); + iterator = twoResults.iterator(); + assertEquals(iterator.next().getId(), id1); + assertEquals(iterator.next().getId(), id2); + } + + @Test + public void testDescribeImagesWithFilter() { + // Just run in the first region - no need to take the time on all of them. + String region = getFirst(ec2Api.getConfiguredRegions(), null); + assertNotNull(region, "region should not be null"); + Set allResults = client.describeImagesInRegion(region); + assertNotNull(allResults); + assertTrue(allResults.size() >= 2); + String id1 = allResults.iterator().next().getId(); + Set filterResult = client.describeImagesInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("image-id", id1) + .build()); + assertNotNull(filterResult); + assertEquals(filterResult.size(), 1); + assertEquals(filterResult.iterator().next().getId(), id1); + } + + @Test(expectedExceptions = AWSResponseException.class) + public void testDescribeImagesWithInvalidFilter() { + // Just run in the first region - no need to take the time on all of them. + String region = getFirst(ec2Api.getConfiguredRegions(), null); + assertNotNull(region, "region should not be null"); + + Set allResults = client.describeImagesInRegion(region); + assertNotNull(allResults); + assertTrue(allResults.size() >= 2); + String id1 = allResults.iterator().next().getId(); + Set filterResult = client.describeImagesInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("invalid-filter-id", id1) + .build()); + assertNotNull(filterResult); + assertEquals(filterResult.size(), 1); + assertEquals(filterResult.iterator().next().getId(), id1); } @Test @@ -136,7 +178,9 @@ public void testCreateAndListEBSBackedImage() throws Exception { Snapshot snapshot = createSnapshot(); // List of images before... - int sizeBefore = client.describeImagesInRegion(regionId).size(); + int sizeBefore = client.describeImagesInRegionWithFilter(regionId, + ImmutableMultimap.builder() + .put("name", ebsBackedImageName).build()).size(); // Register a new image... ebsBackedImageId = client.registerUnixImageBackedByEbsInRegion(regionId, ebsBackedImageName, snapshot.getId(), @@ -154,7 +198,10 @@ public void testCreateAndListEBSBackedImage() throws Exception { "/dev/sda2", new Image.EbsBlockDevice(null, 1, false)).entrySet()); // List of images after - should be one larger than before - int after = client.describeImagesInRegion(regionId).size(); + int after = client.describeImagesInRegionWithFilter(regionId, + ImmutableMultimap.builder() + .put("name", ebsBackedImageName).build()).size(); + assertEquals(after, sizeBefore + 1); } diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiTest.java index c3907ab44a5..b4b7f85a2d0 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiTest.java @@ -54,11 +54,11 @@ public class AMIApiTest extends BaseEC2ApiTest { .addFormParam("Action", "CreateImage") .addFormParam("InstanceId", "instanceId") .addFormParam("Name", "name") - .addFormParam("Signature", "hBIUf4IUOiCKGQKehaNwwbZUjRN4NC4RSNfJ%2B8kvJdY%3D") + .addFormParam("Signature", "MuMtOMs697BLVks2RUZUNeLdVCo6NXPHuDhh0nmNtvc%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testCreateImage() throws SecurityException, NoSuchMethodException, IOException { @@ -87,11 +87,11 @@ public void testCreateImage() throws SecurityException, NoSuchMethodException, I .addFormParam("InstanceId", "instanceId") .addFormParam("Name", "name") .addFormParam("NoReboot", "true") - .addFormParam("Signature", "fz3KW27JxlSq9ivmVOl4IujcHXXw1cOhdig80I7wR6o%3D") + .addFormParam("Signature", "8SgbaWihxOICMXDLvwk3ahy/99nhZvTvbno%2B8dMyvJg%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testCreateImageOptions() throws SecurityException, NoSuchMethodException, IOException { @@ -118,11 +118,11 @@ public void testCreateImageOptions() throws SecurityException, NoSuchMethodExcep .endpoint("https://ec2.us-east-1.amazonaws.com/") .addHeader("Host", "ec2.us-east-1.amazonaws.com") .addFormParam("Action", "DescribeImages") - .addFormParam("Signature", "qE4vexSFJqS0UWK%2BccV3s%2BP9woL3M5HI5bTBoM7s/LY%3D") + .addFormParam("Signature", "hQxNAaRVX6OvXV0IKgx1vV0FoNbRyuHQ2fhRhaPJnS8%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testDescribeImages() throws SecurityException, NoSuchMethodException, IOException { @@ -153,11 +153,11 @@ public void testDescribeImages() throws SecurityException, NoSuchMethodException .addFormParam("ImageId.2", "2") .addFormParam("Owner.1", "fred") .addFormParam("Owner.2", "nancy") - .addFormParam("Signature", "%2BE9wji7oFnNUaGmOBggYNNp6v%2BL8OzSGjuI4nx1l2Jw%3D") + .addFormParam("Signature", "cIft3g1fwMu52NgB0En9NtHyXjVhmeSx7TBP7YR%2BTvI%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testDescribeImagesOptions() throws SecurityException, NoSuchMethodException, IOException { @@ -185,11 +185,11 @@ public void testDescribeImagesOptions() throws SecurityException, NoSuchMethodEx .addHeader("Host", "ec2.us-east-1.amazonaws.com") .addFormParam("Action", "DeregisterImage") .addFormParam("ImageId", "imageId") - .addFormParam("Signature", "3sk9LAJAIr2lG04OMuI0qtzCoBtCU1Ac9I6TTmAWjyA%3D") + .addFormParam("Signature", "tm6nGoPPJh7xt5TSdV5Ov0DJvcGTAW%2BYSfXL7j%2BTkOA%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testDeregisterImage() throws SecurityException, NoSuchMethodException, IOException { @@ -216,11 +216,11 @@ public void testDeregisterImage() throws SecurityException, NoSuchMethodExceptio .addFormParam("Action", "RegisterImage") .addFormParam("ImageLocation", "pathToManifest") .addFormParam("Name", "name") - .addFormParam("Signature", "alGqfUiV/bpmpCAj/YzG9VxdTeCwOYyoPjNfwYhm7os%3D") + .addFormParam("Signature", "Ie7k7w4Bdki3uCGeSFGdJ5EKrp/ohkHvWwivbIaVLEM%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testRegisterImageFromManifest() throws SecurityException, NoSuchMethodException, IOException { @@ -248,11 +248,11 @@ public void testRegisterImageFromManifest() throws SecurityException, NoSuchMeth .addFormParam("Description", "description") .addFormParam("ImageLocation", "pathToManifest") .addFormParam("Name", "name") - .addFormParam("Signature", "p77vQLVlPoak6cP/8eoM%2Bz6zkSXx9e2iSlGgLvIwP7I%3D") + .addFormParam("Signature", "ilWV1eAWW6kTK/jHliQ%2BIkzJR4DRNy4ye%2BSKtnUjjDs%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testRegisterImageFromManifestOptions() throws SecurityException, NoSuchMethodException, IOException { @@ -283,11 +283,11 @@ public void testRegisterImageFromManifestOptions() throws SecurityException, NoS .addFormParam("BlockDeviceMapping.0.Ebs.SnapshotId", "snapshotId") .addFormParam("Name", "imageName") .addFormParam("RootDeviceName", "/dev/sda1") - .addFormParam("Signature", "KGqYXGpJ/UQVTM172Y2TwU4tlG21JXd3Qrx5nSLBVuA%3D") + .addFormParam("Signature", "ZbZcY6uwxPbD65jFmiNZXoWeHY/2zqRuGuDmTfkt84A%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testRegisterImageBackedByEBS() throws SecurityException, NoSuchMethodException, IOException { @@ -324,11 +324,11 @@ public void testRegisterImageBackedByEBS() throws SecurityException, NoSuchMetho .addFormParam("Description", "description") .addFormParam("Name", "imageName") .addFormParam("RootDeviceName", "/dev/sda1") - .addFormParam("Signature", "xuWi0w8iODQrg4E0azwqNm2lz/Rf4hBa7m%2BunDTZvVI%3D") + .addFormParam("Signature", "DrNujyZMGrKvuw73A7ObFTThXvc/MRfNqjvIy8gey5g%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testRegisterImageBackedByEBSOptions() throws SecurityException, NoSuchMethodException, IOException { @@ -358,11 +358,11 @@ public void testRegisterImageBackedByEBSOptions() throws SecurityException, NoSu .addFormParam("Action", "DescribeImageAttribute") .addFormParam("Attribute", "blockDeviceMapping") .addFormParam("ImageId", "imageId") - .addFormParam("Signature", "puwfzm8BlfeKiEZ9CNn5ax86weZ6SQ2xyZhN6etu4gA%3D") + .addFormParam("Signature", "MJCIc1roG%2BnIWxRSUqV9KP9Wc4AWuuiNkxeDSih5/mI%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testGetBlockDeviceMappingsForImage() throws SecurityException, NoSuchMethodException, IOException { @@ -390,11 +390,11 @@ public void testGetBlockDeviceMappingsForImage() throws SecurityException, NoSuc .addFormParam("Action", "DescribeImageAttribute") .addFormParam("Attribute", "launchPermission") .addFormParam("ImageId", "imageId") - .addFormParam("Signature", "ocCMlLh3Kpg6HwIcPKlrwoPPg9C5rt5nD0dl717mOq8%3D") + .addFormParam("Signature", "iN7JbsAhM1NAES3o%2BOw8BaaFJ%2B1g9imBjcU4mFCyrxM%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testGetLaunchPermissionForImage() throws SecurityException, NoSuchMethodException, IOException { @@ -422,14 +422,14 @@ public void testGetLaunchPermissionForImage() throws SecurityException, NoSuchMe .addFormParam("Attribute", "launchPermission") .addFormParam("ImageId", "imageId") .addFormParam("OperationType", "add") - .addFormParam("Signature", "WZzNWOC1KHbuySvXEuLTiBA%2BVUfKpSBN2Lud6MrhlCQ%3D") + .addFormParam("Signature", "ZuMuzW/iQDRURhUJaBzvoAdNJrE454y6X0jM24lcxxk%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") .addFormParam("UserGroup.1", "all") .addFormParam("UserId.1", "bob") .addFormParam("UserId.2", "sue") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testAddLaunchPermissionsToImage() throws SecurityException, NoSuchMethodException, IOException { @@ -459,14 +459,14 @@ public void testAddLaunchPermissionsToImage() throws SecurityException, NoSuchMe .addFormParam("Attribute", "launchPermission") .addFormParam("ImageId", "imageId") .addFormParam("OperationType", "remove") - .addFormParam("Signature", "z8OYGQBAwu4HwXV6VF/vuOZlBtptxLxtCQiLXY7UvMU%3D") + .addFormParam("Signature", "HreSEawbVaUp/UMicCJbhrx%2BmoX01f2pEphJCPz8/5g%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") .addFormParam("UserGroup.1", "all") .addFormParam("UserId.1", "bob") .addFormParam("UserId.2", "sue") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testRemoveLaunchPermissionsFromImage() throws SecurityException, NoSuchMethodException, IOException { @@ -494,11 +494,11 @@ public void testRemoveLaunchPermissionsFromImage() throws SecurityException, NoS .addFormParam("Action", "ResetImageAttribute") .addFormParam("Attribute", "launchPermission") .addFormParam("ImageId", "imageId") - .addFormParam("Signature", "mOVwrqAzidhz%2B4E1dqOJAzG9G9ZX7eDpi8BobN4dA%2BE%3D") + .addFormParam("Signature", "fVCR9aGYvNX/Jt1/uqBGcUQRLrHwxtcvmNYKzpul1P4%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testResetLaunchPermissionsOnImage() throws SecurityException, NoSuchMethodException, IOException { diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApiLiveTest.java index 2867e69d223..3ba83322ca0 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApiLiveTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApiLiveTest.java @@ -62,7 +62,7 @@ public void testDescribeAvailabilityZones() { for (String region : ec2Api.getConfiguredRegions()) { Set allResults = client.describeAvailabilityZonesInRegion(region); assertNotNull(allResults); - assert allResults.size() >= 1 : allResults.size(); + assert !allResults.isEmpty() : allResults.size(); Iterator iterator = allResults.iterator(); String id1 = iterator.next().getZone(); Set oneResult = client.describeAvailabilityZonesInRegion(region, @@ -78,7 +78,7 @@ public void testDescribeRegions() { SortedMap allResults = Maps.newTreeMap(); allResults.putAll(client.describeRegions()); assertNotNull(allResults); - assert allResults.size() >= 1 : allResults.size(); + assert !allResults.isEmpty() : allResults.size(); Iterator> iterator = allResults.entrySet().iterator(); String r1 = iterator.next().getKey(); SortedMap oneResult = Maps.newTreeMap(); diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/EC2ElasticBlockStoreApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/EC2ElasticBlockStoreApiExpectTest.java index a72486f606e..9fc2338b0c3 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/EC2ElasticBlockStoreApiExpectTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/EC2ElasticBlockStoreApiExpectTest.java @@ -16,17 +16,22 @@ */ package org.jclouds.ec2.features; +import static com.google.common.collect.Iterables.getOnlyElement; import static org.testng.Assert.assertEquals; import org.jclouds.ec2.EC2Api; +import org.jclouds.ec2.domain.Snapshot; import org.jclouds.ec2.domain.Volume; import org.jclouds.ec2.internal.BaseEC2ApiExpectTest; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; +import org.jclouds.rest.ResourceNotFoundException; import org.testng.annotations.Test; 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; /** * @author Adrian Cole @@ -52,7 +57,7 @@ public void testCreateVolumeInAvailabilityZone() { .method("POST") .endpoint("https://ec2.us-east-1.amazonaws.com/") .addHeader("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(), + .payload(payloadFromStringWithContentType("Action=CreateVolume&AvailabilityZone=us-east-1a&Signature=NCu8HU8u0A385rTgj%2BN5lq606jkc1eu88jof9yAxb6s%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Size=4&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2010-08-31&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(), HttpResponse.builder() .statusCode(200) .payload(payloadFromResource("/created_volume.xml")).build()); @@ -85,4 +90,83 @@ public void testCreateVolumeFromSnapshotInAvailabilityZoneEuSetsCorrectEndpoint( assertEquals(client.createVolumeFromSnapshotInAvailabilityZone(region + "a", 1, "snap-8b7ffbdd"), creating.toBuilder().region(region).build()); } + + HttpRequest filterVolumes = HttpRequest.builder().method("POST") + .endpoint("https://ec2.us-east-1.amazonaws.com/") + .addHeader("Host", "ec2.us-east-1.amazonaws.com") + .addFormParam("Action", "DescribeVolumes") + .addFormParam("Filter.1.Name", "snapshot-id") + .addFormParam("Filter.1.Value.1", "snap-536d1b3a") + .addFormParam("Signature", "7g2ySW39nIVfxtIbuVttUBom7sssmQknxX/9SThkm2Y%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-08-31") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testFilterVolumesWhenResponseIs2xx() { + HttpResponse filterResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/describe_volumes_single.xml", "text/xml")).build(); + + EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filterVolumes, filterResponse); + + Volume volume = getOnlyElement(apiWhenExist.getElasticBlockStoreApi().get().describeVolumesInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("snapshot-id", "snap-536d1b3a") + .build())); + + assertEquals(volume.getId(), "vol-4282672b"); + } + + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testFilterVolumesWhenResponseIs404() { + HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build(); + + EC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filterVolumes, filterResponse); + + assertEquals(apiWhenNotExist.getElasticBlockStoreApi().get().describeVolumesInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("snapshot-id", "snap-536d1b3a") + .build()), + ImmutableSet.of()); + } + + HttpRequest filterSnapshots = HttpRequest.builder().method("POST") + .endpoint("https://ec2.us-east-1.amazonaws.com/") + .addHeader("Host", "ec2.us-east-1.amazonaws.com") + .addFormParam("Action", "DescribeSnapshots") + .addFormParam("Filter.1.Name", "volume-id") + .addFormParam("Filter.1.Value.1", "4d826724") + .addFormParam("Signature", "vT7R4YmfQJPNLSojXEMY1qcErMh0OzrOTYxbGYSZ4Uw%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-08-31") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testFilterSnapshotsWhenResponseIs2xx() { + HttpResponse filterResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/describe_snapshots.xml", "text/xml")).build(); + + EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filterSnapshots, filterResponse); + + Snapshot snapshot = getOnlyElement(apiWhenExist.getElasticBlockStoreApi().get().describeSnapshotsInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("volume-id", "4d826724") + .build())); + + assertEquals(snapshot.getId(), "snap-78a54011"); + } + + public void testFilterSnapshotsWhenResponseIs404() { + HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build(); + + EC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filterSnapshots, filterResponse); + + assertEquals(apiWhenNotExist.getElasticBlockStoreApi().get().describeSnapshotsInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("volume-id", "4d826724") + .build()), + ImmutableSet.of()); + } } diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiLiveTest.java index 858cf205fd7..bc080a71263 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiLiveTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiLiveTest.java @@ -20,11 +20,13 @@ import static org.jclouds.ec2.options.DescribeSnapshotsOptions.Builder.snapshotIds; import static org.jclouds.util.Predicates2.retry; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import java.util.Set; import java.util.SortedSet; +import org.jclouds.aws.AWSResponseException; import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; import org.jclouds.ec2.EC2Api; import org.jclouds.ec2.domain.AvailabilityZoneInfo; @@ -38,6 +40,7 @@ import com.google.common.base.Predicate; import com.google.common.base.Strings; +import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; @@ -75,17 +78,42 @@ public void setupContext() { @Test void testDescribeVolumes() { - for (String region : ec2Api.getConfiguredRegions()) { - SortedSet allResults = Sets.newTreeSet(client.describeVolumesInRegion(region)); - assertNotNull(allResults); - if (allResults.size() >= 1) { - Volume volume = allResults.last(); - SortedSet result = Sets.newTreeSet(client.describeVolumesInRegion(region, volume.getId())); - assertNotNull(result); - Volume compare = result.last(); - assertEquals(compare, volume); - } - } + String region = defaultRegion; + SortedSet allResults = Sets.newTreeSet(client.describeVolumesInRegion(region)); + assertNotNull(allResults); + assertFalse(allResults.isEmpty()); + Volume volume = allResults.last(); + SortedSet result = Sets.newTreeSet(client.describeVolumesInRegion(region, volume.getId())); + assertNotNull(result); + Volume compare = result.last(); + assertEquals(compare, volume); + } + + @Test + void testDescribeVolumesWithFilter() { + String region = defaultRegion; + SortedSet allResults = Sets.newTreeSet(client.describeVolumesInRegion(region)); + assertNotNull(allResults); + assertFalse(allResults.isEmpty()); + Volume volume = allResults.last(); + SortedSet result = Sets.newTreeSet(client.describeVolumesInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("volume-id", volume.getId()).build())); + assertNotNull(result); + Volume compare = result.last(); + assertEquals(compare, volume); + } + + @Test(expectedExceptions = AWSResponseException.class) + void testDescribeVolumesWithInvalidFilter() { + String region = defaultRegion; + SortedSet allResults = Sets.newTreeSet(client.describeVolumesInRegion(region)); + assertNotNull(allResults); + assertFalse(allResults.isEmpty()); + Volume volume = allResults.last(); + SortedSet result = Sets.newTreeSet(client.describeVolumesInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("invalid-filter", volume.getId()).build())); } @Test @@ -163,16 +191,43 @@ void testDetachVolumeInRegion() { @Test void testDescribeSnapshots() { - for (String region : ec2Api.getConfiguredRegions()) { - SortedSet allResults = Sets.newTreeSet(client.describeSnapshotsInRegion(region)); - assertNotNull(allResults); - if (allResults.size() >= 1) { - Snapshot snapshot = allResults.last(); - Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegion(region, - snapshotIds(snapshot.getId()))); - assertNotNull(result); - assertEquals(result, snapshot); - } + String region = defaultRegion; + SortedSet allResults = Sets.newTreeSet(client.describeSnapshotsInRegion(region)); + assertNotNull(allResults); + if (!allResults.isEmpty()) { + Snapshot snapshot = allResults.last(); + Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegion(region, + snapshotIds(snapshot.getId()))); + assertNotNull(result); + assertEquals(result, snapshot); + } + } + + @Test + void testDescribeSnapshotsWithFilter() { + String region = defaultRegion; + SortedSet allResults = Sets.newTreeSet(client.describeSnapshotsInRegion(region)); + assertNotNull(allResults); + if (!allResults.isEmpty()) { + Snapshot snapshot = allResults.last(); + Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("snapshot-id", snapshot.getId()).build())); + assertNotNull(result); + assertEquals(result, snapshot); + } + } + + @Test(expectedExceptions = AWSResponseException.class) + void testDescribeSnapshotsWithFilterInvalid() { + String region = defaultRegion; + SortedSet allResults = Sets.newTreeSet(client.describeSnapshotsInRegion(region)); + assertNotNull(allResults); + if (!allResults.isEmpty()) { + Snapshot snapshot = allResults.last(); + Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("invalid-filter", snapshot.getId()).build())); } } diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiTest.java index b0b4fbadc8a..fefd2a773e5 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiTest.java @@ -70,11 +70,11 @@ public void testDeleteVolume() throws SecurityException, NoSuchMethodException, .endpoint("https://ec2.us-east-1.amazonaws.com/") .addHeader("Host", "ec2.us-east-1.amazonaws.com") .addFormParam("Action", "DescribeVolumes") - .addFormParam("Signature", "hNuorhZQS%2BThX5dWXOvBkvnmTpgp6SvwHmgzjjfKyG8%3D") + .addFormParam("Signature", "nNxWg5dwYZEQu1QCzCtNp7iDmPR8wXXdKhWmLEKFLGI%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testDescribeVolumes() throws SecurityException, NoSuchMethodException, IOException { @@ -119,11 +119,11 @@ public void testDescribeVolumesArgs() throws SecurityException, NoSuchMethodExce .addFormParam("Action", "AttachVolume") .addFormParam("Device", "/device") .addFormParam("InstanceId", "instanceId") - .addFormParam("Signature", "LaOppR61eWpdNgMYJ3ccfo9vzbmUyJf9Ars%2Bbcu4OGI%3D") + .addFormParam("Signature", "0%2BUY5oCQzoJapEHq4Dl2R/0nAA8uXEHqvHbnnNI5NcA%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("VolumeId", "id") .addFormParam("AWSAccessKeyId", "identity").build(); @@ -151,11 +151,11 @@ public void testAttachVolume() throws SecurityException, NoSuchMethodException, .addHeader("Host", "ec2.us-east-1.amazonaws.com") .addFormParam("Action", "DetachVolume") .addFormParam("Force", "false") - .addFormParam("Signature", "4c6EmHwCYbe%2BifuUV0PNXpKfReoZvJXyme37mKtnLk8%3D") + .addFormParam("Signature", "tfNB1g2WVqb3EwvBJlk4duU1H1fDOa1SBstsm1elpbg%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("VolumeId", "id") .addFormParam("AWSAccessKeyId", "identity").build(); @@ -185,11 +185,11 @@ public void testDetachVolume() throws SecurityException, NoSuchMethodException, .addFormParam("Device", "/device") .addFormParam("Force", "true") .addFormParam("InstanceId", "instanceId") - .addFormParam("Signature", "GrUGXc6H5W%2BNF8zcXU8gSRbt1ELt%2BTcCDEvbY1a88NE%3D") + .addFormParam("Signature", "VFhgwdkKBKXr/dEn2gvk6Vqq3JIunw4zZgM2Tt/ouME%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("VolumeId", "id") .addFormParam("AWSAccessKeyId", "identity").build(); @@ -311,7 +311,7 @@ public void testGetCreateVolumePermissionForSnapshot() throws SecurityException, .addFormParam("Action", "ModifySnapshotAttribute") .addFormParam("Attribute", "createVolumePermission") .addFormParam("OperationType", "add") - .addFormParam("Signature", "AizV1N1rCCXi%2BbzXX/Vz7shFq9yAJAwcmAGyRQMH%2Bjs%3D") + .addFormParam("Signature", "s8m8DqQRXmecWguuRjxfl3Ibd%2B1AjjktGzTlJLUTcPc%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("SnapshotId", "snapshotId") @@ -319,7 +319,7 @@ public void testGetCreateVolumePermissionForSnapshot() throws SecurityException, .addFormParam("UserGroup.1", "all") .addFormParam("UserId.1", "bob") .addFormParam("UserId.2", "sue") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testAddCreateVolumePermissionsToSnapshot() throws SecurityException, NoSuchMethodException, IOException { @@ -348,7 +348,7 @@ public void testAddCreateVolumePermissionsToSnapshot() throws SecurityException, .addFormParam("Action", "ModifySnapshotAttribute") .addFormParam("Attribute", "createVolumePermission") .addFormParam("OperationType", "remove") - .addFormParam("Signature", "Lmlt2daM%2BJ4kIoU9HmCempwVGZP1fC6V%2Br9o8MQjYy8%3D") + .addFormParam("Signature", "RzxHUIWV80cyhQDtrMiHDWUosS1g8cn1%2B7ONLJCe1dg%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("SnapshotId", "snapshotId") @@ -356,7 +356,7 @@ public void testAddCreateVolumePermissionsToSnapshot() throws SecurityException, .addFormParam("UserGroup.1", "all") .addFormParam("UserId.1", "bob") .addFormParam("UserId.2", "sue") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testRemoveCreateVolumePermissionsFromSnapshot() throws SecurityException, NoSuchMethodException, diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiExpectTest.java new file mode 100644 index 00000000000..824a4ffb21a --- /dev/null +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiExpectTest.java @@ -0,0 +1,102 @@ +/* + * 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.ec2.features; + +import static com.google.common.collect.Iterables.getOnlyElement; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +import java.util.Properties; + +import org.jclouds.Constants; +import org.jclouds.ec2.EC2Api; +import org.jclouds.ec2.domain.PublicIpInstanceIdPair; +import org.jclouds.ec2.internal.BaseEC2ApiExpectTest; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.rest.internal.BaseRestApiExpectTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; + +/** + * @author Andrew Bayer + * + * @see org.jclouds.ec2.features.ElasticIPAddressApi + */ +@Test(groups = "unit") +public class ElasticIPAddressApiExpectTest extends BaseEC2ApiExpectTest { + + protected Properties setupProperties() { + Properties props = super.setupProperties(); + props.put(Constants.PROPERTY_API_VERSION, "2010-08-31"); + return props; + } + + HttpRequest filter = + HttpRequest.builder() + .method("POST") + .endpoint("https://ec2.us-east-1.amazonaws.com/") + .addHeader("Host", "ec2.us-east-1.amazonaws.com") + .payload(BaseRestApiExpectTest.payloadFromStringWithContentType( + "Action=DescribeAddresses" + + "&Filter.1.Name=instance-id" + + "&Filter.1.Value.1=i-f15ebb98" + + "&Signature=dJbTUsBGHSrarQQAwmLm8LLI255R/lzdE7ZcYJucOzI%3D" + + "&SignatureMethod=HmacSHA256" + + "&SignatureVersion=2" + + "&Timestamp=2012-04-16T15%3A54%3A08.897Z" + + "&Version=2010-08-31" + + "&AWSAccessKeyId=identity", + "application/x-www-form-urlencoded")) + .build(); + + public void testFilterWhenResponseIs2xx() throws Exception { + + HttpResponse filterResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/describe_addresses_single.xml", "text/xml")).build(); + + + EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, + filter, filterResponse); + + PublicIpInstanceIdPair address = getOnlyElement(apiWhenExist.getElasticIPAddressApi() + .get().describeAddressesInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("instance-id", "i-f15ebb98") + .build())); + assertNotNull(address, "address should not be null"); + + assertEquals(address.getPublicIp(), "67.202.55.255"); + } + + public void testFilterWhenResponseIs404() throws Exception { + + HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build(); + + EC2Api apiWhenDontExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, + filter, filterResponse); + + assertEquals(apiWhenDontExist.getElasticIPAddressApi() + .get().describeAddressesInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("instance-id", "i-f15ebb98") + .build()), ImmutableSet.of()); + } + +} diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiLiveTest.java index 119c2def000..f4354044df7 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiLiveTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiLiveTest.java @@ -23,12 +23,11 @@ import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; import org.jclouds.ec2.EC2Api; -import org.jclouds.ec2.EC2ApiMetadata; -import org.jclouds.ec2.compute.EC2ComputeServiceContext; import org.jclouds.ec2.domain.PublicIpInstanceIdPair; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Sets; /** @@ -58,13 +57,19 @@ void testDescribeAddresses() { for (String region : ec2Api.getConfiguredRegions()) { SortedSet allResults = Sets.newTreeSet(client.describeAddressesInRegion(region)); assertNotNull(allResults); - if (allResults.size() >= 1) { + if (!allResults.isEmpty()) { PublicIpInstanceIdPair pair = allResults.last(); SortedSet result = Sets.newTreeSet(client.describeAddressesInRegion(region, pair .getPublicIp())); assertNotNull(result); PublicIpInstanceIdPair compare = result.last(); assertEquals(compare, pair); + + SortedSet filterResult = Sets.newTreeSet(client.describeAddressesInRegionWithFilter( + region, ImmutableMultimap.builder().put("public-ip", pair.getPublicIp()).build())); + assertNotNull(filterResult); + PublicIpInstanceIdPair filterCompare = filterResult.last(); + assertEquals(filterCompare, pair); } } } diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiTest.java index d230ca409c7..abdfae6cfe1 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiTest.java @@ -63,11 +63,11 @@ public void testDisassociateAddress() throws SecurityException, NoSuchMethodExce .addFormParam("Action", "AssociateAddress") .addFormParam("InstanceId", "me") .addFormParam("PublicIp", "127.0.0.1") - .addFormParam("Signature", "YmPyvEljuFw0INSUbQx5xAhC/1GQ4a1Ht6TdoXeMc9Y%3D") + .addFormParam("Signature", "nLU6xGLqXtT/dmyAvkN4BdL/3CxQlDWJYeskikhl54k%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testAssociateAddress() throws SecurityException, NoSuchMethodException, IOException { diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiExpectTest.java new file mode 100644 index 00000000000..0c19bd7373a --- /dev/null +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiExpectTest.java @@ -0,0 +1,101 @@ +/* + * 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.ec2.features; + +import static com.google.common.collect.Iterables.getOnlyElement; +import static org.testng.Assert.assertNotNull; + +import java.util.Properties; + +import org.jclouds.Constants; +import org.jclouds.ec2.EC2Api; +import org.jclouds.ec2.domain.RunningInstance; +import org.jclouds.ec2.internal.BaseEC2ApiExpectTest; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.rest.internal.BaseRestApiExpectTest; +import org.jclouds.util.Strings2; +import org.testng.Assert; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; + +/** + * @author Andrew Bayer + * + * @see InstanceApi + */ +@Test(groups = "unit") +public class InstanceApiExpectTest extends BaseEC2ApiExpectTest { + + protected Properties setupProperties() { + Properties props = super.setupProperties(); + props.put(Constants.PROPERTY_API_VERSION, "2010-08-31"); + return props; + } + + HttpRequest filter = + HttpRequest.builder() + .method("POST") + .endpoint("https://ec2.us-east-1.amazonaws.com/") + .addHeader("Host", "ec2.us-east-1.amazonaws.com") + .payload(BaseRestApiExpectTest.payloadFromStringWithContentType( + "Action=DescribeInstances" + + "&Filter.1.Name=key-name" + + "&Filter.1.Value.1=" + Strings2.urlEncode("adriancole.ec21") + + "&Signature=%2B2ktAljlAPNUMAJUFh3poQrTvwcwWytuQFBg/ktKdTc%3D" + + "&SignatureMethod=HmacSHA256" + + "&SignatureVersion=2" + + "&Timestamp=2012-04-16T15%3A54%3A08.897Z" + + "&Version=2010-08-31" + + "&AWSAccessKeyId=identity", + "application/x-www-form-urlencoded")) + .build(); + + public void testFilterWhenResponseIs2xx() throws Exception { + + HttpResponse filterResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/describe_instances_running.xml", "text/xml")).build(); + + + EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, + filter, filterResponse); + + RunningInstance instance = getOnlyElement(getOnlyElement(apiWhenExist.getInstanceApi().get().describeInstancesInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("key-name", "adriancole.ec21") + .build()))); + assertNotNull(instance, "Instance should not be null"); + + Assert.assertEquals(instance.getId(), "i-0799056f"); + } + + public void testFilterWhenResponseIs404() throws Exception { + + HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build(); + + EC2Api apiWhenDontExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, + filter, filterResponse); + + Assert.assertEquals(apiWhenDontExist.getInstanceApi().get().describeInstancesInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("key-name", "adriancole.ec21") + .build()), ImmutableSet.of()); + } + +} diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiLiveTest.java index 57f9441195d..6b7818a11d4 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiLiveTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiLiveTest.java @@ -16,22 +16,26 @@ */ package org.jclouds.ec2.features; +import static com.google.common.collect.Iterables.getFirst; import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; import java.util.Set; +import org.jclouds.aws.AWSResponseException; import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; import org.jclouds.ec2.EC2Api; -import org.jclouds.ec2.EC2ApiMetadata; import org.jclouds.ec2.domain.Reservation; import org.jclouds.ec2.domain.RunningInstance; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import com.google.common.collect.ImmutableMultimap; + /** * Tests behavior of {@code EC2Api} * - * @author Adrian Cole + * @author Adrian Cole, Andrew Bayer */ @Test(groups = "live", singleThreaded = true, testName = "InstanceApiLiveTest") public class InstanceApiLiveTest extends BaseComputeServiceContextLiveTest { @@ -55,7 +59,39 @@ void testDescribeInstances() { for (String region : ec2Api.getConfiguredRegions()) { Set> allResults = client.describeInstancesInRegion(region); assertNotNull(allResults); - assert allResults.size() >= 0 : allResults.size(); } } -} + + @Test + void testFilterInstances() { + for (String region : view.unwrapApi(EC2Api.class).getAvailabilityZoneAndRegionApi().get().describeRegions().keySet()) { + Set> allResults = client.describeInstancesInRegion(region); + assertNotNull(allResults); + + if (!allResults.isEmpty()) { + RunningInstance instance = getFirst(getFirst(allResults, null), null); + + assertNotNull(instance); + + Set> filterResults = client.describeInstancesInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("key-name", instance.getKeyName()) + .build()); + + assertNotNull(filterResults); + assertTrue(!filterResults.isEmpty(), "No results found for filter, but there should be."); + + } + } + } + + @Test(expectedExceptions = AWSResponseException.class) + void testInvalidFilterInstances() { + for (String region : view.unwrapApi(EC2Api.class).getAvailabilityZoneAndRegionApi().get().describeRegions().keySet()) { + Set> filterResults = client.describeInstancesInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("invalid-key", "some-value") + .build()); + + } + }} diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiTest.java index 2f177351bba..fbeb57a7bdc 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiTest.java @@ -351,12 +351,12 @@ public void testGetBlockDeviceMappingForInstanceInRegion() throws SecurityExcept .addFormParam("Action", "ModifyInstanceAttribute") .addFormParam("Attribute", "userData") .addFormParam("InstanceId", "1") - .addFormParam("Signature", "LfUmzLM5DsACR5nQcEfGF5FPdznOwwhJ7tjhBWfHtGs%3D") + .addFormParam("Signature", "SfxT/1i/WokibleyEHo0zHizHisLzbDzzRxfOdnr1vY%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") .addFormParam("Value", "dGVzdA%3D%3D") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testSetUserDataForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException { @@ -384,12 +384,12 @@ public void testSetUserDataForInstanceInRegion() throws SecurityException, NoSuc .addFormParam("Action", "ModifyInstanceAttribute") .addFormParam("Attribute", "ramdisk") .addFormParam("InstanceId", "1") - .addFormParam("Signature", "qx6NeVbihiYrKvi5Oe5LzMsGHTjS7%2BqoNhh2abt275g%3D") + .addFormParam("Signature", "aMQzFsknmQt1OA8Rb8aIzZoFXGK23UvrMIy8imNVUeQ%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") .addFormParam("Value", "test") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testSetRamdiskForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException { @@ -417,12 +417,12 @@ public void testSetRamdiskForInstanceInRegion() throws SecurityException, NoSuch .addFormParam("Action", "ModifyInstanceAttribute") .addFormParam("Attribute", "kernel") .addFormParam("InstanceId", "1") - .addFormParam("Signature", "juSiuoiXJzTxj3q0LUW2528HzDyP4JAcKin%2BI4AuIT0%3D") + .addFormParam("Signature", "GaQ9sC0uXHlN5JAMWQpYx%2Bc3XaF38qZgJex/kyqdR1E%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") .addFormParam("Value", "test") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testSetKernelForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException { @@ -450,12 +450,12 @@ public void testSetKernelForInstanceInRegion() throws SecurityException, NoSuchM .addFormParam("Action", "ModifyInstanceAttribute") .addFormParam("Attribute", "disableApiTermination") .addFormParam("InstanceId", "1") - .addFormParam("Signature", "tiBMWWTi22BWeAjsRfuzVom0tQgsOBeYTkatMuWRrbg%3D") + .addFormParam("Signature", "hErzi%2Bf4jBADviJ%2BLVTTGhlHWhMR/pyPUSBZgaHC79I%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") .addFormParam("Value", "true") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testSetApiTerminationDisabledForInstanceInRegion() throws SecurityException, NoSuchMethodException, @@ -484,12 +484,12 @@ public void testSetApiTerminationDisabledForInstanceInRegion() throws SecurityEx .addFormParam("Action", "ModifyInstanceAttribute") .addFormParam("Attribute", "instanceType") .addFormParam("InstanceId", "1") - .addFormParam("Signature", "XK%2BzQmQ0S57gXIgVRMqUkKunURN9TaCJD1YWiYMAOHo%3D") + .addFormParam("Signature", "OYJQ1w79NoxkcrawNK6U71k3Wl78kqz2ikzTXmQCX2E%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") .addFormParam("Value", "c1.medium") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testSetInstanceTypeForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException { @@ -517,12 +517,12 @@ public void testSetInstanceTypeForInstanceInRegion() throws SecurityException, N .addFormParam("Action", "ModifyInstanceAttribute") .addFormParam("Attribute", "instanceInitiatedShutdownBehavior") .addFormParam("InstanceId", "1") - .addFormParam("Signature", "s5xBMLd%2BXNVp44x7C6qVE58qBov//f6yvxoM757KcZU%3D") + .addFormParam("Signature", "2Tgi9M9AcCv5Y%2BEXwq0SD6g8bBGtPPEgjdTtfdGZQlI%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") .addFormParam("Value", "terminate") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testSetInstanceInitiatedShutdownBehaviorForInstanceInRegion() throws SecurityException, diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiExpectTest.java new file mode 100644 index 00000000000..4b08ba7584c --- /dev/null +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiExpectTest.java @@ -0,0 +1,76 @@ +/* + * 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.ec2.features; + +import static com.google.common.collect.Iterables.getOnlyElement; +import static org.testng.Assert.assertEquals; + +import org.jclouds.ec2.EC2Api; +import org.jclouds.ec2.domain.KeyPair; +import org.jclouds.ec2.internal.BaseEC2ApiExpectTest; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; + +/** + * @author Andrew Bayer + */ +@Test(groups = "unit", testName = "KeyPairApiExpectTest") +public class KeyPairApiExpectTest extends BaseEC2ApiExpectTest { + + HttpRequest filter = HttpRequest.builder().method("POST") + .endpoint("https://ec2.us-east-1.amazonaws.com/") + .addHeader("Host", "ec2.us-east-1.amazonaws.com") + .addFormParam("Action", "DescribeKeyPairs") + .addFormParam("Filter.1.Name", "key-name") + .addFormParam("Filter.1.Value.1", "gsg-keypair") + .addFormParam("Signature", "xg8vGx%2Bv9UEG0%2BFGy%2BhincdI2ziWLbwPJvW85l%2Bvqwg%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-08-31") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testFilterWhenResponseIs2xx() { + HttpResponse filterResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/describe_keypairs.xml", "text/xml")).build(); + + EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse); + + KeyPair keyPair = getOnlyElement(apiWhenExist.getKeyPairApi().get().describeKeyPairsInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("key-name", "gsg-keypair") + .build())); + + assertEquals(keyPair.getKeyName(), "gsg-keypair"); + } + + public void testFilterWhenResponseIs404() { + HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build(); + + EC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse); + + assertEquals(apiWhenNotExist.getKeyPairApi().get().describeKeyPairsInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("key-name", "gsg-keypair") + .build()), + ImmutableSet.of()); + } +} \ No newline at end of file diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiLiveTest.java index ad693aca857..b9219a5ca24 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiLiveTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiLiveTest.java @@ -22,6 +22,7 @@ import java.util.Set; import java.util.SortedSet; +import org.jclouds.aws.AWSResponseException; import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; import org.jclouds.ec2.EC2Api; import org.jclouds.ec2.domain.KeyPair; @@ -29,6 +30,7 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Sets; /** @@ -58,7 +60,7 @@ void testDescribeKeyPairs() { for (String region : ec2Api.getConfiguredRegions()) { SortedSet allResults = Sets.newTreeSet(client.describeKeyPairsInRegion(region)); assertNotNull(allResults); - if (allResults.size() >= 1) { + if (!allResults.isEmpty()) { KeyPair pair = allResults.last(); SortedSet result = Sets.newTreeSet(client.describeKeyPairsInRegion(region, pair.getKeyName())); assertNotNull(result); @@ -68,6 +70,37 @@ void testDescribeKeyPairs() { } } + @Test + void testDescribeKeyPairsWithFilter() { + for (String region : ec2Api.getConfiguredRegions()) { + SortedSet allResults = Sets.newTreeSet(client.describeKeyPairsInRegion(region)); + assertNotNull(allResults); + if (!allResults.isEmpty()) { + KeyPair pair = allResults.last(); + SortedSet result = Sets.newTreeSet(client.describeKeyPairsInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("key-name", pair.getKeyName()).build())); + assertNotNull(result); + KeyPair compare = result.last(); + assertEquals(compare, pair); + } + } + } + + @Test(expectedExceptions = AWSResponseException.class) + void testDescribeKeyPairsWithInvalidFilter() { + for (String region : ec2Api.getConfiguredRegions()) { + SortedSet allResults = Sets.newTreeSet(client.describeKeyPairsInRegion(region)); + assertNotNull(allResults); + if (!allResults.isEmpty()) { + KeyPair pair = allResults.last(); + SortedSet result = Sets.newTreeSet(client.describeKeyPairsInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("invalid-filter", pair.getKeyName()).build())); + } + } + } + public static final String PREFIX = System.getProperty("user.name") + "-ec2"; @Test diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiExpectTest.java new file mode 100644 index 00000000000..9e5491efbb8 --- /dev/null +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiExpectTest.java @@ -0,0 +1,76 @@ +/* + * 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.ec2.features; + +import static com.google.common.collect.Iterables.getOnlyElement; +import static org.testng.Assert.assertEquals; + +import org.jclouds.ec2.EC2Api; +import org.jclouds.ec2.domain.SecurityGroup; +import org.jclouds.ec2.internal.BaseEC2ApiExpectTest; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; + +/** + * @author Andrew Bayer + */ +@Test(groups = "unit", testName = "SecurityGroupApiExpectTest") +public class SecurityGroupApiExpectTest extends BaseEC2ApiExpectTest { + + HttpRequest filter = HttpRequest.builder().method("POST") + .endpoint("https://ec2.us-east-1.amazonaws.com/") + .addHeader("Host", "ec2.us-east-1.amazonaws.com") + .addFormParam("Action", "DescribeSecurityGroups") + .addFormParam("Filter.1.Name", "owner-id") + .addFormParam("Filter.1.Value.1", "993194456877") + .addFormParam("Signature", "zk8EEWkG9Hi0bBLPueF9WdTUKapxQqUXgyJTxeZHXBc%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-08-31") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testFilterWhenResponseIs2xx() { + HttpResponse filterResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/describe_securitygroups_extension_single.xml", "text/xml")).build(); + + EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse); + + SecurityGroup group = getOnlyElement(apiWhenExist.getSecurityGroupApi().get().describeSecurityGroupsInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("owner-id", "993194456877") + .build())); + + assertEquals(group.getId(), "sg-3c6ef654"); + } + + public void testFilterWhenResponseIs404() { + HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build(); + + EC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse); + + assertEquals(apiWhenNotExist.getSecurityGroupApi().get().describeSecurityGroupsInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("owner-id", "993194456877") + .build()), + ImmutableSet.of()); + } +} \ No newline at end of file diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiLiveTest.java index 220e14f6f56..edfc3ca5359 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiLiveTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiLiveTest.java @@ -27,9 +27,9 @@ import java.util.Set; +import org.jclouds.aws.AWSResponseException; import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; import org.jclouds.ec2.EC2Api; -import org.jclouds.ec2.EC2ApiMetadata; import org.jclouds.ec2.domain.SecurityGroup; import org.jclouds.ec2.domain.UserIdGroupPair; import org.jclouds.net.domain.IpPermission; @@ -70,20 +70,66 @@ void testDescribe() { for (String region : ec2Api.getConfiguredRegions()) { Set allResults = client.describeSecurityGroupsInRegion(region); assertNotNull(allResults); - if (allResults.size() >= 1) { + if (!allResults.isEmpty()) { final SecurityGroup group = getLast(allResults); // in case there are multiple groups with the same name, which is the case with VPC ImmutableSet expected = FluentIterable.from(allResults) - .filter(new Predicate() { - @Override - public boolean apply(SecurityGroup in) { - return group.getName().equals(in.getName()); - } - }).toSet(); + .filter(new Predicate() { + @Override + public boolean apply(SecurityGroup in) { + return group.getName().equals(in.getName()); + } + }).toSet(); ImmutableSet result = ImmutableSet.copyOf(client.describeSecurityGroupsInRegion(region, - group.getName())); + group.getName())); // the above command has a chance of returning less groups than the original - assertTrue(expected.containsAll(result)); + assertTrue(expected.containsAll(result), "group(s) for name not found"); + } + } + } + + @Test + void testFilter() { + for (String region : ec2Api.getConfiguredRegions()) { + Set allResults = client.describeSecurityGroupsInRegion(region); + assertNotNull(allResults); + if (!allResults.isEmpty()) { + final SecurityGroup group = getLast(allResults); + // in case there are multiple groups with the same name, which is the case with VPC + ImmutableSet expected = FluentIterable.from(allResults) + .filter(new Predicate() { + @Override + public boolean apply(SecurityGroup in) { + return group.getName().equals(in.getName()); + } + }).toSet(); + ImmutableSet result = ImmutableSet.copyOf(client.describeSecurityGroupsInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("group-name", group.getName()).build())); + // the above command has a chance of returning less groups than the original + assertTrue(expected.containsAll(result), "group(s) for name not found"); + } + } + } + + @Test(expectedExceptions = AWSResponseException.class) + void testFilterInvalid() { + for (String region : ec2Api.getConfiguredRegions()) { + Set allResults = client.describeSecurityGroupsInRegion(region); + assertNotNull(allResults); + if (!allResults.isEmpty()) { + final SecurityGroup group = getLast(allResults); + // in case there are multiple groups with the same name, which is the case with VPC + ImmutableSet expected = FluentIterable.from(allResults) + .filter(new Predicate() { + @Override + public boolean apply(SecurityGroup in) { + return group.getName().equals(in.getName()); + } + }).toSet(); + ImmutableSet result = ImmutableSet.copyOf(client.describeSecurityGroupsInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("invalid-filter", group.getName()).build())); } } } diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiTest.java index 85b73741de9..b5d2d17621a 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiTest.java @@ -65,11 +65,11 @@ public void testDeleteSecurityGroup() throws SecurityException, NoSuchMethodExce .addFormParam("Action", "CreateSecurityGroup") .addFormParam("GroupDescription", "description") .addFormParam("GroupName", "name") - .addFormParam("Signature", "F3o0gnZcX9sWrtDUhVwi3k5GY2JKLP0Dhi6CcEqK2vE%3D") + .addFormParam("Signature", "msp9zFJLrRXYsVu/vbSZE8tQVS/TEvF0Cu/ldYVFdcA%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testCreateSecurityGroup() throws SecurityException, NoSuchMethodException, IOException { @@ -153,12 +153,12 @@ public void testAuthorizeSecurityGroupIngressGroup() throws SecurityException, N .addFormParam("FromPort", "6000") .addFormParam("GroupName", "group") .addFormParam("IpProtocol", "tcp") - .addFormParam("Signature", "6NQega9YUGDxdwk3Y0Hv71u/lHi%2B0D6qMCJLpJVD/aI%3D") + .addFormParam("Signature", "xeaZpQ1Lvhp%2BqETpEzOPGHW6isAWYwgtBdCnTqWzkAw%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") .addFormParam("ToPort", "7000") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testAuthorizeSecurityGroupIngressCidr() throws SecurityException, NoSuchMethodException, IOException { @@ -207,12 +207,12 @@ public void testRevokeSecurityGroupIngressGroup() throws SecurityException, NoSu .addFormParam("FromPort", "6000") .addFormParam("GroupName", "group") .addFormParam("IpProtocol", "tcp") - .addFormParam("Signature", "WPlDYXI8P6Ip4F2JIEP3lWrVlP/7gxbZvlshKYlrvxk%3D") + .addFormParam("Signature", "P5lxCXMwz6FE8Wo79nEMh8clgLDK3rZxCPRTOKssKKQ%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") .addFormParam("ToPort", "7000") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testRevokeSecurityGroupIngressCidr() throws SecurityException, NoSuchMethodException, IOException { diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiExpectTest.java index 87dfb874cec..457b08d85a7 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiExpectTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiExpectTest.java @@ -16,16 +16,21 @@ */ package org.jclouds.ec2.features; +import static com.google.common.collect.Iterables.getOnlyElement; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import org.jclouds.ec2.EC2Api; +import org.jclouds.ec2.domain.BundleTask; import org.jclouds.ec2.internal.BaseEC2ApiExpectTest; import org.jclouds.ec2.parse.GetPasswordDataResponseTest; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.testng.annotations.Test; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; + /** * @author Adrian Cole */ @@ -40,16 +45,28 @@ public class WindowsApiExpectTest extends BaseEC2ApiExpectTest { payloadFromStringWithContentType( "Action=GetPasswordData" + "&InstanceId=i-2574e22a" + - "&Signature=vX1Tskc4VuBUWPqsJ%2BzcjEj6/2iMCKzqjWnKFXRkDdA%3D" + + "&Signature=PMr4kU4p%2BSF2ISHXAFUme1kNh%2BCqftIUQchuw3vhKCw%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2012-04-16T15%3A54%3A08.897Z" + - "&Version=2010-06-15" + + "&Version=2010-08-31" + "&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")) .build(); - - + + HttpRequest filter = HttpRequest.builder().method("POST") + .endpoint("https://ec2.us-east-1.amazonaws.com/") + .addHeader("Host", "ec2.us-east-1.amazonaws.com") + .addFormParam("Action", "DescribeBundleTasks") + .addFormParam("Filter.1.Name", "instance-id") + .addFormParam("Filter.1.Value.1", "i-12345678") + .addFormParam("Signature", "y0y3UBUKU/uYwbWPTCbkXzprU%2B8fMhg5LfF%2B5hWU2F4%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z") + .addFormParam("Version", "2010-08-31") + .addFormParam("AWSAccessKeyId", "identity").build(); + public void testGetPasswordDataWhenResponseIs2xx() throws Exception { HttpResponse getResponse = HttpResponse.builder().statusCode(200) @@ -68,4 +85,31 @@ public void testGetPasswordDataWhenResponseIs404() throws Exception { assertNull(apiWhenDontExist.getWindowsApi().get().getPasswordDataForInstance("i-2574e22a")); } + + public void testFilterBundleTasksWhenResponseIs2xx() { + HttpResponse filterResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/describe_bundle_tasks.xml", "text/xml")).build(); + + EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse); + + BundleTask task = getOnlyElement(apiWhenExist.getWindowsApi().get().describeBundleTasksInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("instance-id", "i-12345678") + .build())); + + assertEquals(task.getBundleId(), "bun-c1a540a8"); + } + + public void testFilterBundleTasksWhenResponseIs404() { + HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build(); + + EC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse); + + assertEquals(apiWhenNotExist.getWindowsApi().get().describeBundleTasksInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("instance-id", "i-12345678") + .build()), + ImmutableSet.of()); + } + } diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiTest.java index 572b247f859..d6b44e7a166 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiTest.java @@ -45,7 +45,7 @@ public class WindowsApiTest extends BaseEC2ApiTest { .addHeader("Host", "ec2.us-east-1.amazonaws.com") .addFormParam("Action", "BundleInstance") .addFormParam("InstanceId", "i-e468cd8d") - .addFormParam("Signature", "Uw5gH4eN3H8KXeFfIVLDDt88ApYn8L4pkf31hpojpcM%3D") + .addFormParam("Signature", "78A6SjliGJg%2BKzaICB9I4bqEXFoNa4FKonuIwAj9hik%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Storage.S3.Bucket", "my-bucket") @@ -53,7 +53,7 @@ public class WindowsApiTest extends BaseEC2ApiTest { .addFormParam("Storage.S3.UploadPolicy", "eyJleHBpcmF0aW9uIjogIjIwMDgtMDgtMzBUMDg6NDk6MDlaIiwiY29uZGl0aW9ucyI6IFt7ImJ1Y2tldCI6ICJteS1idWNrZXQifSxbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAibXktbmV3LWltYWdlIl1dfQ%3D%3D") .addFormParam("Storage.S3.UploadPolicySignature", "ih/iohGe0A7y4QVRbKaq6BZShzUsmBEJEa9AdFbxM6Y%3D") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testBundleInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException { @@ -88,7 +88,7 @@ Lists. newArrayList( .addHeader("Host", "ec2.us-east-1.amazonaws.com") .addFormParam("Action", "BundleInstance") .addFormParam("InstanceId","i-e468cd8d") - .addFormParam("Signature", "ahFjX9Tv/DGMFq9EFdF1mWSAnTKyQyyIj7dWJxBOhaE%3D") + .addFormParam("Signature", "9UbWwb%2BnO2vHn2O59K9FpmaK445RwX7vXsruHRznwik%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Storage.S3.AWSAccessKeyId", "10QMXFEV71ZS32XQFTR2") @@ -97,7 +97,7 @@ Lists. newArrayList( .addFormParam("Storage.S3.UploadPolicy", "eyJleHBpcmF0aW9uIjogIjIwMDgtMDgtMzBUMDg6NDk6MDlaIiwiY29uZGl0aW9ucyI6IFt7ImJ1Y2tldCI6ICJteS1idWNrZXQifSxbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAibXktbmV3LWltYWdlIl1dfQ%3D%3D") .addFormParam("Storage.S3.UploadPolicySignature", "ih/iohGe0A7y4QVRbKaq6BZShzUsmBEJEa9AdFbxM6Y%3D") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") - .addFormParam("Version", "2010-06-15") + .addFormParam("Version", "2010-08-31") .addFormParam("AWSAccessKeyId", "identity").build(); public void testBundleInstanceInRegionOptions() throws SecurityException, NoSuchMethodException, IOException { 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 index 993bc34db09..29808b7b39e 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ExpectTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ExpectTest.java @@ -72,7 +72,7 @@ protected void setupDefaultRequests() { .endpoint("https://ec2." + region + ".amazonaws.com/") .addHeader("Host", "ec2." + region + ".amazonaws.com") .payload(payloadFromStringWithContentType( - "Action=DescribeAvailabilityZones&Version=2010-06-15", + "Action=DescribeAvailabilityZones&Version=2010-08-31", MediaType.APPLICATION_FORM_URLENCODED)).build()), HttpResponse.builder().statusCode(200) .payload(payloadFromResourceWithContentType( diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeRegionsResponseHandlerTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeRegionsResponseHandlerTest.java index 6d8bc584029..1e444e3cfa6 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeRegionsResponseHandlerTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeRegionsResponseHandlerTest.java @@ -85,7 +85,7 @@ public void testApplyInputStream() { public void testEuc() { InputStream is = Strings2 - .toInputStream("6a3b36f9-9ff4-47cf-87e3-285b08fbe5e5Eucalyptushttp://173.205.188.130:8773/services/EucalyptusWalrushttp://173.205.188.130:8773/services/Walrus"); + .toInputStream("6a3b36f9-9ff4-47cf-87e3-285b08fbe5e5Eucalyptushttp://173.205.188.130:8773/services/EucalyptusWalrushttp://173.205.188.130:8773/services/Walrus"); Map expected = ImmutableMap. of("Eucalyptus", URI.create("http://173.205.188.130:8773/services/Eucalyptus")); diff --git a/apis/ec2/src/test/resources/describe_addresses_single.xml b/apis/ec2/src/test/resources/describe_addresses_single.xml new file mode 100644 index 00000000000..d9179bd59a2 --- /dev/null +++ b/apis/ec2/src/test/resources/describe_addresses_single.xml @@ -0,0 +1,8 @@ + + + + i-f15ebb98 + 67.202.55.255 + + + \ No newline at end of file diff --git a/apis/ec2/src/test/resources/describe_securitygroups_empty.xml b/apis/ec2/src/test/resources/describe_securitygroups_empty.xml index ca89f4e9697..e3336a7eb5a 100644 --- a/apis/ec2/src/test/resources/describe_securitygroups_empty.xml +++ b/apis/ec2/src/test/resources/describe_securitygroups_empty.xml @@ -1,6 +1,6 @@ + xmlns="http://ec2.amazonaws.com/doc/2010-08-31/"> L6EFIZVPJS76T3K5-0UV diff --git a/apis/ec2/src/test/resources/describe_volumes_single.xml b/apis/ec2/src/test/resources/describe_volumes_single.xml new file mode 100644 index 00000000000..fcc10a5d84a --- /dev/null +++ b/apis/ec2/src/test/resources/describe_volumes_single.xml @@ -0,0 +1,15 @@ + + + 31ab5542-e479-44cb-aa94-c340c2481e0b + + + vol-4282672b + 800 + snap-536d1b3a + us-east-1a + in-use + 2008-05-07T11:51:50.000Z + + + + \ No newline at end of file diff --git a/apis/ec2/src/test/resources/run_instances_cloudbridge.xml b/apis/ec2/src/test/resources/run_instances_cloudbridge.xml index 37d5ae88008..7dc31f064a6 100644 --- a/apis/ec2/src/test/resources/run_instances_cloudbridge.xml +++ b/apis/ec2/src/test/resources/run_instances_cloudbridge.xml @@ -1,5 +1,5 @@ - + 56eeacd9-c790-45c3-85f3-e4380b55e1d8 r-f847a6ca 55ed6530-9b32-48f1-acb7-6ec0d3255a65 diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSInstanceApi.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSInstanceApi.java index 5a26707a9ec..4ccb4a29b34 100644 --- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSInstanceApi.java +++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSInstanceApi.java @@ -30,11 +30,12 @@ import org.jclouds.aws.ec2.xml.AWSDescribeInstancesResponseHandler; import org.jclouds.aws.ec2.xml.AWSRunInstancesResponseHandler; import org.jclouds.aws.filters.FormSigner; +import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams; import org.jclouds.ec2.binders.BindInstanceIdsToIndexedFormParams; import org.jclouds.ec2.binders.IfNotNullBindAvailabilityZoneToFormParam; import org.jclouds.ec2.domain.Reservation; -import org.jclouds.ec2.options.RunInstancesOptions; import org.jclouds.ec2.features.InstanceApi; +import org.jclouds.ec2.options.RunInstancesOptions; import org.jclouds.javax.annotation.Nullable; import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull; import org.jclouds.rest.annotations.BinderParam; @@ -45,6 +46,8 @@ import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; +import com.google.common.collect.Multimap; + /** * Provides access to EC2 Instance Services via their REST API. *

@@ -66,6 +69,16 @@ Set> describeInstancesInRegi @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds); + @Named("DescribeInstances") + @POST + @Path("/") + @FormParams(keys = ACTION, values = "DescribeInstances") + @XMLResponseParser(AWSDescribeInstancesResponseHandler.class) + @Fallback(EmptySetOnNotFoundOr404.class) + Set> describeInstancesInRegionWithFilter( + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, + @BinderParam(BindFiltersToIndexedFormParams.class) Multimap filter); + @Named("RunInstances") @Override @POST diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApi.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApi.java index 6f0f7612944..161afba5ea4 100644 --- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApi.java +++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApi.java @@ -31,6 +31,7 @@ import org.jclouds.aws.ec2.xml.AWSEC2DescribeSecurityGroupsResponseHandler; import org.jclouds.aws.ec2.xml.CreateSecurityGroupResponseHandler; import org.jclouds.aws.filters.FormSigner; +import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams; import org.jclouds.ec2.binders.BindGroupIdsToIndexedFormParams; import org.jclouds.ec2.binders.BindGroupNamesToIndexedFormParams; import org.jclouds.ec2.binders.BindIpPermissionToIndexedFormParams; @@ -49,6 +50,7 @@ import org.jclouds.rest.annotations.XMLResponseParser; import com.google.common.annotations.Beta; +import com.google.common.collect.Multimap; /** * Provides access to EC2 SecurityGroup Services via their REST API. @@ -132,4 +134,14 @@ Set describeSecurityGroupsInRegionById( Set describeSecurityGroupsInRegion( @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, @BinderParam(BindGroupNamesToIndexedFormParams.class) String... securityGroupNames); + + @Named("DescribeSecurityGroups") + @POST + @Path("/") + @FormParams(keys = ACTION, values = "DescribeSecurityGroups") + @XMLResponseParser(AWSEC2DescribeSecurityGroupsResponseHandler.class) + @Fallback(EmptySetOnNotFoundOr404.class) + Set describeSecurityGroupsInRegionWithFilter( + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, + @BinderParam(BindFiltersToIndexedFormParams.class) Multimap filter); } diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/PlacementGroupApi.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/PlacementGroupApi.java index 1acc1217ec6..ec6f9865beb 100644 --- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/PlacementGroupApi.java +++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/PlacementGroupApi.java @@ -30,6 +30,7 @@ import org.jclouds.aws.ec2.domain.PlacementGroup; import org.jclouds.aws.ec2.xml.DescribePlacementGroupsResponseHandler; import org.jclouds.aws.filters.FormSigner; +import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams; import org.jclouds.ec2.binders.BindGroupNamesToIndexedFormParams; import org.jclouds.javax.annotation.Nullable; import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull; @@ -41,6 +42,8 @@ import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; +import com.google.common.collect.Multimap; + /** * Provides access to EC2 Placement Groups via their REST API. *

@@ -133,4 +136,27 @@ Set describePlacementGroupsInRegion( @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, @BinderParam(BindGroupNamesToIndexedFormParams.class) String... placementGroupIds); + /** + * + * Returns information about one or more placement groups in your account. + * + * @param region + * The bundleTask ID is tied to the Region. + * @param filter + * Multimap of filter key/values + * + * @see #deletePlacementGroupInRegion + * @see #createPlacementGroupInRegion + * @see + */ + @Named("DescribePlacementGroups") + @POST + @Path("/") + @FormParams(keys = ACTION, values = "DescribePlacementGroups") + @XMLResponseParser(DescribePlacementGroupsResponseHandler.class) + @Fallback(EmptySetOnNotFoundOr404.class) + Set describePlacementGroupsInRegionWithFilter( + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, + @BinderParam(BindFiltersToIndexedFormParams.class) Multimap filter); } diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/SpotInstanceApi.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/SpotInstanceApi.java index 2d728e444ff..aee2c9d5016 100644 --- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/SpotInstanceApi.java +++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/SpotInstanceApi.java @@ -38,6 +38,7 @@ import org.jclouds.aws.ec2.xml.SpotInstanceHandler; import org.jclouds.aws.ec2.xml.SpotInstancesHandler; import org.jclouds.aws.filters.FormSigner; +import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams; import org.jclouds.javax.annotation.Nullable; import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull; import org.jclouds.rest.annotations.BinderParam; @@ -48,6 +49,8 @@ import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; +import com.google.common.collect.Multimap; + /** * Provides access to EC2 Spot Instances via their REST API. *

@@ -88,6 +91,36 @@ Set describeSpotInstanceRequestsInRegion( @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, @BinderParam(BindSpotInstanceRequestIdsToIndexedFormParams.class) String... requestIds); + /** + * Describes Spot Instance requests. Spot Instances are instances that Amazon EC2 starts on your + * behalf when the maximum price that you specify exceeds the current Spot Price. Amazon EC2 + * periodically sets the Spot Price based on available Spot Instance capacity and current spot + * instance requests. For conceptual information about Spot Instances, refer to the Amazon + * Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide. + * + * @param region + * Region where the spot instance service is running + * @param filter + * Mulitmap of filter key/values. + * + * @see #requestSpotInstancesInRegion + * @see #cancelSpotInstanceRequestsInRegion + * @see #describeSpotPriceHistoryInRegion + * @see + * @return TODO + */ + @Named("DescribeSpotInstanceRequests") + @POST + @Path("/") + @FormParams(keys = ACTION, values = "DescribeSpotInstanceRequests") + @Fallback(EmptySetOnNotFoundOr404.class) + @XMLResponseParser(SpotInstancesHandler.class) + Set describeSpotInstanceRequestsInRegionWithFilter( + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, + @BinderParam(BindFiltersToIndexedFormParams.class) Multimap filter); + /** * request a single spot instance * diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSInstanceApiLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSInstanceApiLiveTest.java index 468de54e18f..c6174394e53 100644 --- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSInstanceApiLiveTest.java +++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSInstanceApiLiveTest.java @@ -21,7 +21,6 @@ import java.util.Set; import org.jclouds.aws.ec2.AWSEC2Api; -import org.jclouds.aws.ec2.AWSEC2ApiMetadata; import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; import org.jclouds.ec2.domain.Reservation; import org.jclouds.ec2.domain.RunningInstance; @@ -58,5 +57,4 @@ void testDescribeInstances() { assert allResults.size() >= 0 : allResults.size(); } } - } diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiExpectTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiExpectTest.java new file mode 100644 index 00000000000..32502b7c9c4 --- /dev/null +++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiExpectTest.java @@ -0,0 +1,78 @@ +/* + * 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.aws.ec2.features; + +import static com.google.common.collect.Iterables.getOnlyElement; +import static org.testng.Assert.assertEquals; + +import org.jclouds.aws.ec2.AWSEC2Api; +import org.jclouds.aws.ec2.compute.internal.BaseAWSEC2ComputeServiceExpectTest; +import org.jclouds.aws.ec2.domain.PlacementGroup; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; + +/** + * @author Andrew Bayer + */ +@Test(groups = "unit", testName = "PlacementGroupApiExpectTest") +public class PlacementGroupApiExpectTest extends BaseAWSEC2ComputeServiceExpectTest { + + HttpRequest filter = HttpRequest.builder().method("POST") + .endpoint("https://ec2.us-east-1.amazonaws.com/") + .addHeader("Host", "ec2.us-east-1.amazonaws.com") + .addFormParam("Action", "DescribePlacementGroups") + .addFormParam("Filter.1.Name", "strategy") + .addFormParam("Filter.1.Value.1", "cluster") + .addFormParam("Signature", "SaA7Un1BE3m9jIEKyjXNdQPzFh/QAJSCebvKXiwUEK0%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z") + .addFormParam("Version", "2012-06-01") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testFilterWhenResponseIs2xx() { + HttpResponse filterResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/describe_placement_groups.xml", "text/xml")).build(); + + AWSEC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse) + .getContext().unwrapApi(AWSEC2Api.class); + + PlacementGroup group = getOnlyElement(apiWhenExist.getPlacementGroupApi().get().describePlacementGroupsInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("strategy", "cluster") + .build())); + + assertEquals(group.getName(), "XYZ-cluster"); + } + + public void testFilterWhenResponseIs404() { + HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build(); + + AWSEC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse) + .getContext().unwrapApi(AWSEC2Api.class); + + assertEquals(apiWhenNotExist.getPlacementGroupApi().get().describePlacementGroupsInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("strategy", "cluster") + .build()), + ImmutableSet.of()); + } +} \ No newline at end of file diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiLiveTest.java index 9c699e97773..ae4d842414a 100644 --- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiLiveTest.java +++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiLiveTest.java @@ -29,6 +29,7 @@ import java.util.Set; import java.util.SortedSet; +import org.jclouds.aws.AWSResponseException; import org.jclouds.aws.domain.Region; import org.jclouds.aws.ec2.AWSEC2Api; import org.jclouds.aws.ec2.domain.PlacementGroup; @@ -53,6 +54,7 @@ import com.google.common.base.Predicate; import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableMultimap; import com.google.inject.Module; /** @@ -84,7 +86,7 @@ public void setupContext() { } @Test - void testDescribe() { + public void testDescribe() { for (String region : supportedRegions) { SortedSet allResults = newTreeSet(client.getPlacementGroupApi().get() .describePlacementGroupsInRegion(region)); @@ -110,7 +112,42 @@ void testDescribe() { } @Test - void testCreatePlacementGroup() { + public void testFilter() { + for (String region : supportedRegions) { + SortedSet allResults = newTreeSet(client.getPlacementGroupApi().get() + .describePlacementGroupsInRegion(region)); + assertNotNull(allResults); + if (allResults.size() >= 1) { + PlacementGroup group = allResults.last(); + SortedSet result = newTreeSet(client.getPlacementGroupApi().get() + .describePlacementGroupsInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("group-name", group.getName()).build())); + assertNotNull(result); + PlacementGroup compare = result.last(); + assertEquals(compare, group); + } + } + } + + @Test(expectedExceptions = AWSResponseException.class) + public void testFilterInvalid() { + for (String region : supportedRegions) { + SortedSet allResults = newTreeSet(client.getPlacementGroupApi().get() + .describePlacementGroupsInRegion(region)); + assertNotNull(allResults); + if (allResults.size() >= 1) { + PlacementGroup group = allResults.last(); + SortedSet result = newTreeSet(client.getPlacementGroupApi().get() + .describePlacementGroupsInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("invalid-filter", group.getName()).build())); + } + } + } + + @Test + public void testCreatePlacementGroup() { String groupName = PREFIX + "1"; for (String region : supportedRegions) { diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiExpectTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiExpectTest.java new file mode 100644 index 00000000000..08c852bcfcc --- /dev/null +++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiExpectTest.java @@ -0,0 +1,78 @@ +/* + * 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.aws.ec2.features; + +import static com.google.common.collect.Iterables.getOnlyElement; +import static org.testng.Assert.assertEquals; + +import org.jclouds.aws.ec2.AWSEC2Api; +import org.jclouds.aws.ec2.compute.internal.BaseAWSEC2ComputeServiceExpectTest; +import org.jclouds.aws.ec2.domain.SpotInstanceRequest; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; + +/** + * @author Andrew Bayer + */ +@Test(groups = "unit", testName = "SpotInstanceApiExpectTest") +public class SpotInstanceApiExpectTest extends BaseAWSEC2ComputeServiceExpectTest { + + HttpRequest filter = HttpRequest.builder().method("POST") + .endpoint("https://ec2.us-east-1.amazonaws.com/") + .addHeader("Host", "ec2.us-east-1.amazonaws.com") + .addFormParam("Action", "DescribeSpotInstanceRequests") + .addFormParam("Filter.1.Name", "instance-id") + .addFormParam("Filter.1.Value.1", "i-ef308e8e") + .addFormParam("Signature", "wQtGpumMCDEzvlldKepCKeEjD9iE7eAyiRBlQztcJMA%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z") + .addFormParam("Version", "2012-06-01") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testFilterWhenResponseIs2xx() { + HttpResponse filterResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/describe_spot_instance.xml", "text/xml")).build(); + + AWSEC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse) + .getContext().unwrapApi(AWSEC2Api.class); + + SpotInstanceRequest request = getOnlyElement(apiWhenExist.getSpotInstanceApi().get().describeSpotInstanceRequestsInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("instance-id", "i-ef308e8e") + .build())); + + assertEquals(request.getId(), "sir-1ede0012"); + } + + public void testFilterWhenResponseIs404() { + HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build(); + + AWSEC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse) + .getContext().unwrapApi(AWSEC2Api.class); + + assertEquals(apiWhenNotExist.getSpotInstanceApi().get().describeSpotInstanceRequestsInRegionWithFilter("us-east-1", + ImmutableMultimap.builder() + .put("instance-id", "i-ef308e8e") + .build()), + ImmutableSet.of()); + } +} \ No newline at end of file diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiLiveTest.java index 88257cdd9e0..ca6ee0adb3f 100644 --- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiLiveTest.java +++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiLiveTest.java @@ -30,6 +30,7 @@ import java.util.SortedSet; import java.util.concurrent.TimeUnit; +import org.jclouds.aws.AWSResponseException; import org.jclouds.aws.domain.Region; import org.jclouds.aws.ec2.AWSEC2Api; import org.jclouds.aws.ec2.domain.AWSRunningInstance; @@ -44,6 +45,7 @@ import org.testng.annotations.Test; import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; @@ -74,7 +76,7 @@ public void setupContext() { } @Test - void testDescribeSpotRequestsInRegion() { + public void testDescribeSpotRequestsInRegion() { for (String region : Region.DEFAULT_REGIONS) { SortedSet allResults = ImmutableSortedSet.copyOf(client.getSpotInstanceApi().get() .describeSpotInstanceRequestsInRegion(region)); @@ -92,7 +94,45 @@ void testDescribeSpotRequestsInRegion() { } @Test - void testDescribeSpotPriceHistoryInRegion() { + public void testDescribeSpotRequestsInRegionFilter() { + for (String region : Region.DEFAULT_REGIONS) { + SortedSet allResults = ImmutableSortedSet.copyOf(client.getSpotInstanceApi().get() + .describeSpotInstanceRequestsInRegion(region)); + assertNotNull(allResults); + if (allResults.size() >= 1) { + SpotInstanceRequest request = allResults.last(); + SortedSet result = ImmutableSortedSet.copyOf(client.getSpotInstanceApi().get() + .describeSpotInstanceRequestsInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("spot-instance-request-id", request.getId()).build())); + + assertNotNull(result); + SpotInstanceRequest compare = result.last(); + assertEquals(compare, request); + } + } + + } + + @Test(expectedExceptions = AWSResponseException.class) + public void testDescribeSpotRequestsInRegionFilterInvalid() { + for (String region : Region.DEFAULT_REGIONS) { + SortedSet allResults = ImmutableSortedSet.copyOf(client.getSpotInstanceApi().get() + .describeSpotInstanceRequestsInRegion(region)); + assertNotNull(allResults); + if (allResults.size() >= 1) { + SpotInstanceRequest request = allResults.last(); + SortedSet result = ImmutableSortedSet.copyOf(client.getSpotInstanceApi().get() + .describeSpotInstanceRequestsInRegionWithFilter(region, + ImmutableMultimap.builder() + .put("invalid-filter", request.getId()).build())); + } + } + + } + + @Test + public void testDescribeSpotPriceHistoryInRegion() { for (String region : Region.DEFAULT_REGIONS) { Set spots = client.getSpotInstanceApi().get().describeSpotPriceHistoryInRegion(region, from(new Date())); assertNotNull(spots); @@ -115,7 +155,7 @@ assert in( } @Test(enabled = true) - void testCreateSpotInstance() { + public void testCreateSpotInstance() { String launchGroup = PREFIX + "1"; for (String region : Region.DEFAULT_REGIONS) for (SpotInstanceRequest request : client.getSpotInstanceApi().get().describeSpotInstanceRequestsInRegion(