cognitect-labs / aws-api

AWS, data driven
Apache License 2.0
724 stars 100 forks source link

SNS Subscribe request with :Attributes key, not working and documentation seems wrong #214

Closed kouvas closed 2 years ago

kouvas commented 2 years ago

Dependencies

{:deps 
           com.cognitect.aws/api       {:mvn/version "0.8.539"}
           com.cognitect.aws/endpoints {:mvn/version "1.1.12.206"}
           com.cognitect.aws/dynamodb  {:mvn/version "821.2.1107.0"}
           com.cognitect.aws/sts       {:mvn/version "822.2.1109.0"}
           com.cognitect.aws/sns       {:mvn/version "822.2.1109.0"}}
 :aliases {}}

Description with failing test case

Trying to create an SNS subscription with a FilterPolicy passed to :Attribues as per documentation:

...
Request

{:TopicArn string,
 :Protocol string,
 :Endpoint string,
 :Attributes [:map-of string string],
 :ReturnSubscriptionArn boolean}

Required

[:TopicArn :Protocol]

-------------------------
Response

{:SubscriptionArn string}

I tried:

(aws/invoke aws-client {:op      :Subscribe
                        :request {:TopicArn              (:iad (:topic params))
                                  :Protocol              "sqs"
                                  :Endpoint              "arn:aws:sqs:eu-west-1:*******"
                                  :ReturnSubscriptionArn true
                                  :Attributes            {"FilterPolicy" ""}}})
=>
{:ErrorResponse {:Error {:Type "Sender",
                         :TypeAttrs {},
                         :Code "InvalidParameter",
                         :CodeAttrs {},
                         :Message "Invalid parameter: Attributes Reason: FilterPolicy: Filter is not an object
                                   at [Source: (String)\"\"; line: 1, column: 1]",
                         :MessageAttrs {}},
                 :ErrorAttrs {},
                 :RequestId "*********",
                 :RequestIdAttrs {}},
 :ErrorResponseAttrs {:xmlns "http://sns.amazonaws.com/doc/2010-03-31/"},
 :cognitect.anomalies/category :cognitect.anomalies/incorrect}

If I pass an empty map to :Attributes it works:

(aws/invoke aws-client {:op      :Subscribe
                          :request {:TopicArn              (:iad (:topic params))
                                    :Protocol              "sqs"
                                    :Endpoint              "arn:aws:sqs:eu-west-1:********:quue1"
                                    :ReturnSubscriptionArn true
                                    :Attributes            {"FilterPolicy" {}}}})
=> {:SubscriptionArn "arn:aws:sns:us-east-1:********"}

But when i pass map with keys and values it fails even when using json-str

(aws/invoke aws-client {:op      :Subscribe
                          :request {:TopicArn              (:iad (:topic params))
                                    :Protocol              "sqs"
                                    :Endpoint              "arn:aws:sqs:eu-west-1:******"
                                    :ReturnSubscriptionArn true
                                    :Attributes            {"FilterPolicy" {"hostname" "example.com"}}}})
=>
{:ErrorResponse {:Error {:Type "Sender",
                         :TypeAttrs {},
                         :Code "InvalidParameter",
                         :CodeAttrs {},
                         :Message "Invalid parameter: Attributes Reason: FilterPolicy: Unexpected character ('\"' (code 34)): was expecting a colon to separate field name and value
                                   at [Source: (String)\"{\"hostname\" \"example.com\"}\"; line: 1, column: 14]",
                         :MessageAttrs {}},
                 :ErrorAttrs {},
                 :RequestId "8b3dee1e-b4ae--8211-",
                 :RequestIdAttrs {}},
 :ErrorResponseAttrs {:xmlns "http://sns.amazonaws.com/doc/2010-03-31/"},
 :cognitect.anomalies/category :cognitect.anomalies/incorrect}
(aws/invoke aws-client {:op      :Subscribe
                          :request {:TopicArn              (:iad (:topic params))
                                    :Protocol              "sqs"
                                    :Endpoint              "arn:aws:sqs:eu-west-1:*****"
                                    :ReturnSubscriptionArn true
                                    :Attributes            {"FilterPolicy" (clojure.data.json/json-str {"hostname" "example.com"})}}})
=>
{:ErrorResponse {:Error {:Type "Sender",
                         :TypeAttrs {},
                         :Code "InvalidParameter",
                         :CodeAttrs {},
                         :Message "Invalid parameter: Attributes Reason: FilterPolicy: \"hostname\" must be an object or an array
                                   at [Source: (String)\"{\"hostname\":\"example.com\"}\"; line: 1, column: 14]",
                         :MessageAttrs {}},
                 :ErrorAttrs {},
                 :RequestId "a1829ced-8ec1-5890-",
                 :RequestIdAttrs {}},
 :ErrorResponseAttrs {:xmlns "http://sns.amazonaws.com/doc/2010-03-31/"},
 :cognitect.anomalies/category :cognitect.anomalies/incorrect}

I need to know how to pass multiple attributes at one when creating a subscription as per https://docs.aws.amazon.com/sns/latest/api/API_Subscribe.html#API_Subscribe_RequestParameters

dchelimsky commented 2 years ago

The error you posted says \"hostname\" must be an object or an array, but you supplied the String "example.com". Unfortunately, I'm struggling to find any AWS documentation for what the "hostname" object or array should contain. I'll keep looking, but that's what you want to look for. I'll leave this open until one of us finds the answer.

dchelimsky commented 2 years ago

I don't have anything set up that I can test right now, but I found the following in this doc about FilterPolicy in the aws cli:

--attribute-name FilterPolicy --attribute-value '{"store":["example_corp"],"event":["order_placed"]}'

This suggests that this might work for :Attributes:

{"FilterPolicy" (clojure.data.json/json-str {"hostname" ["example.com"]})}

Can you give that a shot and report back, please?

kouvas commented 2 years ago

I realized from your example and other cli examples that the values in the stringified json need to be in a vector.

Also, the are two ways to actually do this

if you only have one attribute like FilterPolicy, your example will work like so

  (aws/invoke aws-client {:op      :Subscribe
                          :request {:TopicArn              (:iad (:topic params))
                                    :Protocol              "sqs"
                                    :Endpoint              "arn:aws:sqs:eu-west-1:******"
                                    :ReturnSubscriptionArn true
                                    :AttributeName "FilterPolicy"
                                    :AttributeValue        (clojure.data.json/json-str {"hostname" ["hostname", "anotherhost"],
                                                                                        "anotherKey"    ["somevalue"]})}})

if you have multiple attributes

  (aws/invoke aws-client {:op      :Subscribe
                          :request {:TopicArn              (:iad (:topic params))
                                    :Protocol              "sqs"
                                    :Endpoint              "arn:aws:sqs:eu-west-1:105769927945:LensTesting5"
                                    :ReturnSubscriptionArn true
                                    :Attributes            {"FilterPolicy" (clojure.data.json/json-str {"hostname" ["hostname"]
                                                                                                        "anotherKey" ["somevalue"]})
                                                            "DeliveryPolicy" (clojure.data.json/json-str {"key" ["value"]})}}})

Thanks for taking a look. I think it can be resolved now.