Having trouble writing to a dynamo db with aws api. I have also tried passing JSON as the request map but get the same error. Anyone know what im doing wrong?
(def dynamo-client (aws/client {:api :dynamodb}))
(-> dynamo-client
(aws/invoke {:op :DescribeTable
:request {:TableName "PracticeTable"}}))
=>{:Table
{:TableStatus "ACTIVE",
:ItemCount 0,
:TableId "xxxxxxxxxxxxxxxxxxxx",
:GlobalSecondaryIndexes
[{:IndexSizeBytes 0,
:IndexArn
"arn:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
:ItemCount 0,
:KeySchema
[{:AttributeName "GameTitle", :KeyType "HASH"}
{:AttributeName "TopScore", :KeyType "RANGE"}],
:ProvisionedThroughput
{:NumberOfDecreasesToday 0, :ReadCapacityUnits 10, :WriteCapacityUnits 10},
:IndexStatus "ACTIVE",
:Projection {:ProjectionType "INCLUDE", :NonKeyAttributes ["UserId"]},
:IndexName "GameTitleIndex"}],
:KeySchema
[{:AttributeName "UserId", :KeyType "HASH"}
{:AttributeName "GameTitle", :KeyType "RANGE"}],
:ProvisionedThroughput
{:NumberOfDecreasesToday 0, :ReadCapacityUnits 20, :WriteCapacityUnits 20},
:CreationDateTime #inst "2020-09-05T18:52:50.000-00:00",
:TableName "PracticeTable",
:AttributeDefinitions
[{:AttributeName "GameTitle", :AttributeType "S"}
{:AttributeName "TopScore", :AttributeType "N"}
{:AttributeName "UserId", :AttributeType "S"}],
:TableArn "arn:aws:dynamodb:xxxxxxxxxxxxxxxxxxxxx",
:TableSizeBytes 0}}
(aws/invoke dynamo-client {:op :PutItem
:request {:TableName "PracticeTable"
:Item {:GameTitle "mortal Kombat"
:TopScore 100
:UserId "Bill"}}})
=>{:cognitect.anomalies/category :cognitect.anomalies/fault,
:cognitect.aws.client/throwable #error {
:cause "No implementation of method: :kv-reduce of protocol: #'clojure.core.protocols/IKVReduce found for class: java.lang.String"
:via
[{:type java.lang.IllegalArgumentException
:message "No implementation of method: :kv-reduce of protocol: #'clojure.core.protocols/IKVReduce found for class: java.lang.String"
:at [clojure.core$_cache_protocol_fn invokeStatic "core_deftype.clj" 583]}]
:trace
[[clojure.core$_cache_protocol_fn invokeStatic "core_deftype.clj" 583]
[clojure.core.protocols$fn__8167$G__8162__8176 invoke "protocols.clj" 175]
[clojure.core$reduce_kv invokeStatic "core.clj" 6856]
[clojure.core$reduce_kv invoke "core.clj" 6847]
[cognitect.aws.shape$fn__8987 invokeStatic "shape.clj" 184]
[cognitect.aws.shape$fn__8987 invoke "shape.clj" 181]
[clojure.lang.MultiFn invoke "MultiFn.java" 234]
[cognitect.aws.shape$handle_map$fn__8947 invoke "shape.clj" 117]
[clojure.core$fn__8429$fn__8431 invoke "core.clj" 6840]
[clojure.core.protocols$iter_reduce invokeStatic "protocols.clj" 49]
[clojure.core.protocols$fn__8140 invokeStatic "protocols.clj" 75]
[clojure.core.protocols$fn__8140 invoke "protocols.clj" 75]
[clojure.core.protocols$fn__8088$G__8083__8101 invoke "protocols.clj" 13]
[clojure.core$reduce invokeStatic "core.clj" 6828]
[clojure.core$fn__8429 invokeStatic "core.clj" 6830]
[clojure.core$fn__8429 invoke "core.clj" 6830]
[clojure.core.protocols$fn__8167$G__8162__8176 invoke "protocols.clj" 175]
[clojure.core$reduce_kv invokeStatic "core.clj" 6856]
[clojure.core$reduce_kv invoke "core.clj" 6847]
[cognitect.aws.shape$handle_map invokeStatic "shape.clj" 117]
[cognitect.aws.shape$handle_map invoke "shape.clj" 113]
[cognitect.aws.shape$fn__8993 invokeStatic "shape.clj" 196]
[cognitect.aws.shape$fn__8993 invoke "shape.clj" 194]
[clojure.lang.MultiFn invoke "MultiFn.java" 234]
[cognitect.aws.shape$fn__8987$fn__8988 invoke "shape.clj" 189]
[clojure.core$fn__8429$fn__8431 invoke "core.clj" 6840]
[clojure.core.protocols$iter_reduce invokeStatic "protocols.clj" 49]
[clojure.core.protocols$fn__8140 invokeStatic "protocols.clj" 75]
[clojure.core.protocols$fn__8140 invoke "protocols.clj" 75]
[clojure.core.protocols$fn__8088$G__8083__8101 invoke "protocols.clj" 13]
[clojure.core$reduce invokeStatic "core.clj" 6828]
[clojure.core$fn__8429 invokeStatic "core.clj" 6830]
[clojure.core$fn__8429 invoke "core.clj" 6830]
[clojure.core.protocols$fn__8167$G__8162__8176 invoke "protocols.clj" 175]
[clojure.core$reduce_kv invokeStatic "core.clj" 6856]
[clojure.core$reduce_kv invoke "core.clj" 6847]
[cognitect.aws.shape$fn__8987 invokeStatic "shape.clj" 184]
[cognitect.aws.shape$fn__8987 invoke "shape.clj" 181]
[clojure.lang.MultiFn invoke "MultiFn.java" 234]
[cognitect.aws.shape$json_serialize invokeStatic "shape.clj" 212]
[cognitect.aws.shape$json_serialize invoke "shape.clj" 209]
[cognitect.aws.protocols.json$fn__451 invokeStatic "json.clj" 22]
[cognitect.aws.protocols.json$fn__451 invoke "json.clj" 19]
[clojure.lang.MultiFn invoke "MultiFn.java" 239]
[cognitect.aws.protocols.json$fn__454 invokeStatic "json.clj" 34]
[cognitect.aws.protocols.json$fn__454 invoke "json.clj" 24]
[clojure.lang.MultiFn invoke "MultiFn.java" 234]
[cognitect.aws.client$send_request$fn__9600$state_machine__5044__auto____9627$fn__9629$fn__9643 invoke "client.clj" 99]
[cognitect.aws.client$send_request$fn__9600$state_machine__5044__auto____9627$fn__9629 invoke "client.clj" 96]
[cognitect.aws.client$send_request$fn__9600$state_machine__5044__auto____9627 invoke "client.clj" 84]
[clojure.core.async.impl.ioc_macros$run_state_machine invokeStatic "ioc_macros.clj" 978]
[clojure.core.async.impl.ioc_macros$run_state_machine invoke "ioc_macros.clj" 977]
[clojure.core.async.impl.ioc_macros$run_state_machine_wrapped invokeStatic "ioc_macros.clj" 982]
[clojure.core.async.impl.ioc_macros$run_state_machine_wrapped invoke "ioc_macros.clj" 980]
[cognitect.aws.client$send_request$fn__9600 invoke "client.clj" 84]
[clojure.lang.AFn run "AFn.java" 22]
[java.util.concurrent.ThreadPoolExecutor runWorker "ThreadPoolExecutor.java" 1149]
[java.util.concurrent.ThreadPoolExecutor$Worker run "ThreadPoolExecutor.java" 624]
[clojure.core.async.impl.concurrent$counted_thread_factory$reify__528$fn__529 invoke "concurrent.clj" 29]
[clojure.lang.AFn run "AFn.java" 22]
[java.lang.Thread run "Thread.java" 748]]}}
@dgonsalves22 You need something like
(aws/invoke
dynamodb-client
{:op :PutItem
:request {:TableName "PracticeTable"
:Item {"GameTitle" {:S "mortal Kombat"}
"TopScore" {:N 100}
"UserId" {:S "Bill"}}}})
That was the trick thank you very much
Can I do (.getCredentials (DefaultAWSCredentialsProviderChain.))
using aws-api
?
Yes.
(cognitect.aws.credentials/fetch (cognitect.aws.client.shared/credentials-provider))
Can also use (cognitect.aws.credentials/default-credentials-provider)
to create a new chain.
Did it 🙂
(aws.cred/fetch (aws.cred/default-credentials-provider aws.cred/fetch-async))
It's a public/stable api? cc @dchelimskyI believe aws.creds is part of the public API. Not sure about aws.client.shared. The latter is the one implicitly passed when you don’t explicitly pass a creds provider.
Public? Yes. Stable? “Alpha. Subject to change.” https://cognitect-labs.github.io/aws-api/cognitect.aws.credentials-api.html
I'm pretty sure I've brought this up before, but I forget where we landed. Will returning an anomaly from a CredentialProvider's fetch method result in that anomaly getting returned after calling invoke
?
Not in the current design. In the chained-credentials-provider, it’s only an anomaly if none of the chained providers produce credentials. I think it would be more consistent with the design of the rest of the lib if the individual providers returned anomalies and the chain provider could check for that, and possibly build up list of all the failed providers to include in the anomaly it returns if none provide credentials. Definitely worth looking at.
We’d still need to handle nil in case users provide their own creds providers (in which case the lib could add the appropriate anomaly).
Right, okay. I actually believe it happens to work right now. (tested it with a cached-credentials-with-auto-refresh
)
i.e., if I return an anomaly from my passed in CredentialsProvider, that anomaly will be returned from invoke
.
https://github.com/cognitect-labs/aws-api/blob/e984cccdf78fa2212d8082546fa0ca5aa489051d/src/cognitect/aws/client.clj#L91-L92 makes it appear like it will. However, valid-credentials (https://github.com/cognitect-labs/aws-api/blob/e984cccdf78fa2212d8082546fa0ca5aa489051d/src/cognitect/aws/credentials.clj#L116) is used in all the provided provider constructing functions.
At the very least, it seems returning an anomaly map instead of nil is safe.
It appears like the below part of refresh!
's docstring is not correct.
> If the credentials returned by the provider are not valid, resets
> both atoms to nil, logs an error, and returns nil.
Yeah - that’s what you get for reading the documentation that is clearly left out of the public documentation 😉
It’s mostly correct. The only thing that’s incorrect about it is that the error is only logged if there is an error. The rest is accurate.
Fixed (in github).
@dchelimsky It says "If the credentials returned by the provider are not valid" but I don't see where it is checking to see if they are valid. Am I missing something obvious? 🙈
It’s a sketchy assumption that all the providers use the valid-credentials
fn, which is designed to return valid credentials or nil.
Seems highly unlikely for anyone implementing their own creds provider given the docstring for valid-credentials says "For internal use. Don't call directly."
As I said, sketchy 🙂