diff --git a/labs/sqs/src/main/java/org/jclouds/sqs/SQSApi.java b/labs/sqs/src/main/java/org/jclouds/sqs/SQSApi.java index bc39a283d5..57fb80a70e 100644 --- a/labs/sqs/src/main/java/org/jclouds/sqs/SQSApi.java +++ b/labs/sqs/src/main/java/org/jclouds/sqs/SQSApi.java @@ -25,8 +25,10 @@ import java.util.concurrent.TimeUnit; import org.jclouds.concurrent.Timeout; import org.jclouds.javax.annotation.Nullable; +import org.jclouds.sqs.domain.Action; import org.jclouds.sqs.domain.Message; import org.jclouds.sqs.domain.MessageIdAndMD5; +import org.jclouds.sqs.domain.QueueAttributes; import org.jclouds.sqs.options.CreateQueueOptions; import org.jclouds.sqs.options.ListQueuesOptions; import org.jclouds.sqs.options.ReceiveMessageOptions; @@ -208,6 +210,57 @@ public interface SQSApi { */ void changeMessageVisibility(URI queue, String receiptHandle, int visibilityTimeout); + /** + * The AddPermission action adds a permission to a queue for a specific + * principal. This allows for sharing access to the queue. + * + * When you create a queue, you have full control access rights for the + * queue. Only you (as owner of the queue) can grant or deny permissions to + * the queue. For more information about these permissions, see Shared Queues + * in the Amazon SQS Developer Guide. + * + * Note + * + * AddPermission writes an SQS-generated policy. If you want to write your + * own policy, use SetQueueAttributes to upload your policy. + * + * @param queue + * queue to change permissions on + * @param label + * + * The unique identification of the permission you're setting. + * example: AliceSendMessage + * + * Constraints: Maximum 80 characters; alphanumeric characters, + * hyphens (-), and underscores (_) are allowed. + * @param permission + * The action you want to allow for the specified principal. + * @param accountId + * The AWS account number of the principal who will be given + * permission. The principal must have an AWS account, but does not + * need to be signed up for Amazon SQS. For information about + * locating the AWS account identification, see Your AWS + * Identifiers in the Amazon SQS Developer Guide. + * + * Constraints: Valid 12-digit AWS account number, without hyphens + * + */ + void addPermissionToAccount(URI queue, String label, Action permission, String accountId); + + /** + * The RemovePermission action revokes any permissions in the queue policy + * that matches the Label parameter. Only the owner of the queue can remove + * permissions. + * + * @param queue + * queue to change permissions on + * + * @param label + * The identification of the permission you want to remove. This is + * the label you added in AddPermission. example: AliceSendMessage + */ + void removePermission(URI queue, String label); + /** * The SendMessage action delivers a message to the specified queue. The * maximum allowed message size is 64 KB. @@ -295,7 +348,7 @@ public interface SQSApi { * @param queue * queue to get the attributes of */ - Map getQueueAttributes(URI queue); + QueueAttributes getQueueAttributes(URI queue); /** * The SetQueueAttributes action sets one attribute of a queue per request. @@ -362,6 +415,14 @@ public interface SQSApi { */ Map getQueueAttributes(URI queue, Iterable attributeNames); + /** + * returns an attribute of a queue. + * + * @param queue + * queue to get the attributes of + */ + String getQueueAttribute(URI queue, String attributeName); + /** * same as {@link #receiveMessages(URI, int)} except you can provide options * like VisibilityTimeout parameter in your request, which will be applied to diff --git a/labs/sqs/src/main/java/org/jclouds/sqs/SQSAsyncApi.java b/labs/sqs/src/main/java/org/jclouds/sqs/SQSAsyncApi.java index e3fb939286..238dee8e3a 100644 --- a/labs/sqs/src/main/java/org/jclouds/sqs/SQSAsyncApi.java +++ b/labs/sqs/src/main/java/org/jclouds/sqs/SQSAsyncApi.java @@ -35,14 +35,20 @@ import org.jclouds.javax.annotation.Nullable; import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull; import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.EndpointParam; +import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.FormParams; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; +import org.jclouds.rest.annotations.Transform; import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import org.jclouds.sqs.binders.BindAttributeNamesToIndexedFormParams; +import org.jclouds.sqs.domain.Action; import org.jclouds.sqs.domain.Message; import org.jclouds.sqs.domain.MessageIdAndMD5; +import org.jclouds.sqs.domain.QueueAttributes; +import org.jclouds.sqs.functions.MapToQueueAttributes; import org.jclouds.sqs.options.CreateQueueOptions; import org.jclouds.sqs.options.ListQueuesOptions; import org.jclouds.sqs.options.ReceiveMessageOptions; @@ -53,6 +59,7 @@ import org.jclouds.sqs.xml.ReceiveMessageResponseHandler; import org.jclouds.sqs.xml.RegexListQueuesResponseHandler; import org.jclouds.sqs.xml.RegexMessageIdAndMD5Handler; import org.jclouds.sqs.xml.RegexQueueHandler; +import org.jclouds.sqs.xml.ValueHandler; import com.google.common.util.concurrent.ListenableFuture; @@ -142,7 +149,8 @@ public interface SQSAsyncApi { @Path("/") @FormParams(keys = ACTION, values = "SendMessage") @ResponseParser(RegexMessageIdAndMD5Handler.class) - ListenableFuture sendMessage(@EndpointParam URI queue, @FormParam("MessageBody") String message); + ListenableFuture sendMessage(@EndpointParam URI queue, + @FormParam("MessageBody") String message); /** * @see SQSApi#sendMessage @@ -151,8 +159,8 @@ public interface SQSAsyncApi { @Path("/") @FormParams(keys = ACTION, values = "SendMessage") @ResponseParser(RegexMessageIdAndMD5Handler.class) - ListenableFuture sendMessage(@EndpointParam URI queue, @FormParam("MessageBody") String message, - SendMessageOptions options); + ListenableFuture sendMessage(@EndpointParam URI queue, + @FormParam("MessageBody") String message, SendMessageOptions options); /** * @see SQSApi#receiveMessage @@ -170,7 +178,7 @@ public interface SQSAsyncApi { @Path("/") @FormParams(keys = ACTION, values = "ReceiveMessage") @XMLResponseParser(MessageHandler.class) - ListenableFuture receiveMessage(@EndpointParam URI queue, ReceiveMessageOptions options); + ListenableFuture receiveMessage(@EndpointParam URI queue, ReceiveMessageOptions options); /** * @see SQSApi#getQueueAttributes(URI) @@ -178,8 +186,10 @@ public interface SQSAsyncApi { @POST @Path("/") @FormParams(keys = { ACTION, "AttributeName.1" }, values = { "GetQueueAttributes", "All" }) + @Transform(MapToQueueAttributes.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) @XMLResponseParser(AttributesHandler.class) - ListenableFuture> getQueueAttributes(@EndpointParam URI queue); + ListenableFuture getQueueAttributes(@EndpointParam URI queue); /** * @see SQSApi#getQueueAttributes(URI, Iterable) @@ -191,6 +201,16 @@ public interface SQSAsyncApi { ListenableFuture> getQueueAttributes(@EndpointParam URI queue, @BinderParam(BindAttributeNamesToIndexedFormParams.class) Iterable attributeNames); + /** + * @see SQSApi#getQueueAttribute + */ + @POST + @Path("/") + @FormParams(keys = ACTION, values = "GetQueueAttributes") + @XMLResponseParser(ValueHandler.class) + ListenableFuture getQueueAttribute(@EndpointParam URI queue, + @FormParam("AttributeName.1") String attributeName); + /** * @see SQSApi#setQueueAttribute */ @@ -207,7 +227,8 @@ public interface SQSAsyncApi { @Path("/") @FormParams(keys = ACTION, values = "ReceiveMessage") @XMLResponseParser(ReceiveMessageResponseHandler.class) - ListenableFuture> receiveMessages(@EndpointParam URI queue, @FormParam("MaxNumberOfMessages") int max); + ListenableFuture> receiveMessages(@EndpointParam URI queue, + @FormParam("MaxNumberOfMessages") int max); /** * @see SQSApi#receiveMessages @@ -216,7 +237,24 @@ public interface SQSAsyncApi { @Path("/") @FormParams(keys = ACTION, values = "ReceiveMessage") @XMLResponseParser(ReceiveMessageResponseHandler.class) - ListenableFuture> receiveMessages(@EndpointParam URI queue, @FormParam("MaxNumberOfMessages") int max, - ReceiveMessageOptions options); + ListenableFuture> receiveMessages(@EndpointParam URI queue, + @FormParam("MaxNumberOfMessages") int max, ReceiveMessageOptions options); + + /** + * @see SQSApi#addPermissionToAccount + */ + @POST + @Path("/") + @FormParams(keys = ACTION, values = "AddPermission") + ListenableFuture addPermissionToAccount(@EndpointParam URI queue, @FormParam("Label") String label, + @FormParam("ActionName.1") Action permission, @FormParam("AWSAccountId.1") String accountId); + + /** + * @see SQSApi#removePermission + */ + @POST + @Path("/") + @FormParams(keys = ACTION, values = "RemovePermission") + ListenableFuture removePermission(@EndpointParam URI queue, @FormParam("Label") String label); } diff --git a/labs/sqs/src/main/java/org/jclouds/sqs/domain/Action.java b/labs/sqs/src/main/java/org/jclouds/sqs/domain/Action.java new file mode 100644 index 0000000000..7a1f886e63 --- /dev/null +++ b/labs/sqs/src/main/java/org/jclouds/sqs/domain/Action.java @@ -0,0 +1,80 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.sqs.domain; + +import com.google.common.base.CaseFormat; + +/** + * + * The action you want to allow for the specified principal. + * + * @see + * @author Adrian Cole + */ +public enum Action { + /** + * This permission type grants the following actions to a principal on a + * shared queue: receive messages, send messages, delete messages, change a + * message's visibility, get a queue's attributes. + */ + ALL, + /** + * This grants permission to receive messages in the queue. + */ + RECEIVE_MESSAGE, + /** + * This grants permission to send messages to the queue. SendMessageBatch + * inherits permissions associated with SendMessage. + */ + SEND_MESSAGE, + /** + * This grants permission to delete messages from the queue. + * DeleteMessageBatch inherits permissions associated with DeleteMessage. + */ + DELETE_MESSAGE, + /** + * This grants permission to extend or terminate the read lock timeout of a + * specified message. ChangeMessageVisibilityBatch inherits permissions + * associated with ChangeMessageVisibility. For more information about + * visibility timeout, see Visibility Timeout. For more information about + * this permission type, see the ChangeMessageVisibility operation. + */ + CHANGE_MESSAGE_VISIBILITY, + /** + * This grants permission to receive all of the queue attributes except the + * policy, which can only be accessed by the queue's owner. For more + * information, see the GetQueueAttributes operation. + */ + GET_QUEUE_ATTRIBUTES, + /** + * This grants permission to get the url of a queue by name. + */ + GET_QUEUE_URL; + + public String value() { + return this == ALL ? "*" : CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name()); + } + + @Override + public String toString() { + return value(); + } +} diff --git a/labs/sqs/src/main/java/org/jclouds/sqs/domain/Attribute.java b/labs/sqs/src/main/java/org/jclouds/sqs/domain/Attribute.java new file mode 100644 index 0000000000..048c6922d1 --- /dev/null +++ b/labs/sqs/src/main/java/org/jclouds/sqs/domain/Attribute.java @@ -0,0 +1,88 @@ +/** + * 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.sqs.domain; + +/** + * + * The action you want to allow for the specified principal. + * + * @see + * @author Adrian Cole + */ +public interface Attribute { + + /** + * approximate number of visible messages in a queue. + */ + public static final String APPROXIMATE_NUMBER_OF_MESSAGES = "ApproximateNumberOfMessages"; + /** + * approximate number of messages that are not timed-out and not deleted. + */ + public static final String APPROXIMATE_NUMBER_OF_MESSAGES_NOT_VISIBLE = "ApproximateNumberOfMessagesNotVisible"; + + /** + * approximate number of messages that are not visible because you have set a + * positive delay value on the queue + */ + public static final String APPROXIMATE_NUMBER_OF_MESSAGES_DELAYED = "ApproximateNumberOfMessagesDelayed"; + + /** + * visibility timeout for the queue. + */ + public static final String VISIBILITY_TIMEOUT = "VisibilityTimeout"; + + /** + * time when the queue was created (epoch time in seconds). + */ + public static final String CREATED_TIMESTAMP = "CreatedTimestamp"; + + /** + * time when the queue was last changed (epoch time in seconds). + */ + public static final String LAST_MODIFIED_TIMESTAMP = "LastModifiedTimestamp"; + + /** + * queue's policy. + */ + public static final String POLICY = "Policy"; + + /** + * limit of how many bytes a message can contain before Amazon SQS rejects + * it. + */ + public static final String MAXIMUM_MESSAGE_SIZE = "MaximumMessageSize"; + + /** + * number of seconds Amazon SQS retains a message. + */ + public static final String MESSAGE_RETENTION_PERIOD = "MessageRetentionPeriod"; + + /** + * queue's Amazon resource name (ARN). + */ + public static final String QUEUE_ARN = "QueueArn"; + + /** + * The time in seconds that the delivery of all messages in the queue will be + * delayed. + */ + public static final String DELAY_SECONDS = "DelaySeconds"; +} diff --git a/labs/sqs/src/main/java/org/jclouds/sqs/domain/QueueAttributes.java b/labs/sqs/src/main/java/org/jclouds/sqs/domain/QueueAttributes.java new file mode 100644 index 0000000000..d2e1e2c4bc --- /dev/null +++ b/labs/sqs/src/main/java/org/jclouds/sqs/domain/QueueAttributes.java @@ -0,0 +1,314 @@ +/** + * 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.sqs.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Date; + +import com.google.common.base.Objects; +import com.google.common.base.Optional; + +/** + * + * @author Adrian Cole + * + * @see + */ +public class QueueAttributes { + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromQueueAttributes(this); + } + + public static abstract class Builder> { + protected abstract T self(); + + protected String queueArn; + protected long approximateNumberOfMessages; + protected long approximateNumberOfMessagesNotVisible; + protected long approximateNumberOfMessagesDelayed; + protected int visibilityTimeout; + protected Date createdTimestamp; + protected Date lastModifiedTimestamp; + protected Optional rawPolicy = Optional.absent(); + protected int maximumMessageSize; + protected int messageRetentionPeriod; + protected int delaySeconds; + + /** + * @see QueueAttributes#getQueueArn() + */ + public T queueArn(String queueArn) { + this.queueArn = queueArn; + return self(); + } + + /** + * @see QueueAttributes#getApproximateNumberOfMessages() + */ + public T approximateNumberOfMessages(long approximateNumberOfMessages) { + this.approximateNumberOfMessages = approximateNumberOfMessages; + return self(); + } + + /** + * @see QueueAttributes#getApproximateNumberOfMessagesNotVisible() + */ + public T approximateNumberOfMessagesNotVisible(long approximateNumberOfMessagesNotVisible) { + this.approximateNumberOfMessagesNotVisible = approximateNumberOfMessagesNotVisible; + return self(); + } + + /** + * @see QueueAttributes#getApproximateNumberOfMessagesDelayed() + */ + public T approximateNumberOfMessagesDelayed(long approximateNumberOfMessagesDelayed) { + this.approximateNumberOfMessagesDelayed = approximateNumberOfMessagesDelayed; + return self(); + } + + /** + * @see QueueAttributes#getVisibilityTimeout() + */ + public T visibilityTimeout(int visibilityTimeout) { + this.visibilityTimeout = visibilityTimeout; + return self(); + } + + /** + * @see QueueAttributes#getCreatedTimestamp() + */ + public T createdTimestamp(Date createdTimestamp) { + this.createdTimestamp = createdTimestamp; + return self(); + } + + /** + * @see QueueAttributes#getLastModifiedTimestamp() + */ + public T lastModifiedTimestamp(Date lastModifiedTimestamp) { + this.lastModifiedTimestamp = lastModifiedTimestamp; + return self(); + } + + /** + * @see QueueAttributes#getRawPolicy() + */ + public T rawPolicy(String rawPolicy) { + this.rawPolicy = Optional.fromNullable(rawPolicy); + return self(); + } + + /** + * @see QueueAttributes#getMaximumMessageSize() + */ + public T maximumMessageSize(int maximumMessageSize) { + this.maximumMessageSize = maximumMessageSize; + return self(); + } + + /** + * @see QueueAttributes#getMessageRetentionPeriod() + */ + public T messageRetentionPeriod(int messageRetentionPeriod) { + this.messageRetentionPeriod = messageRetentionPeriod; + return self(); + } + + /** + * @see QueueAttributes#getDelaySeconds() + */ + public T delaySeconds(int delaySeconds) { + this.delaySeconds = delaySeconds; + return self(); + } + + public QueueAttributes build() { + return new QueueAttributes(queueArn, approximateNumberOfMessages, approximateNumberOfMessagesNotVisible, + approximateNumberOfMessagesDelayed, visibilityTimeout, createdTimestamp, lastModifiedTimestamp, + rawPolicy, maximumMessageSize, messageRetentionPeriod, delaySeconds); + } + + public T fromQueueAttributes(QueueAttributes in) { + return queueArn(in.queueArn).approximateNumberOfMessages(in.approximateNumberOfMessages) + .approximateNumberOfMessagesNotVisible(in.approximateNumberOfMessagesNotVisible) + .approximateNumberOfMessagesDelayed(in.approximateNumberOfMessagesDelayed) + .visibilityTimeout(in.visibilityTimeout).createdTimestamp(in.createdTimestamp) + .lastModifiedTimestamp(in.lastModifiedTimestamp).rawPolicy(in.rawPolicy.orNull()) + .maximumMessageSize(in.maximumMessageSize).messageRetentionPeriod(in.messageRetentionPeriod) + .delaySeconds(in.delaySeconds); + + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + protected final long approximateNumberOfMessages; + protected final long approximateNumberOfMessagesNotVisible; + protected final int visibilityTimeout; + protected final Date createdTimestamp; + protected final Date lastModifiedTimestamp; + protected final long approximateNumberOfMessagesDelayed; + protected final Optional rawPolicy; + protected final int maximumMessageSize; + protected final int messageRetentionPeriod; + protected final String queueArn; + protected int delaySeconds; + + protected QueueAttributes(String queueArn, long approximateNumberOfMessages, + long approximateNumberOfMessagesNotVisible, long approximateNumberOfMessagesDelayed, int visibilityTimeout, + Date createdTimestamp, Date lastModifiedTimestamp, Optional rawPolicy, int maximumMessageSize, + int messageRetentionPeriod, int delaySeconds) { + this.queueArn = checkNotNull(queueArn, "queueArn"); + this.approximateNumberOfMessages = approximateNumberOfMessages; + this.approximateNumberOfMessagesNotVisible = approximateNumberOfMessagesNotVisible; + this.approximateNumberOfMessagesDelayed = approximateNumberOfMessagesDelayed; + this.visibilityTimeout = visibilityTimeout; + this.createdTimestamp = checkNotNull(createdTimestamp, "createdTimestamp of %s", queueArn); + this.lastModifiedTimestamp = checkNotNull(lastModifiedTimestamp, "lastModifiedTimestamp of %s", queueArn); + this.rawPolicy = checkNotNull(rawPolicy, "rawPolicy of %s", queueArn); + this.maximumMessageSize = maximumMessageSize; + this.messageRetentionPeriod = messageRetentionPeriod; + this.delaySeconds = delaySeconds; + } + + /** + * @see Attribute#QUEUE_ARN + */ + public String getQueueArn() { + return queueArn; + } + + /** + * @see Attribute#APPROXIMATE_NUMBER_OF_MESSAGES + */ + public long getApproximateNumberOfMessages() { + return approximateNumberOfMessages; + } + + /** + * @see Attribute#APPROXIMATE_NUMBER_OF_MESSAGES_NOT_VISIBLE + */ + public long getApproximateNumberOfMessagesNotVisible() { + return approximateNumberOfMessagesNotVisible; + } + + /** + * @see Attribute#APPROXIMATE_NUMBER_OF_MESSAGES_DELAYED + */ + public long getApproximateNumberOfMessagesDelayed() { + return approximateNumberOfMessagesDelayed; + } + + /** + * @see Attribute#VISIBILITY_TIMEOUT + */ + public int getVisibilityTimeout() { + return visibilityTimeout; + } + + /** + * @see Attribute#CREATED_TIMESTAMP + */ + public Date getCreatedTimestamp() { + return createdTimestamp; + } + + /** + * @see Attribute#LAST_MODIFIED_TIMESTAMP + */ + public Date getLastModifiedTimestamp() { + return lastModifiedTimestamp; + } + + /** + * Note this is in raw Json + * + * @see Attribute#POLICY + */ + public Optional getRawPolicy() { + return rawPolicy; + } + + /** + * @see Attribute#MAXIMUM_MESSAGE_SIZE + */ + public int getMaximumMessageSize() { + return maximumMessageSize; + } + + /** + * @see Attribute#MESSAGE_RETENTION_PERIOD + */ + public int getMessageRetentionPeriod() { + return messageRetentionPeriod; + } + + /** + * @see Attribute#DELAY_SECONDS + */ + public int getDelaySeconds() { + return delaySeconds; + } + + @Override + public int hashCode() { + return Objects.hashCode(queueArn); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + QueueAttributes other = (QueueAttributes) obj; + return Objects.equal(this.queueArn, other.queueArn); + + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return Objects.toStringHelper(this).omitNullValues().add("queueArn", queueArn) + .add("approximateNumberOfMessages", approximateNumberOfMessages) + .add("approximateNumberOfMessagesNotVisible", approximateNumberOfMessagesNotVisible) + .add("approximateNumberOfMessagesDelayed", approximateNumberOfMessagesDelayed) + .add("visibilityTimeout", visibilityTimeout).add("createdTimestamp", createdTimestamp) + .add("lastModifiedTimestamp", lastModifiedTimestamp).add("rawPolicy", rawPolicy.orNull()) + .add("maximumMessageSize", maximumMessageSize).add("messageRetentionPeriod", messageRetentionPeriod) + .add("delaySeconds", delaySeconds).toString(); + } + +} diff --git a/labs/sqs/src/main/java/org/jclouds/sqs/functions/MapToQueueAttributes.java b/labs/sqs/src/main/java/org/jclouds/sqs/functions/MapToQueueAttributes.java new file mode 100644 index 0000000000..1728bebd34 --- /dev/null +++ b/labs/sqs/src/main/java/org/jclouds/sqs/functions/MapToQueueAttributes.java @@ -0,0 +1,57 @@ +/** + * 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.sqs.functions; + +import java.util.Date; +import java.util.Map; + +import org.jclouds.sqs.domain.Attribute; +import org.jclouds.sqs.domain.QueueAttributes; +import org.jclouds.sqs.domain.QueueAttributes.Builder; + +import com.google.common.base.Function; + +/** + * Converts a Map to a typed QueueAttributes object + * + * @author Adrian Cole + */ +public class MapToQueueAttributes implements Function, QueueAttributes> { + + @Override + public QueueAttributes apply(Map input) { + if (input == null) + return null; + Builder builder = QueueAttributes.builder(); + builder.queueArn(input.get(Attribute.QUEUE_ARN)); + builder.approximateNumberOfMessages(Long.parseLong(input.get(Attribute.APPROXIMATE_NUMBER_OF_MESSAGES))); + builder.approximateNumberOfMessagesNotVisible(Long.parseLong(input + .get(Attribute.APPROXIMATE_NUMBER_OF_MESSAGES_NOT_VISIBLE))); + builder.approximateNumberOfMessagesDelayed(Long.parseLong(input + .get(Attribute.APPROXIMATE_NUMBER_OF_MESSAGES_DELAYED))); + builder.visibilityTimeout(Integer.parseInt(input.get(Attribute.VISIBILITY_TIMEOUT))); + builder.createdTimestamp(new Date(Long.parseLong(input.get(Attribute.CREATED_TIMESTAMP)))); + builder.lastModifiedTimestamp(new Date(Long.parseLong(input.get(Attribute.LAST_MODIFIED_TIMESTAMP)))); + builder.rawPolicy(input.get(Attribute.POLICY)); + builder.maximumMessageSize(Integer.parseInt(input.get(Attribute.MAXIMUM_MESSAGE_SIZE))); + builder.messageRetentionPeriod(Integer.parseInt(input.get(Attribute.MESSAGE_RETENTION_PERIOD))); + builder.delaySeconds(Integer.parseInt(input.get(Attribute.DELAY_SECONDS))); + return builder.build(); + } +} diff --git a/labs/sqs/src/main/java/org/jclouds/sqs/xml/RegexMessageIdAndMD5Handler.java b/labs/sqs/src/main/java/org/jclouds/sqs/xml/RegexMessageIdAndMD5Handler.java index 9baf8a5531..c7cf3c0ca2 100644 --- a/labs/sqs/src/main/java/org/jclouds/sqs/xml/RegexMessageIdAndMD5Handler.java +++ b/labs/sqs/src/main/java/org/jclouds/sqs/xml/RegexMessageIdAndMD5Handler.java @@ -40,7 +40,7 @@ import com.google.inject.Singleton; */ @Singleton public class RegexMessageIdAndMD5Handler implements Function { - Pattern pattern = Pattern.compile("([\\S&&[^<]]+)\\s*([\\S&&[^<]]+)", Pattern.DOTALL); + private static final Pattern pattern = Pattern.compile("([\\S&&[^<]]+)\\s*([\\S&&[^<]]+)", Pattern.DOTALL); private final ReturnStringIf2xx returnStringIf200; @Inject diff --git a/labs/sqs/src/main/java/org/jclouds/sqs/xml/ValueHandler.java b/labs/sqs/src/main/java/org/jclouds/sqs/xml/ValueHandler.java new file mode 100644 index 0000000000..b30c622f27 --- /dev/null +++ b/labs/sqs/src/main/java/org/jclouds/sqs/xml/ValueHandler.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.sqs.xml; + +import static org.jclouds.util.SaxUtils.currentOrNull; + +import org.jclouds.http.functions.ParseSax; + +/** + * @see + * + * @author Adrian Cole + */ +public class ValueHandler extends ParseSax.HandlerForGeneratedRequestWithResult { + + private StringBuilder currentText = new StringBuilder(); + private String value; + + @Override + public String getResult() { + return value; + } + + // this could be done with regex, if we had an unescaper + @Override + public void endElement(String uri, String name, String qName) { + if (qName.equals("Value")) { + value = currentOrNull(currentText); + } + currentText = new StringBuilder(); + } + + @Override + public void characters(char ch[], int start, int length) { + currentText.append(ch, start, length); + } + +} diff --git a/labs/sqs/src/test/java/org/jclouds/sqs/SQSApiExpectTest.java b/labs/sqs/src/test/java/org/jclouds/sqs/SQSApiExpectTest.java index 96f01a442c..ec4303ff7b 100644 --- a/labs/sqs/src/test/java/org/jclouds/sqs/SQSApiExpectTest.java +++ b/labs/sqs/src/test/java/org/jclouds/sqs/SQSApiExpectTest.java @@ -24,6 +24,8 @@ import java.net.URI; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; +import org.jclouds.sqs.domain.Action; +import org.jclouds.sqs.functions.MapToQueueAttributesTest; import org.jclouds.sqs.internal.BaseSQSApiExpectTest; import org.jclouds.sqs.parse.CreateQueueResponseTest; import org.jclouds.sqs.parse.GetQueueAttributesResponseTest; @@ -195,6 +197,33 @@ public class SQSApiExpectTest extends BaseSQSApiExpectTest { "eXJYhj5rDr9cAe", 10); } + public HttpRequest getQueueAttribute = HttpRequest.builder() + .method("POST") + .endpoint("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/") + .addHeader("Host", "sqs.us-east-1.amazonaws.com") + .addFormParam("Action", "GetQueueAttributes") + .addFormParam("AttributeName.1", "VisibilityTimeout") + .addFormParam("Signature", "AfydayBBaIk4UGikHHY1CFNmOOAcTnogpFWydZyNass%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") + .addFormParam("Version", "2011-10-01") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testGetQueueAttributeWhenResponseIs2xx() throws Exception { + + HttpResponse getQueueAttributeResponse = HttpResponse.builder() + .statusCode(200) + .payload( + payloadFromStringWithContentType( + "VisibilityTimeout30", + "text/xml")).build(); + + SQSApi apiWhenExist = requestSendsResponse(getQueueAttribute, getQueueAttributeResponse); + + assertEquals(apiWhenExist.getQueueAttribute(URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/"), "VisibilityTimeout"), "30"); + } + public HttpRequest getQueueAttributes = HttpRequest.builder() .method("POST") .endpoint("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/") @@ -215,7 +244,7 @@ public class SQSApiExpectTest extends BaseSQSApiExpectTest { SQSApi apiWhenExist = requestSendsResponse(getQueueAttributes, getQueueAttributesResponse); - assertEquals(apiWhenExist.getQueueAttributes(URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/")).toString(), new GetQueueAttributesResponseTest().expected().toString()); + assertEquals(apiWhenExist.getQueueAttributes(URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/")).toString(), new MapToQueueAttributesTest().expected().toString()); } public HttpRequest getQueueAttributesSubset = HttpRequest.builder() @@ -274,5 +303,60 @@ public class SQSApiExpectTest extends BaseSQSApiExpectTest { apiWhenExist.setQueueAttribute(URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/"), "MaximumMessageSize", "1"); } + + public HttpRequest addPermission = HttpRequest.builder() + .method("POST") + .endpoint("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/") + .addHeader("Host", "sqs.us-east-1.amazonaws.com") + .addFormParam("Action", "AddPermission") + .addFormParam("ActionName.1", "ReceiveMessage") + .addFormParam("AWSAccountId.1", "125074342641") + .addFormParam("Label", "testLabel") + .addFormParam("Signature", "J9sV4q1rJ7dWYJDQp9JxsfEKNXQhpQBYIwBYi1IeXV0%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") + .addFormParam("Version", "2011-10-01") + .addFormParam("AWSAccessKeyId", "identity").build(); + public void testAddPermissionWhenResponseIs2xx() throws Exception { + + HttpResponse addPermissionResponse = HttpResponse.builder() + .statusCode(200) + .payload( + payloadFromStringWithContentType( + "b5293cb5-d306-4a17-9048-b263635abe42", + "text/xml")).build(); + + SQSApi apiWhenExist = requestSendsResponse(addPermission, addPermissionResponse); + + apiWhenExist.addPermissionToAccount(URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/"), "testLabel", Action.RECEIVE_MESSAGE, "125074342641"); + } + + public HttpRequest removePermission = HttpRequest.builder() + .method("POST") + .endpoint("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/") + .addHeader("Host", "sqs.us-east-1.amazonaws.com") + .addFormParam("Action", "RemovePermission") + .addFormParam("Label", "testLabel") + .addFormParam("Signature", "VOA0L1uRVKQDQL1Klt0cYUajGoxN4Ur%2B7ISQ2I4RpRs%3D") + .addFormParam("SignatureMethod", "HmacSHA256") + .addFormParam("SignatureVersion", "2") + .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") + .addFormParam("Version", "2011-10-01") + .addFormParam("AWSAccessKeyId", "identity").build(); + + public void testRemovePermissionWhenResponseIs2xx() throws Exception { + + HttpResponse removePermissionResponse = HttpResponse.builder() + .statusCode(200) + .payload( + payloadFromStringWithContentType( + "b5293cb5-d306-4a17-9048-b263635abe42", + "text/xml")).build(); + + SQSApi apiWhenExist = requestSendsResponse(removePermission, removePermissionResponse); + + apiWhenExist.removePermission(URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/"), "testLabel"); + } } diff --git a/labs/sqs/src/test/java/org/jclouds/sqs/SQSApiLiveTest.java b/labs/sqs/src/test/java/org/jclouds/sqs/SQSApiLiveTest.java index 806d7648b6..ee61013517 100644 --- a/labs/sqs/src/test/java/org/jclouds/sqs/SQSApiLiveTest.java +++ b/labs/sqs/src/test/java/org/jclouds/sqs/SQSApiLiveTest.java @@ -18,8 +18,11 @@ */ package org.jclouds.sqs; +import static org.jclouds.concurrent.MoreExecutors.sameThreadExecutor; +import static org.jclouds.providers.AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint; import static org.jclouds.sqs.options.ListQueuesOptions.Builder.queuePrefix; import static org.jclouds.sqs.options.ReceiveMessageOptions.Builder.attribute; +import static org.jclouds.sqs.reference.SQSParameters.ACTION; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; @@ -28,16 +31,32 @@ import java.net.URI; import java.util.Map; import java.util.Set; import java.util.SortedSet; +import java.util.concurrent.TimeUnit; +import javax.ws.rs.POST; +import javax.ws.rs.Path; + +import org.jclouds.ContextBuilder; +import org.jclouds.concurrent.Timeout; +import org.jclouds.concurrent.config.ExecutorServiceModule; +import org.jclouds.rest.annotations.FormParams; +import org.jclouds.rest.annotations.XMLResponseParser; +import org.jclouds.sqs.domain.Action; +import org.jclouds.sqs.domain.QueueAttributes; import org.jclouds.sqs.internal.BaseSQSApiLiveTest; +import org.jclouds.sqs.xml.ValueHandler; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; import com.google.common.base.Charsets; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import com.google.common.hash.HashCode; import com.google.common.hash.Hashing; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.inject.Module; /** * Tests behavior of {@code SQSApi} @@ -82,24 +101,69 @@ public class SQSApiLiveTest extends BaseSQSApiLiveTest { return queueName; } - String message = "hardyharhar"; - HashCode md5 = Hashing.md5().hashString(message, Charsets.UTF_8); - @Test(dependsOnMethods = "testCanRecreateQueueGracefully") protected void testGetQueueAttributes() { for (URI queue : queues) { - Map attributes = api().getQueueAttributes(queue); + Map attributes = api().getQueueAttributes(queue, ImmutableSet.of("All")); assertEquals(api().getQueueAttributes(queue, attributes.keySet()), attributes); } } - @Test(dependsOnMethods = "testCanRecreateQueueGracefully") + + String message = "hardyharhar"; + HashCode md5 = Hashing.md5().hashString(message, Charsets.UTF_8); + + @Timeout(duration = 5, timeUnit = TimeUnit.SECONDS) + static interface AnonymousAttributesApi { + String getQueueArn(); + } + + static interface AnonymousAttributesAsyncApi { + @POST + @Path("/") + @FormParams(keys = { ACTION, "AttributeName.1" }, values = { "GetQueueAttributes", "QueueArn" }) + @XMLResponseParser(ValueHandler.class) + ListenableFuture getQueueArn(); + } + + @Test(dependsOnMethods = "testGetQueueAttributes") + protected void testAddAnonymousPermission() throws InterruptedException { + for (URI queue : queues) { + QueueAttributes attributes = api().getQueueAttributes(queue); + assertNoPermissions(queue); + + String accountToAuthorize = getAccountToAuthorize(queue); + api().addPermissionToAccount(queue, "fubar", Action.GET_QUEUE_ATTRIBUTES, accountToAuthorize); + + String policyForAuthorizationByAccount = assertPolicyPresent(queue); + + String policyForAnonymous = policyForAuthorizationByAccount.replace("\"" + accountToAuthorize + "\"", "\"*\""); + api().setQueueAttribute(queue, "Policy", policyForAnonymous); + + assertEquals(getAnonymousAttributesApi(queue).getQueueArn(), attributes.getQueueArn()); + } + } + + protected String getAccountToAuthorize(URI queue) { + return Iterables.get(Splitter.on('/').split(queue.getPath()), 1); + } + + @Test(dependsOnMethods = "testAddAnonymousPermission") + protected void testRemovePermission() throws InterruptedException { + for (URI queue : queues) { + api().removePermission(queue, "fubar"); + assertNoPermissions(queue); + } + } + + @Test(dependsOnMethods = "testGetQueueAttributes") protected void testSetQueueAttribute() { for (URI queue : queues) { api().setQueueAttribute(queue, "MaximumMessageSize", "1024"); - assertEquals(api().getQueueAttributes(queue).get("MaximumMessageSize"), "1024"); + assertEquals(api().getQueueAttributes(queue).getMaximumMessageSize(), 1024); } } - @Test(dependsOnMethods = "testCanRecreateQueueGracefully") + + @Test(dependsOnMethods = "testGetQueueAttributes") protected void testSendMessage() { for (URI queue : queues) { assertEquals(api().sendMessage(queue, message).getMD5(), md5); @@ -112,7 +176,7 @@ public class SQSApiLiveTest extends BaseSQSApiLiveTest { assertEquals(api().receiveMessage(queue, attribute("All").visibilityTimeout(0)).getMD5(), md5); } } - + String receiptHandle; @Test(dependsOnMethods = "testReceiveMessageWithoutHidingMessage") @@ -149,4 +213,14 @@ public class SQSApiLiveTest extends BaseSQSApiLiveTest { protected SQSApi api() { return context.getApi(); } + + private AnonymousAttributesApi getAnonymousAttributesApi(URI queue) { + return ContextBuilder + .newBuilder( + forClientMappedToAsyncClientOnEndpoint(AnonymousAttributesApi.class, + AnonymousAttributesAsyncApi.class, queue.toASCIIString())) + .modules(ImmutableSet. of(new ExecutorServiceModule(sameThreadExecutor(), sameThreadExecutor()))) + .buildInjector().getInstance(AnonymousAttributesApi.class); + } + } diff --git a/labs/sqs/src/test/java/org/jclouds/sqs/functions/MapToQueueAttributesTest.java b/labs/sqs/src/test/java/org/jclouds/sqs/functions/MapToQueueAttributesTest.java new file mode 100644 index 0000000000..203a5b78f1 --- /dev/null +++ b/labs/sqs/src/test/java/org/jclouds/sqs/functions/MapToQueueAttributesTest.java @@ -0,0 +1,64 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.sqs.functions; + +import static org.testng.Assert.assertEquals; + +import java.util.Date; + +import org.jclouds.sqs.domain.QueueAttributes; +import org.jclouds.sqs.parse.GetQueueAttributesResponseTest; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +// NOTE:without testName, this will not call @Before* and fail w/NPE during +// surefire +@Test(groups = "unit", testName = "MapToQueueAttributesTest") +public class MapToQueueAttributesTest { + + public void test() { + + + QueueAttributes expected = expected(); + + MapToQueueAttributes fn = new MapToQueueAttributes(); + + QueueAttributes result = fn.apply(new GetQueueAttributesResponseTest().expected()); + + assertEquals(result.toString(), expected.toString()); + + } + + public QueueAttributes expected() { + return QueueAttributes.builder() + .queueArn("arn:aws:sqs:us-east-1:993194456877:adrian-sqs1") + .approximateNumberOfMessages(0) + .approximateNumberOfMessagesNotVisible(0) + .approximateNumberOfMessagesDelayed(0) + .createdTimestamp(new Date(1347566436l)) + .lastModifiedTimestamp(new Date(1347566436)) + .visibilityTimeout(30) + .maximumMessageSize(65536) + .messageRetentionPeriod(345600) + .delaySeconds(0) + .build(); + } +} diff --git a/labs/sqs/src/test/java/org/jclouds/sqs/internal/BaseSQSApiLiveTest.java b/labs/sqs/src/test/java/org/jclouds/sqs/internal/BaseSQSApiLiveTest.java index ace17bdd8c..c95d3def31 100644 --- a/labs/sqs/src/test/java/org/jclouds/sqs/internal/BaseSQSApiLiveTest.java +++ b/labs/sqs/src/test/java/org/jclouds/sqs/internal/BaseSQSApiLiveTest.java @@ -24,6 +24,7 @@ import static org.testng.Assert.assertTrue; import java.net.URI; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; import org.jclouds.apis.BaseContextLiveTest; import org.jclouds.rest.RestContext; @@ -51,6 +52,28 @@ public class BaseSQSApiLiveTest extends BaseContextLiveTest policy = new AtomicReference(); + assertEventually(new Runnable() { + public void run() { + String policyForAuthorizationByAccount = api().getQueueAttribute(queue, "Policy"); + + assertNotNull(policyForAuthorizationByAccount); + policy.set(policyForAuthorizationByAccount); + } + }); + return policy.get(); + } + + protected void assertNoPermissions(final URI queue) throws InterruptedException { + assertEventually(new Runnable() { + public void run() { + String policy = api().getQueueAttribute(queue, "Policy"); + assertTrue(policy == null || policy.indexOf("\"Statement\":[]") != -1, policy); + } + }); + } + protected void assertNoMessages(final URI queue) throws InterruptedException { assertEventually(new Runnable() { public void run() { diff --git a/labs/sqs/src/test/java/org/jclouds/sqs/parse/GetQueueAttributesResponseTest.java b/labs/sqs/src/test/java/org/jclouds/sqs/parse/GetQueueAttributesResponseTest.java index 553f0bfbbd..143d293e6d 100644 --- a/labs/sqs/src/test/java/org/jclouds/sqs/parse/GetQueueAttributesResponseTest.java +++ b/labs/sqs/src/test/java/org/jclouds/sqs/parse/GetQueueAttributesResponseTest.java @@ -51,8 +51,16 @@ public class GetQueueAttributesResponseTest extends BaseHandlerTest { public Map expected() { return ImmutableMap.builder() - .put("VisibilityTimeout", "30") - .put("DelaySeconds", "0") - .build(); + .put("QueueArn", "arn:aws:sqs:us-east-1:993194456877:adrian-sqs1") + .put("ApproximateNumberOfMessages", "0") + .put("ApproximateNumberOfMessagesNotVisible", "0") + .put("ApproximateNumberOfMessagesDelayed", "0") + .put("CreatedTimestamp", "1347566436") + .put("LastModifiedTimestamp", "1347566436") + .put("VisibilityTimeout","30") + .put("MaximumMessageSize", "65536") + .put("MessageRetentionPeriod", "345600") + .put("DelaySeconds", "0") + .build(); } } diff --git a/labs/sqs/src/test/resources/attributes.xml b/labs/sqs/src/test/resources/attributes.xml index 2ae6de4e68..726c246b7f 100644 --- a/labs/sqs/src/test/resources/attributes.xml +++ b/labs/sqs/src/test/resources/attributes.xml @@ -1,12 +1,48 @@ - + + + + QueueArn + arn:aws:sqs:us-east-1:993194456877:adrian-sqs1 + + + ApproximateNumberOfMessages + 0 + + + ApproximateNumberOfMessagesNotVisible + 0 + + + ApproximateNumberOfMessagesDelayed + 0 + + + CreatedTimestamp + 1347566436 + + + LastModifiedTimestamp + 1347566436 + VisibilityTimeout 30 + + MaximumMessageSize + 65536 + + + MessageRetentionPeriod + 345600 + DelaySeconds 0 + + 35566a87-caa1-5841-b60b-224bf7068bf5 + \ No newline at end of file