mirror of https://github.com/apache/jclouds.git
Merge pull request #915 from jclouds/ec2-tag-api
Issue 1110: replace TagClient in aws-ec2 with TagApi in ec2
This commit is contained in:
commit
cf8dce0e21
|
@ -22,6 +22,7 @@ import java.util.Set;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.concurrent.Timeout;
|
||||
import org.jclouds.ec2.features.TagApi;
|
||||
import org.jclouds.ec2.features.WindowsApi;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.location.Region;
|
||||
|
@ -29,7 +30,6 @@ import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
|
|||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
|
@ -66,12 +66,19 @@ public interface EC2Api {
|
|||
* Provides synchronous access to Windows features.
|
||||
*/
|
||||
@Delegate
|
||||
@Beta
|
||||
Optional<? extends WindowsApi> getWindowsApi();
|
||||
|
||||
@Delegate
|
||||
@Beta
|
||||
Optional<? extends WindowsApi> getWindowsApiForRegion(
|
||||
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Tag features.
|
||||
*/
|
||||
@Delegate
|
||||
Optional<? extends TagApi> getTagApi();
|
||||
|
||||
@Delegate
|
||||
Optional<? extends TagApi> getTagApiForRegion(
|
||||
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.jclouds.ec2;
|
|||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.ec2.features.TagAsyncApi;
|
||||
import org.jclouds.ec2.features.WindowsAsyncApi;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.location.Region;
|
||||
|
@ -54,4 +55,14 @@ public interface EC2AsyncApi {
|
|||
@Delegate
|
||||
Optional<? extends WindowsAsyncApi> getWindowsApiForRegion(
|
||||
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to Tag features.
|
||||
*/
|
||||
@Delegate
|
||||
Optional<? extends TagAsyncApi> getTagApi();
|
||||
|
||||
@Delegate
|
||||
Optional<? extends TagAsyncApi> getTagApiForRegion(
|
||||
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
|
||||
}
|
||||
|
|
|
@ -83,4 +83,5 @@ public interface EC2AsyncClient extends EC2AsyncApi {
|
|||
*/
|
||||
@Delegate
|
||||
ElasticBlockStoreAsyncClient getElasticBlockStoreServices();
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.ec2.binders;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.aws.util.AWSUtils;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.rest.Binder;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* Binds the Multimap to form parameters for filtering.
|
||||
*
|
||||
* <pre>
|
||||
* https://ec2.amazonaws.com/?Action=DescribeTags
|
||||
* &Filter.1.Name=resource-type
|
||||
* &Filter.1.Value.1=instance
|
||||
* &Filter.2.Name=key
|
||||
* &Filter.2.Value.1=stack
|
||||
* &Filter.3.Name=value
|
||||
* &Filter.3.Value.1=Test
|
||||
* &Filter.3.Value.2=Production
|
||||
* &AUTHPARAMS
|
||||
* </pre>
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class BindFiltersToIndexedFormParams implements Binder {
|
||||
@Override
|
||||
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||
checkArgument(checkNotNull(input, "input") instanceof Multimap, "this binder is only valid for Multimap");
|
||||
@SuppressWarnings("unchecked")
|
||||
Multimap<String, String> filters = (Multimap<String, String>) input;
|
||||
return AWSUtils.indexMultimapToFormValuesWithPrefix(request, "Filter", "Name", "Value", filters);
|
||||
}
|
||||
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.aws.ec2.binders;
|
||||
package org.jclouds.ec2.binders;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.ec2.binders;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.aws.util.AWSUtils;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.rest.Binder;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* Binds the Iterable<String> to form parameters named with Tag.index.Key
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class BindTagKeysToIndexedFormParams implements Binder {
|
||||
@Override
|
||||
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||
checkArgument(checkNotNull(input, "input") instanceof Iterable, "This binder is only valid for Iterable<String>");
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterable<String> keys = (Iterable<String>) input;
|
||||
return AWSUtils.indexStringArrayToFormValuesWithStringFormat(request, "Tag.%s.Key",
|
||||
Iterables.toArray(keys, String.class));
|
||||
}
|
||||
|
||||
}
|
|
@ -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.ec2.binders;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.aws.util.AWSUtils.indexMapToFormValuesWithPrefix;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.rest.Binder;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMap.Builder;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class BindTagsToIndexedFormParams implements Binder {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||
checkNotNull(input, "tags");
|
||||
Map<String, String> tagValues;
|
||||
if (input instanceof Iterable) {
|
||||
Builder<String, String> builder = ImmutableMap.<String, String> builder();
|
||||
for (String key : (Iterable<String>) input) {
|
||||
builder.put(key, "");
|
||||
}
|
||||
tagValues = builder.build();
|
||||
} else if (input instanceof Map) {
|
||||
tagValues = Map.class.cast(input);
|
||||
} else {
|
||||
throw new IllegalArgumentException("This binder is only valid for Map<String,String> or Iterable<String>");
|
||||
}
|
||||
return indexMapToFormValuesWithPrefix(request, "Tag", "Key", "Value", tagValues);
|
||||
}
|
||||
|
||||
}
|
|
@ -27,6 +27,8 @@ import org.jclouds.ec2.EC2Api;
|
|||
import org.jclouds.ec2.EC2AsyncApi;
|
||||
import org.jclouds.ec2.EC2AsyncClient;
|
||||
import org.jclouds.ec2.EC2Client;
|
||||
import org.jclouds.ec2.features.TagApi;
|
||||
import org.jclouds.ec2.features.TagAsyncApi;
|
||||
import org.jclouds.ec2.features.WindowsApi;
|
||||
import org.jclouds.ec2.features.WindowsAsyncApi;
|
||||
import org.jclouds.ec2.services.AMIAsyncClient;
|
||||
|
@ -82,6 +84,7 @@ public class EC2RestClientModule<S extends EC2Api, A extends EC2AsyncApi> extend
|
|||
.put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)//
|
||||
.put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)//
|
||||
.put(WindowsApi.class, WindowsAsyncApi.class)//
|
||||
.put(TagApi.class, TagAsyncApi.class)//
|
||||
.build();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.ec2.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Objects.ToStringHelper;
|
||||
import com.google.common.base.Optional;
|
||||
|
||||
/**
|
||||
* To help you manage your Amazon EC2 instances, images, and other Amazon EC2
|
||||
* resources, you can assign your own metadata to each resource in the form of
|
||||
* tags.
|
||||
*
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/Using_Tags.html"
|
||||
* >doc</a>
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class Tag {
|
||||
|
||||
/**
|
||||
* Describes the well-known resource types that can be tagged.
|
||||
*/
|
||||
public static interface ResourceType {
|
||||
public static final String CUSTOMER_GATEWAY = "customer-gateway";
|
||||
public static final String DHCP_OPTIONS = "dhcp-options";
|
||||
public static final String IMAGE = "image";
|
||||
public static final String INSTANCE = "instance";
|
||||
public static final String INTERNET_GATEWAY = "internet-gateway";
|
||||
public static final String NETWORK_ACL = "network-acl";
|
||||
public static final String RESERVED_INSTANCES = "reserved-instances";
|
||||
public static final String ROUTE_TABLE = "route-table";
|
||||
public static final String SECURITY_GROUP = "security-group";
|
||||
public static final String SNAPSHOT = "snapshot";
|
||||
public static final String SPOT_INSTANCES_REQUEST = "spot-instances-request";
|
||||
public static final String SUBNET = "subnet";
|
||||
public static final String VOLUME = "volume";
|
||||
public static final String VPC = "vpc";
|
||||
public static final String VPN_CONNECTION = "vpn-connection";
|
||||
public static final String VPN_GATEWAY = "vpn-gateway";
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public Builder toBuilder() {
|
||||
return builder().fromTag(this);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
protected String resourceId;
|
||||
protected String resourceType;
|
||||
protected String key;
|
||||
protected Optional<String> value = Optional.absent();
|
||||
|
||||
/**
|
||||
* @see Tag#getResourceId()
|
||||
*/
|
||||
public Builder resourceId(String resourceId) {
|
||||
this.resourceId = resourceId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Tag#getResourceType()
|
||||
*/
|
||||
public Builder resourceType(String resourceType) {
|
||||
this.resourceType = resourceType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Tag#getKey()
|
||||
*/
|
||||
public Builder key(String key) {
|
||||
this.key = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TagGroup#getValue()
|
||||
*/
|
||||
public Builder value(String value) {
|
||||
this.value = Optional.fromNullable(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Tag build() {
|
||||
return new Tag(resourceId, resourceType, key, value);
|
||||
}
|
||||
|
||||
public Builder fromTag(Tag in) {
|
||||
return this.resourceId(in.getResourceId()).resourceType(in.getResourceType()).key(in.getKey())
|
||||
.value(in.getValue().orNull());
|
||||
}
|
||||
}
|
||||
|
||||
protected final String resourceId;
|
||||
protected final String resourceType;
|
||||
protected final String key;
|
||||
protected final Optional<String> value;
|
||||
|
||||
protected Tag(String resourceId, String resourceType, String key, Optional<String> value) {
|
||||
this.resourceId = checkNotNull(resourceId, "resourceId");
|
||||
this.resourceType = checkNotNull(resourceType, "resourceType");
|
||||
this.key = checkNotNull(key, "key");
|
||||
this.value = checkNotNull(value, "value");
|
||||
}
|
||||
|
||||
/**
|
||||
* The resource ID ex. i-erf235
|
||||
*/
|
||||
public String getResourceId() {
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* The resource type. ex. customer-gateway, dhcp-options, image, instance,
|
||||
* internet-gateway, network-acl, reserved-instances, route-table,
|
||||
* security-group, snapshot, spot-instances-request, subnet, volume, vpc,
|
||||
* vpn-connection, vpn-gateway
|
||||
*/
|
||||
public String getResourceType() {
|
||||
return resourceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* The tag key.
|
||||
*/
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* The tag value.
|
||||
*/
|
||||
public Optional<String> getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(resourceId, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Tag other = (Tag) obj;
|
||||
return Objects.equal(this.resourceId, other.resourceId) && Objects.equal(this.key, other.key);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return string().toString();
|
||||
}
|
||||
|
||||
protected ToStringHelper string() {
|
||||
return Objects.toStringHelper(this).omitNullValues().add("resourceId", resourceId)
|
||||
.add("resourceType", resourceType).add("key", key).add("value", value.orNull());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.ec2.features;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.concurrent.Timeout;
|
||||
import org.jclouds.ec2.domain.Tag;
|
||||
import org.jclouds.ec2.util.TagFilterBuilder;
|
||||
import org.jclouds.rest.annotations.SinceApiVersion;
|
||||
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* Provides access to Amazon EC2 via the Query API
|
||||
* <p/>
|
||||
*
|
||||
* This api is not available in EC2 versions below {@link #MIN_API_VERSION}
|
||||
*
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeTags.html"
|
||||
* >doc</a>
|
||||
* @see TagAsyncApi
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@SinceApiVersion("2010-08-31")
|
||||
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
|
||||
public interface TagApi {
|
||||
|
||||
/**
|
||||
* Adds or overwrites one or more tags for the specified resource or
|
||||
* resources. Each resource can have a maximum of 10 tags. Each tag consists
|
||||
* of a key and optional value. Tag keys must be unique per resource.
|
||||
*
|
||||
* <h4>example</h4>
|
||||
*
|
||||
* <pre>
|
||||
* tagApi.applyToResources(ImmutableMap.of("group", "backend"), ImmutableSet.of("i-1a2b3c4d"));
|
||||
* </pre>
|
||||
*
|
||||
* @param tags
|
||||
* key to an optional value.
|
||||
* @param resourceIds
|
||||
* The ID of a resource to tag. For example, {@code ami-1a2b3c4d}
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateTags.html"
|
||||
* >docs</href>
|
||||
*/
|
||||
void applyToResources(Map<String, String> tags, Iterable<String> resourceIds);
|
||||
|
||||
/**
|
||||
* like {@link #applyToResources(Map, Iterable)} except that the tags have no
|
||||
* values.
|
||||
*
|
||||
* <h4>example</h4>
|
||||
*
|
||||
* <pre>
|
||||
* tagApi.applyToResources(ImmutableSet.of("production", "pci-compliant"), ImmutableSet.of("i-1a2b3c4d"));
|
||||
* </pre>
|
||||
*
|
||||
* @see #applyToResources(Map, Iterable)
|
||||
*/
|
||||
void applyToResources(Iterable<String> tags, Iterable<String> resourceIds);
|
||||
|
||||
/**
|
||||
* Describes all of your tags for your EC2 resources.
|
||||
*
|
||||
* @return tags or empty if there are none
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeTags.html"
|
||||
* >docs</href>
|
||||
*/
|
||||
FluentIterable<Tag> list();
|
||||
|
||||
/**
|
||||
* Describes tags for your EC2 resources qualified by a filter
|
||||
*
|
||||
* <h4>example</h4>
|
||||
*
|
||||
* <pre>
|
||||
* tags = tagApi.filter(new TagFilterBuilder().image().put("version", "1.0").build());
|
||||
* </pre>
|
||||
*
|
||||
* @param filter
|
||||
* which is typically built by {@link TagFilterBuilder}
|
||||
* @return tags or empty if there are none that match the filter
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeTags.html"
|
||||
* >docs</href>
|
||||
*/
|
||||
FluentIterable<Tag> filter(Multimap<String, String> filter);
|
||||
|
||||
/**
|
||||
* Deletes a specific set of tags from a specific set of resources. This call
|
||||
* is designed to follow a {@link #list() list} or {@link #filter(Multimap)
|
||||
* filter} call. You first determine what tags a resource has, and then you
|
||||
* call {@link TagApi#deleteFromResources(Iterable, Iterable) delete} with
|
||||
* the resource ID and the specific tags you want to delete.
|
||||
*
|
||||
* <h4>example</h4>
|
||||
*
|
||||
* <pre>
|
||||
* tagApi.deleteFromResources(ImmutableSet.of("Purpose"), ImmutableSet.of("ami-1a2b3c4d"));
|
||||
* </pre>
|
||||
*
|
||||
* @param tags
|
||||
* the tag keys
|
||||
* @param resourceIds
|
||||
* The ID of a resource with the tag. For example,
|
||||
* {@code ami-1a2b3c4d}
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteTags.html"
|
||||
* >docs</href>
|
||||
*/
|
||||
void deleteFromResources(Iterable<String> tags, Iterable<String> resourceIds);
|
||||
|
||||
/**
|
||||
* like {@link #deleteFromResources(Iterable, Iterable)}, except that the
|
||||
* tags are only deleted if they match the value.
|
||||
*
|
||||
* <h4>example</h4>
|
||||
*
|
||||
* <pre>
|
||||
* tagApi.deleteFromResources(ImmutableMap.of("Purpose", "production"), ImmutableSet.of("ami-1a2b3c4d"));
|
||||
* </pre>
|
||||
*
|
||||
* @param conditionalTagValues
|
||||
* tag id to value it must match before deleting. For a tag without
|
||||
* a value, supply empty string.
|
||||
* @param resourceIds
|
||||
* The ID of a resource with the tag. For example,
|
||||
* {@code ami-1a2b3c4d}
|
||||
* @see #deleteFromResources(Iterable, Iterable)
|
||||
*/
|
||||
void conditionallyDeleteFromResources(Map<String, String> conditionalTagValues, Iterable<String> resourceIds);
|
||||
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.ec2.features;
|
||||
|
||||
import static org.jclouds.aws.reference.FormParameters.ACTION;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
|
||||
import org.jclouds.aws.filters.FormSigner;
|
||||
import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams;
|
||||
import org.jclouds.ec2.binders.BindResourceIdsToIndexedFormParams;
|
||||
import org.jclouds.ec2.binders.BindTagKeysToIndexedFormParams;
|
||||
import org.jclouds.ec2.binders.BindTagsToIndexedFormParams;
|
||||
import org.jclouds.ec2.domain.Tag;
|
||||
import org.jclouds.ec2.xml.DescribeTagsResponseHandler;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.ExceptionParser;
|
||||
import org.jclouds.rest.annotations.FormParams;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.annotations.SinceApiVersion;
|
||||
import org.jclouds.rest.annotations.VirtualHost;
|
||||
import org.jclouds.rest.annotations.XMLResponseParser;
|
||||
import org.jclouds.rest.functions.ReturnEmptyFluentIterableOnNotFoundOr404;
|
||||
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
* Provides access to Amazon EC2 via the Query API
|
||||
* <p/>
|
||||
*
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeTags.html"
|
||||
* >doc</a>
|
||||
* @see TagApi
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@SinceApiVersion("2010-08-31")
|
||||
@RequestFilters(FormSigner.class)
|
||||
@VirtualHost
|
||||
public interface TagAsyncApi {
|
||||
/**
|
||||
* @see TagApi#applyToResources(Iterable, Iterable)
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateTags.html">docs</a>
|
||||
*/
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = ACTION, values = "CreateTags")
|
||||
ListenableFuture<Void> applyToResources(@BinderParam(BindTagsToIndexedFormParams.class) Iterable<String> tags,
|
||||
@BinderParam(BindResourceIdsToIndexedFormParams.class) Iterable<String> resourceIds);
|
||||
|
||||
/**
|
||||
* @see TagApi#applyToResources(Map, Iterable)
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateTags.html">docs</a>
|
||||
*/
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = ACTION, values = "CreateTags")
|
||||
ListenableFuture<Void> applyToResources(@BinderParam(BindTagsToIndexedFormParams.class) Map<String, String> tags,
|
||||
@BinderParam(BindResourceIdsToIndexedFormParams.class) Iterable<String> resourceIds);
|
||||
|
||||
/**
|
||||
* @see TagApi#list()
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeTags.html">docs</a>
|
||||
*/
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = ACTION, values = "DescribeTags")
|
||||
@XMLResponseParser(DescribeTagsResponseHandler.class)
|
||||
@ExceptionParser(ReturnEmptyFluentIterableOnNotFoundOr404.class)
|
||||
ListenableFuture<FluentIterable<Tag>> list();
|
||||
|
||||
/**
|
||||
* @see TagApi#filter
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeTags.html">docs</a>
|
||||
*/
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = ACTION, values = "DescribeTags")
|
||||
@XMLResponseParser(DescribeTagsResponseHandler.class)
|
||||
@ExceptionParser(ReturnEmptyFluentIterableOnNotFoundOr404.class)
|
||||
ListenableFuture<FluentIterable<Tag>> filter(
|
||||
@BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter);
|
||||
|
||||
/**
|
||||
* @see TagApi#deleteFromResources
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteTags.html">docs</a>
|
||||
*/
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = ACTION, values = "DeleteTags")
|
||||
ListenableFuture<Void> deleteFromResources(
|
||||
@BinderParam(BindTagKeysToIndexedFormParams.class) Iterable<String> tags,
|
||||
@BinderParam(BindResourceIdsToIndexedFormParams.class) Iterable<String> resourceIds);
|
||||
|
||||
/**
|
||||
* @see TagApi#conditionallyDeleteFromResources
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteTags.html">docs</a>
|
||||
*/
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = ACTION, values = "DeleteTags")
|
||||
ListenableFuture<Void> conditionallyDeleteFromResources(
|
||||
@BinderParam(BindTagsToIndexedFormParams.class) Map<String, String> conditionalTagValues,
|
||||
@BinderParam(BindResourceIdsToIndexedFormParams.class) Iterable<String> resourceIds);
|
||||
|
||||
}
|
|
@ -0,0 +1,226 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.ec2.util;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.jclouds.ec2.domain.Tag;
|
||||
import org.jclouds.ec2.features.TagApi;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* You can use filters to limit the results when describing tags. For example,
|
||||
* you could get only the tags for a particular resource type. You can specify
|
||||
* multiple values for a filter. A tag must match at least one of the specified
|
||||
* values for it to be included in the results.
|
||||
*
|
||||
* You can specify multiple filters (for example, limit the results to a
|
||||
* specific resource type, and get only tags with values that contain the string
|
||||
* database). The result includes information for a particular tag only if it
|
||||
* matches all your filters. If there's no match, no special message is
|
||||
* returned; the response is simply empty.
|
||||
*
|
||||
* <h4>Wildcards</h4> You can use wildcards with the filter values: {@code *}
|
||||
* matches zero or more characters, and ? matches exactly one character. You can
|
||||
* escape special characters using a backslash before the character. For
|
||||
* example, a value of {@code \*amazon\?\\} searches for the literal string
|
||||
* {@code *amazon?\}.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
* @see TagApi
|
||||
*/
|
||||
public class TagFilterBuilder extends ImmutableMultimap.Builder<String, String> {
|
||||
|
||||
private static final String KEY = "key";
|
||||
private static final String VALUE = "value";
|
||||
private static final String RESOURCE_ID = "resource-id";
|
||||
private static final String RESOURCE_TYPE = "resource-type";
|
||||
|
||||
public TagFilterBuilder key(String key) {
|
||||
return put(KEY, key);
|
||||
}
|
||||
|
||||
public TagFilterBuilder keys(String... keys) {
|
||||
return putAll(KEY, keys);
|
||||
}
|
||||
|
||||
public TagFilterBuilder keys(Iterable<String> keys) {
|
||||
return putAll(KEY, keys);
|
||||
}
|
||||
|
||||
public TagFilterBuilder anyKey() {
|
||||
return putAll(KEY, ImmutableSet.<String> of());
|
||||
}
|
||||
|
||||
public TagFilterBuilder value(String value) {
|
||||
return put(VALUE, value);
|
||||
}
|
||||
|
||||
public TagFilterBuilder values(String... values) {
|
||||
return putAll(VALUE, ImmutableSet.<String> copyOf(values));
|
||||
}
|
||||
|
||||
public TagFilterBuilder values(Iterable<String> values) {
|
||||
return putAll(VALUE, ImmutableSet.<String> copyOf(values));
|
||||
}
|
||||
|
||||
public TagFilterBuilder anyValue() {
|
||||
return putAll(VALUE, ImmutableSet.<String> of());
|
||||
}
|
||||
|
||||
public TagFilterBuilder resourceId(String resourceId) {
|
||||
return put(RESOURCE_ID, resourceId);
|
||||
}
|
||||
|
||||
public TagFilterBuilder resourceIds(String... resourceIds) {
|
||||
return putAll(RESOURCE_ID, resourceIds);
|
||||
}
|
||||
|
||||
public TagFilterBuilder resourceIds(Iterable<String> resourceIds) {
|
||||
return putAll(RESOURCE_ID, resourceIds);
|
||||
}
|
||||
|
||||
public TagFilterBuilder anyResourceId() {
|
||||
return putAll(RESOURCE_TYPE, ImmutableSet.<String> of());
|
||||
}
|
||||
|
||||
public TagFilterBuilder resourceType(String resourceType) {
|
||||
return put(RESOURCE_TYPE, resourceType);
|
||||
}
|
||||
|
||||
public TagFilterBuilder resourceTypes(String... resourceTypes) {
|
||||
return putAll(RESOURCE_TYPE, resourceTypes);
|
||||
}
|
||||
|
||||
public TagFilterBuilder resourceTypes(Iterable<String> resourceTypes) {
|
||||
return putAll(RESOURCE_TYPE, resourceTypes);
|
||||
}
|
||||
|
||||
public TagFilterBuilder anyResourceType() {
|
||||
return putAll(RESOURCE_TYPE, ImmutableSet.<String> of());
|
||||
}
|
||||
|
||||
public TagFilterBuilder customerGateway() {
|
||||
return put(RESOURCE_TYPE, Tag.ResourceType.CUSTOMER_GATEWAY);
|
||||
}
|
||||
|
||||
public TagFilterBuilder dhcpOptions() {
|
||||
return put(RESOURCE_TYPE, Tag.ResourceType.DHCP_OPTIONS);
|
||||
}
|
||||
|
||||
public TagFilterBuilder image() {
|
||||
return put(RESOURCE_TYPE, Tag.ResourceType.IMAGE);
|
||||
}
|
||||
|
||||
public TagFilterBuilder instance() {
|
||||
return put(RESOURCE_TYPE, Tag.ResourceType.INSTANCE);
|
||||
}
|
||||
|
||||
public TagFilterBuilder internetGateway() {
|
||||
return put(RESOURCE_TYPE, Tag.ResourceType.INTERNET_GATEWAY);
|
||||
}
|
||||
|
||||
public TagFilterBuilder networkAcl() {
|
||||
return put(RESOURCE_TYPE, Tag.ResourceType.NETWORK_ACL);
|
||||
}
|
||||
|
||||
public TagFilterBuilder reservedInstance() {
|
||||
return put(RESOURCE_TYPE, Tag.ResourceType.RESERVED_INSTANCES);
|
||||
}
|
||||
|
||||
public TagFilterBuilder routeTable() {
|
||||
return put(RESOURCE_TYPE, Tag.ResourceType.ROUTE_TABLE);
|
||||
}
|
||||
|
||||
public TagFilterBuilder securityGroup() {
|
||||
return put(RESOURCE_TYPE, Tag.ResourceType.SECURITY_GROUP);
|
||||
}
|
||||
|
||||
public TagFilterBuilder snapshot() {
|
||||
return put(RESOURCE_TYPE, Tag.ResourceType.SNAPSHOT);
|
||||
}
|
||||
|
||||
public TagFilterBuilder instancesRequest() {
|
||||
return put(RESOURCE_TYPE, Tag.ResourceType.SPOT_INSTANCES_REQUEST);
|
||||
}
|
||||
|
||||
public TagFilterBuilder subnet() {
|
||||
return put(RESOURCE_TYPE, Tag.ResourceType.SUBNET);
|
||||
}
|
||||
|
||||
public TagFilterBuilder volume() {
|
||||
return put(RESOURCE_TYPE, Tag.ResourceType.VOLUME);
|
||||
}
|
||||
|
||||
public TagFilterBuilder vpc() {
|
||||
return put(RESOURCE_TYPE, Tag.ResourceType.VPC);
|
||||
}
|
||||
|
||||
public TagFilterBuilder vpnConnection() {
|
||||
return put(RESOURCE_TYPE, Tag.ResourceType.VPN_CONNECTION);
|
||||
}
|
||||
|
||||
public TagFilterBuilder vpnGateway() {
|
||||
return put(RESOURCE_TYPE, Tag.ResourceType.VPN_GATEWAY);
|
||||
}
|
||||
|
||||
// to set correct return val in chain
|
||||
|
||||
@Override
|
||||
public TagFilterBuilder put(String key, String value) {
|
||||
return TagFilterBuilder.class.cast(super.put(key, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TagFilterBuilder put(Entry<? extends String, ? extends String> entry) {
|
||||
return TagFilterBuilder.class.cast(super.put(entry));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TagFilterBuilder putAll(String key, Iterable<? extends String> values) {
|
||||
return TagFilterBuilder.class.cast(super.putAll(key, values));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TagFilterBuilder putAll(String key, String... values) {
|
||||
return TagFilterBuilder.class.cast(super.putAll(key, values));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TagFilterBuilder putAll(Multimap<? extends String, ? extends String> multimap) {
|
||||
return TagFilterBuilder.class.cast(super.putAll(multimap));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Beta
|
||||
public TagFilterBuilder orderKeysBy(Comparator<? super String> keyComparator) {
|
||||
return TagFilterBuilder.class.cast(super.orderKeysBy(keyComparator));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Beta
|
||||
public TagFilterBuilder orderValuesBy(Comparator<? super String> valueComparator) {
|
||||
return TagFilterBuilder.class.cast(super.orderValuesBy(valueComparator));
|
||||
}
|
||||
}
|
|
@ -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.ec2.xml;
|
||||
|
||||
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
|
||||
|
||||
import org.jclouds.ec2.domain.Tag;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSet.Builder;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeTags.html"
|
||||
* >xml</a>
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class DescribeTagsResponseHandler extends ParseSax.HandlerForGeneratedRequestWithResult<FluentIterable<Tag>> {
|
||||
|
||||
private final TagHandler tagHander;
|
||||
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
private Builder<Tag> tags = ImmutableSet.<Tag> builder();
|
||||
private boolean inTags;
|
||||
|
||||
@Inject
|
||||
public DescribeTagsResponseHandler(TagHandler tagHander) {
|
||||
this.tagHander = tagHander;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public FluentIterable<Tag> getResult() {
|
||||
return FluentIterable.from(tags.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException {
|
||||
if (equalsOrSuffix(qName, "tagSet")) {
|
||||
inTags = true;
|
||||
}
|
||||
if (inTags) {
|
||||
tagHander.startElement(url, name, qName, attributes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void endElement(String uri, String name, String qName) throws SAXException {
|
||||
if (equalsOrSuffix(qName, "tagSet")) {
|
||||
inTags = false;
|
||||
} else if (equalsOrSuffix(qName, "item")) {
|
||||
tags.add(tagHander.getResult());
|
||||
} else if (inTags) {
|
||||
tagHander.endElement(uri, name, qName);
|
||||
}
|
||||
currentText = new StringBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void characters(char ch[], int start, int length) {
|
||||
if (inTags) {
|
||||
tagHander.characters(ch, start, length);
|
||||
} else {
|
||||
currentText.append(ch, start, length);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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.ec2.xml;
|
||||
|
||||
import static org.jclouds.util.SaxUtils.currentOrNull;
|
||||
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
|
||||
|
||||
import org.jclouds.ec2.domain.Tag;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
/**
|
||||
* @see <a
|
||||
* href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeTags.html"
|
||||
* >xml</a>
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class TagHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Tag> {
|
||||
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
private Tag.Builder builder = Tag.builder();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Tag getResult() {
|
||||
try {
|
||||
return builder.build();
|
||||
} finally {
|
||||
builder = Tag.builder();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void endElement(String uri, String name, String qName) throws SAXException {
|
||||
if (equalsOrSuffix(qName, "resourceId")) {
|
||||
builder.resourceId(currentOrNull(currentText));
|
||||
} else if (equalsOrSuffix(qName, "resourceType")) {
|
||||
builder.resourceType(currentOrNull(currentText));
|
||||
} else if (equalsOrSuffix(qName, "key")) {
|
||||
builder.key(currentOrNull(currentText));
|
||||
} else if (equalsOrSuffix(qName, "value")) {
|
||||
// empty is same as not present
|
||||
builder.value(Strings.emptyToNull(currentOrNull(currentText)));
|
||||
}
|
||||
currentText = new StringBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void characters(char ch[], int start, int length) {
|
||||
currentText.append(ch, start, length);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.ec2.binders;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code BindFiltersToIndexedFormParams}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class BindFiltersToIndexedFormParamsTest {
|
||||
Injector injector = Guice.createInjector();
|
||||
BindFiltersToIndexedFormParams binder = injector.getInstance(BindFiltersToIndexedFormParams.class);
|
||||
|
||||
public void test() {
|
||||
HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
|
||||
request = binder.bindToRequest(request, ImmutableMultimap.<String, String> builder()
|
||||
.put("resource-type", "instance")
|
||||
.put("key", "stack")
|
||||
.putAll("value", "Test", "Production")
|
||||
.build());
|
||||
assertEquals(
|
||||
request.getPayload().getRawContent(),
|
||||
"Filter.1.Name=resource-type&Filter.1.Value.1=instance&Filter.2.Name=key&Filter.2.Value.1=stack&Filter.3.Name=value&Filter.3.Value.1=Test&Filter.3.Value.2=Production");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testMustBeMultimap() {
|
||||
HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();;
|
||||
binder.bindToRequest(request, new File("foo"));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void testNullIsBad() {
|
||||
HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
|
||||
binder.bindToRequest(request, null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package org.jclouds.ec2.binders;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code BindResourceIdsToIndexedFormParams}
|
||||
*
|
||||
* @author grkvlt@apache.org
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class BindResourceIdsToIndexedFormParamsTest {
|
||||
Injector injector = Guice.createInjector();
|
||||
BindResourceIdsToIndexedFormParams binder = injector.getInstance(BindResourceIdsToIndexedFormParams.class);
|
||||
|
||||
public void test() {
|
||||
HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
|
||||
request = binder.bindToRequest(request, ImmutableList.builder().add("alpha").add("omega").build());
|
||||
assertEquals(request.getPayload().getRawContent(), "ResourceId.1=alpha&ResourceId.2=omega");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testMustBeArray() {
|
||||
HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();;
|
||||
binder.bindToRequest(request, new File("foo"));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void testNullIsBad() {
|
||||
HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
|
||||
binder.bindToRequest(request, null);
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.aws.ec2.binders;
|
||||
package org.jclouds.ec2.binders;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
|
@ -25,29 +25,26 @@ import java.io.File;
|
|||
import org.jclouds.http.HttpRequest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code BindResourceIdsToIndexedFormParams}
|
||||
* Tests behavior of {@code BindTagKeysToIndexedFormParams}
|
||||
*
|
||||
* @author grkvlt@apache.org
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class BindResourceIdsToIndexedFormParamsTest {
|
||||
Injector injector = Guice.createInjector();
|
||||
BindResourceIdsToIndexedFormParams binder = injector.getInstance(BindResourceIdsToIndexedFormParams.class);
|
||||
public class BindTagKeysToIndexedFormParamsTest {
|
||||
BindTagKeysToIndexedFormParams binder = new BindTagKeysToIndexedFormParams();
|
||||
|
||||
public void test() {
|
||||
HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
|
||||
request = binder.bindToRequest(request, ImmutableList.builder().add("alpha").add("omega").build());
|
||||
assertEquals(request.getPayload().getRawContent(), "ResourceId.1=alpha&ResourceId.2=omega");
|
||||
request = binder.bindToRequest(request, ImmutableSet.of("one", "two"));
|
||||
assertEquals(request.getPayload().getRawContent(), "Tag.1.Key=one&Tag.2.Key=two");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testMustBeArray() {
|
||||
HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();;
|
||||
public void testMustBeIterable() {
|
||||
HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
|
||||
binder.bindToRequest(request, new File("foo"));
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.ec2.binders;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code BindTagsToIndexedFormParams}
|
||||
*
|
||||
* @author grkvlt@apache.org
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class BindTagsToIndexedFormParamsTest {
|
||||
BindTagsToIndexedFormParams binder = new BindTagsToIndexedFormParams();
|
||||
|
||||
public void test() {
|
||||
HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
|
||||
request = binder.bindToRequest(request, ImmutableMap.of("one", "alpha", "two", "beta"));
|
||||
assertEquals(request.getPayload().getRawContent(),
|
||||
"Tag.1.Key=one&Tag.1.Value=alpha&Tag.2.Key=two&Tag.2.Value=beta");
|
||||
}
|
||||
|
||||
public void testEmpty() {
|
||||
HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
|
||||
request = binder.bindToRequest(request, ImmutableSet.of("empty"));
|
||||
assertEquals(request.getPayload().getRawContent(), "Tag.1.Key=empty&Tag.1.Value=");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testMustBeArray() {
|
||||
HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
|
||||
binder.bindToRequest(request, new File("foo"));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void testNullIsBad() {
|
||||
HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
|
||||
binder.bindToRequest(request, null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,293 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unles required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either expres or implied. See the License for the
|
||||
* specific language governing permisions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.ec2.features;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.ec2.EC2Api;
|
||||
import org.jclouds.ec2.internal.BaseEC2ApiExpectTest;
|
||||
import org.jclouds.ec2.parse.DescribeTagsResponseTest;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.rest.ResourceNotFoundException;
|
||||
import org.jclouds.rest.annotations.SinceApiVersion;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class TagApiExpectTest extends BaseEC2ApiExpectTest<EC2Api> {
|
||||
|
||||
public TagApiExpectTest() {
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TagApi
|
||||
* @see SinceApiVersion
|
||||
*/
|
||||
protected Properties setupProperties() {
|
||||
Properties props = super.setupProperties();
|
||||
props.put(Constants.PROPERTY_API_VERSION, "2010-08-31");
|
||||
return props;
|
||||
}
|
||||
|
||||
HttpRequest apply = HttpRequest.builder()
|
||||
.method("POST")
|
||||
.endpoint("https://ec2.us-east-1.amazonaws.com/")
|
||||
.addHeader("Host", "ec2.us-east-1.amazonaws.com")
|
||||
.payload(
|
||||
payloadFromStringWithContentType(
|
||||
"Action=CreateTags" +
|
||||
"&ResourceId.1=i-43532" +
|
||||
"&Signature=Trp5e5%2BMqeBeBZbLYa9s9gxahQ9nkx6ETfsGl82IV8Y%3D" +
|
||||
"&SignatureMethod=HmacSHA256" +
|
||||
"&SignatureVersion=2" +
|
||||
"&Tag.1.Key=tag" +
|
||||
"&Tag.1.Value=" +
|
||||
"&Timestamp=2012-04-16T15%3A54%3A08.897Z" +
|
||||
"&Version=2010-08-31" +
|
||||
"&AWSAccessKeyId=identity",
|
||||
"application/x-www-form-urlencoded"))
|
||||
.build();
|
||||
|
||||
public void testApplyWhenResponseIs2xx() throws Exception {
|
||||
|
||||
HttpResponse applyResponse = HttpResponse.builder().statusCode(200).build();
|
||||
|
||||
EC2Api apiWhenExist = requestSendsResponse(apply, applyResponse);
|
||||
|
||||
apiWhenExist.getTagApi().get().applyToResources(ImmutableSet.of("tag"), ImmutableSet.of("i-43532"));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = ResourceNotFoundException.class)
|
||||
public void testApplyWhenResponseIs404() throws Exception {
|
||||
|
||||
HttpResponse applyResponse = HttpResponse.builder().statusCode(404).build();
|
||||
|
||||
EC2Api apiWhenDontExist = requestSendsResponse(apply, applyResponse);
|
||||
|
||||
apiWhenDontExist.getTagApi().get().applyToResources(ImmutableSet.of("tag"), ImmutableSet.of("i-43532"));
|
||||
}
|
||||
|
||||
HttpRequest applyWithValues = HttpRequest.builder()
|
||||
.method("POST")
|
||||
.endpoint("https://ec2.us-east-1.amazonaws.com/")
|
||||
.addHeader("Host", "ec2.us-east-1.amazonaws.com")
|
||||
.payload(
|
||||
payloadFromStringWithContentType(
|
||||
"Action=CreateTags" +
|
||||
"&ResourceId.1=i-43532" +
|
||||
"&Signature=jwCQr50j%2BvGkav4t0BN0G8RmNJ7VaFK6%2F7N%2FHKUmHL8%3D" +
|
||||
"&SignatureMethod=HmacSHA256" +
|
||||
"&SignatureVersion=2" +
|
||||
"&Tag.1.Key=tag" +
|
||||
"&Tag.1.Value=value" +
|
||||
"&Timestamp=2012-04-16T15%3A54%3A08.897Z" +
|
||||
"&Version=2010-08-31" +
|
||||
"&AWSAccessKeyId=identity",
|
||||
"application/x-www-form-urlencoded"))
|
||||
.build();
|
||||
|
||||
public void testApplyWithValuesWhenResponseIs2xx() throws Exception {
|
||||
|
||||
HttpResponse applyResponse = HttpResponse.builder().statusCode(200).build();
|
||||
|
||||
EC2Api apiWhenExist = requestSendsResponse(applyWithValues, applyResponse);
|
||||
|
||||
apiWhenExist.getTagApi().get().applyToResources(ImmutableMap.of("tag", "value"), ImmutableSet.of("i-43532"));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = ResourceNotFoundException.class)
|
||||
public void testApplyWithValuesWhenResponseIs404() throws Exception {
|
||||
|
||||
HttpResponse applyResponse = HttpResponse.builder().statusCode(404).build();
|
||||
|
||||
EC2Api apiWhenDontExist = requestSendsResponse(applyWithValues, applyResponse);
|
||||
|
||||
apiWhenDontExist.getTagApi().get().applyToResources(ImmutableMap.of("tag", "value"), ImmutableSet.of("i-43532"));
|
||||
}
|
||||
|
||||
HttpRequest list = HttpRequest.builder()
|
||||
.method("POST")
|
||||
.endpoint("https://ec2.us-east-1.amazonaws.com/")
|
||||
.addHeader("Host", "ec2.us-east-1.amazonaws.com")
|
||||
.payload(
|
||||
payloadFromStringWithContentType(
|
||||
"Action=DescribeTags" +
|
||||
"&Signature=DYUjPGiRl9copBtmpocMZYVAy4OTrK2AJzcAH5QiBuw%3D" +
|
||||
"&SignatureMethod=HmacSHA256" +
|
||||
"&SignatureVersion=2" +
|
||||
"&Timestamp=2012-04-16T15%3A54%3A08.897Z" +
|
||||
"&Version=2010-08-31" +
|
||||
"&AWSAccessKeyId=identity",
|
||||
"application/x-www-form-urlencoded"))
|
||||
.build();
|
||||
|
||||
public void testListWhenResponseIs2xx() throws Exception {
|
||||
|
||||
HttpResponse listResponse = HttpResponse.builder().statusCode(200)
|
||||
.payload(payloadFromResourceWithContentType("/describe_tags.xml", "text/xml")).build();
|
||||
|
||||
EC2Api apiWhenExist = requestSendsResponse(
|
||||
list, listResponse);
|
||||
|
||||
assertEquals(apiWhenExist.getTagApi().get().list().toString(), new DescribeTagsResponseTest().expected().toString());
|
||||
}
|
||||
|
||||
public void testListWhenResponseIs404() throws Exception {
|
||||
|
||||
HttpResponse listResponse = HttpResponse.builder().statusCode(404).build();
|
||||
|
||||
EC2Api apiWhenDontExist = requestSendsResponse(
|
||||
list, listResponse);
|
||||
|
||||
assertEquals(apiWhenDontExist.getTagApi().get().list().toImmutableSet(), ImmutableSet.of());
|
||||
}
|
||||
|
||||
HttpRequest filter =
|
||||
HttpRequest.builder()
|
||||
.method("POST")
|
||||
.endpoint("https://ec2.us-east-1.amazonaws.com/")
|
||||
.addHeader("Host", "ec2.us-east-1.amazonaws.com")
|
||||
.payload(payloadFromStringWithContentType(
|
||||
"Action=DescribeTags" +
|
||||
"&Filter.1.Name=resource-type" +
|
||||
"&Filter.1.Value.1=instance" +
|
||||
"&Filter.2.Name=key" +
|
||||
"&Filter.2.Value.1=stack" +
|
||||
"&Signature=doNEEZHEzXV%2FSD2eSZ6PpB1PADcsAF99lXGvsh3MbS4%3D" +
|
||||
"&SignatureMethod=HmacSHA256" +
|
||||
"&SignatureVersion=2" +
|
||||
"&Timestamp=2012-04-16T15%3A54%3A08.897Z" +
|
||||
"&Version=2010-08-31" +
|
||||
"&AWSAccessKeyId=identity",
|
||||
"application/x-www-form-urlencoded"))
|
||||
.build();
|
||||
|
||||
public void testFilterWhenResponseIs2xx() throws Exception {
|
||||
|
||||
HttpResponse filterResponse = HttpResponse.builder().statusCode(200)
|
||||
.payload(payloadFromResourceWithContentType("/describe_tags.xml", "text/xml")).build();
|
||||
|
||||
EC2Api apiWhenExist = requestSendsResponse(filter, filterResponse);
|
||||
|
||||
assertEquals(apiWhenExist.getTagApi().get().filter(ImmutableMultimap.<String, String> builder()
|
||||
.put("resource-type", "instance")
|
||||
.put("key", "stack")
|
||||
.build()).toString(),
|
||||
new DescribeTagsResponseTest().expected().toString());
|
||||
}
|
||||
|
||||
public void testFilterWhenResponseIs404() throws Exception {
|
||||
|
||||
HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build();
|
||||
|
||||
EC2Api apiWhenDontExist = requestSendsResponse(filter, filterResponse);
|
||||
|
||||
assertEquals(apiWhenDontExist.getTagApi().get().filter(ImmutableMultimap.<String, String> builder()
|
||||
.put("resource-type", "instance")
|
||||
.put("key", "stack")
|
||||
.build()).toImmutableSet(), ImmutableSet.of());
|
||||
}
|
||||
|
||||
HttpRequest delete = HttpRequest.builder()
|
||||
.method("POST")
|
||||
.endpoint("https://ec2.us-east-1.amazonaws.com/")
|
||||
.addHeader("Host", "ec2.us-east-1.amazonaws.com")
|
||||
.payload(
|
||||
payloadFromStringWithContentType(
|
||||
"Action=DeleteTags" +
|
||||
"&ResourceId.1=i-43532" +
|
||||
"&Signature=ytM605menR00re60wXMgBDpozrQCi0lVupf755%2FMpck%3D" +
|
||||
"&SignatureMethod=HmacSHA256" +
|
||||
"&SignatureVersion=2" +
|
||||
"&Tag.1.Key=tag" +
|
||||
"&Timestamp=2012-04-16T15%3A54%3A08.897Z" +
|
||||
"&Version=2010-08-31" +
|
||||
"&AWSAccessKeyId=identity",
|
||||
"application/x-www-form-urlencoded"))
|
||||
.build();
|
||||
|
||||
public void testDeleteWhenResponseIs2xx() throws Exception {
|
||||
|
||||
HttpResponse deleteResponse = HttpResponse.builder().statusCode(200).build();
|
||||
|
||||
EC2Api apiWhenExist = requestSendsResponse(delete, deleteResponse);
|
||||
|
||||
apiWhenExist.getTagApi().get().deleteFromResources(ImmutableSet.of("tag"), ImmutableSet.of("i-43532"));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = ResourceNotFoundException.class)
|
||||
public void testDeleteWhenResponseIs404() throws Exception {
|
||||
|
||||
HttpResponse deleteResponse = HttpResponse.builder().statusCode(404).build();
|
||||
|
||||
EC2Api apiWhenDontExist = requestSendsResponse(delete, deleteResponse);
|
||||
|
||||
apiWhenDontExist.getTagApi().get().deleteFromResources(ImmutableSet.of("tag"), ImmutableSet.of("i-43532"));
|
||||
}
|
||||
|
||||
|
||||
HttpRequest conditionallyDelete = HttpRequest.builder()
|
||||
.method("POST")
|
||||
.endpoint("https://ec2.us-east-1.amazonaws.com/")
|
||||
.addHeader("Host", "ec2.us-east-1.amazonaws.com")
|
||||
.payload(
|
||||
payloadFromStringWithContentType(
|
||||
"Action=DeleteTags" +
|
||||
"&ResourceId.1=i-43532" +
|
||||
"&Signature=vRvgPegVDDjIEKudZ5Tpck0GQrVts%2F%2F1jzk4W5RgI9k%3D" +
|
||||
"&SignatureMethod=HmacSHA256" +
|
||||
"&SignatureVersion=2" +
|
||||
"&Tag.1.Key=tag" +
|
||||
"&Tag.1.Value=value" +
|
||||
"&Timestamp=2012-04-16T15%3A54%3A08.897Z" +
|
||||
"&Version=2010-08-31" +
|
||||
"&AWSAccessKeyId=identity",
|
||||
"application/x-www-form-urlencoded"))
|
||||
.build();
|
||||
|
||||
public void testConditionallyDeleteWhenResponseIs2xx() throws Exception {
|
||||
|
||||
HttpResponse conditionallyDeleteResponse = HttpResponse.builder().statusCode(200).build();
|
||||
|
||||
EC2Api apiWhenExist = requestSendsResponse(conditionallyDelete, conditionallyDeleteResponse);
|
||||
|
||||
apiWhenExist.getTagApi().get().conditionallyDeleteFromResources(ImmutableMap.of("tag", "value"), ImmutableSet.of("i-43532"));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = ResourceNotFoundException.class)
|
||||
public void testConditionallyDeleteWhenResponseIs404() throws Exception {
|
||||
|
||||
HttpResponse conditionallyDeleteResponse = HttpResponse.builder().statusCode(404).build();
|
||||
|
||||
EC2Api apiWhenDontExist = requestSendsResponse(conditionallyDelete, conditionallyDeleteResponse);
|
||||
|
||||
apiWhenDontExist.getTagApi().get().conditionallyDeleteFromResources(ImmutableMap.of("tag", "value"), ImmutableSet.of("i-43532"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.ec2.features.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jclouds.ec2.domain.Tag;
|
||||
import org.jclouds.ec2.features.TagApi;
|
||||
import org.jclouds.ec2.internal.BaseEC2ApiLiveTest;
|
||||
import org.jclouds.ec2.util.TagFilterBuilder;
|
||||
import org.jclouds.predicates.RetryablePredicate;
|
||||
import org.testng.SkipException;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* tests ability to tag, filter, and delete tags from a resource.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "live")
|
||||
public abstract class BaseTagApiLiveTest extends BaseEC2ApiLiveTest {
|
||||
|
||||
private Resource resource;
|
||||
|
||||
private Tag tag;
|
||||
private Tag tag2;
|
||||
|
||||
public void testApplyTag() {
|
||||
|
||||
api().applyToResources(ImmutableSet.of("foo"), ImmutableSet.of(resource.id));
|
||||
|
||||
tag = api().filter(new TagFilterBuilder().resourceId(resource.id).key("foo").build()).get(0);
|
||||
|
||||
Logger.getAnonymousLogger().info("created tag: " + tag);
|
||||
|
||||
assertEquals(tag.getKey(), "foo");
|
||||
assertEquals(tag.getResourceId(), resource.id);
|
||||
assertEquals(tag.getResourceType(), resource.type);
|
||||
assertFalse(tag.getValue().isPresent());
|
||||
}
|
||||
|
||||
public void testApplyTagWithValue() {
|
||||
|
||||
api().applyToResources(ImmutableMap.of("type", "bar"), ImmutableSet.of(resource.id));
|
||||
|
||||
tag2 = api().filter(new TagFilterBuilder().resourceId(resource.id).key("type").build()).get(0);
|
||||
|
||||
Logger.getAnonymousLogger().info("created tag: " + tag2);
|
||||
|
||||
assertEquals(tag2.getKey(), "type");
|
||||
assertEquals(tag2.getResourceId(), resource.id);
|
||||
assertEquals(tag2.getResourceType(), resource.type);
|
||||
assertEquals(tag2.getValue().get(), "bar");
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = { "testApplyTag", "testApplyTagWithValue" })
|
||||
protected void testList() {
|
||||
assertTrue(new RetryablePredicate<Iterable<Tag>>(new Predicate<Iterable<Tag>>() {
|
||||
|
||||
@Override
|
||||
public boolean apply(Iterable<Tag> input) {
|
||||
return api().list().filter(new Predicate<Tag>() {
|
||||
@Override
|
||||
public boolean apply(Tag in) {
|
||||
return in.getResourceId().equals(resource.id);
|
||||
}
|
||||
}).toImmutableSet().equals(input);
|
||||
}
|
||||
|
||||
}, 600, 200, 200, TimeUnit.MILLISECONDS).apply(ImmutableSet.of(tag, tag2)));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "testList")
|
||||
public void testDeleteTags() {
|
||||
// shouldn't delete with the incorrect values
|
||||
api().conditionallyDeleteFromResources(ImmutableMap.of(tag.getKey(), "FOO", tag2.getKey(), "FOO"),
|
||||
ImmutableSet.of(tag.getResourceId(), tag2.getResourceId()));
|
||||
|
||||
assertEquals(tagsForResource().size(), 2);
|
||||
|
||||
api().deleteFromResources(ImmutableSet.of(tag.getKey(), tag2.getKey()),
|
||||
ImmutableSet.of(tag.getResourceId(), tag2.getResourceId()));
|
||||
|
||||
assertEquals(tagsForResource().size(), 0);
|
||||
|
||||
Logger.getAnonymousLogger().info("tags deleted: " + tag + ", " + tag2);
|
||||
}
|
||||
|
||||
private FluentIterable<Tag> tagsForResource() {
|
||||
return api().filter(new TagFilterBuilder().resourceId(resource.id).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
@BeforeClass(groups = "live")
|
||||
public void setupContext() {
|
||||
super.setupContext();
|
||||
resource = checkNotNull(createResourceForTagging(System.getProperty("user.name") + "-tag"), "resource");
|
||||
}
|
||||
|
||||
public static class Resource {
|
||||
public String id;
|
||||
public String type;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param id
|
||||
* ex. {sg-abc23d}
|
||||
* @param type
|
||||
* a type listed in {@link Tag.ResourceType}
|
||||
*/
|
||||
public Resource(String id, String type) {
|
||||
this.id = checkNotNull(id, "id");
|
||||
this.type = checkNotNull(type, "type of %s", id);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Resource createResourceForTagging(String prefix);
|
||||
|
||||
protected abstract void cleanupResource(Resource resource);
|
||||
|
||||
protected TagApi api() {
|
||||
Optional<? extends TagApi> tagOption = context.getApi().getTagApi();
|
||||
if (!tagOption.isPresent())
|
||||
throw new SkipException("tag api not present");
|
||||
return tagOption.get();
|
||||
}
|
||||
|
||||
@AfterClass(groups = "live")
|
||||
protected void tearDownContext() {
|
||||
if (resource != null)
|
||||
cleanupResource(resource);
|
||||
super.tearDownContext();
|
||||
}
|
||||
}
|
|
@ -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.ec2.parse;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.jclouds.ec2.domain.Tag;
|
||||
import org.jclouds.ec2.xml.DescribeTagsResponseHandler;
|
||||
import org.jclouds.http.functions.BaseHandlerTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class DescribeTagsResponseTest extends BaseHandlerTest {
|
||||
|
||||
public void test() {
|
||||
InputStream is = getClass().getResourceAsStream("/describe_tags.xml");
|
||||
|
||||
FluentIterable<Tag> expected = expected();
|
||||
|
||||
DescribeTagsResponseHandler handler = injector.getInstance(DescribeTagsResponseHandler.class);
|
||||
FluentIterable<Tag> result = factory.create(handler).parse(is);
|
||||
|
||||
assertEquals(result.toString(), expected.toString());
|
||||
|
||||
}
|
||||
public FluentIterable<Tag> expected() {
|
||||
return FluentIterable.from(ImmutableSet.<Tag>builder()
|
||||
.add(Tag.builder()
|
||||
.resourceId("i-5f4e3d2a")
|
||||
.resourceType("instance")
|
||||
.key("webserver")
|
||||
.build())
|
||||
.add(Tag.builder()
|
||||
.resourceId("i-5f4e3d2a")
|
||||
.resourceType("instance")
|
||||
.key("stack")
|
||||
.value("Production")
|
||||
.build())
|
||||
.add(Tag.builder()
|
||||
.resourceId("i-12345678")
|
||||
.resourceType("instance")
|
||||
.key("database_server")
|
||||
.build())
|
||||
.add(Tag.builder()
|
||||
.resourceId("i-12345678")
|
||||
.resourceType("instance")
|
||||
.key("stack")
|
||||
.value("Test")
|
||||
.build()).build());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<DescribeTagsResponse xmlns="http://ec2.amazonaws.com/doc/2012-10-01/">
|
||||
<requestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</requestId>
|
||||
<tagSet>
|
||||
<item>
|
||||
<resourceId>i-5f4e3d2a</resourceId>
|
||||
<resourceType>instance</resourceType>
|
||||
<key>webserver</key>
|
||||
<value/>
|
||||
</item>
|
||||
<item>
|
||||
<resourceId>i-5f4e3d2a</resourceId>
|
||||
<resourceType>instance</resourceType>
|
||||
<key>stack</key>
|
||||
<value>Production</value>
|
||||
</item>
|
||||
<item>
|
||||
<resourceId>i-12345678</resourceId>
|
||||
<resourceType>instance</resourceType>
|
||||
<key>database_server</key>
|
||||
<value/>
|
||||
</item>
|
||||
<item>
|
||||
<resourceId>i-12345678</resourceId>
|
||||
<resourceType>instance</resourceType>
|
||||
<key>stack</key>
|
||||
<value>Test</value>
|
||||
</item>
|
||||
</tagSet>
|
||||
</DescribeTagsResponse>
|
|
@ -46,6 +46,8 @@ import org.jclouds.ec2.EC2AsyncClient;
|
|||
import org.jclouds.ec2.EC2Client;
|
||||
import org.jclouds.ec2.config.EC2RestClientModule;
|
||||
import org.jclouds.ec2.domain.RunningInstance;
|
||||
import org.jclouds.ec2.features.TagApi;
|
||||
import org.jclouds.ec2.features.TagAsyncApi;
|
||||
import org.jclouds.ec2.features.WindowsApi;
|
||||
import org.jclouds.ec2.features.WindowsAsyncApi;
|
||||
import org.jclouds.ec2.options.RunInstancesOptions;
|
||||
|
@ -91,6 +93,7 @@ public class AWSEC2RestClientModule extends EC2RestClientModule<AWSEC2Client, AW
|
|||
.put(SpotInstanceClient.class, SpotInstanceAsyncClient.class)//
|
||||
.put(TagClient.class, TagAsyncClient.class)//
|
||||
.put(WindowsApi.class, WindowsAsyncApi.class)//
|
||||
.put(TagApi.class, TagAsyncApi.class)//
|
||||
.build();
|
||||
|
||||
public AWSEC2RestClientModule() {
|
||||
|
|
|
@ -26,9 +26,14 @@ import com.google.common.base.Objects;
|
|||
import com.google.common.collect.ComparisonChain;
|
||||
|
||||
/**
|
||||
* <h3>Important</h3>
|
||||
* This will be removed in jclouds version 1.6
|
||||
*
|
||||
* @see <a href= "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-ItemType-TagSetItemType.html" />
|
||||
* @see org.jclouds.ec2.domain.Tag
|
||||
* @author grkvlt@apache.org
|
||||
*/
|
||||
@Deprecated
|
||||
public class Tag implements Comparable<Tag> {
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
|
|
|
@ -26,13 +26,13 @@ import java.util.Set;
|
|||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
|
||||
import org.jclouds.aws.ec2.binders.BindResourceIdsToIndexedFormParams;
|
||||
import org.jclouds.aws.ec2.binders.BindTagFiltersToIndexedFormParams;
|
||||
import org.jclouds.aws.ec2.binders.BindTagsToIndexedFormParams;
|
||||
import org.jclouds.aws.ec2.domain.Tag;
|
||||
import org.jclouds.aws.ec2.util.TagFilters.FilterName;
|
||||
import org.jclouds.aws.ec2.xml.DescribeTagsResponseHandler;
|
||||
import org.jclouds.aws.filters.FormSigner;
|
||||
import org.jclouds.ec2.binders.BindResourceIdsToIndexedFormParams;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
|
@ -50,8 +50,12 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||
/**
|
||||
* Provides access to EC2 Tags via their REST API.
|
||||
*
|
||||
* <h3>Important</h3>
|
||||
* This will be removed in jclouds version 1.6
|
||||
*
|
||||
* @author grkvlt@apache.org
|
||||
*/
|
||||
@Deprecated
|
||||
@RequestFilters(FormSigner.class)
|
||||
@VirtualHost
|
||||
public interface TagAsyncClient {
|
||||
|
|
|
@ -28,11 +28,17 @@ import org.jclouds.concurrent.Timeout;
|
|||
import org.jclouds.javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
*
|
||||
* Provides Tag services for EC2. For more information, refer to the Amazon EC2
|
||||
* Developer Guide.
|
||||
*
|
||||
* <h3>Important</h3>
|
||||
* This will be removed in jclouds version 1.6
|
||||
*
|
||||
* @author grkvlt@apache.org
|
||||
* @see TagApi
|
||||
*/
|
||||
@Deprecated
|
||||
@Timeout(duration = 45, timeUnit = TimeUnit.SECONDS)
|
||||
public interface TagClient {
|
||||
/**
|
||||
|
|
|
@ -22,6 +22,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.ec2.features.TagApi;
|
||||
|
||||
import com.google.common.base.CaseFormat;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
@ -30,8 +32,14 @@ import com.google.common.collect.Maps;
|
|||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* <h3>Important</h3>
|
||||
* This will be removed in jclouds version 1.6
|
||||
*
|
||||
* @author grkvlt@apache.org
|
||||
*
|
||||
* @see TagApi
|
||||
*/
|
||||
@Deprecated
|
||||
public class TagFilters {
|
||||
public static enum FilterName {
|
||||
KEY, RESOURCE_ID, RESOURCE_TYPE, VALUE;
|
||||
|
@ -54,6 +62,12 @@ public class TagFilters {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <h3>Important</h3> This will be removed in jclouds version 1.6
|
||||
*
|
||||
* @see TagApi
|
||||
*/
|
||||
@Deprecated
|
||||
public static enum ResourceType {
|
||||
CUSTOMER_GATEWAY, DHCP_OPTIONS, IMAGE, INSTANCE, INTERNET_GATEWAY, NETWORK_ACL, RESERVED_INSTANCES, ROUTE_TABLE, SECURITY_GROUP, SNAPSHOT, SPOT_INSTANCES_REQUEST, SUBNET, VOLUME, VPC, VPN_CONNECTION, VPN_GATEWAY;
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* 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.aws.ec2.features;
|
||||
|
||||
import static org.jclouds.ec2.domain.Tag.ResourceType.SECURITY_GROUP;
|
||||
|
||||
import org.jclouds.aws.ec2.AWSEC2Client;
|
||||
import org.jclouds.aws.ec2.services.AWSSecurityGroupClient;
|
||||
import org.jclouds.ec2.features.internal.BaseTagApiLiveTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "live", singleThreaded = true)
|
||||
public class TagSecurityGroupLiveTest extends BaseTagApiLiveTest {
|
||||
public TagSecurityGroupLiveTest() {
|
||||
provider = "aws-ec2";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Resource createResourceForTagging(String prefix) {
|
||||
try {
|
||||
return new Resource(securityGroupApi().createSecurityGroupInRegionAndReturnId(null, prefix, prefix),
|
||||
SECURITY_GROUP);
|
||||
} catch (IllegalStateException e) {
|
||||
return new Resource(Iterables.get(securityGroupApi().describeSecurityGroupsInRegion(null, prefix), 0).getId(),
|
||||
SECURITY_GROUP);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void cleanupResource(Resource resource) {
|
||||
securityGroupApi().deleteSecurityGroupInRegionById(null, resource.id);
|
||||
}
|
||||
|
||||
private AWSSecurityGroupClient securityGroupApi() {
|
||||
return AWSEC2Client.class.cast(context.getApi()).getSecurityGroupServices();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue