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 d433926d68..49ee0219ec 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatch.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatch.java @@ -20,6 +20,8 @@ package org.jclouds.cloudwatch; import java.util.List; +import com.google.common.base.Function; +import com.google.common.collect.Iterables; import org.jclouds.cloudwatch.domain.Metric; import org.jclouds.cloudwatch.domain.MetricDatum; import org.jclouds.cloudwatch.features.MetricApi; @@ -27,9 +29,6 @@ import org.jclouds.cloudwatch.options.ListMetricsOptions; import org.jclouds.collect.IterableWithMarker; import org.jclouds.collect.PagedIterables; -import com.google.common.base.Function; -import com.google.common.collect.Iterables; - /** * Utilities for using CloudWatch. * diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchApi.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchApi.java index 100dbd3229..82995247be 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchApi.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchApi.java @@ -21,14 +21,14 @@ package org.jclouds.cloudwatch; import java.io.Closeable; import java.util.Set; +import com.google.inject.Provides; +import org.jclouds.cloudwatch.features.AlarmApi; import org.jclouds.cloudwatch.features.MetricApi; 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 *

@@ -58,4 +58,16 @@ public interface CloudWatchApi extends Closeable { */ @Delegate MetricApi getMetricApiForRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region); + + /** + * Provides synchronous access to Alarm features. + */ + @Delegate + AlarmApi getAlarmApi(); + + /** + * Provides synchronous access to Alarm features. + */ + @Delegate + AlarmApi getAlarmApiForRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region); } 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 77495a8767..cf9aa43773 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchApiMetadata.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchApiMetadata.java @@ -24,12 +24,11 @@ import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG; import java.net.URI; import java.util.Properties; +import com.google.common.reflect.TypeToken; import org.jclouds.apis.ApiMetadata; import org.jclouds.cloudwatch.config.CloudWatchRestClientModule; import org.jclouds.rest.internal.BaseRestApiMetadata; -import com.google.common.reflect.TypeToken; - /** * Implementation of {@link ApiMetadata} for Amazon's CloudWatch api. * diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchAsyncApi.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchAsyncApi.java index eddb4b636e..ab0d447e38 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchAsyncApi.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchAsyncApi.java @@ -21,6 +21,8 @@ package org.jclouds.cloudwatch; import java.io.Closeable; import java.util.Set; +import com.google.inject.Provides; +import org.jclouds.cloudwatch.features.AlarmAsyncApi; import org.jclouds.cloudwatch.features.MetricAsyncApi; import org.jclouds.javax.annotation.Nullable; import org.jclouds.location.Region; @@ -28,8 +30,6 @@ 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 *

@@ -57,7 +57,21 @@ public interface CloudWatchAsyncApi extends Closeable { @Delegate MetricAsyncApi getMetricApi(); + /** + * Provides asynchronous access to Metric features. + */ @Delegate MetricAsyncApi getMetricApiForRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region); + /** + * Provides asynchronous access to Alarm features. + */ + @Delegate + AlarmAsyncApi getAlarmApi(); + + /** + * Provides asynchronous access to Metric features. + */ + @Delegate + AlarmAsyncApi getAlarmApiForRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region); } diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/binders/AlarmNamesBinder.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/binders/AlarmNamesBinder.java new file mode 100644 index 0000000000..c193da288a --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/binders/AlarmNamesBinder.java @@ -0,0 +1,50 @@ +/** + * 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 static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ImmutableMultimap; +import org.jclouds.http.HttpRequest; + +/** + * Binds the alarm names request to the http request + * + * @author Jeremy Whitlock + */ +@Beta +public class AlarmNamesBinder implements org.jclouds.rest.Binder { + + @SuppressWarnings("unchecked") + @Override + public R bindToRequest(R request, Object input) { + Iterable alarmNames = (Iterable) checkNotNull(input, "alarm names must be set"); + ImmutableMultimap.Builder formParameters = ImmutableMultimap.builder(); + int alarmNameIndex = 1; + + for (String alarmName : alarmNames) { + formParameters.put("AlarmNames.member." + alarmNameIndex, alarmName); + alarmNameIndex++; + } + + return (R) request.toBuilder().replaceFormParams(formParameters.build()).build(); + } + +} 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 8e34d9c55a..64a3369248 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,18 +18,23 @@ */ package org.jclouds.cloudwatch.config; -import static org.jclouds.reflect.Reflection2.typeToken; - -import java.util.Map; - +import com.google.common.collect.ImmutableMap; import org.jclouds.aws.config.FormSigningRestClientModule; import org.jclouds.cloudwatch.CloudWatchApi; import org.jclouds.cloudwatch.CloudWatchAsyncApi; +import org.jclouds.cloudwatch.features.AlarmApi; +import org.jclouds.cloudwatch.features.AlarmAsyncApi; import org.jclouds.cloudwatch.features.MetricApi; import org.jclouds.cloudwatch.features.MetricAsyncApi; +import org.jclouds.cloudwatch.handlers.CloudWatchErrorHandler; +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.annotation.ClientError; +import org.jclouds.http.annotation.ServerError; import org.jclouds.rest.ConfiguresRestClient; -import com.google.common.collect.ImmutableMap; +import java.util.Map; + +import static org.jclouds.reflect.Reflection2.typeToken; /** * Configures the Monitoring connection. @@ -40,10 +45,17 @@ import com.google.common.collect.ImmutableMap; public class CloudWatchRestClientModule extends FormSigningRestClientModule { public static final Map, Class> DELEGATE_MAP = ImmutableMap., Class> builder()// .put(MetricApi.class, MetricAsyncApi.class) + .put(AlarmApi.class, AlarmAsyncApi.class) .build(); public CloudWatchRestClientModule() { super(typeToken(CloudWatchApi.class), typeToken(CloudWatchAsyncApi.class), DELEGATE_MAP); } + @Override + protected void bindErrorHandlers() { + bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(CloudWatchErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(CloudWatchErrorHandler.class); + } + } diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Alarm.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Alarm.java new file mode 100644 index 0000000000..5987c85667 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Alarm.java @@ -0,0 +1,329 @@ +/** + * 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.domain; + +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Objects.toStringHelper; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Date; +import java.util.Set; + +import com.google.common.annotations.Beta; +import com.google.common.base.Objects; +import com.google.common.base.Optional; + +/** + * @see + * + * @author Jeremy Whitlock + */ +@Beta +public class Alarm { + + public static enum State { + ALARM, + INSUFFICIENT_DATA, + OK, + UNRECOGNIZED; + + public static State fromValue(String value) { + try { + return State.valueOf(checkNotNull(value, "value")); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + } + + private final boolean areActionsEnabled; + private final Set alarmActions; + private final String alarmARN; + private final Date alarmConfigurationUpdatedTimestamp; + private final String alarmDescription; + private final String alarmName; + private final ComparisonOperator comparisonOperator; + private final Set dimensions; + private final int evaluationPeriods; + private final Set insufficientDataActions; + private final String metricName; + private final String namespace; + private final Set okActions; + private final int period; + private final String stateReason; + private final Optional stateReasonData; + private final Date stateUpdatedTimestamp; + private final State state; + private final Statistics statistic; + private final double threshold; + private final Optional unit; + + public Alarm(boolean areActionsEnabled, Set alarmActions, String alarmARN, + Date alarmConfigurationUpdatedTimestamp, String alarmDescription, String alarmName, + ComparisonOperator comparisonOperator, Set dimensions, int evaluationPeriods, + Set insufficientDataActions, String metricName, String namespace, Set okActions, + int period, String stateReason, Optional stateReasonData, Date stateUpdatedTimestamp, + State state, Statistics statistic, double threshold, Optional unit) { + this.alarmName = checkNotNull(alarmName, "alarmName"); + this.areActionsEnabled = checkNotNull(areActionsEnabled, "actionsEnabled for %s", alarmName); + this.alarmActions = checkNotNull(alarmActions, "alarmActions for %s", alarmName); + this.alarmARN = checkNotNull(alarmARN, "alarmArn for %s", alarmName); + this.alarmConfigurationUpdatedTimestamp = checkNotNull(alarmConfigurationUpdatedTimestamp, + "alarmConfigurationUpdatedTimestamp for %s", alarmName); + this.alarmDescription = checkNotNull(alarmDescription, "alarmDescription for %s", alarmName); + this.comparisonOperator = checkNotNull(comparisonOperator, "comparisonOperator for %s", alarmName); + checkArgument(comparisonOperator != ComparisonOperator.UNRECOGNIZED, "comparisonOperator unrecognized"); + this.dimensions = checkNotNull(dimensions, "dimensions for %s", alarmName); + this.evaluationPeriods = checkNotNull(evaluationPeriods, "evaluationPeriods for %s", alarmName); + this.insufficientDataActions = checkNotNull(insufficientDataActions, "insufficientDataActions for %s", alarmName); + this.metricName = checkNotNull(metricName, "metricName for %s", alarmName); + this.namespace = checkNotNull(namespace, "namespace for %s", alarmName); + this.okActions = checkNotNull(okActions, "okActions for %s", alarmName); + this.period = checkNotNull(period, "period for %s", alarmName); + this.stateReason = checkNotNull(stateReason, "stateReason for %s", alarmName); + this.stateReasonData = checkNotNull(stateReasonData, "stateReasonData for %s", alarmName); + this.stateUpdatedTimestamp = checkNotNull(stateUpdatedTimestamp, "stateUpdatedTimestamp for %s", alarmName); + this.state = checkNotNull(state, "state for %s", alarmName); + checkArgument(state != State.UNRECOGNIZED, "state unrecognized"); + this.statistic = checkNotNull(statistic, "statistic for %s", alarmName); + checkArgument(statistic != Statistics.UNRECOGNIZED, "statistic unrecognized"); + this.threshold = checkNotNull(threshold, "threshold for %s", alarmName); + this.unit = checkNotNull(unit, "unit for %s", alarmName); + if (unit.isPresent()) { + checkArgument(unit.get() != Unit.UNRECOGNIZED, "unit unrecognized"); + } + } + + /** + * return whether actions are enabled if the alarm state changes + */ + public boolean areActionsEnabled() { + return areActionsEnabled; + } + + /** + * return list of actions to perform when the alarm state changes to {@link org.jclouds.cloudwatch.domain.Alarm.State#ALARM} from any other state + */ + public Set getAlarmActions() { + return alarmActions; + } + + /** + * return the Amazon Resource Name (ARN) of the alarm + */ + public String getAlarmARN() { + return alarmARN; + } + + /** + * return the date timestamp of when the alarm was last updated + */ + public Date getAlarmConfigurationUpdatedTimestamp() { + return alarmConfigurationUpdatedTimestamp; + } + + /** + * return the description of the alarm + */ + public String getAlarmDescription() { + return alarmDescription; + } + + /** + * return the name of the alarm + */ + public String getAlarmName() { + return alarmName; + } + + /** + * return the arithmetic operation to use when comparing the specified statistic and threshold + */ + public ComparisonOperator getComparisonOperator() { + return comparisonOperator; + } + + /** + * return the list of dimensions associated with the alarm's associated metric + */ + public Set getDimensions() { + return dimensions; + } + + /** + * return the number of periods over which data is compared to the specified threshold + */ + public int getEvaluationPeriods() { + return evaluationPeriods; + } + + /** + * return the list of actions to execute when this alarm transitions into an {@link org.jclouds.cloudwatch.domain.Alarm.State#INSUFFICIENT_DATA} state + * from any other state + */ + public Set getInsufficientDataActions() { + return insufficientDataActions; + } + + /** + * return the name of the alarm's metric + */ + public String getMetricName() { + return metricName; + } + + /** + * return the namespace of alarm's associated metric + */ + public String getNamespace() { + return namespace; + } + + /** + * return the list of actions to execute when this alarm transitions into an {@link org.jclouds.cloudwatch.domain.Alarm.State#OK} state from any other + * state + */ + public Set getOkActions() { + return okActions; + } + + /** + * return the period in seconds over which the statistic is applied + */ + public int getPeriod() { + return period; + } + + /** + * return the human-readable explanation for the alarm's state + */ + public String getStateReason() { + return stateReason; + } + + /** + * return the explanation for the alarm's state in machine-readable JSON format + */ + public Optional getStateReasonData() { + return stateReasonData; + } + + /** + * return the time stamp of the last update to the alarm's state + */ + public Date getStateUpdatedTimestamp() { + return stateUpdatedTimestamp; + } + + /** + * return the state value for the alarm + */ + public State getState() { + return state; + } + + /** + * return the statistic to apply to the alarm's associated metric + */ + public Statistics getStatistic() { + return statistic; + } + + /** + * return the value against which the specified statistic is compared + */ + public double getThreshold() { + return threshold; + } + + /** + * return the unit of the alarm's associated metric + */ + public Optional getUnit() { + return unit; + } + + @Override + public int hashCode() { + return Objects.hashCode(alarmActions, alarmARN, alarmConfigurationUpdatedTimestamp, alarmDescription, alarmName, + areActionsEnabled, comparisonOperator, dimensions, evaluationPeriods, + insufficientDataActions, metricName, namespace, okActions, period, stateReason, + stateReasonData, stateUpdatedTimestamp, state, statistic, threshold, unit); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Alarm other = (Alarm) obj; + return equal(this.alarmActions, other.alarmActions) && + equal(this.alarmARN, other.alarmARN) && + equal(this.alarmConfigurationUpdatedTimestamp, other.alarmConfigurationUpdatedTimestamp) && + equal(this.alarmDescription, other.alarmDescription) && + equal(this.alarmName, other.alarmName) && + equal(this.areActionsEnabled, other.areActionsEnabled) && + equal(this.comparisonOperator, other.comparisonOperator) && + equal(this.dimensions, other.dimensions) && + equal(this.evaluationPeriods, other.evaluationPeriods) && + equal(this.insufficientDataActions, other.insufficientDataActions) && + equal(this.metricName, other.metricName) && + equal(this.namespace, other.namespace) && + equal(this.okActions, other.okActions) && + equal(this.period, other.period) && + equal(this.stateReason, other.stateReason) && + equal(this.stateReasonData, other.stateReasonData) && + equal(this.stateUpdatedTimestamp, other.stateUpdatedTimestamp) && + equal(this.state, other.state) && + equal(this.statistic, other.statistic) && + equal(this.threshold, other.threshold) && + equal(this.unit, other.unit); + } + + @Override + public String toString() { + return toStringHelper(this) + .add("alarmActions", alarmActions) + .add("alarmARN", alarmARN) + .add("alarmConfigurationUpdateTimestamp", alarmConfigurationUpdatedTimestamp) + .add("alarmDescription", alarmDescription) + .add("alarmName", alarmName) + .add("areActionsEnabled", areActionsEnabled) + .add("comparisonOperator", comparisonOperator) + .add("dimensions", dimensions) + .add("evaluationPeriods", evaluationPeriods) + .add("insufficientDataActions", insufficientDataActions) + .add("metricName", metricName) + .add("namespace", namespace) + .add("okActions", okActions) + .add("period", period) + .add("stateReason", stateReason) + .add("stateReasonData", stateReasonData.orNull()) + .add("stateUpdatedTimestamp", stateUpdatedTimestamp) + .add("state", state) + .add("statistic", statistic) + .add("threshold", threshold) + .add("unit", unit.orNull()).toString(); + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/AlarmHistoryItem.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/AlarmHistoryItem.java new file mode 100644 index 0000000000..7e7ec7a03d --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/AlarmHistoryItem.java @@ -0,0 +1,119 @@ +/** + * 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.domain; + +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Objects.toStringHelper; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Date; + +import com.google.common.annotations.Beta; +import com.google.common.base.Objects; + +/** + * @see + * + * @author Jeremy Whitlock + */ +@Beta +public class AlarmHistoryItem { + + private final String alarmName; + private final String historyData; + private final HistoryItemType historyItemType; + private final String historySummary; + private final Date timestamp; + + public AlarmHistoryItem(String alarmName, String historyData, HistoryItemType historyItemType, + String historySummary, Date timestamp) { + this.alarmName = checkNotNull(alarmName, "alarmName"); + this.historyData = checkNotNull(historyData, "historyData for %s", alarmName); + this.historyItemType = checkNotNull(historyItemType, "historyItemType for %s", alarmName); + this.historySummary = checkNotNull(historySummary, "historySummary for %s", alarmName); + this.timestamp = checkNotNull(timestamp, "timestamp for %s", alarmName); + } + + /** + * return the descriptive name for the alarm + */ + public String getAlarmName() { + return alarmName; + } + + /** + * return the machine-readable data about the alarm in JSON format + */ + public String getHistoryData() { + return historyData; + } + + /** + * return the type of alarm history item + */ + public HistoryItemType getHistoryItemType() { + return historyItemType; + } + + /** + * return the human-readable summary of the alarm history + */ + public String getHistorySummary() { + return historySummary; + } + + /** + * return the time stamp for the alarm history item + */ + public Date getTimestamp() { + return timestamp; + } + + @Override + public int hashCode() { + return Objects.hashCode(alarmName, historyData, historyItemType, historySummary, timestamp); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AlarmHistoryItem other = (AlarmHistoryItem) obj; + return equal(this.alarmName, other.alarmName) && + equal(this.historyData, other.historyData) && + equal(this.historyItemType, other.historyItemType) && + equal(this.historySummary, other.historySummary) && + equal(this.timestamp, other.timestamp); + } + + @Override + public String toString() { + return toStringHelper(this) + .add("alarmName", alarmName) + .add("historyData", historyData) + .add("historyItemType", historyItemType) + .add("historySummary", historySummary) + .add("timestamp", timestamp).toString(); + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/ComparisonOperator.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/ComparisonOperator.java new file mode 100644 index 0000000000..be79e00f6c --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/ComparisonOperator.java @@ -0,0 +1,58 @@ +/** + * 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.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.Beta; +import com.google.common.base.CaseFormat; + +/** + * @see + * + * @author Jeremy Whitlock + */ +@Beta +public enum ComparisonOperator { + + GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + GREATER_THAN_THRESHOLD, + LESS_THAN_THRESHOLD, + LESS_THAN_OR_EQUAL_TO_THRESHOLD, + UNRECOGNIZED; + + public String value() { + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name()); + } + + @Override + public String toString() { + return value(); + } + + public static ComparisonOperator fromValue(String value) { + try { + return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(value, "value"))); + + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/HistoryItemType.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/HistoryItemType.java new file mode 100644 index 0000000000..c50e430431 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/HistoryItemType.java @@ -0,0 +1,56 @@ +/** + * 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.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.Beta; +import com.google.common.base.CaseFormat; + +/** + * @see + * + * @author Jeremy Whitlock + */ +@Beta +public enum HistoryItemType { + + CONFIGURATION_UPDATE, + STATE_UPDATE, + ACTION, + UNRECOGNIZED; + + public String value() { + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name()); + } + + @Override + public String toString() { + return value(); + } + + public static HistoryItemType fromValue(String value) { + try { + return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(value, "value"))); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} 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 77e2810863..8fe416f8ee 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 @@ -32,7 +32,7 @@ import com.google.common.collect.ImmutableSet; * * @author Jeremy Whitlock */ -public class ListMetricsResponse extends ForwardingSet{ +public class ListMetricsResponse extends ForwardingSet { private final Set metrics; private final String nextToken; diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Unit.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Unit.java index 5f936d2dc9..6b0f06b270 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Unit.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Unit.java @@ -66,10 +66,10 @@ public enum Unit { return value(); } - public static Unit fromValue(String state) { + public static Unit fromValue(String value) { try { - return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(state, "state").replace( - "/", "_PER_"))); + return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(value, "value").replace( + "/", "Per"))); } catch (IllegalArgumentException e) { return UNRECOGNIZED; } diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/AlarmApi.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/AlarmApi.java new file mode 100644 index 0000000000..103da3a7e9 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/AlarmApi.java @@ -0,0 +1,142 @@ +/** + * 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 com.google.common.annotations.Beta; +import com.google.common.collect.FluentIterable; +import org.jclouds.cloudwatch.domain.Alarm; +import org.jclouds.cloudwatch.domain.AlarmHistoryItem; +import org.jclouds.cloudwatch.options.ListAlarmHistoryOptions; +import org.jclouds.cloudwatch.options.ListAlarmsForMetric; +import org.jclouds.cloudwatch.options.ListAlarmsOptions; +import org.jclouds.cloudwatch.options.SaveAlarmOptions; +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.collect.PagedIterable; +import org.jclouds.javax.annotation.Nullable; + +/** + * Provides access to Amazon CloudWatch via the Query API + *

+ * + * @see AlarmAsyncApi + * @see + * @author Jeremy Whitlock + */ +@Beta +public interface AlarmApi { + + /** + * Deletes all specified alarms. + * + *

+ *

Note

In the event of an error, no alarms are deleted. + * + * @param alarmNames the list of alarms to delete + */ + void delete(Iterable alarmNames); + + /** + * Return all history for all alarms. + * + * @return the response object + */ + PagedIterable listHistory(); + + /** + * Return all history based on the options query + * + * @return the response object + */ + PagedIterable listHistory(ListAlarmHistoryOptions options); + + /** + * Return a single page of history for the specified alarm. + * + * @param nextToken the token corresponding with the data you want to get + * + * @return the response object + */ + IterableWithMarker listHistoryAt(String nextToken); + + /** + * Return all alarms. + * + * @return the response object + */ + PagedIterable list(); + + /** + * Return all alarms based on the options query + * + * @param options the options describing the alarms query + * + * @return the response object + */ + PagedIterable list(ListAlarmsOptions options); + + /** + * Return a single page of alarms based on the options query + * + * @param nextToken the token corresponding with the data you want to get + * + * @return the response object + */ + IterableWithMarker listAt(String nextToken); + + /** + * Return alarms all alarms for a single metric. + * + * @param options the options describing the alarms for metric query + * + * @return the response object + */ + FluentIterable listForMetric(ListAlarmsForMetric options); + + /** + * Disables actions for the specified alarms. + * + * @param alarmNames the list of alarms to disable + */ + void disable(Iterable alarmNames); + + /** + * Enables actions for the specified alarms. + * + * @param alarmNames the list of alarms to enable + */ + void enable(Iterable alarmNames); + + /** + * Creates or updates an alarm and associates it with the specified Amazon CloudWatch metric. + * + * @param options the options describing the metric alarm to create/update + */ + void save(SaveAlarmOptions options); + + /** + * Temporarily sets the state of an alarm. + * + * @param alarmName the descriptive name for the alarm + * @param stateReason the reason that this alarm is set to this specific state (in human-readable text format) + * @param stateReasonData the reason that this alarm is set to this specific state (in machine-readable JSON format) + * @param state the value of the state + */ + void setState(String alarmName, String stateReason, @Nullable String stateReasonData, Alarm.State state); + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/AlarmAsyncApi.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/AlarmAsyncApi.java new file mode 100644 index 0000000000..5bdc4d0aa9 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/AlarmAsyncApi.java @@ -0,0 +1,195 @@ +/** + * 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.inject.Named; +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; + +import com.google.common.annotations.Beta; +import com.google.common.collect.FluentIterable; +import com.google.common.util.concurrent.ListenableFuture; +import org.jclouds.Fallbacks; +import org.jclouds.aws.filters.FormSigner; +import org.jclouds.cloudwatch.binders.AlarmNamesBinder; +import org.jclouds.cloudwatch.domain.Alarm; +import org.jclouds.cloudwatch.domain.AlarmHistoryItem; +import org.jclouds.cloudwatch.functions.ListAlarmsToPagedIterable; +import org.jclouds.cloudwatch.options.ListAlarmHistoryOptions; +import org.jclouds.cloudwatch.options.ListAlarmsForMetric; +import org.jclouds.cloudwatch.options.ListAlarmsOptions; +import org.jclouds.cloudwatch.options.SaveAlarmOptions; +import org.jclouds.cloudwatch.xml.ListAlarmHistoryResponseHandler; +import org.jclouds.cloudwatch.xml.ListAlarmsForMetricResponseHandler; +import org.jclouds.cloudwatch.xml.ListAlarmsResponseHandler; +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.collect.PagedIterable; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.Fallback; +import org.jclouds.rest.annotations.FormParams; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.Transform; +import org.jclouds.rest.annotations.VirtualHost; +import org.jclouds.rest.annotations.XMLResponseParser; + +/** + * Provides access to Amazon CloudWatch via the Query API + *

+ * + * @see + * @author Jeremy Whitlock + */ +@RequestFilters(FormSigner.class) +@VirtualHost +@Beta +public interface AlarmAsyncApi { + + /** + * @see AlarmApi#delete(Iterable) + */ + @Named("DeleteAlarms") + @POST + @Path("/") + @FormParams(keys = "Action", values = "DeleteAlarms") + ListenableFuture delete(@BinderParam(AlarmNamesBinder.class) Iterable alarmNames); + + /** + * @see AlarmApi#listHistory() + */ + @Named("DescribeAlarmHistory") + @POST + @Path("/") + @XMLResponseParser(ListAlarmHistoryResponseHandler.class) + @FormParams(keys = "Action", values = "DescribeAlarmHistory") + @Transform(ListAlarmsToPagedIterable.class) + @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class) + ListenableFuture> listHistory(); + + /** + * @see AlarmApi#listHistory(org.jclouds.cloudwatch.options.ListAlarmHistoryOptions) + */ + @Named("DescribeAlarmHistory") + @POST + @Path("/") + @XMLResponseParser(ListAlarmHistoryResponseHandler.class) + @FormParams(keys = "Action", values = "DescribeAlarmHistory") + @Transform(ListAlarmsToPagedIterable.class) + @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class) + ListenableFuture> listHistory(ListAlarmHistoryOptions options); + + /** + * @see AlarmApi#listHistoryAt(String) + */ + @Named("DescribeAlarmHistory") + @POST + @Path("/") + @XMLResponseParser(ListAlarmHistoryResponseHandler.class) + @FormParams(keys = "Action", values = "DescribeAlarmHistory") + @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class) + ListenableFuture> listHistoryAt(@FormParam("NextToken") + String nextToken); + + /** + * @see org.jclouds.cloudwatch.features.AlarmApi#list() + */ + @Named("DescribeAlarms") + @POST + @Path("/") + @XMLResponseParser(ListAlarmsResponseHandler.class) + @FormParams(keys = "Action", values = "DescribeAlarms") + @Transform(ListAlarmsToPagedIterable.class) + @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class) + ListenableFuture> list(); + + /** + * @see AlarmApi#list(org.jclouds.cloudwatch.options.ListAlarmsOptions) + */ + @Named("DescribeAlarms") + @POST + @Path("/") + @XMLResponseParser(ListAlarmsResponseHandler.class) + @FormParams(keys = "Action", values = "DescribeAlarms") + @Transform(ListAlarmsToPagedIterable.class) + @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class) + ListenableFuture> list(ListAlarmsOptions options); + + /** + * @see AlarmApi#listAt(String) + */ + @Named("DescribeAlarms") + @POST + @Path("/") + @XMLResponseParser(ListAlarmsResponseHandler.class) + @FormParams(keys = "Action", values = "DescribeAlarms") + @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class) + ListenableFuture> listAt(@FormParam("NextToken") String nextToken); + + /** + * @see AlarmApi#listForMetric(org.jclouds.cloudwatch.options.ListAlarmsForMetric) + */ + @Named("DescribeAlarmsForMetric") + @POST + @Path("/") + @XMLResponseParser(ListAlarmsForMetricResponseHandler.class) + @FormParams(keys = "Action", values = "DescribeAlarmsForMetric") + @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class) + ListenableFuture> listForMetric(ListAlarmsForMetric options); + + /** + * @see AlarmApi#disable(Iterable) + */ + @Named("DisableAlarmActions") + @POST + @Path("/") + @FormParams(keys = "Action", values = "DisableAlarmActions") + ListenableFuture disable(@BinderParam(AlarmNamesBinder.class) Iterable alarmNames); + + /** + * @see AlarmApi#enable(Iterable) + */ + @Named("EnableAlarmActions") + @POST + @Path("/") + @FormParams(keys = "Action", values = "EnableAlarmActions") + ListenableFuture enable(@BinderParam(AlarmNamesBinder.class) Iterable alarmNames); + + /** + * @see AlarmApi#save(org.jclouds.cloudwatch.options.SaveAlarmOptions) + */ + @Named("PutMetricAlarm") + @POST + @Path("/") + @FormParams(keys = "Action", values = "PutMetricAlarm") + ListenableFuture save(SaveAlarmOptions options); + + /** + * @see AlarmApi#setState(String, String, String, org.jclouds.cloudwatch.domain.Alarm.State) + */ + @Named("SetAlarmState") + @POST + @Path("/") + @FormParams(keys = "Action", values = "SetAlarmState") + ListenableFuture setState(@FormParam("AlarmName") String alarmName, + @FormParam("StateReason") String stateReason, + @FormParam("StateReasonData") @Nullable String stateReasonData, + @FormParam("StateValue") Alarm.State state); + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/functions/ListAlarmHistoryToPagedIterable.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/functions/ListAlarmHistoryToPagedIterable.java new file mode 100644 index 0000000000..3e1b596c5d --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/functions/ListAlarmHistoryToPagedIterable.java @@ -0,0 +1,63 @@ +/** + * 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.functions; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.inject.Inject; +import org.jclouds.cloudwatch.CloudWatchApi; +import org.jclouds.cloudwatch.domain.AlarmHistoryItem; +import org.jclouds.cloudwatch.features.AlarmApi; +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.collect.internal.CallerArg0ToPagedIterable; + +/** + * @author Jeremy Whitlock + */ +@Beta +public class ListAlarmHistoryToPagedIterable + extends CallerArg0ToPagedIterable { + + private final CloudWatchApi api; + + @Inject + ListAlarmHistoryToPagedIterable(CloudWatchApi api) { + this.api = checkNotNull(api, "api"); + } + + @Override + protected Function> markerToNextForCallingArg0(final String arg0) { + final AlarmApi alarmApi = api.getAlarmApiForRegion(arg0); + return new Function>() { + + @Override + public IterableWithMarker apply(Object input) { + return alarmApi.listHistoryAt(input.toString()); + } + + @Override + public String toString() { + return "listHistory(" + arg0 + ")"; + } + }; + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/functions/ListAlarmsToPagedIterable.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/functions/ListAlarmsToPagedIterable.java new file mode 100644 index 0000000000..7611931fa8 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/functions/ListAlarmsToPagedIterable.java @@ -0,0 +1,63 @@ +/** + * 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.functions; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.inject.Inject; +import org.jclouds.cloudwatch.CloudWatchApi; +import org.jclouds.cloudwatch.domain.Alarm; +import org.jclouds.cloudwatch.features.AlarmApi; +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.collect.internal.CallerArg0ToPagedIterable; + +/** + * @author Jeremy Whitlock + */ +@Beta +public class ListAlarmsToPagedIterable + extends CallerArg0ToPagedIterable { + + private final CloudWatchApi api; + + @Inject + ListAlarmsToPagedIterable(CloudWatchApi api) { + this.api = checkNotNull(api, "api"); + } + + @Override + protected Function> markerToNextForCallingArg0(final String arg0) { + final AlarmApi alarmApi = api.getAlarmApiForRegion(arg0); + return new Function>() { + + @Override + public IterableWithMarker apply(Object input) { + return alarmApi.listAt(input.toString()); + } + + @Override + public String toString() { + return "listAlarms(" + arg0 + ")"; + } + }; + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/handlers/CloudWatchErrorHandler.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/handlers/CloudWatchErrorHandler.java new file mode 100644 index 0000000000..1e509966ad --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/handlers/CloudWatchErrorHandler.java @@ -0,0 +1,86 @@ +/** + * 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.handlers; + +import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream; +import static org.jclouds.http.HttpUtils.releasePayload; + +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; + +import com.google.common.annotations.Beta; +import org.jclouds.aws.AWSResponseException; +import org.jclouds.aws.domain.AWSError; +import org.jclouds.aws.xml.ErrorHandler; +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpResponseException; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.rest.InsufficientResourcesException; + +/** + * @author Jeremy Whitlock + */ +@Beta +@Singleton +public class CloudWatchErrorHandler implements HttpErrorHandler { + + private final ParseSax.Factory factory; + private final Provider handlers; + + @Inject + CloudWatchErrorHandler(ParseSax.Factory factory, Provider handlers) { + this.factory = factory; + this.handlers = handlers; + } + + @Override + public void handleError(HttpCommand command, HttpResponse response) { + Exception exception = new HttpResponseException(command, response); + try { + if (response.getPayload() != null) { + AWSError error = factory.create(handlers.get()) + .parse(new String(closeClientButKeepContentStream(response))); + exception = refineException(new AWSResponseException(command, response, error)); + } + } finally { + releasePayload(response); + command.setException(exception); + } + } + + private Exception refineException(AWSResponseException in) { + int statusCode = in.getResponse().getStatusCode(); + String errorCode = in.getError().getCode(); + String message = in.getError().getMessage(); + + if (statusCode == 400) { + if ("LimitExceeded".equals(errorCode)) { + return new InsufficientResourcesException(message, in); + } else if ("InvalidFormat".equals(errorCode)) { + return new IllegalArgumentException(message, in); + } + } + + return in; + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/ListAlarmHistoryOptions.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/ListAlarmHistoryOptions.java new file mode 100644 index 0000000000..86236eaa74 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/ListAlarmHistoryOptions.java @@ -0,0 +1,108 @@ +/** + * 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.options; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Date; + +import com.google.common.annotations.Beta; +import org.jclouds.cloudwatch.domain.HistoryItemType; +import org.jclouds.date.DateService; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.http.options.BaseHttpRequestOptions; + +/** + * Options used to describe alarm history. + * + * @see + * + * @author Jeremy Whitlock + */ +@Beta +public class ListAlarmHistoryOptions extends BaseHttpRequestOptions { + + private static final DateService dateService = new SimpleDateFormatDateService(); + + /** + * The name of the alarm you want to filter against. + * + * @param alarmName the name of the alarm you want to filter against + * + * @return this {@code ListAlarmHistoryOptions} object + */ + public ListAlarmHistoryOptions alarmName(String alarmName) { + checkNotNull(alarmName, "alarmName"); + checkArgument(alarmName.length() <= 255, "alarmName must be between 1 and 255 characters in length"); + formParameters.put("AlarmName", alarmName); + return this; + } + + /** + * The ending date to retrieve alarm history. + * + * @param endDate the ending date to retrieve alarm history + * + * @return this {@code ListAlarmHistoryOptions} object + */ + public ListAlarmHistoryOptions endDate(Date endDate) { + formParameters.put("EndDate", dateService.iso8601DateFormat(checkNotNull(endDate, "endDate"))); + return this; + } + + /** + * The type of alarm histories to retrieve. + * + * @param historyItemType type of alarm histories to retrieve + * + * @return this {@code ListAlarmHistoryOptions} object + */ + public ListAlarmHistoryOptions historyItemType(HistoryItemType historyItemType) { + checkNotNull(historyItemType, "historyItemType"); + checkArgument(historyItemType != HistoryItemType.UNRECOGNIZED, "historyItemType unrecognized"); + formParameters.put("HistoryItemType", historyItemType.toString()); + return this; + } + + /** + * The maximum number of alarm history records to retrieve. + * + * @param maxRecords maximum number of alarm history records to retrieve + * + * @return this {@code ListAlarmHistoryOptions} object + */ + public ListAlarmHistoryOptions maxRecords(int maxRecords) { + formParameters.put("MaxRecords", checkNotNull(maxRecords, "maxRecords").toString()); + return this; + } + + /** + * The starting date to retrieve alarm history. + * + * @param startDate the starting date to retrieve alarm history + * + * @return this {@code ListAlarmHistoryOptions} object + */ + public ListAlarmHistoryOptions startDate(Date startDate) { + formParameters.put("StartDate", dateService.iso8601DateFormat(checkNotNull(startDate, "startDate"))); + return this; + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/ListAlarmsForMetric.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/ListAlarmsForMetric.java new file mode 100644 index 0000000000..d1e1dfd52c --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/ListAlarmsForMetric.java @@ -0,0 +1,142 @@ +/** + * 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.options; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Set; + +import com.google.common.annotations.Beta; +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.cloudwatch.domain.Unit; +import org.jclouds.http.options.BaseHttpRequestOptions; + +/** + * Options used to describe alarms for metric. + * + * @see + * + * @author Jeremy Whitlock + */ +@Beta +public class ListAlarmsForMetric extends BaseHttpRequestOptions { + + int dimensionIndex = 1; + + /** + * The list of dimensions associated with the metric. + * + * @param dimensions the list of dimensions associated with the metric + * + * @return this {@code ListAlarmsForMetric} object + */ + public ListAlarmsForMetric dimensions(Set dimensions) { + for (Dimension dimension : checkNotNull(dimensions, "dimensions")) { + dimension(dimension); + } + return this; + } + + /** + * The dimension associated with the metric. + * + * @param dimension the dimension associated with the metric + * + * @return this {@code ListAlarmsForMetric} object + */ + public ListAlarmsForMetric dimension(Dimension dimension) { + checkNotNull(dimension, "dimension"); + checkArgument(dimensionIndex <= 10, "maximum number of dimensions is 10"); + formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName()); + formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue()); + dimensionIndex++; + return this; + } + + /** + * The name of the metric. + * + * @param metricName the name of the metric + * + * @return this {@code ListAlarmsForMetric} object + */ + public ListAlarmsForMetric metricName(String metricName) { + checkNotNull(metricName, "metricName"); + checkArgument(metricName.length() <= 255, "metricName must be between 1 and 255 characters in length"); + formParameters.put("MetricName", metricName); + return this; + } + + /** + * The namespace of the metric. + * + * @param namespace namespace of the metric + * + * @return this {@code ListAlarmsForMetric} object + */ + public ListAlarmsForMetric namespace(String namespace) { + checkNotNull(namespace, "namespace"); + checkArgument(namespace.length() <= 255, "namespace must be between 1 and 255 characters in length"); + formParameters.put("Namespace", namespace); + return this; + } + + /** + * The period in seconds over which the statistic is applied. + * + * @param period period in seconds over which the statistic is applied + * + * @return this {@code ListAlarmsForMetric} object + */ + public ListAlarmsForMetric period(int period) { + formParameters.put("Period", checkNotNull(period, "period").toString()); + return this; + } + + /** + * The statistic for the metric. + * + * @param statistic statistic for the metric + * + * @return this {@code ListAlarmsForMetric} object + */ + public ListAlarmsForMetric statistic(Statistics statistic) { + checkNotNull(statistic, "statistic"); + checkArgument(statistic != Statistics.UNRECOGNIZED, "statistic unrecognized"); + formParameters.put("Statistic", statistic.toString()); + return this; + } + + /** + * The unit for the metric. + * + * @param unit unit for the metric + * + * @return this {@code ListAlarmsForMetric} object + */ + public ListAlarmsForMetric unit(Unit unit) { + checkNotNull(unit, "unit"); + checkArgument(unit != Unit.UNRECOGNIZED, "unit unrecognized"); + formParameters.put("Unit", unit.toString()); + return this; + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/ListAlarmsOptions.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/ListAlarmsOptions.java new file mode 100644 index 0000000000..da23348bd3 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/ListAlarmsOptions.java @@ -0,0 +1,122 @@ +/** + * 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.options; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Set; + +import org.jclouds.cloudwatch.domain.Alarm; +import org.jclouds.http.options.BaseHttpRequestOptions; + +/** + * Options used to describe alarms. + * + * @see + * + * @author Jeremy Whitlock + */ +public class ListAlarmsOptions extends BaseHttpRequestOptions { + + int alarmIndex = 1; + + /** + * The action name prefix. + * + * @param actionPrefix the action name prefix + * + * @return this {@code ListAlarmsOptions} object + */ + public ListAlarmsOptions actionPrefix(String actionPrefix) { + checkNotNull(actionPrefix, "actionPrefix"); + checkArgument(actionPrefix.length() <= 1024, "actionPrefix must be between 1 and 1024 characters in length"); + formParameters.put("ActionPrefix", actionPrefix); + return this; + } + + /** + * The alarm name prefix. + * + * @param alarmNamePrefix the alarm name prefix + * + * @return this {@code ListAlarmsOptions} object + */ + public ListAlarmsOptions alarmNamePrefix(String alarmNamePrefix) { + checkNotNull(alarmNamePrefix, "alarmNamePrefix"); + checkArgument(alarmNamePrefix.length() <= 255, "actionPrefix must be between 1 and 255 characters in length"); + formParameters.put("AlarmNamePrefix", alarmNamePrefix); + return this; + } + + /** + * The list of alarm names to retrieve information for. + * + * @param alarmNames the alarm names + * + * @return this {@code ListAlarmsOptions} object + */ + public ListAlarmsOptions alarmNames(Set alarmNames) { + for (String alarmName : checkNotNull(alarmNames, "alarmNames")) { + alarmName(alarmName); + } + return this; + } + + /** + * The alarm name to retrieve information for. + * + * @param alarmName the alarm name + * + * @return this {@code ListAlarmsOptions} object + */ + public ListAlarmsOptions alarmName(String alarmName) { + checkArgument(alarmIndex <= 100, "maximum number of alarm names is 100"); + formParameters.put("AlarmNames.member." + alarmIndex, checkNotNull(alarmName, "alarmName")); + alarmIndex++; + return this; + } + + /** + * The maximum number of alarm descriptions to retrieve. + * + * @param maxRecords maximum number of alarm descriptions to retrieve + * + * @return this {@code ListAlarmsOptions} object + */ + public ListAlarmsOptions maxRecords(int maxRecords) { + formParameters.put("MaxRecords", checkNotNull(maxRecords, "maxRecords").toString()); + return this; + } + + /** + * The state value to be used in matching alarms. + * + * @param state state value to be used in matching alarms + * + * @return this {@code ListAlarmsOptions} object + */ + public ListAlarmsOptions state(Alarm.State state) { + checkNotNull(state, "state"); + checkArgument(state != Alarm.State.UNRECOGNIZED, "state unrecognized"); + formParameters.put("StateValue", state.toString()); + return this; + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/ListMetricsOptions.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/ListMetricsOptions.java index c96e676a86..f7fe16bad8 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/ListMetricsOptions.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/ListMetricsOptions.java @@ -166,14 +166,14 @@ public class ListMetricsOptions extends BaseHttpRequestOptions implements Clonea } /** - * @see ListMetricsOptions#dimension(String) + * @see ListMetricsOptions#dimension(Dimension) */ public static ListMetricsOptions dimension(Dimension dimension) { return new ListMetricsOptions().dimension(dimension); } /** - * @see ListMetricsOptions#afterMarker(String) + * @see ListMetricsOptions#afterMarker(Object) */ public static ListMetricsOptions afterMarker(Object afterMarker) { return new ListMetricsOptions().afterMarker(afterMarker); diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/SaveAlarmOptions.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/SaveAlarmOptions.java new file mode 100644 index 0000000000..3989a080a7 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/SaveAlarmOptions.java @@ -0,0 +1,305 @@ +/** + * 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.options; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Set; + +import com.google.common.annotations.Beta; +import org.jclouds.cloudwatch.domain.ComparisonOperator; +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.cloudwatch.domain.Unit; +import org.jclouds.http.options.BaseHttpRequestOptions; + +/** + * Options used to create/update an alarm. + * + * @see + * + * @author Jeremy Whitlock + */ +@Beta +public class SaveAlarmOptions extends BaseHttpRequestOptions { + + int alarmActionIndex = 1; + int dimensionIndex = 1; + int insufficientDataActionsIndex = 1; + int okActionsIndex = 1; + + /** + * Indicates whether or not actions should be executed during any changes to the alarm's state. + * + * @param actionsEnabled indicates whether or not actions should be executed during any changes to the alarm's state + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions actionsEnabled(boolean actionsEnabled) { + formParameters.put("ActionsEnabled", checkNotNull(actionsEnabled, "actionsEnabled").toString()); + return this; + } + + /** + * The list of actions to execute when this alarm transitions into an ALARM state from any other state. + * + * @param alarmActions the list of actions to execute when this alarm transitions into an ALARM state from any other + * state + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions alarmActions(Set alarmActions) { + for (String alarmAction : checkNotNull(alarmActions, "alarmActions")) { + alarmAction(alarmAction); + } + return this; + } + + /** + * The action to execute when this alarm transitions into an ALARM state from any other state. + * + * @param alarmAction the actions to execute when this alarm transitions into an ALARM state from any other state + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions alarmAction(String alarmAction) { + checkArgument(alarmActionIndex <= 5, "maximum number of alarm actions is 5"); + formParameters.put("AlarmActions.member." + alarmActionIndex, checkNotNull(alarmAction, "alarmAction")); + alarmActionIndex++; + return this; + } + + /** + * The description of the alarm. + * + * @param alarmDescription the description of the alarm + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions alarmDescription(String alarmDescription) { + formParameters.put("AlarmDescription", checkNotNull(alarmDescription, "alarmDescription")); + return this; + } + + /** + * The name of the alarm. + * + * @param alarmName the name of the alarm + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions alarmName(String alarmName) { + formParameters.put("AlarmName", checkNotNull(alarmName, "alarmName")); + return this; + } + + /** + * The arithmetic operation to use when comparing the specified statistic and threshold. + * + * @param comparisonOperator the arithmetic operation to use when comparing the specified statistic and threshold + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions comparisonOperator(ComparisonOperator comparisonOperator) { + checkNotNull(comparisonOperator, "comparisonOperator"); + checkArgument(comparisonOperator != ComparisonOperator.UNRECOGNIZED, "comparisonOperator unrecognized"); + formParameters.put("ComparisonOperator", comparisonOperator.toString()); + return this; + } + + /** + * The dimensions for the alarm's associated metric. + * + * @param dimensions the dimensions for the alarm's associated metric + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions dimensions(Set dimensions) { + for (Dimension dimension : checkNotNull(dimensions, "dimensions")) { + dimension(dimension); + } + return this; + } + + /** + * The dimension for the alarm's associated metric. + * + * @param dimension the dimension for the alarm's associated metric + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions dimension(Dimension dimension) { + checkNotNull(dimension, "dimension"); + checkArgument(dimensionIndex <= 10, "maximum number of dimensions is 10"); + formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName()); + formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue()); + dimensionIndex++; + return this; + } + + /** + * The number of periods over which data is compared to the specified threshold. + * + * @param evaluationPeriods the number of periods over which data is compared to the specified threshold + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions evaluationPeriods(int evaluationPeriods) { + formParameters.put("EvaluationPeriods", checkNotNull(evaluationPeriods, "evaluationPeriods").toString()); + return this; + } + + /** + * The list of actions to execute when this alarm transitions into an INSUFFICIENT_DATA state from any other state. + * + * @param insufficientDataActions the list of actions to execute when this alarm transitions into an + * INSUFFICIENT_DATA state from any other state + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions insufficientDataActions(Set insufficientDataActions) { + for (String insufficientDataAction : checkNotNull(insufficientDataActions)) { + insufficientDataAction(insufficientDataAction); + } + return this; + } + + /** + * The actions to execute when this alarm transitions into an INSUFFICIENT_DATA state from any other state. + * + * @param insufficientDataAction the action to execute when this alarm transitions into an INSUFFICIENT_DATA state + * from any other state + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions insufficientDataAction(String insufficientDataAction) { + checkNotNull(insufficientDataAction, "insufficientDataAction"); + checkArgument(insufficientDataActionsIndex <= 5, "maximum number of insufficient data actions is 5"); + formParameters.put("InsufficientDataActions.member." + insufficientDataActionsIndex, insufficientDataAction); + insufficientDataActionsIndex++; + return this; + } + + /** + * The name for the alarm's associated metric. + * + * @param metricName the name for the alarm's associated metric + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions metricName(String metricName) { + formParameters.put("MetricName", checkNotNull(metricName, "metricName")); + return this; + } + + /** + * The namespace for the alarm's associated metric. + * + * @param namespace the namespace for the alarm's associated metric + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions namespace(String namespace) { + formParameters.put("Namespace", checkNotNull(namespace)); + return this; + } + + /** + * The list of actions to execute when this alarm transitions into an OK state from any other state. + * + * @param okActions the list of actions to execute when this alarm transitions into an OK state from any other state + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions okActions(Set okActions) { + for (String okAction : checkNotNull(okActions, "okActions")) { + okAction(okAction); + } + return this; + } + + /** + * The action to execute when this alarm transitions into an OK state from any other state. + * + * @param okAction the action to execute when this alarm transitions into an OK state from any other state + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions okAction(String okAction) { + checkNotNull(okAction, "okAction"); + checkArgument(okActionsIndex <= 5, "maximum number of ok actions is 5"); + formParameters.put("OKActions.member." + okActionsIndex, okAction); + okActionsIndex++; + return this; + } + + /** + * The period in seconds over which the specified statistic is applied. + * + * @param period the period in seconds over which the specified statistic is applied + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions period(int period) { + formParameters.put("Period", checkNotNull(period, "period").toString()); + return this; + } + + /** + * The statistic to apply to the alarm's associated metric. + * + * @param statistic the statistic to apply to the alarm's associated metric + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions statistic(Statistics statistic) { + checkNotNull(statistic, "statistic"); + checkArgument(statistic != Statistics.UNRECOGNIZED, "statistic unrecognized"); + formParameters.put("Statistic", statistic.toString()); + return this; + } + + /** + * The value against which the specified statistic is compared. + * + * @param threshold the value against which the specified statistic is compared + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions threshold(double threshold) { + formParameters.put("Threshold", checkNotNull(threshold).toString()); + return this; + } + + /** + * The unit for the alarm's associated metric. + * + * @param unit the unit for the alarm's associated metric + * + * @return this {@code SaveAlarmOptions} object + */ + public SaveAlarmOptions unit(Unit unit) { + checkNotNull(unit, "unit"); + checkArgument(unit != Unit.UNRECOGNIZED, "unit unrecognized"); + formParameters.put("Unit", unit.toString()); + return this; + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/AlarmHistoryItemHandler.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/AlarmHistoryItemHandler.java new file mode 100644 index 0000000000..d926983b75 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/AlarmHistoryItemHandler.java @@ -0,0 +1,94 @@ +/** + * 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.xml; + +import javax.inject.Inject; +import java.util.Date; + +import com.google.common.annotations.Beta; +import org.jclouds.cloudwatch.domain.AlarmHistoryItem; +import org.jclouds.cloudwatch.domain.HistoryItemType; +import org.jclouds.date.DateService; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.util.SaxUtils; +import org.xml.sax.SAXException; + +/** + * @see + * + * @author Jeremy Whitlock + */ +@Beta +public class AlarmHistoryItemHandler extends ParseSax.HandlerForGeneratedRequestWithResult { + + protected final DateService dateService; + + private StringBuilder currentText = new StringBuilder(); + private String alarmName; + private String historyData; + private HistoryItemType historyItemType; + private String historySummary; + private Date timestamp; + + @Inject + public AlarmHistoryItemHandler(DateService dateService) { + this.dateService = dateService; + } + + @Override + public void endElement(String uri, String name, String qName) throws SAXException { + if (qName.equals("AlarmName")) { + alarmName = SaxUtils.currentOrNull(currentText); + } else if (qName.equals("HistoryData")) { + String rawJson = SaxUtils.currentOrNull(currentText); + + if (rawJson != null) { + historyData = rawJson.trim(); + } + } else if (qName.equals("HistoryItemType")) { + historyItemType = HistoryItemType.fromValue(SaxUtils.currentOrNull(currentText)); + } else if (qName.equals("HistorySummary")) { + historySummary = SaxUtils.currentOrNull(currentText); + } else if (qName.equals("Timestamp")) { + timestamp = dateService.iso8601DateParse(currentText.toString().trim()); + } + + currentText = new StringBuilder(); + } + + @Override + public void characters(char ch[], int start, int length) { + currentText.append(ch, start, length); + } + + @Override + public AlarmHistoryItem getResult() { + AlarmHistoryItem result = new AlarmHistoryItem(alarmName, historyData, historyItemType, historySummary, + timestamp); + + alarmName = null; + historyData = null; + historyItemType = null; + historySummary = null; + timestamp = null; + + return result; + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/ListAlarmHistoryResponseHandler.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/ListAlarmHistoryResponseHandler.java new file mode 100644 index 0000000000..73f883e1db --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/ListAlarmHistoryResponseHandler.java @@ -0,0 +1,101 @@ +/** + * 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.xml; + +import java.util.Set; + +import com.google.common.annotations.Beta; +import com.google.common.collect.Sets; +import com.google.inject.Inject; +import org.jclouds.cloudwatch.domain.AlarmHistoryItem; +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.collect.IterableWithMarkers; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.util.SaxUtils; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +/** + * @see + * + * @author Jeremy Whitlock + */ +@Beta +public class ListAlarmHistoryResponseHandler + extends ParseSax.HandlerForGeneratedRequestWithResult> { + + private final AlarmHistoryItemHandler alarmHistoryItemHandler; + + private StringBuilder currentText = new StringBuilder(); + private Set alarmHistoryItems = Sets.newLinkedHashSet(); + private String nextToken; + private boolean inAlarmHistoryItems; + + @Inject + public ListAlarmHistoryResponseHandler(AlarmHistoryItemHandler alarmHistoryItemHandler) { + this.alarmHistoryItemHandler = alarmHistoryItemHandler; + } + + @Override + public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException { + if (SaxUtils.equalsOrSuffix(qName, "AlarmHistoryItems")) { + inAlarmHistoryItems = true; + } + if (inAlarmHistoryItems) { + alarmHistoryItemHandler.startElement(url, name, qName, attributes); + } + } + + @Override + public void endElement(String uri, String name, String qName) throws SAXException { + if (inAlarmHistoryItems) { + if (qName.equals("AlarmHistoryItems")) { + inAlarmHistoryItems = false; + } else if (qName.equals("member")) { + alarmHistoryItems.add(alarmHistoryItemHandler.getResult()); + } else { + alarmHistoryItemHandler.endElement(uri, name, qName); + } + } else if (qName.equals("NextToken")) { + nextToken = SaxUtils.currentOrNull(currentText); + } + + currentText = new StringBuilder(); + } + + @Override + public void characters(char ch[], int start, int length) { + if (inAlarmHistoryItems) { + alarmHistoryItemHandler.characters(ch, start, length); + } else { + currentText.append(ch, start, length); + } + } + + @Override + public IterableWithMarker getResult() { + IterableWithMarker result = IterableWithMarkers.from(alarmHistoryItems, nextToken); + + alarmHistoryItems = Sets.newLinkedHashSet(); + nextToken = null; + + return result; + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/ListAlarmsForMetricResponseHandler.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/ListAlarmsForMetricResponseHandler.java new file mode 100644 index 0000000000..7cc5ad36db --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/ListAlarmsForMetricResponseHandler.java @@ -0,0 +1,95 @@ +/** + * 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.xml; + +import java.util.Set; + +import com.google.common.annotations.Beta; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.Sets; +import com.google.inject.Inject; +import org.jclouds.cloudwatch.domain.Alarm; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.util.SaxUtils; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +/** + * @see + * + * @author Jeremy Whitlock + */ +@Beta +public class ListAlarmsForMetricResponseHandler + extends ParseSax.HandlerForGeneratedRequestWithResult> { + + private final MetricAlarmHandler metricAlarmHandler; + + private StringBuilder currentText = new StringBuilder(); + private Set alarms = Sets.newLinkedHashSet(); + private boolean inMetricAlarms; + + @Inject + public ListAlarmsForMetricResponseHandler(MetricAlarmHandler metricAlarmHandler) { + this.metricAlarmHandler = metricAlarmHandler; + } + + @Override + public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException { + if (SaxUtils.equalsOrSuffix(qName, "MetricAlarms")) { + inMetricAlarms = true; + } + if (inMetricAlarms) { + metricAlarmHandler.startElement(url, name, qName, attributes); + } + } + + @Override + public void endElement(String uri, String name, String qName) throws SAXException { + if (inMetricAlarms) { + if (qName.equals("MetricAlarms")) { + inMetricAlarms = false; + } else if (qName.equals("member") && !metricAlarmHandler.shouldHandleMemberTag()) { + alarms.add(metricAlarmHandler.getResult()); + } else { + metricAlarmHandler.endElement(uri, name, qName); + } + } + + currentText = new StringBuilder(); + } + + @Override + public void characters(char ch[], int start, int length) { + if (inMetricAlarms) { + metricAlarmHandler.characters(ch, start, length); + } else { + currentText.append(ch, start, length); + } + } + + @Override + public FluentIterable getResult() { + FluentIterable result = FluentIterable.from(alarms); + + alarms = Sets.newLinkedHashSet(); + + return result; + } +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/ListAlarmsResponseHandler.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/ListAlarmsResponseHandler.java new file mode 100644 index 0000000000..edbc37f3c8 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/ListAlarmsResponseHandler.java @@ -0,0 +1,101 @@ +/** + * 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.xml; + +import java.util.Set; + +import com.google.common.annotations.Beta; +import com.google.common.collect.Sets; +import com.google.inject.Inject; +import org.jclouds.cloudwatch.domain.Alarm; +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.collect.IterableWithMarkers; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.util.SaxUtils; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +/** + * @see + * + * @author Jeremy Whitlock + */ +@Beta +public class ListAlarmsResponseHandler + extends ParseSax.HandlerForGeneratedRequestWithResult> { + + private final MetricAlarmHandler metricAlarmHandler; + + private StringBuilder currentText = new StringBuilder(); + private Set alarms = Sets.newLinkedHashSet(); + private String nextToken; + private boolean inMetricAlarms; + + @Inject + public ListAlarmsResponseHandler(MetricAlarmHandler metricAlarmHandler) { + this.metricAlarmHandler = metricAlarmHandler; + } + + @Override + public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException { + if (SaxUtils.equalsOrSuffix(qName, "MetricAlarms")) { + inMetricAlarms = true; + } + if (inMetricAlarms) { + metricAlarmHandler.startElement(url, name, qName, attributes); + } + } + + @Override + public void endElement(String uri, String name, String qName) throws SAXException { + if (inMetricAlarms) { + if (qName.equals("MetricAlarms")) { + inMetricAlarms = false; + } else if (qName.equals("member") && !metricAlarmHandler.shouldHandleMemberTag()) { + alarms.add(metricAlarmHandler.getResult()); + } else { + metricAlarmHandler.endElement(uri, name, qName); + } + } else if (qName.equals("NextToken")) { + nextToken = SaxUtils.currentOrNull(currentText); + } + + currentText = new StringBuilder(); + } + + @Override + public void characters(char ch[], int start, int length) { + if (inMetricAlarms) { + metricAlarmHandler.characters(ch, start, length); + } else { + currentText.append(ch, start, length); + } + } + + @Override + public IterableWithMarker getResult() { + IterableWithMarker result = IterableWithMarkers.from(alarms, nextToken); + + alarms = Sets.newLinkedHashSet(); + nextToken = null; + + return result; + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/MetricAlarmHandler.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/MetricAlarmHandler.java new file mode 100644 index 0000000000..618b3814a9 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/MetricAlarmHandler.java @@ -0,0 +1,218 @@ +/** + * 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.xml; + +import java.util.Date; +import java.util.Set; + +import com.google.common.annotations.Beta; +import com.google.common.base.Optional; +import com.google.common.collect.Sets; +import com.google.inject.Inject; +import org.jclouds.cloudwatch.domain.Alarm; +import org.jclouds.cloudwatch.domain.ComparisonOperator; +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.http.functions.ParseSax; +import org.jclouds.util.SaxUtils; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +/** + * @see + * + * @author Jeremy Whitlock + */ +@Beta +public class MetricAlarmHandler extends ParseSax.HandlerForGeneratedRequestWithResult { + + protected final DateService dateService; + protected final DimensionHandler dimensionHandler; + + private StringBuilder currentText = new StringBuilder(); + private Set alarmActions = Sets.newLinkedHashSet(); + private Set dimensions = Sets.newLinkedHashSet(); + private Set insufficientDataActions = Sets.newLinkedHashSet(); + private Set okActions = Sets.newLinkedHashSet(); + private boolean inAlarmActions = false; + private boolean inDimensions = false; + private boolean inInsufficientDataActions = false; + private boolean inOkActions = false; + private boolean actionsEnabled; + private String alarmARN; + private Date alarmConfigurationUpdatedTimestamp; + private String alarmDescription; + private String alarmName; + private ComparisonOperator comparisonOperator; + private int evaluationPeriods; + private String metricName; + private String namespace; + private int period; + private String stateReason; + private String stateReasonData; + private Date stateUpdatedTimestamp; + private Alarm.State state; + private Statistics statistic; + private double threshold; + private Unit unit; + + @Inject + public MetricAlarmHandler(DateService dateService, DimensionHandler dimensionHandler) { + this.dateService = dateService; + this.dimensionHandler = dimensionHandler; + } + + public boolean shouldHandleMemberTag() { + return inAlarmActions || inDimensions || inInsufficientDataActions || inOkActions; + } + + @Override + public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException { + if (SaxUtils.equalsOrSuffix(qName, "AlarmActions")) { + inAlarmActions = true; + } else if (SaxUtils.equalsOrSuffix(qName, "Dimensions")) { + inDimensions = true; + } else if (SaxUtils.equalsOrSuffix(qName, "InsufficientDataActions") || + SaxUtils.equalsOrSuffix(qName, "UnknownActions")) { + inInsufficientDataActions = true; + } else if (SaxUtils.equalsOrSuffix(qName, "OKActions")) { + inOkActions = true; + } + if (inDimensions) { + dimensionHandler.startElement(url, name, qName, attributes); + } + } + + @Override + public void endElement(String uri, String name, String qName) throws SAXException { + if (inAlarmActions) { + if (qName.equals("AlarmActions")) { + inAlarmActions = false; + } else if (qName.equals("member")) { + alarmActions.add(SaxUtils.currentOrNull(currentText)); + } + } else if (inDimensions) { + if (qName.equals("Dimensions")) { + inDimensions = false; + } else if (qName.equals("member")) { + dimensions.add(dimensionHandler.getResult()); + } else { + dimensionHandler.endElement(uri, name, qName); + } + } else if (inInsufficientDataActions) { + if (qName.equals("InsufficientDataActions") || qName.equals("UnknownActions")) { + inInsufficientDataActions = false; + } else if (qName.equals("member")) { + insufficientDataActions.add(SaxUtils.currentOrNull(currentText)); + } + } else if (inOkActions) { + if (qName.equals("OKActions")) { + inOkActions = false; + } else if (qName.equals("member")) { + okActions.add(SaxUtils.currentOrNull(currentText)); + } + } else if (qName.equals("ActionsEnabled")) { + actionsEnabled = Boolean.valueOf(SaxUtils.currentOrNull(currentText)); + } else if (qName.equals("AlarmArn")) { + alarmARN = SaxUtils.currentOrNull(currentText); + } else if (qName.equals("AlarmConfigurationUpdatedTimestamp")) { + alarmConfigurationUpdatedTimestamp = dateService.iso8601DateParse(currentText.toString().trim()); + } else if (qName.equals("AlarmDescription")) { + alarmDescription = SaxUtils.currentOrNull(currentText); + } else if (qName.equals("AlarmName")) { + alarmName = SaxUtils.currentOrNull(currentText); + } else if (qName.equals("ComparisonOperator")) { + comparisonOperator = ComparisonOperator.fromValue(SaxUtils.currentOrNull(currentText)); + } else if (qName.equals("EvaluationPeriods")) { + evaluationPeriods = Integer.valueOf(SaxUtils.currentOrNull(currentText)); + } else if (qName.equals("MetricName")) { + metricName = SaxUtils.currentOrNull(currentText); + } else if (qName.equals("Namespace")) { + namespace = SaxUtils.currentOrNull(currentText); + } else if (qName.equals("Period")) { + period = Integer.valueOf(SaxUtils.currentOrNull(currentText)); + } else if (qName.equals("StateReason")) { + stateReason = SaxUtils.currentOrNull(currentText); + } else if (qName.equals("StateReasonData")) { + String rawJson = SaxUtils.currentOrNull(currentText); + + if (rawJson != null) { + stateReasonData = rawJson.trim(); + } + } else if (qName.equals("StateUpdatedTimestamp")) { + stateUpdatedTimestamp = dateService.iso8601DateParse(currentText.toString().trim()); + } else if (qName.equals("StateValue")) { + state = Alarm.State.fromValue(SaxUtils.currentOrNull(currentText)); + } else if (qName.equals("Statistic")) { + statistic = Statistics.fromValue(SaxUtils.currentOrNull(currentText)); + } else if (qName.equals("Threshold")) { + threshold = Double.valueOf(SaxUtils.currentOrNull(currentText)); + } else if (qName.equals("Unit")) { + unit = Unit.fromValue(SaxUtils.currentOrNull(currentText)); + } + + currentText = new StringBuilder(); + } + + @Override + public void characters(char ch[], int start, int length) { + if (inDimensions) { + dimensionHandler.characters(ch, start, length); + } else { + currentText.append(ch, start, length); + } + } + + @Override + public Alarm getResult() { + Alarm result = new Alarm(actionsEnabled, alarmActions, alarmARN, alarmConfigurationUpdatedTimestamp, + alarmDescription, alarmName, comparisonOperator, dimensions, + evaluationPeriods, insufficientDataActions, metricName, namespace, okActions, + period, stateReason, Optional.fromNullable(stateReasonData), + stateUpdatedTimestamp, state, statistic, threshold, + Optional.fromNullable(unit)); + + actionsEnabled = false; + alarmActions = Sets.newLinkedHashSet(); + alarmARN = null; + alarmConfigurationUpdatedTimestamp = null; + alarmDescription = null; + alarmName = null; + comparisonOperator = null; + dimensions = Sets.newLinkedHashSet(); + evaluationPeriods = 0; + insufficientDataActions = Sets.newLinkedHashSet(); + metricName = null; + namespace = null; + okActions = Sets.newLinkedHashSet(); + period = 0; + stateReason = null; + stateReasonData = null; + stateUpdatedTimestamp = null; + state = null; + statistic = null; + threshold = 0.0; + unit = null; + + return result; + } + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchLiveTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchLiveTest.java index 0b1994a806..29369c1eeb 100644 --- a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchLiveTest.java +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchLiveTest.java @@ -18,44 +18,36 @@ */ package org.jclouds.cloudwatch; -import static com.google.common.base.Preconditions.checkArgument; import static java.util.concurrent.TimeUnit.MINUTES; import static org.jclouds.util.Predicates2.retry; import java.util.Date; import java.util.Set; -import org.jclouds.apis.BaseApiLiveTest; -import org.jclouds.cloudwatch.domain.Dimension; -import org.jclouds.cloudwatch.domain.MetricDatum; -import org.jclouds.cloudwatch.domain.Unit; -import org.jclouds.cloudwatch.options.ListMetricsOptions; -import org.testng.Assert; -import org.testng.annotations.Test; - import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.cloudwatch.domain.MetricDatum; +import org.jclouds.cloudwatch.domain.Unit; +import org.jclouds.cloudwatch.internal.BaseCloudWatchApiLiveTest; +import org.jclouds.cloudwatch.options.ListMetricsOptions; +import org.testng.Assert; +import org.testng.annotations.Test; /** * Tests behavior of {@code CloudWatch}. * * @author Jeremy Whitlock */ -public class CloudWatchLiveTest extends BaseApiLiveTest { +public class CloudWatchLiveTest extends BaseCloudWatchApiLiveTest { public CloudWatchLiveTest() { provider = "cloudwatch"; } @Test - protected void testCloudWatchListMetrics() { - // Just make sure there is at least one metric returned (Much better if the account you use has more than 500) - checkArgument(CloudWatch.listMetrics(api, null, new ListMetricsOptions()).iterator().hasNext()); - } - - @Test - protected void testCloudWatchPutMetrics() { + protected void testCloudWatch() { String metricName = "TestMetricName" + System.currentTimeMillis(); String namespace = "JCLOUDS/Test"; Date metricTimestamp = new Date(); 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 b5637a82d1..ad749c3e8e 100644 --- a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchTest.java +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchTest.java @@ -25,6 +25,9 @@ import static org.easymock.EasyMock.expect; import java.util.List; import java.util.Set; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Sets; import org.easymock.EasyMock; import org.jclouds.cloudwatch.domain.Metric; import org.jclouds.cloudwatch.domain.MetricDatum; @@ -35,10 +38,6 @@ import org.jclouds.collect.IterableWithMarkers; import org.testng.Assert; import org.testng.annotations.Test; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; - /** * Tests behavior of {@code CloudWatch}. * diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/binders/AlarmNamesBinderTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/binders/AlarmNamesBinderTest.java new file mode 100644 index 0000000000..b633122121 --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/binders/AlarmNamesBinderTest.java @@ -0,0 +1,50 @@ +/** + * 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 com.google.common.collect.ImmutableSet; +import com.google.inject.Guice; +import com.google.inject.Injector; +import org.jclouds.http.HttpRequest; +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@link AlarmNamesBinder}. + * + * @author Jeremy Whitlock + */ +@Test(groups = "unit", testName = "AlarmNamesBinderTest") +public class AlarmNamesBinderTest { + + Injector injector = Guice.createInjector(); + AlarmNamesBinder binder = injector.getInstance(AlarmNamesBinder.class); + + HttpRequest request() { + return HttpRequest.builder().method("POST").endpoint("http://localhost").build(); + } + + public void testAlarmNamesBinder() throws Exception { + HttpRequest request = binder.bindToRequest(request(), ImmutableSet.of("TestAlarmName1", "TestAlarmName2")); + + Assert.assertEquals(request.getPayload().getRawContent(), + "AlarmNames.member.1=TestAlarmName1&AlarmNames.member.2=TestAlarmName2"); + } + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/AlarmApiExpectTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/AlarmApiExpectTest.java new file mode 100644 index 0000000000..10d79e56df --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/AlarmApiExpectTest.java @@ -0,0 +1,389 @@ +/** + * 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 org.testng.Assert.assertEquals; + +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import org.jclouds.cloudwatch.CloudWatchApi; +import org.jclouds.cloudwatch.domain.Alarm; +import org.jclouds.cloudwatch.domain.ComparisonOperator; +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.cloudwatch.domain.HistoryItemType; +import org.jclouds.cloudwatch.domain.Namespaces; +import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.cloudwatch.domain.Unit; +import org.jclouds.cloudwatch.internal.BaseCloudWatchApiExpectTest; +import org.jclouds.cloudwatch.options.ListAlarmHistoryOptions; +import org.jclouds.cloudwatch.options.ListAlarmsForMetric; +import org.jclouds.cloudwatch.options.ListAlarmsOptions; +import org.jclouds.cloudwatch.options.SaveAlarmOptions; +import org.jclouds.cloudwatch.xml.ListAlarmHistoryResponseHandlerTest; +import org.jclouds.cloudwatch.xml.ListAlarmsForMetricResponseHandlerTest; +import org.jclouds.cloudwatch.xml.ListAlarmsResponseHandlerTest; +import org.jclouds.date.DateService; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payload; +import org.jclouds.rest.InsufficientResourcesException; +import org.jclouds.rest.ResourceNotFoundException; +import org.testng.annotations.Test; + +/** + * @author Jeremy Whitlock + */ +@Test(groups = "unit", testName = "AlarmApiExpectTest") +public class AlarmApiExpectTest extends BaseCloudWatchApiExpectTest { + + private DateService dateService = new SimpleDateFormatDateService(); + private HttpRequest deleteAlarmsRequest = alarmRequest(ImmutableMap.of( + "Action", "DeleteAlarms", + "AlarmNames.member.1", "TestAlarmName1", + "AlarmNames.member.2", "TestAlarmName2", + "Signature", "w9dhEBQCsmOhYKDp9Ht7/Ra6/xZcgAzhF0Bgtj8vpwQ%3D" + )); + private HttpRequest putMetricAlarmRequest = alarmRequest( + ImmutableMap.builder() + .put("Action", "PutMetricAlarm") + .put("ActionsEnabled", "true") + .put("AlarmActions.member.1", "TestAlarmAction1") + .put("AlarmActions.member.2", "TestAlarmAction2") + .put("AlarmDescription", "Test%20alarm%20description.") + .put("AlarmName", "TestAlarmName") + .put("ComparisonOperator", ComparisonOperator.GREATER_THAN_THRESHOLD.toString()) + .put("Dimensions.member.1.Name", "TestDimensionName1") + .put("Dimensions.member.1.Value", "TestDimensionValue1") + .put("Dimensions.member.2.Name", "TestDimensionName2") + .put("Dimensions.member.2.Value", "TestDimensionValue2") + .put("EvaluationPeriods", "60") + .put("InsufficientDataActions.member.1", "TestAlarmAction1") + .put("InsufficientDataActions.member.2", "TestAlarmAction2") + .put("MetricName", "TestMetricName") + .put("Namespace", Namespaces.EBS) + .put("OKActions.member.1", "TestAlarmAction1") + .put("OKActions.member.2", "TestAlarmAction2") + .put("Period", "60") + .put("Statistic", Statistics.SAMPLE_COUNT.toString()) + .put("Threshold", "1.0") + .put("Unit", Unit.GIGABYTES_PER_SECOND.toString()) + .put("Signature", "6RXD%2Bp1393a0maPdMLn%2Bv%2BbIcOJnAViAtbMgcA%2BogWs%3D").build() + ); + private SaveAlarmOptions saveAlarmOptions = new SaveAlarmOptions() + .alarmActions(ImmutableSet.of("TestAlarmAction1", "TestAlarmAction2")) + .alarmDescription("Test alarm description.") + .alarmName("TestAlarmName") + .metricName("TestMetricName") + .actionsEnabled(true) + .comparisonOperator(ComparisonOperator.GREATER_THAN_THRESHOLD) + .dimensions(ImmutableSet.of( + new Dimension("TestDimensionName1", + "TestDimensionValue1"), + new Dimension("TestDimensionName2", + "TestDimensionValue2") + )) + .evaluationPeriods(60) + .insufficientDataActions(ImmutableSet.of("TestAlarmAction1", "TestAlarmAction2")) + .namespace(Namespaces.EBS) + .okActions(ImmutableSet.of("TestAlarmAction1", "TestAlarmAction2")) + .period(60) + .statistic(Statistics.SAMPLE_COUNT) + .threshold(1.0) + .unit(Unit.GIGABYTES_PER_SECOND); + private HttpRequest setAlarmStateRequest = alarmRequest( + ImmutableMap.builder() + .put("Action", "SetAlarmState") + .put("AlarmName", "TestAlarmName") + .put("StateReason", "TestStateReason") + .put("StateReasonData", "%7B%22reason%22%3A%20%22Some%20reason%22%7D") + .put("StateValue", Alarm.State.OK.toString()) + .put("Signature", "W3juJzJEoSTPfYnrK7s/Pbj4uA/PGNF7eoxa7NhByqU%3D").build() + ); + + public AlarmApiExpectTest() { + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); + } + + public void testSetAlarmStateIs2xx() throws Exception { + Payload payload = payloadFromResourceWithContentType("/VoidResponse.xml", "text/xml"); + CloudWatchApi cloudWatchApi = requestSendsResponse(setAlarmStateRequest, + HttpResponse.builder() + .payload(payload) + .statusCode(200) + .build()); + + // Ensure there is no error returned + cloudWatchApi.getAlarmApiForRegion(null).setState("TestAlarmName", "TestStateReason", + "{\"reason\": \"Some reason\"}", + Alarm.State.OK); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testSetAlarmStateIs400() throws Exception { + Payload payload = payloadFromResourceWithContentType("/InvalidFormatResponse.xml", "text/xml"); + CloudWatchApi cloudWatchApi = requestSendsResponse(setAlarmStateRequest, + HttpResponse.builder() + .payload(payload) + .statusCode(400) + .build()); + + // Ensure an IllegalArgumentException is thrown + cloudWatchApi.getAlarmApiForRegion(null).setState("TestAlarmName", "TestStateReason", + "{\"reason\": \"Some reason\"}", + Alarm.State.OK); + } + + public void testPutMetricAlarmIs2xx() throws Exception { + Payload payload = payloadFromResourceWithContentType("/VoidResponse.xml", "text/xml"); + CloudWatchApi cloudWatchApi = requestSendsResponse(putMetricAlarmRequest, + HttpResponse.builder() + .statusCode(200) + .payload(payload) + .build()); + + // Ensure there is no error returned + cloudWatchApi.getAlarmApiForRegion(null).save(saveAlarmOptions); + } + + @Test(expectedExceptions = InsufficientResourcesException.class) + public void testPutMetricAlarmIs400() throws Exception { + Payload payload = payloadFromResourceWithContentType("/LimitExceededResponse.xml", "text/xml"); + CloudWatchApi cloudWatchApi = requestSendsResponse(putMetricAlarmRequest, + HttpResponse.builder() + .payload(payload) + .statusCode(400) + .build()); + + // Ensure an InsufficientResourcesException is thrown + cloudWatchApi.getAlarmApiForRegion(null).save(saveAlarmOptions); + } + + public void testEnableAlarmActions() throws Exception { + CloudWatchApi cloudWatchApi = requestSendsResponse(alarmRequest(ImmutableMap.of( + "Action", "EnableAlarmActions", + "AlarmNames.member.1", "TestAlarmName1", + "AlarmNames.member.2", "TestAlarmName2", + "Signature", "Q1VemnXpc57PKMs9NVCX6R%2B/TSDgsGzQwpOHQ70aJuU%3D" + )), HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResourceWithContentType("/VoidResponse.xml", "text/xml")) + .build()); + + // Ensure there is no error returned + cloudWatchApi.getAlarmApiForRegion(null).enable(ImmutableSet.of( + "TestAlarmName1", + "TestAlarmName2" + )); + } + + public void testDisableAlarmActions() throws Exception { + CloudWatchApi cloudWatchApi = requestSendsResponse(alarmRequest(ImmutableMap.of( + "Action", "DisableAlarmActions", + "AlarmNames.member.1", "TestAlarmName1", + "AlarmNames.member.2", "TestAlarmName2", + "Signature", "tvSfJ%2BgcrHowwUECSniV0TQP2OObpWCuba0S5dd723Y%3D" + )), HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResourceWithContentType("/VoidResponse.xml", "text/xml")) + .build()); + + // Ensure there is no error returned + cloudWatchApi.getAlarmApiForRegion(null).disable(ImmutableSet.of( + "TestAlarmName1", + "TestAlarmName2" + )); + } + + public void testDescribeAlarmsForMetric() throws Exception { + String metricName = "TestMetricName"; + String namespace = Namespaces.EC2; + int period = 60; + Statistics statistics = Statistics.SAMPLE_COUNT; + Unit unit = Unit.SECONDS; + CloudWatchApi cloudWatchApi = requestSendsResponse( + alarmRequest(ImmutableMap.builder() + .put("Action", "DescribeAlarmsForMetric") + .put("Dimensions.member.1.Name", "TestDimensionName1") + .put("Dimensions.member.1.Value", "TestDimensionValue1") + .put("Dimensions.member.2.Name", "TestDimensionName2") + .put("Dimensions.member.2.Value", "TestDimensionValue2") + .put("MetricName", metricName) + .put("Namespace", namespace) + .put("Period", Integer.toString(period)) + .put("Statistic", statistics.toString()) + .put("Unit", unit.toString()) + .put("Signature", "y%2BpU0Lp6AAO2QSrNld1VQY4DhKVHcyn44dIfnrmJhpg%3D") + .build()), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResourceWithContentType("/DescribeAlarmsForMetricResponse.xml", "text/xml")) + .build() + ); + + assertEquals(new ListAlarmsForMetricResponseHandlerTest().expected().toString(), + cloudWatchApi.getAlarmApiForRegion(null) + .listForMetric(new ListAlarmsForMetric() + .dimensions(ImmutableSet.of( + new Dimension("TestDimensionName1", + "TestDimensionValue1"), + new Dimension("TestDimensionName2", + "TestDimensionValue2") + )) + .metricName(metricName) + .namespace(namespace) + .period(period) + .statistic(statistics) + .unit(unit) + ).toString()); + } + + public void testDescribeAlarms() throws Exception { + String actionPrefix = "TestActionPrefix"; + String alarmNamePrefix = "TestAlarmNamePrefix"; + Set alarmNames = ImmutableSet.of("TestAlarmName1", "TestAlarmName2"); + int maxRecords = 10; + Alarm.State state = Alarm.State.ALARM; + CloudWatchApi cloudWatchApi = requestSendsResponse( + alarmRequest(ImmutableMap.builder() + .put("Action", "DescribeAlarms") + .put("ActionPrefix", actionPrefix) + .put("AlarmNamePrefix", alarmNamePrefix) + .put("AlarmNames.member.1", "TestAlarmName1") + .put("AlarmNames.member.2", "TestAlarmName2") + .put("MaxRecords", Integer.toString(maxRecords)) + .put("StateValue", state.toString()) + .put("Signature", "jPP1enbHPfOphIZv796W0KN4/EsLdPp6nK1qpbt5Dog%3D") + .build()), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResourceWithContentType("/DescribeAlarmsResponse.xml", "text/xml")) + .build() + ); + + assertEquals(new ListAlarmsResponseHandlerTest().expected().toString(), + cloudWatchApi.getAlarmApiForRegion(null) + .list(new ListAlarmsOptions() + .actionPrefix(actionPrefix) + .alarmNamePrefix(alarmNamePrefix) + .alarmNames(alarmNames) + .maxRecords(maxRecords) + .state(state) + ).get(0).toString()); + } + + public void testDescribeAlarmHistory() throws Exception { + String alarmName = "TestAlarmName"; + HistoryItemType historyItemType = HistoryItemType.ACTION; + int maxRecords = 10; + String endDateStr = "2013-01-02T00:00:00.000Z"; + String startDateStr = "2013-01-01T00:00:00.000Z"; + CloudWatchApi cloudWatchApi = requestSendsResponse( + alarmRequest(ImmutableMap. builder() + .put("Action", "DescribeAlarmHistory") + .put("AlarmName", alarmName) + .put("EndDate", "2013-01-02T00%3A00%3A00.000Z") + .put("HistoryItemType", historyItemType.toString()) + .put("MaxRecords", Integer.toString(maxRecords)) + .put("StartDate", "2013-01-01T00%3A00%3A00.000Z") + .put("Signature", "O2u9yIQvCuVpKdUeUDJcswri0YD0sD4%2B/SR5TtYbPeQ%3D") + .build()), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResourceWithContentType("/DescribeAlarmHistoryResponse.xml", "text/xml")) + .build()); + + assertEquals(new ListAlarmHistoryResponseHandlerTest().expected().toString(), + cloudWatchApi.getAlarmApiForRegion(null) + .listHistory(new ListAlarmHistoryOptions() + .alarmName("TestAlarmName") + .endDate(dateService.iso8601DateParse(endDateStr)) + .historyItemType(HistoryItemType.ACTION) + .maxRecords(maxRecords) + .startDate(dateService.iso8601DateParse(startDateStr)) + ).get(0).toString()); + } + + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testDeleteAlarmsIs404() throws Exception { + CloudWatchApi cloudWatchApi = requestSendsResponse(deleteAlarmsRequest, + HttpResponse.builder().statusCode(404).build()); + + // Ensure a ResourceNotFoundException is thrown + cloudWatchApi.getAlarmApiForRegion(null).delete(ImmutableSet.of( + "TestAlarmName1", + "TestAlarmName2" + )); + } + + public void testDeleteAlarmsIs2xx() throws Exception { + Payload payload = payloadFromResourceWithContentType("/VoidResponse.xml", "text/xml"); + CloudWatchApi cloudWatchApi = requestSendsResponse(deleteAlarmsRequest, + HttpResponse.builder() + .statusCode(200) + .payload(payload) + .build()); + + // Ensure there is no error returned + cloudWatchApi.getAlarmApiForRegion(null).delete(ImmutableSet.of( + "TestAlarmName1", + "TestAlarmName2" + )); + } + + private HttpRequest alarmRequest(Map arguments) { + Map sortedArguments = Maps.newTreeMap(); + Map defaultArguments = + ImmutableMap. builder() + .put("SignatureMethod", "HmacSHA256") + .put("SignatureVersion", "2") + .put("Timestamp", "2009-11-08T15%3A54%3A08.897Z") + .put("Version", "2010-08-01") + .build(); + + sortedArguments.putAll(arguments); + + for (Map.Entry defaultArgument : defaultArguments.entrySet()) { + if (!sortedArguments.containsKey(defaultArgument.getKey())) { + sortedArguments.put(defaultArgument.getKey(), defaultArgument.getValue()); + } + } + + Map realArguments = Maps.newLinkedHashMap(sortedArguments); + + realArguments.put("AWSAccessKeyId", "identity"); + + return HttpRequest.builder() + .method("POST") + .endpoint("https://monitoring.us-east-1.amazonaws.com/") + .addHeader("Host", "monitoring.us-east-1.amazonaws.com") + .payload(payloadFromStringWithContentType(Joiner.on("&") + .withKeyValueSeparator("=") + .join(realArguments).trim(), + "application/x-www-form-urlencoded")) + .build(); + } + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/AlarmApiLiveTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/AlarmApiLiveTest.java new file mode 100644 index 0000000000..5d52d22c32 --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/AlarmApiLiveTest.java @@ -0,0 +1,274 @@ +/** + * 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 java.util.concurrent.TimeUnit.MINUTES; +import static org.jclouds.util.Predicates2.retry; + +import java.util.Date; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.jclouds.cloudwatch.domain.Alarm; +import org.jclouds.cloudwatch.domain.AlarmHistoryItem; +import org.jclouds.cloudwatch.domain.ComparisonOperator; +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.cloudwatch.domain.Metric; +import org.jclouds.cloudwatch.domain.MetricDatum; +import org.jclouds.cloudwatch.domain.StatisticValues; +import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.cloudwatch.domain.Unit; +import org.jclouds.cloudwatch.internal.BaseCloudWatchApiLiveTest; +import org.jclouds.cloudwatch.options.ListAlarmHistoryOptions; +import org.jclouds.cloudwatch.options.ListAlarmsForMetric; +import org.jclouds.cloudwatch.options.ListAlarmsOptions; +import org.jclouds.cloudwatch.options.ListMetricsOptions; +import org.jclouds.cloudwatch.options.SaveAlarmOptions; +import org.jclouds.collect.IterableWithMarker; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * @author Jeremy Whitlock + */ +@Test(groups = "live", testName = "AlarmApiLiveTest") +public class AlarmApiLiveTest extends BaseCloudWatchApiLiveTest { + + private String alarmName = "TestAlarmName" + System.currentTimeMillis(); + private String metricName = "TestMetricForAlarms"; + private String namespace = "JCLOUDS/Test"; + + @BeforeClass + protected void beforeClass() throws Exception { + IterableWithMarker metrics = metricApi().list(new ListMetricsOptions().metricName(metricName)); + + if (Iterables.size(metrics) == 0) { + metricApi().putMetricsInNamespace(ImmutableSet.of( + MetricDatum.builder() + .metricName(metricName) + .statisticValues(StatisticValues.builder() + .maximum(4.0) + .minimum(1.0) + .sampleCount(4.0) + .sum(10.0) + .build()) + .dimension(new Dimension("BaseMetricName", metricName)) + .dimension(new Dimension("TestDimension2", "TEST2")) + .unit(Unit.COUNT) + .timestamp(new Date()) + .build() + ), namespace); + + ListMetricsOptions lmo = ListMetricsOptions.Builder.namespace(namespace) + .metricName(metricName); + boolean success = retry(new Predicate() { + public boolean apply(ListMetricsOptions options) { + return Iterables.size(metricApi().list(options)) == 1; + } + }, 5, 1, MINUTES).apply(lmo); + + if (!success) { + Assert.fail("Unable to create the test CloudWatch metric within the time (5m) allotted."); + } + } + } + + @AfterClass + protected void afterClass() throws Exception { + IterableWithMarker alarms = api().list(new ListAlarmsOptions().alarmName(alarmName)).get(0); + if (Iterables.size(alarms) > 0) { + api().delete(ImmutableSet.of(alarmName)); + } + } + + @Test + protected void testAlarmCRUD() throws Exception { + // Create new alarm + api().save(new SaveAlarmOptions() + .actionsEnabled(true) + .alarmDescription("This is a test alarm for jclouds.") + .alarmName(alarmName) + .comparisonOperator(ComparisonOperator.GREATER_THAN_THRESHOLD) + .evaluationPeriods(5) + .metricName(metricName) + .namespace(namespace) + .period(60) + .statistic(Statistics.SAMPLE_COUNT) + .threshold(1.0)); + + // Poll alarms until alarm is found + ListAlarmsOptions dmo = new ListAlarmsOptions().alarmName(alarmName); + boolean success = retry(new Predicate() { + public boolean apply(ListAlarmsOptions options) { + return Iterables.size(api().list(options).get(0)) == 1; + } + }, 5, 1, MINUTES).apply(dmo); + + if (!success) { + Assert.fail("Unable to create the test CloudWatch alarm within the time (5m) allotted."); + } + + // Poll all alarms until alarm is found + success = retry(new Predicate() { + public boolean apply(Void arg) { + for (IterableWithMarker page : api().list()) { + for (Alarm alarm : page) { + if (alarm.getAlarmName().equals(alarmName)) { + return true; + } + } + } + return false; + } + }, 5, 1, MINUTES).apply(null); + + if (!success) { + Assert.fail("Unable to create the test CloudWatch alarm within the time (5m) allotted."); + } + + // Poll for alarms for metric until alarm is found + ListAlarmsForMetric dafmo = new ListAlarmsForMetric() + .metricName(metricName) + .namespace(namespace); + success = retry(new Predicate() { + public boolean apply(ListAlarmsForMetric options) { + for (Alarm alarm : api().listForMetric(options)) { + if (alarm.getAlarmName().equals(alarmName)) { + return true; + } + } + return false; + } + }, 5, 1, MINUTES).apply(dafmo); + + if (!success) { + Assert.fail("Unable to create the test CloudWatch alarm history item within the time (5m) allotted."); + } + + // Create history item by changing its state + api().setState(alarmName, "Updating the state.", null, Alarm.State.OK); + + // Poll for alarm history + ListAlarmHistoryOptions daho = new ListAlarmHistoryOptions().alarmName(alarmName); + success = retry(new Predicate() { + public boolean apply(ListAlarmHistoryOptions options) { + for (IterableWithMarker page : api().listHistory(options)) { + for (AlarmHistoryItem alarmHistoryItem : page) { + if (alarmHistoryItem.getAlarmName().equals(alarmName)) { + JsonObject historyData = new JsonParser().parse(alarmHistoryItem.getHistoryData()) + .getAsJsonObject(); + + if (historyData.has("newState") && historyData.getAsJsonObject("newState").has("stateReason") && + historyData.getAsJsonObject("newState").get("stateReason").getAsString() + .equals("Updating the state.")) { + return true; + } + } + } + } + return false; + } + }, 5, 1, MINUTES).apply(daho); + + if (!success) { + Assert.fail("Unable to create the test CloudWatch alarm history item within the time (5m) allotted."); + } + + success = retry(new Predicate() { + public boolean apply(Void arg) { + for (IterableWithMarker page : api().listHistory()) { + for (AlarmHistoryItem alarmHistoryItem : page) { + if (alarmHistoryItem.getAlarmName().equals(alarmName)) { + JsonObject historyData = new JsonParser().parse(alarmHistoryItem.getHistoryData()) + .getAsJsonObject(); + + if (historyData.has("newState") && historyData.getAsJsonObject("newState").has("stateReason") && + historyData.getAsJsonObject("newState").get("stateReason").getAsString() + .equals("Updating the state.")) { + return true; + } + } + } + } + return false; + } + }, 5, 1, MINUTES).apply(null); + + if (!success) { + Assert.fail("Unable to create the test CloudWatch alarm history item within the time (5m) allotted."); + } + + // Disable alarm actions + api().disable(ImmutableSet.of(alarmName)); + + // Validate + success = retry(new Predicate() { + public boolean apply(ListAlarmsOptions options) { + Iterable alarms = api().list(options).get(0); + return Iterables.size(alarms) == 1 && !alarms.iterator().next().areActionsEnabled(); + } + }, 5, 1, MINUTES).apply(dmo); + + if (!success) { + Assert.fail("Unable to validate the test CloudWatch alarm disablement within the time (5m) allotted."); + } + + // Enable alarm actions + api().enable(ImmutableSet.of(alarmName)); + + // Validate + success = retry(new Predicate() { + public boolean apply(ListAlarmsOptions options) { + IterableWithMarker alarms = api().list(options).get(0); + return Iterables.size(alarms) == 1 && alarms.iterator().next().areActionsEnabled(); + } + }, 5, 1, MINUTES).apply(dmo); + + if (!success) { + Assert.fail("Unable to validate the test CloudWatch alarm enablement within the time (5m) allotted."); + } + + // Delete the alarm + api().delete(ImmutableSet.of(alarmName)); + + success = retry(new Predicate() { + public boolean apply(ListAlarmsOptions options) { + return Iterables.size(api().list(options).get(0)) == 0; + } + }, 5, 1, MINUTES).apply(dmo); + + if (!success) { + Assert.fail("Unable to delete the test CloudWatch alarm within the time (5m) allotted."); + } + } + + protected AlarmApi api() { + return api.getAlarmApiForRegion(null); + } + + protected MetricApi metricApi() { + return api.getMetricApiForRegion(null); + } + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricApiExpectTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricApiExpectTest.java index 7e40a2b11e..dd05d6ac17 100644 --- a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricApiExpectTest.java +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricApiExpectTest.java @@ -9,11 +9,11 @@ * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unles required by applicable law or agreed to in writing, + * 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 expres or implied. See the License for the - * specific language governing permisions and limitations + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations * under the License. */ package org.jclouds.cloudwatch.features; diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricApiLiveTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricApiLiveTest.java index d711ae1f69..ef6d0c7688 100644 --- a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricApiLiveTest.java +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricApiLiveTest.java @@ -269,13 +269,16 @@ public class MetricApiLiveTest extends BaseCloudWatchApiLiveTest { for (Metric metric : response) { Set dimensions = metric.getDimensions(); + boolean dimensionFound = false; - checkArgument(dimensions.size() == 1, "There should only be one Dimension."); + for (Dimension dimension : dimensions) { + if (dimension.getName().equals(testDimensionName)) { + dimensionFound = true; + break; + } + } - Dimension dimension = dimensions.iterator().next(); - - checkArgument(dimension.equals(testDimension), - "The retrieved Dimension and test Dimension should be equal."); + checkArgument(dimensionFound, "All metrics should have the " + testDimensionName + " Dimension.Name."); } } } diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchApiLiveTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchApiLiveTest.java index f633b67f31..0e497f3ae5 100644 --- a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchApiLiveTest.java +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchApiLiveTest.java @@ -28,7 +28,9 @@ import org.testng.annotations.Test; */ @Test(groups = "live") public class BaseCloudWatchApiLiveTest extends BaseApiLiveTest { + public BaseCloudWatchApiLiveTest() { provider = "cloudwatch"; } + } diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/options/ListAlarmHistoryOptionsTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/options/ListAlarmHistoryOptionsTest.java new file mode 100644 index 0000000000..b5c5ab59d1 --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/options/ListAlarmHistoryOptionsTest.java @@ -0,0 +1,75 @@ +/** + * 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.options; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; + +import java.util.Date; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; +import org.jclouds.cloudwatch.domain.HistoryItemType; +import org.jclouds.date.DateService; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code ListAlarmHistoryOptions}. + * + * @author Jeremy Whitlock + */ +@Test(groups = "unit") +public class ListAlarmHistoryOptionsTest { + + private DateService dateService = new SimpleDateFormatDateService(); + + public void testEmptyOptions() throws Exception { + Multimap formParameters = new ListAlarmHistoryOptions().buildFormParameters(); + + assertFalse(formParameters.containsKey("AlarmName")); + assertFalse(formParameters.containsKey("EndDate")); + assertFalse(formParameters.containsKey("HistoryItemType")); + assertFalse(formParameters.containsKey("MaxRecords")); + assertFalse(formParameters.containsKey("NextToken")); + assertFalse(formParameters.containsKey("StartDate")); + } + + public void testPopulatedOptions() throws Exception { + String alarmName = "TestAlarmName"; + Date endDate = new Date(new Date().getTime() + 5000); + HistoryItemType historyItemType = HistoryItemType.ACTION; + int maxRecords = 5; + Date startDate = new Date(); + Multimap formParameters = new ListAlarmHistoryOptions() + .alarmName(alarmName) + .endDate(endDate) + .historyItemType(historyItemType) + .maxRecords(maxRecords) + .startDate(startDate) + .buildFormParameters(); + + assertEquals(formParameters.get("AlarmName"), ImmutableSet.of(alarmName)); + assertEquals(formParameters.get("EndDate"), ImmutableSet.of(dateService.iso8601DateFormat(endDate))); + assertEquals(formParameters.get("HistoryItemType"), ImmutableSet.of(historyItemType.toString())); + assertEquals(formParameters.get("MaxRecords"), ImmutableSet.of(Integer.toString(maxRecords))); + assertEquals(formParameters.get("StartDate"), ImmutableSet.of(dateService.iso8601DateFormat(startDate))); + } + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/options/ListAlarmsForMetricTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/options/ListAlarmsForMetricTest.java new file mode 100644 index 0000000000..250f1288ae --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/options/ListAlarmsForMetricTest.java @@ -0,0 +1,89 @@ +/** + * 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.options; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; + +import java.util.Set; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.cloudwatch.domain.Namespaces; +import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.cloudwatch.domain.Unit; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code ListAlarmsForMetric}. + * + * @author Jeremy Whitlock + */ +@Test(groups = "unit") +public class ListAlarmsForMetricTest { + + public void testEmptyOptions() throws Exception { + Multimap formParameters = new ListAlarmsForMetric().buildFormParameters(); + + assertFalse(formParameters.containsKey("Dimensions.member.1.Name")); + assertFalse(formParameters.containsKey("Dimensions.member.1.Value")); + assertFalse(formParameters.containsKey("MetricName")); + assertFalse(formParameters.containsKey("Namespace")); + assertFalse(formParameters.containsKey("Period")); + assertFalse(formParameters.containsKey("Statistic")); + assertFalse(formParameters.containsKey("Unit")); + } + + public void testPopulatedOptions() throws Exception { + Set dimensions = ImmutableSet.of( + new Dimension("TestDimension1", "TestValue1"), + new Dimension("TestDimension2", "TestValue2") + ); + String metricName = "TestMetricName"; + String namespace = Namespaces.EC2; + int period = 60; + Statistics statistic = Statistics.AVERAGE; + Unit unit = Unit.COUNT; + Multimap formParameters = new ListAlarmsForMetric() + .dimensions(dimensions) + .metricName(metricName) + .namespace(namespace) + .period(period) + .statistic(statistic) + .unit(unit) + .buildFormParameters(); + int dimensionIndex = 1; + + for (Dimension dimension : dimensions) { + assertEquals(formParameters.get("Dimensions.member." + dimensionIndex + ".Name"), + ImmutableSet.of(dimension.getName())); + assertEquals(formParameters.get("Dimensions.member." + dimensionIndex + ".Value"), + ImmutableSet.of(dimension.getValue())); + dimensionIndex++; + } + + assertEquals(formParameters.get("MetricName"), ImmutableSet.of(metricName)); + assertEquals(formParameters.get("Namespace"), ImmutableSet.of(namespace)); + assertEquals(formParameters.get("Period"), ImmutableSet.of(Integer.toString(period))); + assertEquals(formParameters.get("Statistic"), ImmutableSet.of(statistic.toString())); + assertEquals(formParameters.get("Unit"), ImmutableSet.of(unit.toString())); + } + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/options/ListAlarmsOptionsTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/options/ListAlarmsOptionsTest.java new file mode 100644 index 0000000000..0b15f78cae --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/options/ListAlarmsOptionsTest.java @@ -0,0 +1,79 @@ +/** + * 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.options; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; + +import java.util.Set; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; +import org.jclouds.cloudwatch.domain.Alarm; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code ListAlarmsOptions}. + * + * @author Jeremy Whitlock + */ +@Test(groups = "unit") +public class ListAlarmsOptionsTest { + + public void testEmptyOptions() throws Exception { + Multimap formParameters = new ListAlarmsOptions().buildFormParameters(); + + assertFalse(formParameters.containsKey("ActionPrefix")); + assertFalse(formParameters.containsKey("AlarmNamePrefix")); + assertFalse(formParameters.containsKey("AlarmNames.member.1")); + assertFalse(formParameters.containsKey("MaxRecords")); + assertFalse(formParameters.containsKey("NextToken")); + assertFalse(formParameters.containsKey("StateValue")); + } + + public void testPopulatedOptions() throws Exception { + String actionPrefix = "TestActionPrefix"; + String alarmNamePrefix = "TestAlarmNamePrefix"; + Set alarmNames = ImmutableSet.of( + "TestAlarmName1", + "TestAlarmName2" + ); + int maxRecords = 5; + Alarm.State state = Alarm.State.ALARM; + int alarmNameIndex = 1; + Multimap formParameters = new ListAlarmsOptions() + .actionPrefix(actionPrefix) + .alarmNamePrefix(alarmNamePrefix) + .alarmNames(alarmNames) + .maxRecords(maxRecords) + .state(state) + .buildFormParameters(); + + assertEquals(formParameters.get("ActionPrefix"), ImmutableSet.of(actionPrefix)); + assertEquals(formParameters.get("AlarmNamePrefix"), ImmutableSet.of(alarmNamePrefix)); + assertEquals(formParameters.get("MaxRecords"), ImmutableSet.of(Integer.toString(maxRecords))); + assertEquals(formParameters.get("StateValue"), ImmutableSet.of(state.toString())); + + for (String alarmName : alarmNames) { + assertEquals(formParameters.get("AlarmNames.member." + alarmNameIndex), ImmutableSet.of(alarmName)); + alarmNameIndex++; + } + } + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/options/SaveAlarmOptionsTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/options/SaveAlarmOptionsTest.java new file mode 100644 index 0000000000..aee12656e0 --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/options/SaveAlarmOptionsTest.java @@ -0,0 +1,151 @@ +/** + * 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.options; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; + +import java.util.Set; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; +import org.jclouds.cloudwatch.domain.ComparisonOperator; +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.cloudwatch.domain.Namespaces; +import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.cloudwatch.domain.Unit; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code SaveAlarmOptions}. + * + * @author Jeremy Whitlock + */ +@Test(groups = "unit") +public class SaveAlarmOptionsTest { + + public void testEmptyOptions() throws Exception { + Multimap formParameters = new SaveAlarmOptions().buildFormParameters(); + + assertFalse(formParameters.containsKey("ActionsEnabled")); + assertFalse(formParameters.containsKey("AlarmActions.member.1")); + assertFalse(formParameters.containsKey("AlarmDescription")); + assertFalse(formParameters.containsKey("AlarmName")); + assertFalse(formParameters.containsKey("ComparisonOperator")); + assertFalse(formParameters.containsKey("Dimensions.member.1.Name")); + assertFalse(formParameters.containsKey("Dimensions.member.1.Value")); + assertFalse(formParameters.containsKey("EvaluationPeriods")); + assertFalse(formParameters.containsKey("InsufficientDataActions.member.1")); + assertFalse(formParameters.containsKey("MetricName")); + assertFalse(formParameters.containsKey("Namespace")); + assertFalse(formParameters.containsKey("OKActions.member.1")); + assertFalse(formParameters.containsKey("Period")); + assertFalse(formParameters.containsKey("Statistic")); + assertFalse(formParameters.containsKey("Threshold")); + assertFalse(formParameters.containsKey("Unit")); + } + + public void testPopulatedOptions() throws Exception { + boolean actionsEnabled = false; + Set alarmActions = ImmutableSet.of( + "TestAlarmAction1", + "TestAlarmAction2" + ); + String alarmDescription = "TestAlarmDescription"; + String alarmName = "TestAlarmName"; + ComparisonOperator comparisonOperator = ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD; + Set dimensions = ImmutableSet.of( + new Dimension("TestDimension1", "TestValue1"), + new Dimension("TestDimension2", "TestValue2") + ); + int evaluationPeriods = 360; + Set insufficientDataActions = ImmutableSet.of( + "TestInsufficientDataAction1", + "TestInsufficientDataAction2" + ); + String metricName = "TestMetricName"; + String namespace = Namespaces.AUTO_SCALING; + Set okActions = ImmutableSet.of( + "TestOKAction1", + "TestOKAction2" + ); + int period = 300; + Statistics statistic = Statistics.SAMPLE_COUNT; + double threshold = 1.0; + Unit unit = Unit.BITS; + Multimap formParameters = new SaveAlarmOptions() + .actionsEnabled(actionsEnabled) + .alarmActions(alarmActions) + .alarmDescription(alarmDescription) + .alarmName(alarmName) + .comparisonOperator(comparisonOperator) + .dimensions(dimensions) + .evaluationPeriods(evaluationPeriods) + .insufficientDataActions(insufficientDataActions) + .metricName(metricName) + .namespace(namespace) + .okActions(okActions) + .period(period) + .statistic(statistic) + .threshold(threshold) + .unit(unit) + .buildFormParameters(); + int alarmActionIndex = 1; + int dimensionIndex = 1; + int insufficientDataActionIndex = 1; + int okActionIndex = 1; + + for (String alarmAction : alarmActions) { + assertEquals(formParameters.get("AlarmActions.member." + alarmActionIndex), ImmutableSet.of(alarmAction)); + alarmActionIndex++; + } + + for (Dimension dimension : dimensions) { + assertEquals(formParameters.get("Dimensions.member." + dimensionIndex + ".Name"), + ImmutableSet.of(dimension.getName())); + assertEquals(formParameters.get("Dimensions.member." + dimensionIndex + ".Value"), + ImmutableSet.of(dimension.getValue())); + dimensionIndex++; + } + + for (String insufficientDataAction : insufficientDataActions) { + assertEquals(formParameters.get("InsufficientDataActions.member." + insufficientDataActionIndex), + ImmutableSet.of(insufficientDataAction)); + insufficientDataActionIndex++; + } + + for (String okAction : okActions) { + assertEquals(formParameters.get("OKActions.member." + okActionIndex), ImmutableSet.of(okAction)); + okActionIndex++; + } + + assertEquals(formParameters.get("ActionsEnabled"), ImmutableSet.of(Boolean.toString(actionsEnabled))); + assertEquals(formParameters.get("AlarmDescription"), ImmutableSet.of(alarmDescription)); + assertEquals(formParameters.get("AlarmName"), ImmutableSet.of(alarmName)); + assertEquals(formParameters.get("ComparisonOperator"), ImmutableSet.of(comparisonOperator.toString())); + assertEquals(formParameters.get("EvaluationPeriods"), ImmutableSet.of(Integer.toString(evaluationPeriods))); + assertEquals(formParameters.get("MetricName"), ImmutableSet.of(metricName)); + assertEquals(formParameters.get("Namespace"), ImmutableSet.of(namespace)); + assertEquals(formParameters.get("Period"), ImmutableSet.of(Integer.toString(period))); + assertEquals(formParameters.get("Statistic"), ImmutableSet.of(statistic.toString())); + assertEquals(formParameters.get("Threshold"), ImmutableSet.of(Double.toString(threshold))); + assertEquals(formParameters.get("Unit"), ImmutableSet.of(unit.toString())); + } + +} \ No newline at end of file diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/ListAlarmHistoryResponseHandlerTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/ListAlarmHistoryResponseHandlerTest.java new file mode 100644 index 0000000000..ff8a397f71 --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/ListAlarmHistoryResponseHandlerTest.java @@ -0,0 +1,78 @@ +/** + * 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.xml; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; + +import java.util.Set; + +import com.google.common.collect.Sets; +import org.jclouds.cloudwatch.domain.AlarmHistoryItem; +import org.jclouds.cloudwatch.domain.HistoryItemType; +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.collect.IterableWithMarkers; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.http.functions.BaseHandlerTest; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code ListAlarmHistoryResponseHandler}. Implicitly tests behavior of + * {@code MetricAlarmHandler}. + * + * @author Jeremy Whitlock + */ +// NOTE: Without testName, this will not call @Before* and fail w/NPE during surefire +@Test(groups = "unit", testName = "ListAlarmHistoryResponseHandlerTest") +public class ListAlarmHistoryResponseHandlerTest extends BaseHandlerTest { + + /** + * Tests parsing all possible XML elements that could be encountered by {@link ListAlarmHistoryResponseHandler}. + * + * @throws Exception if something goes wrong + */ + public void testParseFullResponse() throws Exception { + IterableWithMarker alarmHistoryItems = + factory.create(injector.getInstance(ListAlarmHistoryResponseHandler.class)) + .parse(getClass().getResourceAsStream("/DescribeAlarmHistoryResponse.xml")); + + assertEquals(alarmHistoryItems.toString(), expected().toString()); + assertFalse(alarmHistoryItems.nextMarker().isPresent()); + } + + public IterableWithMarker expected() { + Set alarmHistoryItems = Sets.newLinkedHashSet(); + + for (int i = 1; i <= 2; i++) { + alarmHistoryItems.add(new AlarmHistoryItem( + "TestAlarmName" + i, + "{\"reason\": \"" + i + "\"}", + i == 1 ? + HistoryItemType.ACTION : + HistoryItemType.CONFIGURATION_UPDATE, + "This is test " + i + ".", + new SimpleDateFormatDateService() + .iso8601SecondsDateParse("2013-01-0" + i + "T00:00:00Z") + )); + } + + return IterableWithMarkers.from(alarmHistoryItems); + } + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/ListAlarmsForMetricResponseHandlerTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/ListAlarmsForMetricResponseHandlerTest.java new file mode 100644 index 0000000000..ea6d78db91 --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/ListAlarmsForMetricResponseHandlerTest.java @@ -0,0 +1,107 @@ +/** + * 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.xml; + +import static org.testng.Assert.assertEquals; + +import java.util.Set; + +import com.beust.jcommander.internal.Sets; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSet; +import org.jclouds.cloudwatch.domain.Alarm; +import org.jclouds.cloudwatch.domain.ComparisonOperator; +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.cloudwatch.domain.Namespaces; +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.functions.BaseHandlerTest; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code ListAlarmsForMetricResponseHandler}. Implicitly tests behavior of + * {@code MetricAlarmHandler}. + * + * @author Jeremy Whitlock + */ +// NOTE: Without testName, this will not call @Before* and fail w/NPE during surefire +@Test(groups = "unit", testName = "ListAlarmsForMetricResponseHandlerTest") +public class ListAlarmsForMetricResponseHandlerTest extends BaseHandlerTest { + + private final DateService dateService = new SimpleDateFormatDateService(); + + /** + * Tests parsing all possible XML elements that could be encountered by {@link ListAlarmsForMetricResponseHandler}. + * + * @throws Exception if something goes wrong + */ + public void testParseFullResponse() throws Exception { + Iterable metricAlarms = + factory.create(injector.getInstance(ListAlarmsForMetricResponseHandler.class)) + .parse(getClass().getResourceAsStream("/DescribeAlarmsForMetricResponse.xml")); + + assertEquals(metricAlarms.toString(), expected().toString()); + } + + public Iterable expected() { + Set alarms = Sets.newLinkedHashSet(); + + for (int i = 1; i <= 2; i++) { + alarms.add(new Alarm( + i == 1, + ImmutableSet.of("TestAction1", "TestAction2"), + "TestAlarmARN" + i, + dateService.iso8601SecondsDateParse("2013-01-0" + i + "T00:00:00Z"), + "This is test alarm " + i + ".", + "TestAlarmName" + i, + i == 1 ? + ComparisonOperator.GREATER_THAN_THRESHOLD : + ComparisonOperator.LESS_THAN_THRESHOLD, + ImmutableSet.of( + new Dimension("TestDimensionName1", "TestDimensionValue1"), + new Dimension("TestDimensionName2", "TestDimensionValue2") + ), + 60 * i, + ImmutableSet.of("TestAction1", "TestAction2"), + "TestMetricName" + i, + Namespaces.EC2, + ImmutableSet.of("TestAction1", "TestAction2"), + 60 * i, + "This is state reason " + i + ".", + Optional.of("{\"reason\": \"" + i + "\"}"), + dateService.iso8601SecondsDateParse("2013-01-0" + i + "T00:00:00Z"), + i == 1 ? + Alarm.State.INSUFFICIENT_DATA : + Alarm.State.OK, + i == 1 ? + Statistics.SAMPLE_COUNT : + Statistics.AVERAGE, + Double.valueOf(Integer.toString(i)), + i == 1 ? + Optional.of(Unit.SECONDS) : + Optional.of(Unit.COUNT_PER_SECOND) + )); + } + + return alarms; + } + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/ListAlarmsResponseHandlerTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/ListAlarmsResponseHandlerTest.java new file mode 100644 index 0000000000..f5b46a759a --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/ListAlarmsResponseHandlerTest.java @@ -0,0 +1,112 @@ +/** + * 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.xml; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; + +import java.util.Set; + +import com.beust.jcommander.internal.Sets; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSet; +import org.jclouds.cloudwatch.domain.Alarm; +import org.jclouds.cloudwatch.domain.ComparisonOperator; +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.cloudwatch.domain.Namespaces; +import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.cloudwatch.domain.Unit; +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.collect.IterableWithMarkers; +import org.jclouds.date.DateService; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.http.functions.BaseHandlerTest; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code ListAlarmsResponseHandler}. Implicitly tests behavior of {@code MetricAlarmHandler}. + * + * @author Jeremy Whitlock + */ +// NOTE: Without testName, this will not call @Before* and fail w/NPE during surefire +@Test(groups = "unit", testName = "ListAlarmsResponseHandlerTest") +public class ListAlarmsResponseHandlerTest extends BaseHandlerTest { + + private final DateService dateService = new SimpleDateFormatDateService(); + + /** + * Tests parsing all possible XML elements that could be encountered by {@link ListAlarmsResponseHandler}. + * + * @throws Exception if something goes wrong + */ + public void testParseFullResponse() throws Exception { + IterableWithMarker metricAlarms = + factory.create(injector.getInstance(ListAlarmsResponseHandler.class)) + .parse(getClass().getResourceAsStream("/DescribeAlarmsResponse.xml")); + + assertEquals(metricAlarms.toString(), expected().toString()); + assertFalse(metricAlarms.nextMarker().isPresent()); + } + + public IterableWithMarker expected() { + Set alarms = Sets.newLinkedHashSet(); + + for (int i = 1; i <= 2; i++) { + alarms.add(new Alarm( + i == 1, + ImmutableSet.of("TestAction1", "TestAction2"), + "TestAlarmARN" + i, + dateService.iso8601SecondsDateParse("2013-01-0" + i + "T00:00:00Z"), + "This is test alarm " + i + ".", + "TestAlarmName" + i, + i == 1 ? + ComparisonOperator.GREATER_THAN_THRESHOLD : + ComparisonOperator.LESS_THAN_THRESHOLD, + ImmutableSet.of( + new Dimension("TestDimensionName1", "TestDimensionValue1"), + new Dimension("TestDimensionName2", "TestDimensionValue2") + ), + 60 * i, + ImmutableSet.of("TestAction1", "TestAction2"), + "TestMetricName" + i, + i == 1 ? + Namespaces.EC2 : + Namespaces.EBS, + ImmutableSet.of("TestAction1", "TestAction2"), + 60 * i, + "This is state reason " + i + ".", + Optional.of("{\"reason\": \"" + i + "\"}"), + dateService.iso8601SecondsDateParse("2013-01-0" + i + "T00:00:00Z"), + i == 1 ? + Alarm.State.OK : + Alarm.State.ALARM, + i == 1 ? + Statistics.SAMPLE_COUNT : + Statistics.AVERAGE, + Double.valueOf(Integer.toString(i)), + i == 1 ? + Optional.of(Unit.SECONDS) : + Optional.of(Unit.COUNT_PER_SECOND) + )); + } + + return IterableWithMarkers.from(alarms); + } + +} diff --git a/apis/cloudwatch/src/test/resources/DescribeAlarmHistoryResponse.xml b/apis/cloudwatch/src/test/resources/DescribeAlarmHistoryResponse.xml new file mode 100644 index 0000000000..9bb984436a --- /dev/null +++ b/apis/cloudwatch/src/test/resources/DescribeAlarmHistoryResponse.xml @@ -0,0 +1,20 @@ + + + + + TestAlarmName1 + {"reason": "1"} + Action + This is test 1. + 2013-01-01T00:00:00.000+0000 + + + TestAlarmName2 + {"reason": "2"} + ConfigurationUpdate + This is test 2. + 2013-01-02T00:00:00.000+0000 + + + + \ No newline at end of file diff --git a/apis/cloudwatch/src/test/resources/DescribeAlarmsForMetricResponse.xml b/apis/cloudwatch/src/test/resources/DescribeAlarmsForMetricResponse.xml new file mode 100644 index 0000000000..f16bfff834 --- /dev/null +++ b/apis/cloudwatch/src/test/resources/DescribeAlarmsForMetricResponse.xml @@ -0,0 +1,88 @@ + + + + + true + + TestAction1 + TestAction2 + + TestAlarmARN1 + 2013-01-01T00:00:00.000+0000 + This is test alarm 1. + TestAlarmName1 + GreaterThanThreshold + + + TestDimensionName1 + TestDimensionValue1 + + + TestDimensionName2 + TestDimensionValue2 + + + 60 + + TestAction1 + TestAction2 + + TestMetricName1 + AWS/EC2 + + TestAction1 + TestAction2 + + 60 + This is state reason 1. + {"reason": "1"} + 2013-01-01T00:00:00.000+0000 + INSUFFICIENT_DATA + SampleCount + 1.0 + Seconds + + + false + + TestAction1 + TestAction2 + + TestAlarmARN2 + 2013-01-02T00:00:00.000+0000 + This is test alarm 2. + TestAlarmName2 + LessThanThreshold + + + TestDimensionName1 + TestDimensionValue1 + + + TestDimensionName2 + TestDimensionValue2 + + + 120 + + TestAction1 + TestAction2 + + TestMetricName2 + AWS/EC2 + + TestAction1 + TestAction2 + + 120 + This is state reason 2. + {"reason": "2"} + 2013-01-02T00:00:00.000+0000 + OK + Average + 2.0 + Count/Second + + + + \ No newline at end of file diff --git a/apis/cloudwatch/src/test/resources/DescribeAlarmsResponse.xml b/apis/cloudwatch/src/test/resources/DescribeAlarmsResponse.xml new file mode 100644 index 0000000000..75306dfc7c --- /dev/null +++ b/apis/cloudwatch/src/test/resources/DescribeAlarmsResponse.xml @@ -0,0 +1,88 @@ + + + + + true + + TestAction1 + TestAction2 + + TestAlarmARN1 + 2013-01-01T00:00:00.000+0000 + This is test alarm 1. + TestAlarmName1 + GreaterThanThreshold + + + TestDimensionName1 + TestDimensionValue1 + + + TestDimensionName2 + TestDimensionValue2 + + + 60 + + TestAction1 + TestAction2 + + TestMetricName1 + AWS/EC2 + + TestAction1 + TestAction2 + + 60 + This is state reason 1. + {"reason": "1"} + 2013-01-01T00:00:00.000+0000 + OK + SampleCount + 1.0 + Seconds + + + false + + TestAction1 + TestAction2 + + TestAlarmARN2 + 2013-01-02T00:00:00.000+0000 + This is test alarm 2. + TestAlarmName2 + LessThanThreshold + + + TestDimensionName1 + TestDimensionValue1 + + + TestDimensionName2 + TestDimensionValue2 + + + 120 + + TestAction1 + TestAction2 + + TestMetricName2 + AWS/EBS + + TestAction1 + TestAction2 + + 120 + This is state reason 2. + {"reason": "2"} + 2013-01-02T00:00:00.000+0000 + ALARM + Average + 2.0 + Count/Second + + + + \ No newline at end of file diff --git a/apis/cloudwatch/src/test/resources/InvalidFormatResponse.xml b/apis/cloudwatch/src/test/resources/InvalidFormatResponse.xml new file mode 100644 index 0000000000..667b3cdbf2 --- /dev/null +++ b/apis/cloudwatch/src/test/resources/InvalidFormatResponse.xml @@ -0,0 +1,9 @@ + + + + InvalidFormat + Data was not syntactically valid JSON. + + + a9f8f3a3-e40f-11dd-af0f-cf11f65ec49d + \ No newline at end of file diff --git a/apis/cloudwatch/src/test/resources/LimitExceededResponse.xml b/apis/cloudwatch/src/test/resources/LimitExceededResponse.xml new file mode 100644 index 0000000000..603a9c9417 --- /dev/null +++ b/apis/cloudwatch/src/test/resources/LimitExceededResponse.xml @@ -0,0 +1,9 @@ + + + + LimitExceeded + The quota for alarms for this customer has already been reached. + + + a9f8f3a3-e40f-11dd-af0f-cf11f65ec49d + \ No newline at end of file diff --git a/apis/cloudwatch/src/test/resources/VoidResponse.xml b/apis/cloudwatch/src/test/resources/VoidResponse.xml new file mode 100644 index 0000000000..e3592f0e5c --- /dev/null +++ b/apis/cloudwatch/src/test/resources/VoidResponse.xml @@ -0,0 +1,5 @@ + + + a9f8f3a3-e40f-11dd-af0f-cf11f65ec49d + + \ No newline at end of file diff --git a/apis/cloudwatch/src/test/resources/get_metric_statistics.xml b/apis/cloudwatch/src/test/resources/get_metric_statistics.xml index c72f51899a..b0a9cd225a 100644 --- a/apis/cloudwatch/src/test/resources/get_metric_statistics.xml +++ b/apis/cloudwatch/src/test/resources/get_metric_statistics.xml @@ -1,22 +1,22 @@ - - - - 2009-01-16T00:00:00Z - Percent - 9.0 - 0.17777777777777778 - - - 2009-01-16T00:01:00Z - Percent - 8.0 - 0.1 - - - - - - a9f8f3a3-e40f-11dd-af0f-cf11f65ec49d - + + + + 2009-01-16T00:00:00Z + Percent + 9.0 + 0.17777777777777778 + + + 2009-01-16T00:01:00Z + Percent + 8.0 + 0.1 + + + + + + a9f8f3a3-e40f-11dd-af0f-cf11f65ec49d + \ No newline at end of file