From 2d8f5ec807747e0cdaf95ef7431cbbdda575bbef Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Tue, 1 May 2012 10:11:01 -0700 Subject: [PATCH] modernized cloudwatch --- .../org/jclouds/cloudwatch/CloudWatch.java | 14 +- .../cloudwatch/CloudWatchApiMetadata.java | 2 +- .../cloudwatch/CloudWatchAsyncClient.java | 62 ++--- .../jclouds/cloudwatch/CloudWatchClient.java | 64 ++--- .../binders/GetMetricStatisticsBinder.java | 80 ++++++ .../config/CloudWatchRestClientModule.java | 14 ++ .../jclouds/cloudwatch/domain/Datapoint.java | 2 +- .../GetMetricStatistics.java} | 53 +--- .../domain/GetMetricStatisticsResponse.java | 31 +-- .../domain/ListMetricsResponse.java | 29 +-- .../features/MetricAsyncClient.java | 91 +++++++ .../cloudwatch/features/MetricClient.java | 73 ++++++ .../options/GetMetricStatisticsOptions.java | 80 +++++- .../cloudwatch/CloudWatchAsyncClientTest.java | 156 ++---------- .../cloudwatch/CloudWatchClientLiveTest.java | 198 +-------------- .../jclouds/cloudwatch/CloudWatchTest.java | 32 ++- .../features/MetricClientExpectTest.java | 236 ++++++++++++++++++ .../features/MetricClientLiveTest.java | 214 ++++++++++++++++ .../BaseCloudWatchAsyncClientExpectTest.java | 38 +++ .../BaseCloudWatchClientExpectTest.java | 29 +++ .../BaseCloudWatchClientLiveTest.java | 46 ++++ .../internal/BaseCloudWatchExpectTest.java | 82 ++++++ ...etMetricStatisticsResponseHandlerTest.java | 17 +- .../src/test/resources/list_metrics.xml | 16 ++ 24 files changed, 1162 insertions(+), 497 deletions(-) create mode 100644 apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/binders/GetMetricStatisticsBinder.java rename apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/{options/GetMetricStatisticsOptionsV2.java => domain/GetMetricStatistics.java} (85%) create mode 100644 apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/MetricAsyncClient.java create mode 100644 apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/MetricClient.java create mode 100644 apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricClientExpectTest.java create mode 100644 apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricClientLiveTest.java create mode 100644 apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchAsyncClientExpectTest.java create mode 100644 apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchClientExpectTest.java create mode 100644 apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchClientLiveTest.java create mode 100644 apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchExpectTest.java create mode 100644 apis/cloudwatch/src/test/resources/list_metrics.xml diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatch.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatch.java index 91de69af63..e544a8a411 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatch.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatch.java @@ -21,6 +21,7 @@ package org.jclouds.cloudwatch; import com.google.common.collect.AbstractIterator; import org.jclouds.cloudwatch.domain.ListMetricsResponse; import org.jclouds.cloudwatch.domain.Metric; +import org.jclouds.cloudwatch.features.MetricClient; import org.jclouds.cloudwatch.options.ListMetricsOptions; import java.util.Iterator; @@ -41,15 +42,16 @@ public class CloudWatch { * * @return iterable of metrics fitting the criteria */ - public static Iterable listMetrics(final CloudWatchClient cloudWatchClient, - final String region, final ListMetricsOptions options) { + public static Iterable listMetrics(CloudWatchClient cloudWatchClient, String region, + final ListMetricsOptions options) { + final MetricClient metricClientForRegion = cloudWatchClient.getMetricClientForRegion(region); return new Iterable() { public Iterator iterator() { return new AbstractIterator() { private ListMetricsOptions lastOptions = options; - private ListMetricsResponse response = cloudWatchClient.listMetrics(region, lastOptions); - private Iterator iterator = response.getMetrics().iterator(); + private ListMetricsResponse response = metricClientForRegion.listMetrics(lastOptions); + private Iterator iterator = response.iterator(); /** * {@inheritDoc} @@ -64,8 +66,8 @@ public class CloudWatch { .namespace(lastOptions.getNamespace()) .nextToken(response.getNextToken()) .build(); - response = cloudWatchClient.listMetrics(region, lastOptions); - iterator = response.getMetrics().iterator(); + response = metricClientForRegion.listMetrics(lastOptions); + iterator = response.iterator(); } if (iterator.hasNext()) { return iterator.next(); diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchApiMetadata.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchApiMetadata.java index d40bd4ee25..726aab070e 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchApiMetadata.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchApiMetadata.java @@ -73,7 +73,7 @@ public class CloudWatchApiMetadata extends BaseRestApiMetadata { .name("Amazon CloudWatch Api") .identityName("Access Key ID") .credentialName("Secret Access Key") - .version(CloudWatchAsyncClient.VERSION) + .version("2010-08-01") .documentation(URI.create("http://docs.amazonwebservices.com/AmazonCloudWatch/latest/APIReference/")) .defaultEndpoint("https://monitoring.us-east-1.amazonaws.com") .defaultProperties(CloudWatchApiMetadata.defaultProperties()) diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchAsyncClient.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchAsyncClient.java index c98e12873e..a609bc6e7c 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchAsyncClient.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchAsyncClient.java @@ -18,21 +18,24 @@ */ package org.jclouds.cloudwatch; -import com.google.common.util.concurrent.ListenableFuture; +import java.util.Date; +import java.util.Set; + +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; + import org.jclouds.aws.filters.FormSigner; import org.jclouds.cloudwatch.domain.Datapoint; -import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse; -import org.jclouds.cloudwatch.domain.ListMetricsResponse; import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.cloudwatch.features.MetricAsyncClient; import org.jclouds.cloudwatch.functions.ISO8601Format; import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions; -import org.jclouds.cloudwatch.options.GetMetricStatisticsOptionsV2; -import org.jclouds.cloudwatch.options.ListMetricsOptions; import org.jclouds.cloudwatch.xml.GetMetricStatisticsResponseHandler; -import org.jclouds.cloudwatch.xml.GetMetricStatisticsResponseHandlerV2; -import org.jclouds.cloudwatch.xml.ListMetricsResponseHandler; import org.jclouds.javax.annotation.Nullable; +import org.jclouds.location.Region; import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull; +import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.annotations.EndpointParam; import org.jclouds.rest.annotations.FormParams; import org.jclouds.rest.annotations.ParamParser; @@ -40,28 +43,31 @@ import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; -import javax.ws.rs.FormParam; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import java.util.Date; -import java.util.Set; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.inject.Provides; /** * Provides access to Amazon CloudWatch via the Query API *

* * @see * @author Adrian Cole */ @RequestFilters(FormSigner.class) @VirtualHost public interface CloudWatchAsyncClient { - public static final String VERSION = "2010-08-01"; - /** - * @see CloudWatchClient#getMetricStatisticsInRegion + * + * @return the Region codes configured + */ + @Provides + @Region + Set getConfiguredRegions(); + + /** + * @see MetricAsyncClient#getMetricStatistics */ @Deprecated @POST @@ -77,27 +83,11 @@ public interface CloudWatchAsyncClient { @FormParam("Period") int period, @FormParam("Statistics.member.1") Statistics statistics, GetMetricStatisticsOptions... options); - + /** - * @see CloudWatchClient#listMetrics(String, org.jclouds.cloudwatch.options.ListMetricsOptions) + * Provides asynchronous access to Metric features. */ - @POST - @Path("/") - @XMLResponseParser(ListMetricsResponseHandler.class) - @FormParams(keys = "Action", values = "ListMetrics") - ListenableFuture listMetrics( - @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, - ListMetricsOptions options); - - /** - * @see CloudWatchClient#getMetricStatistics(String, org.jclouds.cloudwatch.options.GetMetricStatisticsOptionsV2) - */ - @POST - @Path("/") - @XMLResponseParser(GetMetricStatisticsResponseHandlerV2.class) - @FormParams(keys = "Action", values = "GetMetricStatistics") - ListenableFuture getMetricStatistics( - @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, - GetMetricStatisticsOptionsV2 options); + @Delegate + MetricAsyncClient getMetricClientForRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region); } diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchClient.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchClient.java index cb3da3bb92..2633563111 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchClient.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchClient.java @@ -18,32 +18,42 @@ */ package org.jclouds.cloudwatch; -import org.jclouds.cloudwatch.domain.Datapoint; -import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse; -import org.jclouds.cloudwatch.domain.ListMetricsResponse; -import org.jclouds.cloudwatch.domain.Statistics; -import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions; -import org.jclouds.cloudwatch.options.GetMetricStatisticsOptionsV2; -import org.jclouds.cloudwatch.options.ListMetricsOptions; -import org.jclouds.concurrent.Timeout; -import org.jclouds.javax.annotation.Nullable; - import java.util.Date; import java.util.Set; import java.util.concurrent.TimeUnit; +import org.jclouds.cloudwatch.domain.Datapoint; +import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.cloudwatch.features.MetricClient; +import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions; +import org.jclouds.concurrent.Timeout; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.location.Region; +import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull; +import org.jclouds.rest.annotations.Delegate; +import org.jclouds.rest.annotations.EndpointParam; + +import com.google.inject.Provides; + /** * Provides access to Amazon CloudWatch via the Query API *

* * @see * @author Adrian Cole */ @Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) public interface CloudWatchClient { - + /** + * + * @return the Region codes configured + */ + @Provides + @Region + Set getConfiguredRegions(); + /** * This call returns data for one or more statistics of given a metric. For more information, see * Statistic and Metric. @@ -80,35 +90,15 @@ public interface CloudWatchClient { * The statistics to be returned for the given metric. ex. Average * @param options * more filtering options (e.g. instance ID) + * @see MetricsClient#getMetricStatistics */ @Deprecated Set getMetricStatisticsInRegion(@Nullable String region, String metricName, String namespace, Date startTime, Date endTime, int period, Statistics statistics, GetMetricStatisticsOptions... options); - + /** - * Returns a list of valid metrics stored for the AWS account owner. - * - *

- *

Note

Up to 500 results are returned for any one call. To retrieve further results, use returned - * NextToken ({@link org.jclouds.cloudwatch.domain.ListMetricsResponse#getNextToken()}) - * value with subsequent calls .To retrieve all available metrics with one call, use - * {@link CloudWatch#listMetrics(CloudWatchClient, String, org.jclouds.cloudwatch.options.ListMetricsOptions)}. - * - * @param region the region to query metrics in - * @param options the options describing the metrics query - * - * @return the response object + * Provides synchronous access to Metric features. */ - ListMetricsResponse listMetrics(@Nullable String region, ListMetricsOptions options); - - /** - * Gets statistics for the specified metric. - * - * @param region the region to gather metrics in - * @param options the options describing the metric statistics query - * - * @return the response object - */ - GetMetricStatisticsResponse getMetricStatistics(@Nullable String region, GetMetricStatisticsOptionsV2 options); - + @Delegate + MetricClient getMetricClientForRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region); } diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/binders/GetMetricStatisticsBinder.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/binders/GetMetricStatisticsBinder.java new file mode 100644 index 0000000000..1e2b6f49c7 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/binders/GetMetricStatisticsBinder.java @@ -0,0 +1,80 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.cloudwatch.binders; + +import javax.inject.Inject; + +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.cloudwatch.domain.GetMetricStatistics; +import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.date.DateService; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.utils.ModifyRequest; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ImmutableMultimap; + +/** + * Binds the metrics request to the http request + * + * @see + * + * @author Jeremy Whitlock, Adrian Cole + */ +@Beta +public class GetMetricStatisticsBinder implements org.jclouds.rest.Binder { + + private final DateService dateService; + + @Inject + protected GetMetricStatisticsBinder(DateService dateService){ + this.dateService =dateService; + } + + @Override + public R bindToRequest(R request, Object payload) { + GetMetricStatistics getRequest = GetMetricStatistics.class.cast(payload); + int dimensionIndex = 1; + int statisticIndex = 1; + + ImmutableMultimap.Builder formParameters = ImmutableMultimap. builder(); + for (Dimension dimension : getRequest.getDimensions()) { + formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName()); + formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue()); + dimensionIndex++; + } + + formParameters.put("EndTime", dateService.iso8601SecondsDateFormat(getRequest.getEndTime())); + formParameters.put("MetricName", getRequest.getMetricName()); + formParameters.put("Namespace", getRequest.getNamespace()); + formParameters.put("Period", Integer.toString(getRequest.getPeriod())); + formParameters.put("StartTime", dateService.iso8601SecondsDateFormat(getRequest + .getStartTime())); + + for (Statistics statistic : getRequest.getStatistics()) { + formParameters.put("Statistics.member." + statisticIndex, statistic.toString()); + statisticIndex++; + } + + formParameters.put("Unit", getRequest.getUnit().toString()); + + return ModifyRequest.putFormParams(request, formParameters.build()); + } +} \ No newline at end of file diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/config/CloudWatchRestClientModule.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/config/CloudWatchRestClientModule.java index 7905335acb..15efa04983 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/config/CloudWatchRestClientModule.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/config/CloudWatchRestClientModule.java @@ -18,11 +18,18 @@ */ package org.jclouds.cloudwatch.config; +import java.util.Map; + import org.jclouds.aws.config.FormSigningRestClientModule; import org.jclouds.cloudwatch.CloudWatchAsyncClient; import org.jclouds.cloudwatch.CloudWatchClient; +import org.jclouds.cloudwatch.features.MetricAsyncClient; +import org.jclouds.cloudwatch.features.MetricClient; import org.jclouds.rest.ConfiguresRestClient; +import com.google.common.collect.ImmutableMap; +import com.google.common.reflect.TypeToken; + /** * Configures the Monitoring connection. * @@ -30,5 +37,12 @@ import org.jclouds.rest.ConfiguresRestClient; */ @ConfiguresRestClient public class CloudWatchRestClientModule extends FormSigningRestClientModule { + public static final Map, Class> DELEGATE_MAP = ImmutableMap., Class> builder()// + .put(MetricClient.class, MetricAsyncClient.class) + .build(); + + public CloudWatchRestClientModule() { + super(TypeToken.of(CloudWatchClient.class), TypeToken.of(CloudWatchAsyncClient.class), DELEGATE_MAP); + } } diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Datapoint.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Datapoint.java index c9f0459d66..f430a647a4 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Datapoint.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Datapoint.java @@ -24,7 +24,7 @@ import org.jclouds.javax.annotation.Nullable; import java.util.Date; /** - * @see * * @author Adrian Cole diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/GetMetricStatisticsOptionsV2.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/GetMetricStatistics.java similarity index 85% rename from apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/GetMetricStatisticsOptionsV2.java rename to apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/GetMetricStatistics.java index 602b0d3e37..1b5167c293 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/GetMetricStatisticsOptionsV2.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/GetMetricStatistics.java @@ -16,21 +16,17 @@ * specific language governing permissions and limitations * under the License. */ -package org.jclouds.cloudwatch.options; +package org.jclouds.cloudwatch.domain; + +import java.util.Date; +import java.util.Set; + +import org.jclouds.cloudwatch.options.ListMetricsOptions; +import org.jclouds.javax.annotation.Nullable; import com.google.common.annotations.Beta; import com.google.common.base.Preconditions; import com.google.common.collect.Sets; -import org.jclouds.cloudwatch.domain.Dimension; -import org.jclouds.cloudwatch.domain.Statistics; -import org.jclouds.cloudwatch.domain.Unit; -import org.jclouds.date.DateService; -import org.jclouds.date.internal.SimpleDateFormatDateService; -import org.jclouds.http.options.BaseHttpRequestOptions; -import org.jclouds.javax.annotation.Nullable; - -import java.util.Date; -import java.util.Set; /** * Options use to get statistics for the specified metric. @@ -40,9 +36,8 @@ import java.util.Set; * @author Jeremy Whitlock */ @Beta -public class GetMetricStatisticsOptionsV2 extends BaseHttpRequestOptions { +public class GetMetricStatistics { - private static final DateService dateService = new SimpleDateFormatDateService(); private final Set dimensions; private final Date endTime; private final String metricName; @@ -55,7 +50,7 @@ public class GetMetricStatisticsOptionsV2 extends BaseHttpRequestOptions { /** * Private constructor to enforce using {@link Builder}. */ - private GetMetricStatisticsOptionsV2(@Nullable Set dimensions, Date endTime, String metricName, + private GetMetricStatistics(@Nullable Set dimensions, Date endTime, String metricName, String namespace, int period, Date startTime, Set statistics, Unit unit) { this.dimensions = dimensions; @@ -330,7 +325,7 @@ public class GetMetricStatisticsOptionsV2 extends BaseHttpRequestOptions { * @throws NullPointerException if any of the required fields are null * @throws IllegalArgumentException if any of the provided fields don't meet required criteria */ - public GetMetricStatisticsOptionsV2 build() { + public GetMetricStatistics build() { Preconditions.checkNotNull(endTime, "endTime cannot be null."); Preconditions.checkNotNull(metricName, "metricName cannot be null."); Preconditions.checkNotNull(namespace, "namespace cannot be null."); @@ -340,34 +335,8 @@ public class GetMetricStatisticsOptionsV2 extends BaseHttpRequestOptions { Preconditions.checkNotNull(unit, "unit cannot be null."); Preconditions.checkArgument(statistics.size() >= 1, "statistics must have at least one member"); - GetMetricStatisticsOptionsV2 options = new GetMetricStatisticsOptionsV2(dimensions, endTime, metricName, - namespace, period, startTime, - statistics, unit); - int dimensionIndex = 1; - int statisticIndex = 1; - - for (Dimension dimension : dimensions) { - options.formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName()); - options.formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue()); - dimensionIndex++; - } - - options.formParameters.put("EndTime", dateService.iso8601SecondsDateFormat(endTime)); - options.formParameters.put("MetricName", metricName); - options.formParameters.put("Namespace", namespace); - options.formParameters.put("Period", Integer.toString(period)); - options.formParameters.put("StartTime", dateService.iso8601SecondsDateFormat(startTime)); - - for (Statistics statistic : statistics) { - options.formParameters.put("Statistics.member." + statisticIndex, statistic.toString()); - statisticIndex++; - } - - options.formParameters.put("Unit", unit.toString()); - - return options; + return new GetMetricStatistics(dimensions, endTime, metricName,namespace, period, startTime, statistics, unit); } - } } diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/GetMetricStatisticsResponse.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/GetMetricStatisticsResponse.java index 35c195f0f8..146de9c569 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/GetMetricStatisticsResponse.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/GetMetricStatisticsResponse.java @@ -18,38 +18,36 @@ */ package org.jclouds.cloudwatch.domain; -import com.google.common.base.Objects; -import com.google.common.collect.Sets; -import org.jclouds.javax.annotation.Nullable; - import java.util.Set; +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.base.Objects; +import com.google.common.collect.ForwardingSet; +import com.google.common.collect.ImmutableSet; + /** + * the list of {@link Datapoint} for the metric + * * @see * * @author Jeremy Whitlock */ -public class GetMetricStatisticsResponse { +public class GetMetricStatisticsResponse extends ForwardingSet { private final Set datapoints; private final String label; public GetMetricStatisticsResponse(@Nullable Set datapoints, String label) { + // Default to an empty set if (datapoints == null) { - this.datapoints = Sets.newLinkedHashSet(); + this.datapoints = ImmutableSet.of(); } else { - this.datapoints = datapoints; + this.datapoints = ImmutableSet.copyOf(datapoints); } this.label = label; } - /** - * return the list of {@link Datapoint} for the metric - */ - public Set getDatapoints() { - return datapoints; - } - /** * return the label describing the specified metric */ @@ -91,4 +89,9 @@ public class GetMetricStatisticsResponse { .add("datapoints", datapoints).toString(); } + @Override + protected Set delegate() { + return datapoints; + } + } diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/ListMetricsResponse.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/ListMetricsResponse.java index 7411f46a7e..77e2810863 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/ListMetricsResponse.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/ListMetricsResponse.java @@ -18,18 +18,21 @@ */ package org.jclouds.cloudwatch.domain; -import com.google.common.base.Objects; -import com.google.common.collect.Sets; -import org.jclouds.javax.annotation.Nullable; - import java.util.Set; +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.base.Objects; +import com.google.common.collect.ForwardingSet; +import com.google.common.collect.ImmutableSet; + /** + * list of {@link Metric} * @see * * @author Jeremy Whitlock */ -public class ListMetricsResponse { +public class ListMetricsResponse extends ForwardingSet{ private final Set metrics; private final String nextToken; @@ -37,20 +40,13 @@ public class ListMetricsResponse { public ListMetricsResponse(@Nullable Set metrics, @Nullable String nextToken) { // Default to an empty set if (metrics == null) { - this.metrics = Sets.newLinkedHashSet(); + this.metrics = ImmutableSet.of(); } else { - this.metrics = metrics; + this.metrics = ImmutableSet.copyOf(metrics); } this.nextToken = nextToken; } - /** - * return the list of {@link Metric} - */ - public Set getMetrics() { - return metrics; - } - /** * return the next token or null if there is none. */ @@ -93,4 +89,9 @@ public class ListMetricsResponse { .add("nextToken", nextToken).toString(); } + @Override + protected Set delegate() { + return metrics; + } + } diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/MetricAsyncClient.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/MetricAsyncClient.java new file mode 100644 index 0000000000..6c1852e2c2 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/MetricAsyncClient.java @@ -0,0 +1,91 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.cloudwatch.features; + +import javax.ws.rs.POST; +import javax.ws.rs.Path; + +import org.jclouds.aws.filters.FormSigner; +import org.jclouds.cloudwatch.binders.GetMetricStatisticsBinder; +import org.jclouds.cloudwatch.domain.GetMetricStatistics; +import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse; +import org.jclouds.cloudwatch.domain.ListMetricsResponse; +import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions; +import org.jclouds.cloudwatch.options.ListMetricsOptions; +import org.jclouds.cloudwatch.xml.GetMetricStatisticsResponseHandlerV2; +import org.jclouds.cloudwatch.xml.ListMetricsResponseHandler; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.FormParams; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.VirtualHost; +import org.jclouds.rest.annotations.XMLResponseParser; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides access to Amazon CloudWatch via the Query API + *

+ * + * @see + * @author Jeremy Whitlock + */ +@RequestFilters(FormSigner.class) +@VirtualHost +public interface MetricAsyncClient { + + /** + * @see MetricClient#listMetrics() + */ + @POST + @Path("/") + @XMLResponseParser(ListMetricsResponseHandler.class) + @FormParams(keys = "Action", values = "ListMetrics") + ListenableFuture listMetrics(); + + /** + * @see MetricClient#listMetrics(ListMetricsOptions) + */ + @POST + @Path("/") + @XMLResponseParser(ListMetricsResponseHandler.class) + @FormParams(keys = "Action", values = "ListMetrics") + ListenableFuture listMetrics(ListMetricsOptions options); + + /** + * @see MetricClient#getMetricStatistics(GetMetricStatistics) + */ + @POST + @Path("/") + @XMLResponseParser(GetMetricStatisticsResponseHandlerV2.class) + @FormParams(keys = "Action", values = "GetMetricStatistics") + ListenableFuture getMetricStatistics( + @BinderParam(GetMetricStatisticsBinder.class) GetMetricStatistics statistics); + + /** + * @see MetricClient#getMetricStatistics(GetMetricStatistics, GetMetricStatisticsOptions) + */ + @POST + @Path("/") + @XMLResponseParser(GetMetricStatisticsResponseHandlerV2.class) + @FormParams(keys = "Action", values = "GetMetricStatistics") + ListenableFuture getMetricStatistics( + @BinderParam(GetMetricStatisticsBinder.class) GetMetricStatistics statistics, + GetMetricStatisticsOptions options); + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/MetricClient.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/MetricClient.java new file mode 100644 index 0000000000..7f5d465185 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/MetricClient.java @@ -0,0 +1,73 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.cloudwatch.features; + +import java.util.concurrent.TimeUnit; + +import org.jclouds.cloudwatch.domain.GetMetricStatistics; +import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse; +import org.jclouds.cloudwatch.domain.ListMetricsResponse; +import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions; +import org.jclouds.cloudwatch.options.ListMetricsOptions; +import org.jclouds.concurrent.Timeout; + +/** + * Provides access to Amazon CloudWatch via the Query API + *

+ * + * @see + * @author Jeremy Whitlock + */ +@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) +public interface MetricClient { + + /** + * Returns a list of valid metrics stored for the AWS account owner. + * + *

+ *

Note

Up to 500 results are returned for any one call. To retrieve further results, + * use returned NextToken ( + * {@link org.jclouds.cloudwatch.domain.ListMetricsResponse#getNextToken()}) value with + * subsequent calls .To retrieve all available metrics with one call, use + * {@link #list(MetricsClient, String, org.jclouds.cloudwatch.options.ListMetricsOptions)}. + * + * @param options + * the options describing the metrics query + * + * @return the response object + */ + ListMetricsResponse listMetrics(ListMetricsOptions options); + + ListMetricsResponse listMetrics(); + + /** + * Gets statistics for the specified metric. + * + * @param statistics + * the statistics to gather + * @param options + * the options describing the metric statistics query + * + * @return the response object + */ + GetMetricStatisticsResponse getMetricStatistics(GetMetricStatistics statistics, GetMetricStatisticsOptions options); + + GetMetricStatisticsResponse getMetricStatistics(GetMetricStatistics statistics); + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/GetMetricStatisticsOptions.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/GetMetricStatisticsOptions.java index 7a3c5de87a..b100f6e240 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/GetMetricStatisticsOptions.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/GetMetricStatisticsOptions.java @@ -18,11 +18,19 @@ */ package org.jclouds.cloudwatch.options; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Set; + import org.jclouds.aws.util.AWSUtils; +import org.jclouds.cloudwatch.domain.Dimension; import org.jclouds.cloudwatch.domain.Unit; import org.jclouds.http.options.BaseHttpRequestOptions; -import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; +import com.google.common.collect.Sets; /** * Options used to control metric statistics are returned @@ -30,13 +38,46 @@ import static com.google.common.base.Preconditions.checkNotNull; * @see - * @author Andrei Savu + * @author Andrei Savu, Jeremy Whitlock */ -@Deprecated public class GetMetricStatisticsOptions extends BaseHttpRequestOptions { - public static final GetMetricStatisticsOptions NONE = new GetMetricStatisticsOptions(); - + private Set dimensions = Sets.newLinkedHashSet(); + + /** + * A dimension describing qualities of the metric. (Can be called multiple times up to a maximum of 10 times.) + * + * @param dimension the dimension describing the qualities of the metric + * + * @return this {@code Builder} object + * + * @throws IllegalArgumentException if the number of dimensions would be greater than 10 after adding + */ + public GetMetricStatisticsOptions dimension(Dimension dimension) { + if (dimension != null) { + Preconditions.checkArgument(dimensions.size() < 10, "dimension member maximum count of 10 exceeded."); + this.dimensions.add(dimension); + } + return this; + } + + /** + * A list of dimensions describing qualities of the metric. (Set can be 10 or less items.) + * + * @param dimensions the dimensions describing the qualities of the metric + * + * @return this {@code Builder} object + * + * @throws IllegalArgumentException if this is invoked more than 10 times + */ + public GetMetricStatisticsOptions dimensions(Set dimensions) { + if (dimensions != null) { + Preconditions.checkArgument(dimensions.size() <= 10, "dimensions can have 10 or fewer members."); + this.dimensions = ImmutableSet.copyOf(dimensions); + } + return this; + } + /** * @param instanceId * filter metrics by instance Id @@ -74,7 +115,34 @@ public class GetMetricStatisticsOptions extends BaseHttpRequestOptions { GetMetricStatisticsOptions options = new GetMetricStatisticsOptions(); return options.unit(unit); } - + + /** + * @see GetMetricStatisticsOptions#dimension + */ + public static GetMetricStatisticsOptions dimension(Dimension dimension) { + GetMetricStatisticsOptions options = new GetMetricStatisticsOptions(); + return options.dimension(dimension); + } + + /** + * @see GetMetricStatisticsOptions#dimensions + */ + public static GetMetricStatisticsOptions dimensions(Set dimensions) { + GetMetricStatisticsOptions options = new GetMetricStatisticsOptions(); + return options.dimensions(dimensions); + } } + @Override + public Multimap buildFormParameters() { + Multimap formParameters = super.buildFormParameters(); + int dimensionIndex = 1; + for (Dimension dimension : dimensions) { + formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName()); + formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue()); + dimensionIndex++; + } + return formParameters; + } + } diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchAsyncClientTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchAsyncClientTest.java index a79ce1a9bd..d313ccd9b7 100644 --- a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchAsyncClientTest.java +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchAsyncClientTest.java @@ -18,23 +18,24 @@ */ package org.jclouds.cloudwatch; -import com.google.common.base.Supplier; -import com.google.common.collect.ImmutableMap; -import com.google.inject.Module; -import com.google.inject.TypeLiteral; +import static com.google.common.collect.Maps.transformValues; +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URI; +import java.util.Date; +import java.util.Map; + +import javax.inject.Named; + import org.jclouds.Constants; import org.jclouds.apis.ApiMetadata; import org.jclouds.aws.domain.Region; import org.jclouds.aws.filters.FormSigner; import org.jclouds.cloudwatch.config.CloudWatchRestClientModule; -import org.jclouds.cloudwatch.domain.Dimension; -import org.jclouds.cloudwatch.domain.EC2Constants; -import org.jclouds.cloudwatch.domain.Namespaces; import org.jclouds.cloudwatch.domain.Statistics; -import org.jclouds.cloudwatch.domain.Unit; import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions; -import org.jclouds.cloudwatch.options.GetMetricStatisticsOptionsV2; -import org.jclouds.cloudwatch.options.ListMetricsOptions; import org.jclouds.cloudwatch.xml.GetMetricStatisticsResponseHandler; import org.jclouds.date.DateService; import org.jclouds.http.HttpRequest; @@ -47,16 +48,10 @@ import org.jclouds.rest.internal.RestAnnotationProcessor; import org.jclouds.util.Suppliers2; import org.testng.annotations.Test; -import javax.inject.Named; -import java.io.IOException; -import java.lang.reflect.Method; -import java.net.URI; -import java.net.URLEncoder; -import java.util.Date; -import java.util.Map; - -import static com.google.common.collect.Maps.transformValues; -import static org.testng.Assert.assertEquals; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; +import com.google.inject.Module; +import com.google.inject.TypeLiteral; /** * Tests behavior of {@code CloudWatchAsyncClient} @@ -66,128 +61,9 @@ import static org.testng.Assert.assertEquals; // NOTE:without testName, this will not call @Before* and fail w/NPE during // surefire @Test(groups = "unit", testName = "CloudWatchAsyncClientTest") +@Deprecated public class CloudWatchAsyncClientTest extends BaseAsyncClientTest { - /** - * Tests that {@link CloudWatchAsyncClient#getMetricStatistics(String, org.jclouds.cloudwatch.options.GetMetricStatisticsOptionsV2)} - * works as expected. - * - * @throws Exception if anything goes wrong - */ - public void testGetMetricStatisticsV2() throws Exception { - Dimension dimension1 = new Dimension(EC2Constants.Dimension.INSTANCE_ID, "SOMEINSTANCEID"); - Dimension dimension2 = new Dimension(EC2Constants.Dimension.INSTANCE_TYPE, "t1.micro"); - Date endTime = new Date(10000000l); - String metricName = EC2Constants.MetricName.CPU_UTILIZATION; - String namespace = Namespaces.EC2; - int period = 60; - Date startTime = new Date(10000000l); - Statistics statistic1 = Statistics.MAXIMUM; - Statistics statistic2 = Statistics.MINIMUM; - Unit unit = Unit.PERCENT; - - GetMetricStatisticsOptionsV2 goodOptions = GetMetricStatisticsOptionsV2.builder() - .dimension(dimension1) - .dimension(dimension2) - .endTime(endTime) - .metricName(metricName) - .namespace(namespace) - .period(period) - .startTime(startTime) - .statistic(statistic1) - .statistic(statistic2) - .unit(unit).build(); - Method method = CloudWatchAsyncClient.class.getMethod("getMetricStatistics", String.class, - GetMetricStatisticsOptionsV2.class); - HttpRequest request = processor.createRequest(method, null, goodOptions); - - assertRequestLineEquals(request, "POST https://monitoring.us-east-1.amazonaws.com/ HTTP/1.1"); - assertNonPayloadHeadersEqual(request, "Host: monitoring.us-east-1.amazonaws.com\n"); - - // Note: Order of request params is alphabetical - assertPayloadEquals(request, - "Action=GetMetricStatistics" + - "&Dimensions.member.1.Name=" + dimension1.getName() + - "&Dimensions.member.1.Value=" + dimension1.getValue() + - "&Dimensions.member.2.Name=" + dimension2.getName() + - "&Dimensions.member.2.Value=" + dimension2.getValue() + - "&EndTime=1970-01-01T02%3A46%3A40Z" + - "&MetricName=" + metricName + - "&Namespace=" + URLEncoder.encode(namespace, "UTF-8") + - "&Period=" + period + - "&StartTime=1970-01-01T02%3A46%3A40Z" + - "&Statistics.member.1=" + statistic1 + - "&Statistics.member.2=" + statistic2 + - "&Unit=" + unit, - "application/x-www-form-urlencoded", false); - } - - /** - * Tests that {@link CloudWatchAsyncClient#listMetrics(String, org.jclouds.cloudwatch.options.ListMetricsOptions)} works - * as expected. - * - * @throws Exception if anything goes wrong - */ - public void testListMetrics() throws Exception { - Method method = CloudWatchAsyncClient.class.getMethod("listMetrics", String.class, ListMetricsOptions.class); - HttpRequest request; - - // Test an empty request - request = processor.createRequest(method, null, ListMetricsOptions.builder().build()); - - assertRequestLineEquals(request, "POST https://monitoring.us-east-1.amazonaws.com/ HTTP/1.1"); - assertNonPayloadHeadersEqual(request, "Host: monitoring.us-east-1.amazonaws.com\n"); - assertPayloadEquals(request, - "Action=ListMetrics", - "application/x-www-form-urlencoded", false); - - // Note: Order of request params is as follows => Namespace, MetricName, Dimensions, NextToken - - // Test a request with all (only one dimension) - Dimension dimension1 = new Dimension(EC2Constants.Dimension.INSTANCE_ID, "SOMEINSTANCEID"); - String metricName = EC2Constants.MetricName.CPU_UTILIZATION; - String nextToken = "SOMENEXTTOKEN"; - String namespace = Namespaces.EC2; - request = processor.createRequest(method, null, ListMetricsOptions.builder() - .dimension(dimension1) - .metricName(metricName) - .namespace(namespace) - .nextToken(nextToken) - .build()); - - assertRequestLineEquals(request, "POST https://monitoring.us-east-1.amazonaws.com/ HTTP/1.1"); - assertNonPayloadHeadersEqual(request, "Host: monitoring.us-east-1.amazonaws.com\n"); - assertPayloadEquals(request, - "Action=ListMetrics" + - "&Namespace=" + URLEncoder.encode(namespace, "UTF-8") + - "&MetricName=" + metricName + - "&Dimensions.member.1.Name=" + dimension1.getName() + - "&Dimensions.member.1.Value=" + dimension1.getValue() + - "&NextToken=" + nextToken, - "application/x-www-form-urlencoded", false); - - // Test a request with multiple dimensions and no NextToken - Dimension dimension2 = new Dimension(EC2Constants.Dimension.INSTANCE_TYPE, "t1.micro"); - request = processor.createRequest(method, null, ListMetricsOptions.builder() - .dimension(dimension1) - .dimension(dimension2) - .metricName(metricName) - .namespace(namespace) - .build()); - - assertRequestLineEquals(request, "POST https://monitoring.us-east-1.amazonaws.com/ HTTP/1.1"); - assertNonPayloadHeadersEqual(request, "Host: monitoring.us-east-1.amazonaws.com\n"); - assertPayloadEquals(request, - "Action=ListMetrics" + - "&Namespace=" + URLEncoder.encode(namespace, "UTF-8") + - "&MetricName=" + metricName + - "&Dimensions.member.1.Name=" + dimension1.getName() + - "&Dimensions.member.1.Value=" + dimension1.getValue() + - "&Dimensions.member.2.Name=" + dimension2.getName() + - "&Dimensions.member.2.Value=" + dimension2.getValue(), - "application/x-www-form-urlencoded", false); - } - public void testRegisterInstancesWithMeasure() throws SecurityException, NoSuchMethodException, IOException { Date date = new Date(10000000l); Method method = CloudWatchAsyncClient.class.getMethod("getMetricStatisticsInRegion", String.class, String.class, diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchClientLiveTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchClientLiveTest.java index febe3b7c83..f79c8042db 100644 --- a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchClientLiveTest.java +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchClientLiveTest.java @@ -18,38 +18,30 @@ */ package org.jclouds.cloudwatch; -import com.google.common.collect.ImmutableSet; -import com.google.common.reflect.TypeToken; -import org.jclouds.apis.BaseContextLiveTest; -import org.jclouds.cloudwatch.domain.Datapoint; -import org.jclouds.cloudwatch.domain.Dimension; -import org.jclouds.cloudwatch.domain.EC2Constants; -import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse; -import org.jclouds.cloudwatch.domain.ListMetricsResponse; -import org.jclouds.cloudwatch.domain.Metric; -import org.jclouds.cloudwatch.domain.Namespaces; -import org.jclouds.cloudwatch.domain.Statistics; -import org.jclouds.cloudwatch.domain.Unit; -import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions; -import org.jclouds.cloudwatch.options.GetMetricStatisticsOptionsV2; -import org.jclouds.cloudwatch.options.ListMetricsOptions; -import org.jclouds.rest.RestContext; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; +import static com.google.common.base.Preconditions.checkNotNull; import java.util.Calendar; import java.util.Date; import java.util.Set; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; +import org.jclouds.apis.BaseContextLiveTest; +import org.jclouds.cloudwatch.domain.Datapoint; +import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.cloudwatch.domain.Unit; +import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions; +import org.jclouds.rest.RestContext; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import com.google.common.reflect.TypeToken; /** * Tests behavior of {@code CloudWatchClient} * * @author Adrian Cole */ -@Test(groups = "live", singleThreaded = true) +@Test(groups = "live", testName ="CloudWatchClientLiveTest", singleThreaded = true) +@Deprecated public class CloudWatchClientLiveTest extends BaseContextLiveTest> { public CloudWatchClientLiveTest() { provider = "cloudwatch"; @@ -64,170 +56,6 @@ public class CloudWatchClientLiveTest extends BaseContextLiveTest 0) { - for (Metric metric : metricsResponse.getMetrics()) { - Set dimensions = metric.getDimensions(); - boolean testRan = false; - - for (Dimension dimension : dimensions) { - Date endTime = new Date(); - Calendar cal = Calendar.getInstance(); - - cal.add(Calendar.MINUTE, -60 * 24); // 24 hours - - GetMetricStatisticsOptionsV2 options = - GetMetricStatisticsOptionsV2.builder() - .dimension(dimension) - .endTime(endTime) - .metricName(metric.getMetricName()) - .namespace(metric.getNamespace()) - .period(300) - .startTime(cal.getTime()) - .statistics(ImmutableSet.of(Statistics.MAXIMUM, - Statistics.MINIMUM)) - .unit(Unit.PERCENT).build(); - GetMetricStatisticsResponse response = client.getMetricStatistics(null, options); - - if (response.getDatapoints().size() > 0) { - checkNotNull(response.getLabel()); - - for (Datapoint datapoint : response.getDatapoints()) { - checkArgument(datapoint.getAverage() == null); - checkNotNull(datapoint.getMaximum()); - checkNotNull(datapoint.getMinimum()); - } - - testRan = true; - break; - } - } - - if (testRan) { - break; - } - } - } - } - - @Test - protected void testListMetrics() { - ListMetricsResponse response; - String testNamespace = Namespaces.EC2; - String testMetricName = EC2Constants.MetricName.CPU_UTILIZATION; - String testDimensionName = EC2Constants.Dimension.INSTANCE_TYPE; - String testDimensionValue = "t1.micro"; - - // Test an empty request (pulls all stored metric options across all products) - response = client.listMetrics(null, ListMetricsOptions.builder().build()); - - performDefaultMetricsTests(response); - - if (response.getMetrics().size() > 0) { - Metric metric = response.getMetrics().iterator().next(); - - testMetricName = metric.getMetricName(); - testNamespace = metric.getNamespace(); - - if (metric.getDimensions().size() > 0) { - Dimension dimension = metric.getDimensions().iterator().next(); - - testDimensionName = dimension.getName(); - testDimensionValue = dimension.getValue(); - } - - if (testDimensionName == null) { - for (Metric metric1 : response.getMetrics()) { - Set dimensions = metric1.getDimensions(); - - if (dimensions.size() > 0) { - Dimension dimension = metric.getDimensions().iterator().next(); - - testDimensionName = dimension.getName(); - testDimensionValue = dimension.getValue(); - - break; - } - } - } - } - - // Test with a NextToken, even if it's null - response = client.listMetrics(null, ListMetricsOptions.builder().nextToken(response.getNextToken()).build()); - - performDefaultMetricsTests(response); - - // Test with a Namespace - response = client.listMetrics(null, ListMetricsOptions.builder().namespace(testNamespace).build()); - - performDefaultMetricsTests(response); - - for (Metric metric : response.getMetrics()) { - checkArgument(metric.getNamespace().equals(testNamespace), - "All metrics should have the " + testNamespace + " Namespace."); - } - - // Test with a MetricName - response = client.listMetrics(null, ListMetricsOptions.builder().metricName(testMetricName).build()); - - performDefaultMetricsTests(response); - - for (Metric metric : response.getMetrics()) { - checkArgument(metric.getMetricName().equals(testMetricName), - "All metrics should have the " + testMetricName + " MetricName."); - } - - // Test with a Dimension - if (testDimensionName != null) { - Dimension testDimension = new Dimension(testDimensionName, testDimensionValue); - - response = client.listMetrics(null, ListMetricsOptions.builder().dimension(testDimension).build()); - - performDefaultMetricsTests(response); - - for (Metric metric : response.getMetrics()) { - Set dimensions = metric.getDimensions(); - - checkArgument(dimensions.size() == 1, "There should only be one Dimension."); - - Dimension dimension = dimensions.iterator().next(); - - checkArgument(dimension.equals(testDimension), - "The retrieved Dimension and test Dimension should be equal."); - } - } - } - - private void performDefaultMetricsTests(ListMetricsResponse response) { - // If there are less than 500 metrics, NextToken should be null - if (response.getMetrics().size() < 500) { - checkArgument(response.getNextToken() == null, - "NextToken should be null for response with fewer than 500 metrics."); - } - - for (Metric metric : response.getMetrics()) { - Set dimensions = metric.getDimensions(); - - checkArgument(dimensions.size() <= 10, "Dimensions set cannot be greater than 10 items."); - - for (Dimension dimension : dimensions) { - checkNotNull(dimension.getName(), "Name cannot be null for a Dimension."); - checkNotNull(dimension.getValue(), "Value cannot be null for a Dimension."); - } - - checkNotNull(metric.getMetricName(), "MetricName cannot be null for a Metric."); - checkNotNull(metric.getNamespace(), "Namespace cannot be null for a Metric."); - } - } - - @Test - protected void testGetMetricStatisticsInRegion() { - getEC2MetricStatisticsInRegion(null); - } protected Set getEC2MetricStatisticsInRegion(String region) { Calendar cal = Calendar.getInstance(); diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchTest.java index 127ba56425..ac34d5e09f 100644 --- a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchTest.java +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchTest.java @@ -18,18 +18,20 @@ */ package org.jclouds.cloudwatch; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; + import org.easymock.EasyMock; import org.jclouds.cloudwatch.domain.ListMetricsResponse; import org.jclouds.cloudwatch.domain.Metric; +import org.jclouds.cloudwatch.features.MetricClient; import org.jclouds.cloudwatch.options.ListMetricsOptions; import org.testng.Assert; import org.testng.annotations.Test; -import static org.easymock.EasyMock.anyObject; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.expect; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; /** * Tests behavior of {@code CloudWatch}. @@ -47,14 +49,19 @@ public class CloudWatchTest { @Test public void testSinglePageResult() throws Exception { CloudWatchClient client = createMock(CloudWatchClient.class); + MetricClient metricClient = createMock(MetricClient.class); ListMetricsOptions options = ListMetricsOptions.builder().build(); ListMetricsResponse response = new ListMetricsResponse(ImmutableSet.of(createMock(Metric.class)), null); + + expect(client.getMetricClientForRegion(null)) + .andReturn(metricClient) + .atLeastOnce(); - expect(client.listMetrics(null, options)) + expect(metricClient.listMetrics(options)) .andReturn(response) .once(); - EasyMock.replay(client); + EasyMock.replay(client, metricClient); Assert.assertEquals(1, Iterables.size(CloudWatch.listMetrics(client, null, options))); } @@ -68,19 +75,24 @@ public class CloudWatchTest { @Test public void testMultiPageResult() throws Exception { CloudWatchClient client = createMock(CloudWatchClient.class); + MetricClient metricClient = createMock(MetricClient.class); ListMetricsOptions options = ListMetricsOptions.builder().build(); ListMetricsResponse response1 = new ListMetricsResponse(ImmutableSet.of(createMock(Metric.class)), "NEXTTOKEN"); ListMetricsResponse response2 = new ListMetricsResponse(ImmutableSet.of(createMock(Metric.class)), null); // Using EasyMock.eq("") because EasyMock makes it impossible to pass null as a String value here - expect(client.listMetrics(EasyMock.eq(""), anyObject(ListMetricsOptions.class))) + expect(client.getMetricClientForRegion(EasyMock.eq(""))) + .andReturn(metricClient) + .atLeastOnce(); + + expect(metricClient.listMetrics(anyObject(ListMetricsOptions.class))) .andReturn(response1) .once(); - expect(client.listMetrics(EasyMock.eq(""), anyObject(ListMetricsOptions.class))) + expect(metricClient.listMetrics(anyObject(ListMetricsOptions.class))) .andReturn(response2) .once(); - EasyMock.replay(client); + EasyMock.replay(client, metricClient); Assert.assertEquals(2, Iterables.size(CloudWatch.listMetrics(client, "", options))); } diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricClientExpectTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricClientExpectTest.java new file mode 100644 index 0000000000..0701846d48 --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricClientExpectTest.java @@ -0,0 +1,236 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unles 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 expres or implied. See the License for the + * specific language governing permisions and limitations + * under the License. + */ +package org.jclouds.cloudwatch.features; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; +import java.util.Date; + +import org.jclouds.cloudwatch.CloudWatchClient; +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.cloudwatch.domain.EC2Constants; +import org.jclouds.cloudwatch.domain.GetMetricStatistics; +import org.jclouds.cloudwatch.domain.Namespaces; +import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.cloudwatch.domain.Unit; +import org.jclouds.cloudwatch.internal.BaseCloudWatchClientExpectTest; +import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions; +import org.jclouds.cloudwatch.options.ListMetricsOptions; +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.ImmutableMultimap; + +/** + * @author Jeremy Whitlock, Adrian Cole + */ +@Test(groups = "unit", testName = "MetricClientExpectTest") +public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest { + HttpRequest listMetrics = HttpRequest.builder() + .method("POST") + .endpoint(URI.create("https://monitoring.us-east-1.amazonaws.com/")) + .headers(ImmutableMultimap. builder() + .put("Host", "monitoring.us-east-1.amazonaws.com") + .build()) + .payload( + payloadFromStringWithContentType( + new StringBuilder() + .append("Action=ListMetrics").append('&') + .append("Signature=KSh9oQydCR0HMAV6QPYwDzqwQIpxs8I%2Fig7brYgHVZU%3D").append('&') + .append("SignatureMethod=HmacSHA256").append('&') + .append("SignatureVersion=2").append('&') + .append("Timestamp=2009-11-08T15%3A54%3A08.897Z").append('&') + .append("Version=2010-08-01").append('&') + .append("AWSAccessKeyId=identity").toString(), "application/x-www-form-urlencoded")) + .build(); + + public void testListMetricsWhenResponseIs2xx() throws Exception { + + HttpResponse listMetricsResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/list_metrics.xml", "text/xml")).build(); + + CloudWatchClient clientWhenMetricsExist = requestSendsResponse( + listMetrics, listMetricsResponse); + + assertEquals(clientWhenMetricsExist.getMetricClientForRegion(null).listMetrics().toString(), + "ListMetricsResponse{metrics=[Metric{namespace=AWS/EC2, metricName=CPUUtilization, dimension=[Dimension{name=InstanceId, value=i-689fcf0f}]}], nextToken=null}"); + } + + // TODO: this should really be an empty set + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testListMetricsWhenResponseIs404() throws Exception { + + HttpResponse listMetricsResponse = HttpResponse.builder().statusCode(404).build(); + + CloudWatchClient clientWhenMetricsDontExist = requestSendsResponse( + listMetrics, listMetricsResponse); + + clientWhenMetricsDontExist.getMetricClientForRegion(null).listMetrics(); + } + + public void testListMetricsWithOptionsWhenResponseIs2xx() throws Exception { + HttpRequest listMetricsWithOptions = HttpRequest.builder() + .method("POST") + .endpoint(URI.create("https://monitoring.us-east-1.amazonaws.com/")) + .headers(ImmutableMultimap. builder() + .put("Host", "monitoring.us-east-1.amazonaws.com") + .build()) + .payload( + payloadFromStringWithContentType( + new StringBuilder() + .append("Action=ListMetrics").append('&') + .append("Dimensions.member.1.Name=InstanceId").append('&') + .append("Dimensions.member.1.Value=SOMEINSTANCEID").append('&') + .append("MetricName=CPUUtilization").append('&') + .append("Namespace=SOMENEXTTOKEN").append('&') + .append("NextToken=AWS%2FEC2").append('&') + .append("Signature=G05HKEx9FJpGZBk02OVYwt3u4g%2FilAY9nU5hJI9LDXA%3D").append('&') + .append("SignatureMethod=HmacSHA256").append('&') + .append("SignatureVersion=2").append('&') + .append("Timestamp=2009-11-08T15%3A54%3A08.897Z").append('&') + .append("Version=2010-08-01").append('&') + .append("AWSAccessKeyId=identity").toString(), "application/x-www-form-urlencoded")) + .build(); + + HttpResponse listMetricsWithOptionsResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/list_metrics.xml", "text/xml")).build(); + + CloudWatchClient clientWhenMetricsWithOptionsExist = requestSendsResponse(listMetricsWithOptions, + listMetricsWithOptionsResponse); + + assertEquals( + clientWhenMetricsWithOptionsExist.getMetricClientForRegion(null).listMetrics( + ListMetricsOptions.builder() + .dimension(new Dimension(EC2Constants.Dimension.INSTANCE_ID, "SOMEINSTANCEID")) + .metricName(EC2Constants.MetricName.CPU_UTILIZATION) + .namespace("SOMENEXTTOKEN") + .nextToken( Namespaces.EC2) + .build()).toString(), + "ListMetricsResponse{metrics=[Metric{namespace=AWS/EC2, metricName=CPUUtilization, dimension=[Dimension{name=InstanceId, value=i-689fcf0f}]}], nextToken=null}"); + } + + GetMetricStatistics stats = GetMetricStatistics.builder() + .endTime(new Date(10000000l)) + .metricName(EC2Constants.MetricName.CPU_UTILIZATION) + .namespace(Namespaces.EC2) + .period(60) + .startTime(new Date(10000000l)) + .statistic(Statistics.MAXIMUM) + .statistic(Statistics.MINIMUM) + .unit(Unit.PERCENT).build(); + + HttpRequest getMetricStatistics = HttpRequest.builder() + .method("POST") + .endpoint(URI.create("https://monitoring.us-east-1.amazonaws.com/")) + .headers(ImmutableMultimap. builder() + .put("Host", "monitoring.us-east-1.amazonaws.com") + .build()) + .payload( + payloadFromStringWithContentType( + new StringBuilder() + .append("Action=GetMetricStatistics").append('&') + .append("EndTime=1970-01-01T02%3A46%3A40Z").append('&') + .append("MetricName=CPUUtilization").append('&') + .append("Namespace=AWS%2FEC2").append('&') + .append("Period=60").append('&') + .append("Signature=rmg8%2Ba7w4ycy%2FKfO8rnuj6rDL0jNE96m8GKfjh3SWcw%3D").append('&') + .append("SignatureMethod=HmacSHA256").append('&') + .append("SignatureVersion=2").append('&') + .append("StartTime=1970-01-01T02%3A46%3A40Z").append('&') + .append("Statistics.member.1=Maximum").append('&') + .append("Statistics.member.2=Minimum").append('&') + .append("Timestamp=2009-11-08T15%3A54%3A08.897Z").append('&') + .append("Unit=Percent").append('&').append("Version=2010-08-01").append('&') + .append("AWSAccessKeyId=identity").toString(), "application/x-www-form-urlencoded")) + .build(); + + public void testGetMetricStatisticsWhenResponseIs2xx() throws Exception { + + HttpResponse getMetricStatisticsResponse = HttpResponse.builder().statusCode(200).payload( + payloadFromResourceWithContentType("/get_metric_statistics.xml", "text/xml")).build(); + + CloudWatchClient clientWhenMetricsExist = requestSendsResponse(getMetricStatistics, getMetricStatisticsResponse); + + assertEquals( + clientWhenMetricsExist.getMetricClientForRegion(null).getMetricStatistics(stats).toString(), + // TODO: make an object for this + "GetMetricStatisticsResponse{label=CPUUtilization, datapoints=[Datapoint{timestamp=Thu Jan 15 16:00:00 PST 2009, customUnit=null, maximum=null, minimum=null, average=0.17777777777777778, sum=null, samples=9.0, unit=Percent}, Datapoint{timestamp=Thu Jan 15 16:01:00 PST 2009, customUnit=null, maximum=null, minimum=null, average=0.1, sum=null, samples=8.0, unit=Percent}]}"); + } + + // TODO: this should really be an empty set + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testGetMetricStatisticsWhenResponseIs404() throws Exception { + + HttpResponse getMetricStatisticsResponse = HttpResponse.builder().statusCode(404).build(); + + CloudWatchClient clientWhenMetricsDontExist = requestSendsResponse(getMetricStatistics, getMetricStatisticsResponse); + + clientWhenMetricsDontExist.getMetricClientForRegion(null).getMetricStatistics(stats); + } + + public void testGetMetricStatisticsWithOptionsWhenResponseIs2xx() throws Exception { + HttpRequest getMetricStatistics = HttpRequest.builder() + .method("POST") + .endpoint(URI.create("https://monitoring.us-east-1.amazonaws.com/")) + .headers(ImmutableMultimap. builder() + .put("Host", "monitoring.us-east-1.amazonaws.com") + .build()) + .payload( + payloadFromStringWithContentType( + new StringBuilder() + .append("Action=GetMetricStatistics").append('&') + .append("Dimensions.member.1.Name=InstanceId").append('&') + .append("Dimensions.member.1.Value=SOMEINSTANCEID").append('&') + .append("Dimensions.member.2.Name=InstanceType").append('&') + .append("Dimensions.member.2.Value=t1.micro").append('&') + .append("EndTime=1970-01-01T02%3A46%3A40Z").append('&') + .append("MetricName=CPUUtilization").append('&') + .append("Namespace=AWS%2FEC2").append('&') + .append("Period=60").append('&') + .append("Signature=e0WyI%2FNm4hN2%2BMEm1mjRUzsvgvMCdFXbVJWi4ORpwic%3D").append('&') + .append("SignatureMethod=HmacSHA256").append('&') + .append("SignatureVersion=2").append('&') + .append("StartTime=1970-01-01T02%3A46%3A40Z").append('&') + .append("Statistics.member.1=Maximum").append('&') + .append("Statistics.member.2=Minimum").append('&') + .append("Timestamp=2009-11-08T15%3A54%3A08.897Z").append('&') + .append("Unit=Percent").append('&') + .append("Version=2010-08-01").append('&') + .append("AWSAccessKeyId=identity").toString(), "application/x-www-form-urlencoded")) + .build(); + + HttpResponse getMetricStatisticsResponse = HttpResponse.builder().statusCode(200).payload( + payloadFromResourceWithContentType("/get_metric_statistics.xml", "text/xml")).build(); + + CloudWatchClient clientWhenMetricsExist = requestSendsResponse(getMetricStatistics, getMetricStatisticsResponse); + + Dimension dimension1 = new Dimension(EC2Constants.Dimension.INSTANCE_ID, "SOMEINSTANCEID"); + Dimension dimension2 = new Dimension(EC2Constants.Dimension.INSTANCE_TYPE, "t1.micro"); + + assertEquals( + clientWhenMetricsExist.getMetricClientForRegion(null).getMetricStatistics(stats, + GetMetricStatisticsOptions.Builder.dimension(dimension1).dimension(dimension2)).toString(), + // TODO: make an object for this + "GetMetricStatisticsResponse{label=CPUUtilization, datapoints=[Datapoint{timestamp=Thu Jan 15 16:00:00 PST 2009, customUnit=null, maximum=null, minimum=null, average=0.17777777777777778, sum=null, samples=9.0, unit=Percent}, Datapoint{timestamp=Thu Jan 15 16:01:00 PST 2009, customUnit=null, maximum=null, minimum=null, average=0.1, sum=null, samples=8.0, unit=Percent}]}"); + } + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricClientLiveTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricClientLiveTest.java new file mode 100644 index 0000000000..ad463ae819 --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricClientLiveTest.java @@ -0,0 +1,214 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.cloudwatch.features; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Calendar; +import java.util.Date; +import java.util.Set; + +import org.jclouds.cloudwatch.domain.Datapoint; +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.cloudwatch.domain.EC2Constants; +import org.jclouds.cloudwatch.domain.GetMetricStatistics; +import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse; +import org.jclouds.cloudwatch.domain.ListMetricsResponse; +import org.jclouds.cloudwatch.domain.Metric; +import org.jclouds.cloudwatch.domain.Namespaces; +import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.cloudwatch.domain.Unit; +import org.jclouds.cloudwatch.internal.BaseCloudWatchClientLiveTest; +import org.jclouds.cloudwatch.options.ListMetricsOptions; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * @author Jeremy Whitlock, Adrian Cole + */ +@Test(groups = "live", testName = "MetricClientLiveTest") +public class MetricClientLiveTest extends BaseCloudWatchClientLiveTest { + + // TODO: change this test to retrieve pre-seeded custom metrics + @Test + protected void testGetMetricStatistics() { + ListMetricsResponse metricsResponse = client().listMetrics(); + + // Walk through all datapoints in all metrics until we find a metric datapoint that returns statistics + if (metricsResponse.size() > 0) { + for (Metric metric : metricsResponse) { + Set dimensions = metric.getDimensions(); + boolean testRan = false; + + for (Dimension dimension : dimensions) { + Date endTime = new Date(); + Calendar cal = Calendar.getInstance(); + + cal.add(Calendar.MINUTE, -60 * 24); // 24 hours + + GetMetricStatistics options = + GetMetricStatistics.builder() + .dimension(dimension) + .endTime(endTime) + .metricName(metric.getMetricName()) + .namespace(metric.getNamespace()) + .period(300) + .startTime(cal.getTime()) + .statistics(ImmutableSet.of(Statistics.MAXIMUM, + Statistics.MINIMUM)) + .unit(Unit.PERCENT).build(); + GetMetricStatisticsResponse response = client().getMetricStatistics(options); + + if (response.size() > 0) { + checkNotNull(response.getLabel()); + + for (Datapoint datapoint : response) { + checkArgument(datapoint.getAverage() == null); + checkNotNull(datapoint.getMaximum()); + checkNotNull(datapoint.getMinimum()); + } + + testRan = true; + break; + } + } + + if (testRan) { + break; + } + } + } + } + + @Test + protected void testListMetrics() { + ListMetricsResponse response; + String testNamespace = Namespaces.EC2; + String testMetricName = EC2Constants.MetricName.CPU_UTILIZATION; + String testDimensionName = EC2Constants.Dimension.INSTANCE_TYPE; + String testDimensionValue = "t1.micro"; + + // Test an empty request (pulls all stored metric options across all products) + response = client().listMetrics(); + + performDefaultMetricsTests(response); + + if (response.size() > 0) { + Metric metric = response.iterator().next(); + + testMetricName = metric.getMetricName(); + testNamespace = metric.getNamespace(); + + if (metric.getDimensions().size() > 0) { + Dimension dimension = metric.getDimensions().iterator().next(); + + testDimensionName = dimension.getName(); + testDimensionValue = dimension.getValue(); + } + + if (testDimensionName == null) { + for (Metric metric1 : response) { + Set dimensions = metric1.getDimensions(); + + if (dimensions.size() > 0) { + Dimension dimension = metric.getDimensions().iterator().next(); + + testDimensionName = dimension.getName(); + testDimensionValue = dimension.getValue(); + + break; + } + } + } + } + + // Test with a NextToken, even if it's null + response = client().listMetrics(ListMetricsOptions.builder().nextToken(response.getNextToken()).build()); + + performDefaultMetricsTests(response); + + // Test with a Namespace + response = client().listMetrics(ListMetricsOptions.builder().namespace(testNamespace).build()); + + performDefaultMetricsTests(response); + + for (Metric metric : response) { + checkArgument(metric.getNamespace().equals(testNamespace), + "All metrics should have the " + testNamespace + " Namespace."); + } + + // Test with a MetricName + response = client().listMetrics(ListMetricsOptions.builder().metricName(testMetricName).build()); + + performDefaultMetricsTests(response); + + for (Metric metric : response) { + checkArgument(metric.getMetricName().equals(testMetricName), + "All metrics should have the " + testMetricName + " MetricName."); + } + + // Test with a Dimension + if (testDimensionName != null) { + Dimension testDimension = new Dimension(testDimensionName, testDimensionValue); + + response = client().listMetrics(ListMetricsOptions.builder().dimension(testDimension).build()); + + performDefaultMetricsTests(response); + + for (Metric metric : response) { + Set dimensions = metric.getDimensions(); + + checkArgument(dimensions.size() == 1, "There should only be one Dimension."); + + Dimension dimension = dimensions.iterator().next(); + + checkArgument(dimension.equals(testDimension), + "The retrieved Dimension and test Dimension should be equal."); + } + } + } + + private void performDefaultMetricsTests(ListMetricsResponse response) { + // If there are less than 500 metrics, NextToken should be null + if (response.size() < 500) { + checkArgument(response.getNextToken() == null, + "NextToken should be null for response with fewer than 500 metrics."); + } + + for (Metric metric : response) { + Set dimensions = metric.getDimensions(); + + checkArgument(dimensions.size() <= 10, "Dimensions set cannot be greater than 10 items."); + + for (Dimension dimension : dimensions) { + checkNotNull(dimension.getName(), "Name cannot be null for a Dimension."); + checkNotNull(dimension.getValue(), "Value cannot be null for a Dimension."); + } + + checkNotNull(metric.getMetricName(), "MetricName cannot be null for a Metric."); + checkNotNull(metric.getNamespace(), "Namespace cannot be null for a Metric."); + } + } + + protected MetricClient client() { + return context.getApi().getMetricClientForRegion(null); + } +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchAsyncClientExpectTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchAsyncClientExpectTest.java new file mode 100644 index 0000000000..89445fbdb3 --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchAsyncClientExpectTest.java @@ -0,0 +1,38 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.cloudwatch.internal; + +import java.util.Properties; + +import org.jclouds.cloudwatch.CloudWatchAsyncClient; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; + +import com.google.common.base.Function; +import com.google.inject.Module; + +/** + * + * @author Adrian Cole + */ +public class BaseCloudWatchAsyncClientExpectTest extends BaseCloudWatchExpectTest { + public CloudWatchAsyncClient createClient(Function fn, Module module, Properties props) { + return createInjector(fn, module, props).getInstance(CloudWatchAsyncClient.class); + } +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchClientExpectTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchClientExpectTest.java new file mode 100644 index 0000000000..61c7c1ac92 --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchClientExpectTest.java @@ -0,0 +1,29 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.cloudwatch.internal; + +import org.jclouds.cloudwatch.CloudWatchClient; + +/** + * + * @author Adrian Cole + */ +public class BaseCloudWatchClientExpectTest extends BaseCloudWatchExpectTest { + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchClientLiveTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchClientLiveTest.java new file mode 100644 index 0000000000..c6af13ca05 --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchClientLiveTest.java @@ -0,0 +1,46 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.cloudwatch.internal; + +import org.jclouds.apis.BaseContextLiveTest; +import org.jclouds.cloudwatch.CloudWatchApiMetadata; +import org.jclouds.cloudwatch.CloudWatchAsyncClient; +import org.jclouds.cloudwatch.CloudWatchClient; +import org.jclouds.rest.RestContext; +import org.testng.annotations.Test; + +import com.google.common.reflect.TypeToken; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "live") +public class BaseCloudWatchClientLiveTest extends BaseContextLiveTest> { + + public BaseCloudWatchClientLiveTest() { + provider = "cloudwatch"; + } + + @Override + protected TypeToken> contextType() { + return CloudWatchApiMetadata.CONTEXT_TOKEN; + } + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchExpectTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchExpectTest.java new file mode 100644 index 0000000000..d4576ac55a --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchExpectTest.java @@ -0,0 +1,82 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.cloudwatch.internal; + +import static com.google.common.collect.Maps.transformValues; + +import java.net.URI; +import java.util.Map; + +import javax.inject.Named; + +import org.jclouds.Constants; +import org.jclouds.aws.domain.Region; +import org.jclouds.cloudwatch.config.CloudWatchRestClientModule; +import org.jclouds.date.DateService; +import org.jclouds.location.config.LocationModule; +import org.jclouds.location.suppliers.RegionIdToURISupplier; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.internal.BaseRestClientExpectTest; +import org.jclouds.util.Suppliers2; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; +import com.google.inject.Module; + +/** + * + * @author Adrian Cole + */ +public class BaseCloudWatchExpectTest extends BaseRestClientExpectTest { + + public BaseCloudWatchExpectTest() { + provider = "cloudwatch"; + } + + @ConfiguresRestClient + private static final class TestMonitoringRestClientModule extends CloudWatchRestClientModule { + + @Override + protected void installLocations() { + install(new LocationModule()); + bind(RegionIdToURISupplier.class).toInstance(new RegionIdToURISupplier() { + + @Override + public Map> get() { + return transformValues(ImmutableMap. of(Region.EU_WEST_1, URI + .create("https://ec2.eu-west-1.amazonaws.com"), Region.US_EAST_1, URI + .create("https://ec2.us-east-1.amazonaws.com"), Region.US_WEST_1, URI + .create("https://ec2.us-west-1.amazonaws.com")), Suppliers2. ofInstanceFunction()); + } + + }); + } + + @Override + protected String provideTimeStamp(final DateService dateService, + @Named(Constants.PROPERTY_SESSION_INTERVAL) int expiration) { + return "2009-11-08T15:54:08.897Z"; + } + } + + @Override + protected Module createModule() { + return new TestMonitoringRestClientModule(); + } +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/GetMetricStatisticsResponseHandlerTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/GetMetricStatisticsResponseHandlerTest.java index 289b2d1618..c3951173e5 100644 --- a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/GetMetricStatisticsResponseHandlerTest.java +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/GetMetricStatisticsResponseHandlerTest.java @@ -26,6 +26,7 @@ import java.util.Set; import org.jclouds.cloudwatch.domain.Datapoint; import org.jclouds.cloudwatch.domain.Unit; import org.jclouds.date.DateService; +import org.jclouds.date.internal.SimpleDateFormatDateService; import org.jclouds.http.functions.BaseHandlerTest; import org.testng.annotations.Test; @@ -40,13 +41,9 @@ import com.google.common.collect.ImmutableSet; @Test(groups = "unit", testName = "GetMetricStatisticsResponseHandlerTest") public class GetMetricStatisticsResponseHandlerTest extends BaseHandlerTest { public void testApplyInputStream() { - DateService dateService = injector.getInstance(DateService.class); InputStream is = getClass().getResourceAsStream("/get_metric_statistics.xml"); - Set expected = ImmutableSet.of(new Datapoint(0.17777777777777778, null, null, dateService - .iso8601SecondsDateParse("2009-01-16T00:00:00Z"), 9.0, null, Unit.PERCENT, null), new Datapoint( - 0.1, null, null, dateService.iso8601SecondsDateParse("2009-01-16T00:01:00Z"), 8.0, null, - Unit.PERCENT, null)); + Set expected = expected(); GetMetricStatisticsResponseHandler handler = injector.getInstance(GetMetricStatisticsResponseHandler.class); Set result = factory.create(handler).parse(is); @@ -54,4 +51,14 @@ public class GetMetricStatisticsResponseHandlerTest extends BaseHandlerTest { assertEquals(result, expected); } + DateService dateService = new SimpleDateFormatDateService(); + + public Set expected() { + + Set expected = ImmutableSet.of(new Datapoint(0.17777777777777778, null, null, dateService + .iso8601SecondsDateParse("2009-01-16T00:00:00Z"), 9.0, null, Unit.PERCENT, null), new Datapoint(0.1, + null, null, dateService.iso8601SecondsDateParse("2009-01-16T00:01:00Z"), 8.0, null, Unit.PERCENT, null)); + return expected; + } + } diff --git a/apis/cloudwatch/src/test/resources/list_metrics.xml b/apis/cloudwatch/src/test/resources/list_metrics.xml new file mode 100644 index 0000000000..92385f44c6 --- /dev/null +++ b/apis/cloudwatch/src/test/resources/list_metrics.xml @@ -0,0 +1,16 @@ + + + + + + + InstanceId + i-689fcf0f + + + CPUUtilization + AWS/EC2 + + + + \ No newline at end of file