diff --git a/.github/issue_template.md b/.github/issue_template.md
index 9626f3ce..cb8c1477 100644
--- a/.github/issue_template.md
+++ b/.github/issue_template.md
@@ -16,8 +16,10 @@ e.g.
## Description with failing test case
Please describe what you are trying to do, what you expect to see, and
-what you're seeing instead. Include a code example that we can paste
-as/is into a REPL, execute, and watch fail.
+what you're seeing instead.
+
+*Important*: Please include a complete minimal code example that we
+can paste as/is into a REPL, execute, and watch fail.
## Stack traces
diff --git a/CHANGES.md b/CHANGES.md
index 41427859..819fab63 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,6 +1,70 @@
-# aws-api 0.8
+# aws-api
-### DEV
+## 0.8.484 / 2020-11-05
+
+* make date parsing more tolerant [#155](https://github.com/cognitect-labs/aws-api/issues/155)
+
+## 0.8.474 / 2020-08-15
+
+* fix bug decoding GetBucketPolicy response [#148](https://github.com/cognitect-labs/aws-api/issues/148)
+
+## 0.8.469 / 2020-07-10
+
+* fix bug parsing iso8601 dates with fractional seconds [#144](https://github.com/cognitect-labs/aws-api/issues/144)
+* fix memory leak when validating requests [#143](https://github.com/cognitect-labs/aws-api/issues/143)
+
+## 0.8.456 / 2020-03-27
+
+* upgrade to tools.logging-1.0.0, data.json-1.0.0, and core.async-1.0.567
+* let core.async manage the threadpool for fetching credentials and region
+ * fixes deadlock with concurrent credentials fetch [#137](https://github.com/cognitect-labs/aws-api/issues/137)
+
+## 0.8.445 / 2020-02-25
+
+* fix deadlock using composite credentials providers (e.g. assume role example) [#130](https://github.com/cognitect-labs/aws-api/issues/130)
+
+## 0.8.437 / 2020-02-14
+
+* fix issue with `invoke` hanging when no region or creds are found [#124](https://github.com/cognitect-labs/aws-api/issues/124)
+
+## 0.8.430 / 2020-02-10
+
+* upgrade to com.cognitect/http-client 0.1.104 [#115](https://github.com/cognitect-labs/aws-api/issues/115)
+* all aws clients use shared http-client, credentials-provider, and region-provider by default
+ * addresses [#109](https://github.com/cognitect-labs/aws-api/issues/109)
+ * first call to invoke takes hit of fetching region and credentials
+* `com.cognitect.aws.api/stop` will not stop the shared http-client, but stop any other instance
+
+See [Upgrade Notes](https://github.com/cognitect-labs/aws-api/blob/master/UPGRADE.md) for more
+information about upgrading to this version.
+
+## 0.8.423 / 2020-01-17
+
+* Remove dep on commons-codec [#113](https://github.com/cognitect-labs/aws-api/issues/113)
+* Convey anomaly from http-client as/is [#114](https://github.com/cognitect-labs/aws-api/issues/114)
+
+## 0.8.408 / 2019-11-25
+
+* Reduce noise from reflection warnings in java 9+ [#106](https://github.com/cognitect-labs/aws-api/issues/106)
+* Get signing region from endpoint config [#105](https://github.com/cognitect-labs/aws-api/issues/105)
+* Add documentationUrl when available [#108](https://github.com/cognitect-labs/aws-api/issues/108)
+
+## 0.8.391 / 2019-10-25
+
+* Fix: S3 HeadObject fails with large files [#97](https://github.com/cognitect-labs/aws-api/issues/97)
+ * This was fixed in cognitect/http-client 0.1.101
+* Fix concurrency 4 limit introduced in 0.8.383
+
+## ~~0.8.383 / 2019-10-24~~
+
+* Make http calls to fetch credentials async / non-blocking.
+
+## 0.8.378 / 2019-10-19
+
+* Include service full names in latest-releases.edn [#32](https://github.com/cognitect-labs/aws-api/issues/32)
+* Wrap dynamic require of protocol ns in locking form [#92](https://github.com/cognitect-labs/aws-api/issues/92)
+
+## 0.8.352 / 2019-07-26
* Use custom dynaload for http-client [#88](https://github.com/cognitect-labs/aws-api/issues/88)
* Restores compatibility with Clojure-1.9
diff --git a/README.md b/README.md
index c180920d..988f78ca 100644
--- a/README.md
+++ b/README.md
@@ -70,9 +70,9 @@ of your choice, e.g. `com.cognitect.aws/s3`.
To use, for example, the s3 api, add the following to deps.edn
``` clojure
-{:deps {com.cognitect.aws/api {:mvn/version "0.8.345"}
- com.cognitect.aws/endpoints {:mvn/version "1.1.11.592"}
- com.cognitect.aws/s3 {:mvn/version "726.2.488.0"}}}
+{:deps {com.cognitect.aws/api {:mvn/version "0.8.498"}
+ com.cognitect.aws/endpoints {:mvn/version "1.1.11.934"}
+ com.cognitect.aws/s3 {:mvn/version "810.2.817.0"}}}
```
* See [latest releases](latest-releases.edn) for a list of the latest releases of
@@ -175,7 +175,7 @@ involved example using AWS STS.
## Region lookup
-The aws-api client looks up the region the same with the [java
+The aws-api client looks up the region the same way the [java
SDK](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/java-dg-region-selection.html)
does, with an additional check for a System property named
"aws.region" after it checks for the AWS_REGION environment variable
@@ -216,27 +216,16 @@ the `:path` in the `:endpoint-override` map.
## http-client
+NOTE: the behavior of `com.cognitect.aws.api/client` and `com.cognitect.aws.api/stop`
+changed as of release 0.8.430. See [Upgrade
+Notes](https://github.com/cognitect-labs/aws-api/blob/master/UPGRADE.md)
+for more information.
+
The aws-api client uses an http-client to send requests to AWS,
including any operations you invoke _and_ fetching the region and
credentials when you're running in EC2 or ECS. By default, each
-aws-api client creates its own http-client, which, in turn, manages
-its own resources. Invoke `cognitect.aws.client.api/stop` on the
-client if you want it to shut down any resources it and its
-http-client are using.
-
-If you're creating multiple aws-api clients, you can, optionally,
-create a single http-client and share it across aws-api clients e.g.
-
-``` clojure
-(require '[cognitect.aws.client.api :as aws])
-(def http-client (aws/default-http-client))
-(def s3-client (aws/client {:api :s3 :http-client http-client}))
-(def ssm-client (aws/client {:api :ssm :http-client http-client}))
-;; etc
-```
-
-If you call `stop` on `s3-client` or `ssm-client` in this example, the
-single http-client gets shut down for both.
+aws-api client uses a single, shared http-client, whose resources
+are managed by aws-api.
## Contributing
@@ -246,6 +235,27 @@ aws-api is incorporated into products and client projects, we prefer
to do development internally and are not accepting pull requests or
patches.
+## Contributors
+
+`aws-api` was extracted from an internal project at Cognitect, and
+some contributors are missing from the commit log. Here are all the
+folks from Cognitect who either committed code directly, or
+contributed significantly to research and design:
+
+[Timothy Baldridge](https://github.com/halgari)
+[David Chelimsky](https://github.com/dchelimsky)
+[BenoƮt Fleury](https://github.com/benfle)
+[Fogus](https://github.com/fogus)
+[Stuart Halloway](https://github.com/stuarthalloway)
+[Rich Hickey](https://github.com/richhickey)
+[George Kierstein](https://github.com/MissInterpret)
+[Carin Meier](https://github.com/gigasquid)
+[Alex Miller](https://github.com/puredanger)
+[Michael Nygard](https://github.com/mtnygard)
+[Ghadi Shayban](https://github.com/ghadishayban)
+[Joseph Smith](https://github.com/solussd)
+[Marshall Thompson](https://github.com/Glassonion)
+
## Troubleshooting
### General
@@ -276,6 +286,17 @@ access.
Remedy: check [AWS Regions and Endpoints](https://docs.aws.amazon.com/general/latest/gr/rande.html),
and supply the correct endpoint as described in [nodename nor servname provided, or not known](#nodename-nor-servname-provided-or-not-known), above.
+#### Ops limit reached
+
+The underlying http-client has a `:pending-ops-limit` configuration
+which, when reached, results in an exception with the message "Ops
+limit reached". As of this writing, aws-api does not provide access to
+the http-client's configuration. Programs that encounter "Ops limit
+reached" can avoid it by creating separate http-clients for each
+aws-client. You may wish to explicitly stop
+(`com.cognitect.aws.api/stop`) these aws-clients when the are not
+longer in use to conserve resources.
+
### S3 Issues
#### "Invalid 'Location' header: null"
diff --git a/UPGRADE.md b/UPGRADE.md
new file mode 100644
index 00000000..a31b4edf
--- /dev/null
+++ b/UPGRADE.md
@@ -0,0 +1,48 @@
+# Upgrade Notes
+
+## 0.8.430
+
+This release changed the behavior of the following functions:
+
+### com.cognitect.aws.api/client
+
+As of 0.8.430, each aws-api client uses a single shared http-client by
+default. Before this release, each aws-client got its own instance of
+http-client by default, which caused the number of threads consumed to
+increase linearly in relation to the number of aws-clients created.
+To reduce resource consumption in the case of many aws-clients, we
+recommended that you create a single instance of the http-client and
+explicitly share it across all aws-clients. This is no longer
+necessary.
+
+### com.cognitect.aws.api/stop
+
+With the introduction of a shared http-client, this function was
+updated so that it has no effect when using the shared http-client,
+but will continue to call `cognitect.aws.http/stop` on any other
+http-client instance.
+
+### effects
+
+These changes have the following effects:
+
+Programs that were creating multiple aws-clients without supplying
+an http-client, and without ever calling stop, will see a reduction
+in resource consumption.
+
+Programs that were creating an instance of
+`cognitect.aws.client.api/default-http-client` and sharing it across
+aws-clients should see no change. You can, however, safely stop doing
+that.
+
+For programs that were using the default aws-client constructor and
+calling stop on each aws-client, the shared http-client will not be
+shut down. This should have no negative impact on resource consumption,
+as there is only one http-client in this case, and its resources are
+managed by aws-api.
+
+For programs that were creating multiple aws-clients in order to get
+around an ["Ops limit reached"
+error](https://github.com/cognitect-labs/aws-api/issues/98), this is a
+breaking change. For this case, we recommend, for now, that you supply
+a new http-client for each aws-client.
diff --git a/build/doc b/build/doc
index df05b9d1..d37559a3 100755
--- a/build/doc
+++ b/build/doc
@@ -4,7 +4,7 @@ set -e
echo "Building docs...\n"
rm -rf ./target/autodoc
-mvn clojure:autodoc
+mvn -Pautodoc clojure:autodoc
echo -e "Checking out gh-pages branch\n"
rm -rf gh-pages
diff --git a/build/release b/build/release
index 0746884f..ca5642cc 100755
--- a/build/release
+++ b/build/release
@@ -5,6 +5,15 @@ set -e
echo "Cleaning..."
rm -rf ./target
+echo "Aligning pom.xml with deps.edn ..."
+clj -Srepro -Spom
+if [ "$(git diff pom.xml)" = "" ]; then
+ echo "nothing to change"
+else
+ git add pom.xml
+ git commit -m "Update deps in pom.xml"
+fi
+
echo "Calculating version..."
prefix=`cat VERSION_PREFIX`
suffix=`build/revision`
@@ -23,7 +32,7 @@ git tag -a v${version} -m "Release ${version}"
git push origin v${version}
echo "Updating README.md, CHANGES.md, and latest-releases.edn with ${version}"
-clj -A:update-versions
+clj -A:update-versions --update-latest-releases --update-changelog --update-readme
git commit -m "Update README.md, CHANGES.md, and latest-releases.edn with ${version}" \
README.md CHANGES.md latest-releases.edn
git push
diff --git a/build/src/cognitect/aws/release_updater.clj b/build/src/cognitect/aws/release_updater.clj
deleted file mode 100644
index 377f44e8..00000000
--- a/build/src/cognitect/aws/release_updater.clj
+++ /dev/null
@@ -1,68 +0,0 @@
-(ns cognitect.aws.release-updater
- (:require [clojure.java.io :as io]
- [clojure.string :as str]
- [clojure.edn :as edn]
- [clojure.pprint :as pprint]
- [clojure.java.shell :as shell])
- (:import (java.util Date)))
-
-(defn version-prefix []
- (read-string (slurp (io/file "VERSION_PREFIX"))))
-
-(defn git-revision []
- (-> (:out (shell/sh "build/revision"))
- (str/split #"\n")
- first))
-
-(defn version []
- (str (version-prefix) "." (git-revision)))
-
-(defn update-version-in-line [version line]
- (if (re-find (re-pattern (str "com.cognitect.aws\\/api")) line)
- (str/replace-first line (re-pattern "\\d+.\\d+.\\d+") version)
- line))
-
-(defn update-file [fname ext xform]
- (let [f (io/file (str fname "." ext))
- cp (java.io.File/createTempFile fname (str "." ext))]
- (io/copy f cp)
- (with-open [r (io/reader cp)
- w (io/writer f)]
- (doseq [l (line-seq r)]
- (.write w (xform l))
- (.newLine w)))))
-
-(defn update-readme [version]
- (update-file "README"
- "md"
- #(if (re-find (re-pattern (str "com.cognitect.aws\\/api")) %)
- (str/replace-first % (re-pattern "\\d+.\\d+.\\d+") version)
- %)))
-
-(defn update-changelog [version]
- (update-file "CHANGES"
- "md"
- #(if (re-find (re-pattern "## DEV") %)
- (str/replace-first %
- (re-pattern "DEV")
- (str version " / " (.format (java.text.SimpleDateFormat. "yyyy-MM-dd") (Date.))))
- %)))
-
-(defn update-latest-releases [version]
- (let [f (io/file "latest-releases.edn")
- data (edn/read-string (slurp f))]
- (binding [*print-namespace-maps* false
- *print-length* 500]
- (spit f
- (with-out-str
- (clojure.pprint/pprint
- (-> data
- (assoc-in [:api 'com.cognitect.aws/api] version)
- (update :services #(into (sorted-map) %)))))))))
-
-(defn -main []
- (let [v (version)]
- (update-readme v)
- (update-changelog v)
- (update-latest-releases v))
- (System/exit 0))
diff --git a/build/src/cognitect/aws/version_updater.clj b/build/src/cognitect/aws/version_updater.clj
new file mode 100644
index 00000000..6e594697
--- /dev/null
+++ b/build/src/cognitect/aws/version_updater.clj
@@ -0,0 +1,111 @@
+(ns cognitect.aws.version-updater
+ (:require [clojure.java.io :as io]
+ [clojure.string :as str]
+ [clojure.edn :as edn]
+ [clojure.pprint :as pprint]
+ [clojure.java.shell :as shell])
+ (:import (java.util Date)))
+
+(set! *print-namespace-maps* false)
+
+(defn release-log-map []
+ (sorted-map-by (-> (fn [a b]
+ (cond (= "api" (name a) (name b)) 0
+ (= "api" (name a)) -1
+ (= "api" (name b)) 1
+ :else 0))
+ (.thenComparing
+ (fn [a b]
+ (cond (= "endpoints" (name a) (name b)) 0
+ (= "endpoints" (name a)) -1
+ (= "endpoints" (name b)) 1
+ :else 0)))
+ (.thenComparing compare))))
+
+(defn version-prefix []
+ (read-string (slurp (io/file "VERSION_PREFIX"))))
+
+(defn git-revision []
+ (-> (:out (shell/sh "build/revision"))
+ (str/split #"\n")
+ first))
+
+(defn version []
+ (str (version-prefix) "." (git-revision)))
+
+(defn update-file [fname* xform]
+ (let [[fname ext] (str/split fname* #"\.")
+ f (io/file fname*)
+ cp (java.io.File/createTempFile fname (str "." ext))]
+ (io/copy f cp)
+ (with-open [r (io/reader cp)
+ w (io/writer f)]
+ (doseq [l (line-seq r)]
+ (.write w (xform l))
+ (.newLine w)))))
+
+(defn latest-releases []
+ (-> (io/file "latest-releases.edn")
+ slurp
+ edn/read-string))
+
+(defn update-version-in [fname latest libname]
+ (let [version (get-in latest [(symbol "com.cognitect.aws" libname) :mvn/version])]
+ version
+ (update-file fname
+ #(if (re-find (re-pattern (str "com.cognitect.aws\\/" libname "\\s+\\{:mvn\\/version")) %)
+ (str/replace-first % (re-pattern "\\d+(.\\d+)+") version)
+ %))))
+
+(defn update-versions-in-readme []
+ (let [latest (latest-releases)]
+ (doseq [svc ["api" "endpoints" "s3"]]
+ (update-version-in "README.md" latest svc))))
+
+(defn update-versions-in-deps []
+ (let [latest (latest-releases)]
+ (doseq [svc ["endpoints" "dynamodb" "ec2" "iam" "lambda" "s3" "ssm" "sts"]]
+ (update-version-in "deps.edn" latest svc))))
+
+(defn update-changelog [version]
+ (update-file "CHANGES.md"
+ #(if (re-find (re-pattern "## DEV") %)
+ (str/replace-first %
+ (re-pattern "DEV")
+ (str version " / " (.format (java.text.SimpleDateFormat. "yyyy-MM-dd") (Date.))))
+ %)))
+
+(defn update-api-version-in-latest-releases [version]
+ (let [f (io/file "latest-releases.edn")
+ data (edn/read-string (slurp f))]
+ (binding [*print-namespace-maps* false
+ *print-length* 500]
+ (spit f
+ (with-out-str
+ (clojure.pprint/pprint
+ (into (release-log-map)
+ (assoc-in data ['com.cognitect.aws/api :mvn/version] version))))))))
+
+(defn -main [& argv]
+ (let [args (set argv)
+ v (version)]
+ (when (contains? args "--update-latest-releases")
+ (prn "Updating api version in latest releases")
+ (update-api-version-in-latest-releases v))
+ (when (contains? args "--update-changelog")
+ (println "Updating changelog")
+ (update-changelog v))
+ (when (contains? args "--update-readme")
+ (println "Updating README")
+ (update-versions-in-readme))
+ (when (contains? args "--update-deps")
+ (println "Updating deps.edn")
+ (update-versions-in-deps)))
+ (System/exit 0))
+
+(comment
+ (version)
+
+ (git-revision)
+
+ )
diff --git a/deps.edn b/deps.edn
index 96aaaaa8..b5345148 100644
--- a/deps.edn
+++ b/deps.edn
@@ -3,33 +3,34 @@
{:paths ["src" "resources"]
:deps {org.clojure/clojure {:mvn/version "1.10.1"}
- org.clojure/core.async {:mvn/version "0.4.490"}
- org.clojure/tools.logging {:mvn/version "0.4.0"}
+ org.clojure/core.async {:mvn/version "1.3.610"}
+ org.clojure/tools.logging {:mvn/version "1.1.0"}
+ org.clojure/data.json {:mvn/version "1.0.0"}
commons-codec/commons-codec {:mvn/version "1.11"}
- byte-streams {:mvn/version "0.2.5-alpha2"}
+ byte-streams/byte-streams {:mvn/version "0.2.5-alpha2"}
metosin/jsonista {:mvn/version "0.2.3"}
org.clojure/data.xml {:mvn/version "0.2.0-alpha6"}
- com.cognitect/http-client {:mvn/version "0.1.99"}
+ com.cognitect/http-client {:mvn/version "0.1.105"}
;NVD
org.eclipse.jetty/jetty-client {:mvn/version "9.4.20.v20190813"}}
:aliases {:update-versions {:extra-paths ["build/src"]
- :main-opts ["-m" "cognitect.aws.release-updater"]}
- :project-dev {:extra-paths ["dev/src" "dev/resources" "test/src" "test/resources"]
- :extra-deps {commons-io/commons-io {:mvn/version "2.5"}
- org.clojure/test.check {:mvn/version "0.10.0-RC1"}
- org.slf4j/slf4j-log4j12 {:mvn/version "1.7.25"}
- http-kit {:mvn/version "2.3.0"}}}
- :test {:extra-deps {com.cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner.git"
- :sha "209b64504cb3bd3b99ecfec7937b358a879f55c1"}}
- :main-opts ["-m" "cognitect.test-runner"]}
+ :main-opts ["-m" "cognitect.aws.version-updater"]}
+ :dev {:extra-paths ["dev/src" "dev/resources" "test/src" "test/resources"]
+ :extra-deps {commons-io/commons-io {:mvn/version "2.8.0"}
+ org.clojure/test.check {:mvn/version "1.1.0"}
+ org.slf4j/slf4j-log4j12 {:mvn/version "1.7.30"}
+ http-kit/http-kit {:mvn/version "2.5.0"}
+ com.cognitect.aws/endpoints {:mvn/version "1.1.11.926"}
+ com.cognitect.aws/s3 {:mvn/version "810.2.817.0"}}}
+ :test {:extra-deps {com.cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner.git"
+ :sha "cb96e80f6f3d3b307c59cbeb49bb0dcb3a2a780b"}}
+ :main-opts ["-m" "cognitect.test-runner"]}
:examples {:extra-paths ["examples" "examples/resources" "dev/resources"]
- :extra-deps {org.clojure/test.check {:mvn/version "0.10.0-RC1"}
- org.slf4j/slf4j-log4j12 {:mvn/version "1.7.25"}
- com.cognitect.aws/endpoints {:mvn/version "1.1.11.586"}
- com.cognitect.aws/dynamodb {:mvn/version "726.2.484.0"}
- com.cognitect.aws/ec2 {:mvn/version "726.2.488.0"}
- com.cognitect.aws/iam {:mvn/version "726.2.480.0"}
- com.cognitect.aws/lambda {:mvn/version "718.2.454.0"}
- com.cognitect.aws/s3 {:mvn/version "726.2.488.0"}
- com.cognitect.aws/ssm {:mvn/version "726.2.481.0"}
- com.cognitect.aws/sts {:mvn/version "722.2.464.0"}}}}}
+ :extra-deps {org.clojure/test.check {:mvn/version "1.1.0"}
+ org.slf4j/slf4j-log4j12 {:mvn/version "1.7.30"}
+ com.cognitect.aws/dynamodb {:mvn/version "810.2.801.0"}
+ com.cognitect.aws/ec2 {:mvn/version "810.2.817.0"}
+ com.cognitect.aws/iam {:mvn/version "801.2.704.0"}
+ com.cognitect.aws/lambda {:mvn/version "810.2.817.0"}
+ com.cognitect.aws/ssm {:mvn/version "810.2.817.0"}
+ com.cognitect.aws/sts {:mvn/version "809.2.784.0"}}}}}
diff --git a/examples/assume_role_example.clj b/examples/assume_role_example.clj
index d09a4392..806ffaf7 100644
--- a/examples/assume_role_example.clj
+++ b/examples/assume_role_example.clj
@@ -24,7 +24,8 @@
"Principal" {"AWS" [(:Arn me)]}
"Action" ["sts:AssumeRole"]}]})}})
-(def new-role (:Role *1))
+(def new-role (:Role (aws/invoke iam {:op :GetRole
+ :request {:RoleName "aws-api-example-role"}})))
;; make a policy to use for this example
(aws/invoke iam {:op :CreatePolicy
@@ -36,29 +37,32 @@
"Action" ["iam:GetUser"]
"Resource" [(:Arn me)]}]})}})
-(def policy (:Policy *1))
+(def policy (->> (aws/invoke iam {:op :ListPolicies})
+ :Policies
+ (filter #(re-find #"IAMGetMe" (:Arn %)))
+ first))
;; attach the new policy to the new role
(aws/invoke iam {:op :AttachRolePolicy :request {:RoleName (:RoleName new-role)
:PolicyArn (:Arn policy)}})
;; make a credentials provider that can assume a role
-(defn assumed-role-credentials-provider [role-arn session-name refresh-every-n-seconds]
+(defn assumed-role-credentials-provider [role-arn]
(let [sts (aws/client {:api :sts})]
- (credentials/auto-refreshing-credentials
+ (credentials/cached-credentials-with-auto-refresh
(reify credentials/CredentialsProvider
(fetch [_]
(when-let [creds (:Credentials
(aws/invoke sts
{:op :AssumeRole
:request {:RoleArn role-arn
- :RoleSessionName session-name}}))]
+ :RoleSessionName (str (gensym "example-session-"))}}))]
{:aws/access-key-id (:AccessKeyId creds)
:aws/secret-access-key (:SecretAccessKey creds)
:aws/session-token (:SessionToken creds)
- ::credentials/ttl refresh-every-n-seconds}))))))
+ ::credentials/ttl (credentials/calculate-ttl creds)}))))))
-(def provider (assumed-role-credentials-provider (:Arn new-role) "example-session" 600))
+(def provider (assumed-role-credentials-provider (:Arn new-role)))
;; make a client using the assumed role credentials provider
(def iam-with-assumed-role (aws/client {:api :iam :credentials-provider provider}))
@@ -67,7 +71,6 @@
(aws/invoke iam-with-assumed-role {:op :GetUser :request {:UserName (:UserName me)}})
;; clean up
-(credentials/stop provider)
(aws/invoke iam {:op :DetachRolePolicy :request {:RoleName (:RoleName new-role) :PolicyArn (:Arn policy)}})
(aws/invoke iam {:op :DeletePolicy :request {:PolicyArn (:Arn policy)}})
(aws/invoke iam {:op :DeleteRole :request {:RoleName "aws-api-example-role"}})
diff --git a/examples/autoscaling.repl b/examples/autoscaling.repl
new file mode 100644
index 00000000..bc73c4b3
--- /dev/null
+++ b/examples/autoscaling.repl
@@ -0,0 +1,5 @@
+(require '[cognitect.aws.client.api :as aws])
+
+(def client (aws/client {:api :autoscaling}))
+(aws/invoke client {:op :DescribeAutoScalingGroups
+ :request {}})
diff --git a/examples/deps.edn b/examples/deps.edn
new file mode 100644
index 00000000..623dd860
--- /dev/null
+++ b/examples/deps.edn
@@ -0,0 +1,10 @@
+{:deps {com.cognitect.aws/api {:mvn/version "0.8.391"
+ :exclusions [org.slf4j/slf4j-log4j12]}
+ com.cognitect.aws/dynamodb {:mvn/version "746.2.533.0"}
+ com.cognitect.aws/ec2 {:mvn/version "759.2.556.0"}
+ com.cognitect.aws/endpoints {:mvn/version "1.1.11.664"}
+ com.cognitect.aws/logs {:mvn/version "747.2.533.0"}
+ com.cognitect.aws/autoscaling {:mvn/version "770.2.568.0"}
+ com.cognitect.aws/cloudformation {:mvn/version "746.2.533.0"}
+ com.cognitect.aws/s3 {:mvn/version "762.2.558.0"}
+ com.cognitect.aws/resourcegroupstaggingapi {:mvn/version "747.2.533.0"}}}
diff --git a/examples/dynamodb_examples.clj b/examples/dynamodb_examples.clj
index dd2e9f0c..876ac4cd 100644
--- a/examples/dynamodb_examples.clj
+++ b/examples/dynamodb_examples.clj
@@ -21,7 +21,7 @@
;; doc!
(aws/doc ddb :ListTables)
(aws/doc ddb :CreateTable)
-(aws/doc ddb :Scan) ;; this one has references in the request/response
+(aws/doc ddb :Scan) ;; this one has a Given section with shape/AttributeValue
;; 1. Create Example Tables
diff --git a/latest-releases.edn b/latest-releases.edn
index a90e4d2d..9edf3e36 100644
--- a/latest-releases.edn
+++ b/latest-releases.edn
@@ -1,498 +1,442 @@
-{com.cognitect.aws/api {:mvn/version "0.8.345"},
- com.cognitect.aws/endpoints {:mvn/version "1.1.11.592"},
+{com.cognitect.aws/api {:mvn/version "0.8.498"},
+ com.cognitect.aws/endpoints {:mvn/version "1.1.11.934"},
+ com.cognitect.aws/AWS242AppRegistry
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS Service Catalog App Registry"},
com.cognitect.aws/AWSMigrationHub
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "AWS Migration Hub"},
+ {:mvn/version "796.2.657.0", :aws/serviceFullName "AWS Migration Hub"},
+ com.cognitect.aws/accessanalyzer
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "Access Analyzer"},
com.cognitect.aws/acm
- {:mvn/version "715.2.434.0",
- :aws/serviceFullName "AWS Certificate Manager"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS Certificate Manager"},
com.cognitect.aws/acm-pca
- {:mvn/version "726.2.479.0",
- :aws/serviceFullName
- "AWS Certificate Manager Private Certificate Authority"},
+ {:mvn/version "811.2.824.0",
+ :aws/serviceFullName "AWS Certificate Manager Private Certificate Authority"},
com.cognitect.aws/alexaforbusiness
- {:mvn/version "726.2.485.0",
- :aws/serviceFullName "Alexa For Business"},
- com.cognitect.aws/amplify
- {:mvn/version "729.2.490.0", :aws/serviceFullName "AWS Amplify"},
+ {:mvn/version "802.2.713.0", :aws/serviceFullName "Alexa For Business"},
+ com.cognitect.aws/amp
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Prometheus Service"},
+ com.cognitect.aws/amplify {:mvn/version "809.2.797.0", :aws/serviceFullName "AWS Amplify"},
+ com.cognitect.aws/amplifybackend
+ {:mvn/version "810.2.805.0", :aws/serviceFullName "AmplifyBackend"},
com.cognitect.aws/apigateway
- {:mvn/version "726.2.481.0",
- :aws/serviceFullName "Amazon API Gateway"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon API Gateway"},
com.cognitect.aws/apigatewaymanagementapi
- {:mvn/version "701.2.393.0",
- :aws/serviceFullName "AmazonApiGatewayManagementApi"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "AmazonApiGatewayManagementApi"},
com.cognitect.aws/apigatewayv2
- {:mvn/version "736.2.493.0",
- :aws/serviceFullName "AmazonApiGatewayV2"},
+ {:mvn/version "811.2.824.0", :aws/serviceFullName "AmazonApiGatewayV2"},
+ com.cognitect.aws/appconfig {:mvn/version "801.2.697.0", :aws/serviceFullName "Amazon AppConfig"},
+ com.cognitect.aws/appflow {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon Appflow"},
+ com.cognitect.aws/appintegrations
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon AppIntegrations Service"},
com.cognitect.aws/application-autoscaling
- {:mvn/version "711.2.412.0",
- :aws/serviceFullName "Application Auto Scaling"},
+ {:mvn/version "811.2.824.0", :aws/serviceFullName "Application Auto Scaling"},
com.cognitect.aws/application-insights
- {:mvn/version "726.2.488.0",
- :aws/serviceFullName "Amazon CloudWatch Application Insights"},
- com.cognitect.aws/appmesh
- {:mvn/version "723.2.475.0", :aws/serviceFullName "AWS App Mesh"},
- com.cognitect.aws/appstream
- {:mvn/version "726.2.487.0", :aws/serviceFullName "Amazon AppStream"},
- com.cognitect.aws/appsync
- {:mvn/version "717.2.451.0", :aws/serviceFullName "AWS AppSync"},
- com.cognitect.aws/athena
- {:mvn/version "707.2.409.0", :aws/serviceFullName "Amazon Athena"},
- com.cognitect.aws/autoscaling
- {:mvn/version "736.2.494.0", :aws/serviceFullName "Auto Scaling"},
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon CloudWatch Application Insights"},
+ com.cognitect.aws/appmesh {:mvn/version "809.2.797.0", :aws/serviceFullName "AWS App Mesh"},
+ com.cognitect.aws/appstream {:mvn/version "809.2.734.0", :aws/serviceFullName "Amazon AppStream"},
+ com.cognitect.aws/appsync {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS AppSync"},
+ com.cognitect.aws/athena {:mvn/version "801.2.687.0", :aws/serviceFullName "Amazon Athena"},
+ com.cognitect.aws/auditmanager
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS Audit Manager"},
+ com.cognitect.aws/autoscaling {:mvn/version "811.2.824.0", :aws/serviceFullName "Auto Scaling"},
com.cognitect.aws/autoscaling-plans
- {:mvn/version "711.2.413.0",
- :aws/serviceFullName "AWS Auto Scaling Plans"},
- com.cognitect.aws/backup
- {:mvn/version "697.2.391.0", :aws/serviceFullName "AWS Backup"},
- com.cognitect.aws/batch
- {:mvn/version "717.2.443.0", :aws/serviceFullName "AWS Batch"},
- com.cognitect.aws/budgets
- {:mvn/version "719.2.461.0", :aws/serviceFullName "AWS Budgets"},
+ {:mvn/version "811.2.824.0", :aws/serviceFullName "AWS Auto Scaling Plans"},
+ com.cognitect.aws/backup {:mvn/version "809.2.797.0", :aws/serviceFullName "AWS Backup"},
+ com.cognitect.aws/batch {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS Batch"},
+ com.cognitect.aws/braket {:mvn/version "810.2.797.0", :aws/serviceFullName "Braket"},
+ com.cognitect.aws/budgets {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS Budgets"},
com.cognitect.aws/ce
- {:mvn/version "729.2.489.0",
- :aws/serviceFullName "AWS Cost Explorer Service"},
- com.cognitect.aws/chime
- {:mvn/version "722.2.464.0", :aws/serviceFullName "Amazon Chime"},
- com.cognitect.aws/cloud9
- {:mvn/version "707.2.409.0", :aws/serviceFullName "AWS Cloud9"},
+ {:mvn/version "811.2.824.0", :aws/serviceFullName "AWS Cost Explorer Service"},
+ com.cognitect.aws/chime {:mvn/version "809.2.797.0", :aws/serviceFullName "Amazon Chime"},
+ com.cognitect.aws/cloud9 {:mvn/version "809.2.734.0", :aws/serviceFullName "AWS Cloud9"},
com.cognitect.aws/clouddirectory
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon CloudDirectory"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon CloudDirectory"},
com.cognitect.aws/cloudformation
- {:mvn/version "717.2.442.0",
- :aws/serviceFullName "AWS CloudFormation"},
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "AWS CloudFormation"},
com.cognitect.aws/cloudfront
- {:mvn/version "723.2.476.0",
- :aws/serviceFullName "Amazon CloudFront"},
- com.cognitect.aws/cloudhsm
- {:mvn/version "697.2.391.0", :aws/serviceFullName "Amazon CloudHSM"},
- com.cognitect.aws/cloudhsmv2
- {:mvn/version "697.2.391.0", :aws/serviceFullName "AWS CloudHSM V2"},
+ {:mvn/version "811.2.824.0", :aws/serviceFullName "Amazon CloudFront"},
+ com.cognitect.aws/cloudhsm {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon CloudHSM"},
+ com.cognitect.aws/cloudhsmv2 {:mvn/version "809.2.797.0", :aws/serviceFullName "AWS CloudHSM V2"},
com.cognitect.aws/cloudsearch
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon CloudSearch"},
+ {:mvn/version "811.2.824.0", :aws/serviceFullName "Amazon CloudSearch"},
com.cognitect.aws/cloudsearchdomain
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon CloudSearch Domain"},
- com.cognitect.aws/cloudtrail
- {:mvn/version "697.2.391.0", :aws/serviceFullName "AWS CloudTrail"},
- com.cognitect.aws/codebuild
- {:mvn/version "723.2.472.0", :aws/serviceFullName "AWS CodeBuild"},
- com.cognitect.aws/codecommit
- {:mvn/version "726.2.483.0", :aws/serviceFullName "AWS CodeCommit"},
- com.cognitect.aws/codedeploy
- {:mvn/version "736.2.495.0", :aws/serviceFullName "AWS CodeDeploy"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon CloudSearch Domain"},
+ com.cognitect.aws/cloudtrail {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS CloudTrail"},
+ com.cognitect.aws/codeartifact {:mvn/version "810.2.801.0", :aws/serviceFullName "CodeArtifact"},
+ com.cognitect.aws/codebuild {:mvn/version "810.2.802.0", :aws/serviceFullName "AWS CodeBuild"},
+ com.cognitect.aws/codecommit {:mvn/version "801.2.704.0", :aws/serviceFullName "AWS CodeCommit"},
+ com.cognitect.aws/codedeploy {:mvn/version "799.2.681.0", :aws/serviceFullName "AWS CodeDeploy"},
+ com.cognitect.aws/codeguru-reviewer
+ {:mvn/version "809.2.797.0", :aws/serviceFullName "Amazon CodeGuru Reviewer"},
+ com.cognitect.aws/codeguruprofiler
+ {:mvn/version "803.2.717.0", :aws/serviceFullName "Amazon CodeGuru Profiler"},
com.cognitect.aws/codepipeline
- {:mvn/version "718.2.456.0", :aws/serviceFullName "AWS CodePipeline"},
- com.cognitect.aws/codestar
- {:mvn/version "697.2.391.0", :aws/serviceFullName "AWS CodeStar"},
+ {:mvn/version "811.2.824.0", :aws/serviceFullName "AWS CodePipeline"},
+ com.cognitect.aws/codestar {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS CodeStar"},
+ com.cognitect.aws/codestar-connections
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "AWS CodeStar connections"},
+ com.cognitect.aws/codestar-notifications
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS CodeStar Notifications"},
com.cognitect.aws/cognito-identity
- {:mvn/version "712.2.425.0",
- :aws/serviceFullName "Amazon Cognito Identity"},
+ {:mvn/version "809.2.797.0", :aws/serviceFullName "Amazon Cognito Identity"},
com.cognitect.aws/cognito-idp
- {:mvn/version "717.2.449.0",
- :aws/serviceFullName "Amazon Cognito Identity Provider"},
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon Cognito Identity Provider"},
com.cognitect.aws/cognito-sync
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon Cognito Sync"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon Cognito Sync"},
com.cognitect.aws/comprehend
- {:mvn/version "736.2.495.0",
- :aws/serviceFullName "Amazon Comprehend"},
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon Comprehend"},
com.cognitect.aws/comprehendmedical
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "AWS Comprehend Medical"},
- com.cognitect.aws/config
- {:mvn/version "736.2.494.0", :aws/serviceFullName "AWS Config"},
+ {:mvn/version "801.2.708.0", :aws/serviceFullName "AWS Comprehend Medical"},
+ com.cognitect.aws/compute-optimizer
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS Compute Optimizer"},
+ com.cognitect.aws/config {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS Config"},
com.cognitect.aws/connect
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon Connect Service"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Connect Service"},
+ com.cognitect.aws/connect-contact-lens
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon Connect Contact Lens"},
+ com.cognitect.aws/connectparticipant
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Connect Participant Service"},
com.cognitect.aws/cur
- {:mvn/version "711.2.411.0",
- :aws/serviceFullName "AWS Cost and Usage Report Service"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS Cost and Usage Report Service"},
+ com.cognitect.aws/customer-profiles
+ {:mvn/version "810.2.802.0", :aws/serviceFullName "Amazon Connect Customer Profiles"},
+ com.cognitect.aws/databrew {:mvn/version "810.2.797.0", :aws/serviceFullName "AWS Glue DataBrew"},
+ com.cognitect.aws/dataexchange
+ {:mvn/version "801.2.698.0", :aws/serviceFullName "AWS Data Exchange"},
com.cognitect.aws/datapipeline
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "AWS Data Pipeline"},
- com.cognitect.aws/datasync
- {:mvn/version "719.2.460.0", :aws/serviceFullName "AWS DataSync"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS Data Pipeline"},
+ com.cognitect.aws/datasync {:mvn/version "809.2.797.0", :aws/serviceFullName "AWS DataSync"},
com.cognitect.aws/dax
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon DynamoDB Accelerator (DAX)"},
- com.cognitect.aws/devicefarm
- {:mvn/version "726.2.480.0", :aws/serviceFullName "AWS Device Farm"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon DynamoDB Accelerator (DAX)"},
+ com.cognitect.aws/detective {:mvn/version "796.2.650.0", :aws/serviceFullName "Amazon Detective"},
+ com.cognitect.aws/devicefarm {:mvn/version "784.2.595.0", :aws/serviceFullName "AWS Device Farm"},
com.cognitect.aws/devices
- {:mvn/version "715.2.437.0",
- :aws/serviceFullName "AWS IoT 1-Click Devices Service"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS IoT 1-Click Devices Service"},
+ com.cognitect.aws/devops-guru
+ {:mvn/version "811.2.824.0", :aws/serviceFullName "Amazon DevOps Guru"},
com.cognitect.aws/directconnect
- {:mvn/version "726.2.484.0",
- :aws/serviceFullName "AWS Direct Connect"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS Direct Connect"},
com.cognitect.aws/discovery
- {:mvn/version "716.2.440.0",
- :aws/serviceFullName "AWS Application Discovery Service"},
+ {:mvn/version "788.2.608.0", :aws/serviceFullName "AWS Application Discovery Service"},
com.cognitect.aws/dlm
- {:mvn/version "722.2.465.0",
- :aws/serviceFullName "Amazon Data Lifecycle Manager"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Data Lifecycle Manager"},
com.cognitect.aws/dms
- {:mvn/version "736.2.494.0",
- :aws/serviceFullName "AWS Database Migration Service"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS Database Migration Service"},
com.cognitect.aws/docdb
- {:mvn/version "726.2.486.0",
- :aws/serviceFullName "Amazon DocumentDB with MongoDB compatibility"},
- com.cognitect.aws/ds
- {:mvn/version "707.2.406.0",
- :aws/serviceFullName "AWS Directory Service"},
- com.cognitect.aws/dynamodb
- {:mvn/version "726.2.484.0", :aws/serviceFullName "Amazon DynamoDB"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "Amazon DocumentDB with MongoDB compatibility"},
+ com.cognitect.aws/ds {:mvn/version "810.2.805.0", :aws/serviceFullName "AWS Directory Service"},
+ com.cognitect.aws/dynamodb {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon DynamoDB"},
+ com.cognitect.aws/ebs
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "Amazon Elastic Block Store"},
com.cognitect.aws/ec2
- {:mvn/version "726.2.488.0",
- :aws/serviceFullName "Amazon Elastic Compute Cloud"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Elastic Compute Cloud"},
com.cognitect.aws/ec2-instance-connect
- {:mvn/version "726.2.488.0",
- :aws/serviceFullName "AWS EC2 Instance Connect"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS EC2 Instance Connect"},
com.cognitect.aws/ecr
- {:mvn/version "701.2.394.0",
- :aws/serviceFullName "Amazon EC2 Container Registry"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon EC2 Container Registry"},
+ com.cognitect.aws/ecr-public
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon Elastic Container Registry Public"},
com.cognitect.aws/ecs
- {:mvn/version "736.2.495.0",
- :aws/serviceFullName "Amazon EC2 Container Service"},
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon EC2 Container Service"},
com.cognitect.aws/eks
- {:mvn/version "726.2.482.0",
- :aws/serviceFullName "Amazon Elastic Kubernetes Service"},
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon Elastic Kubernetes Service"},
+ com.cognitect.aws/elastic-inference
+ {:mvn/version "796.2.663.0", :aws/serviceFullName "Amazon Elastic Inference"},
com.cognitect.aws/elasticache
- {:mvn/version "736.2.495.0",
- :aws/serviceFullName "Amazon ElastiCache"},
+ {:mvn/version "811.2.824.0", :aws/serviceFullName "Amazon ElastiCache"},
com.cognitect.aws/elasticbeanstalk
- {:mvn/version "712.2.419.0",
- :aws/serviceFullName "AWS Elastic Beanstalk"},
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "AWS Elastic Beanstalk"},
com.cognitect.aws/elasticfilesystem
- {:mvn/version "729.2.490.0",
- :aws/serviceFullName "Amazon Elastic File System"},
+ {:mvn/version "802.2.711.0", :aws/serviceFullName "Amazon Elastic File System"},
com.cognitect.aws/elasticloadbalancing
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Elastic Load Balancing"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "Elastic Load Balancing"},
com.cognitect.aws/elasticloadbalancingv2
- {:mvn/version "714.2.430.0",
- :aws/serviceFullName "Elastic Load Balancing"},
+ {:mvn/version "809.2.797.0", :aws/serviceFullName "Elastic Load Balancing"},
com.cognitect.aws/elasticmapreduce
- {:mvn/version "715.2.433.0",
- :aws/serviceFullName "Amazon Elastic MapReduce"},
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon Elastic MapReduce"},
com.cognitect.aws/elastictranscoder
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon Elastic Transcoder"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon Elastic Transcoder"},
com.cognitect.aws/email
- {:mvn/version "722.2.470.0",
- :aws/serviceFullName "Amazon Simple Email Service"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon Simple Email Service"},
+ com.cognitect.aws/emr-containers
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon EMR Containers"},
com.cognitect.aws/entitlement-marketplace
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "AWS Marketplace Entitlement Service"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS Marketplace Entitlement Service"},
com.cognitect.aws/es
- {:mvn/version "736.2.493.0",
- :aws/serviceFullName "Amazon Elasticsearch Service"},
+ {:mvn/version "809.2.797.0", :aws/serviceFullName "Amazon Elasticsearch Service"},
com.cognitect.aws/eventbridge
- {:mvn/version "729.2.492.0",
- :aws/serviceFullName "Amazon EventBridge"},
+ {:mvn/version "809.2.797.0", :aws/serviceFullName "Amazon EventBridge"},
com.cognitect.aws/events
- {:mvn/version "729.2.492.0",
- :aws/serviceFullName "Amazon CloudWatch Events"},
+ {:mvn/version "809.2.797.0", :aws/serviceFullName "Amazon CloudWatch Events"},
com.cognitect.aws/firehose
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon Kinesis Firehose"},
+ {:mvn/version "807.2.729.0", :aws/serviceFullName "Amazon Kinesis Firehose"},
com.cognitect.aws/fms
- {:mvn/version "712.2.428.0",
- :aws/serviceFullName "Firewall Management Service"},
- com.cognitect.aws/fsx
- {:mvn/version "726.2.481.0", :aws/serviceFullName "Amazon FSx"},
- com.cognitect.aws/gamelift
- {:mvn/version "729.2.490.0", :aws/serviceFullName "Amazon GameLift"},
- com.cognitect.aws/glacier
- {:mvn/version "729.2.491.0", :aws/serviceFullName "Amazon Glacier"},
+ {:mvn/version "809.2.797.0", :aws/serviceFullName "Firewall Management Service"},
+ com.cognitect.aws/forecast
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Forecast Service"},
+ com.cognitect.aws/forecastquery
+ {:mvn/version "789.2.612.0", :aws/serviceFullName "Amazon Forecast Query Service"},
+ com.cognitect.aws/frauddetector
+ {:mvn/version "809.2.797.0", :aws/serviceFullName "Amazon Fraud Detector"},
+ com.cognitect.aws/fsx {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon FSx"},
+ com.cognitect.aws/gamelift {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon GameLift"},
+ com.cognitect.aws/glacier {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon Glacier"},
com.cognitect.aws/globalaccelerator
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "AWS Global Accelerator"},
- com.cognitect.aws/glue
- {:mvn/version "726.2.479.0", :aws/serviceFullName "AWS Glue"},
- com.cognitect.aws/greengrass
- {:mvn/version "715.2.432.0", :aws/serviceFullName "AWS Greengrass"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS Global Accelerator"},
+ com.cognitect.aws/glue {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS Glue"},
+ com.cognitect.aws/greengrass {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS Greengrass"},
+ com.cognitect.aws/greengrassv2
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS IoT Greengrass V2"},
com.cognitect.aws/groundstation
- {:mvn/version "722.2.470.0",
- :aws/serviceFullName "AWS Ground Station"},
- com.cognitect.aws/guardduty
- {:mvn/version "723.2.475.0", :aws/serviceFullName "Amazon GuardDuty"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS Ground Station"},
+ com.cognitect.aws/guardduty {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon GuardDuty"},
com.cognitect.aws/health
- {:mvn/version "726.2.479.0",
- :aws/serviceFullName "AWS Health APIs and Notifications"},
+ {:mvn/version "807.2.729.0", :aws/serviceFullName "AWS Health APIs and Notifications"},
+ com.cognitect.aws/healthlake
+ {:mvn/version "811.2.824.0", :aws/serviceFullName "Amazon HealthLake"},
+ com.cognitect.aws/honeycode {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon Honeycode"},
com.cognitect.aws/iam
- {:mvn/version "736.2.493.0",
- :aws/serviceFullName "AWS Identity and Access Management"},
+ {:mvn/version "801.2.704.0", :aws/serviceFullName "AWS Identity and Access Management"},
+ com.cognitect.aws/identitystore
+ {:mvn/version "810.2.797.0", :aws/serviceFullName "AWS SSO Identity Store"},
+ com.cognitect.aws/imagebuilder
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "EC2 Image Builder"},
com.cognitect.aws/importexport
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "AWS Import/Export"},
- com.cognitect.aws/inspector
- {:mvn/version "718.2.443.0", :aws/serviceFullName "Amazon Inspector"},
- com.cognitect.aws/iot
- {:mvn/version "712.2.426.0", :aws/serviceFullName "AWS IoT"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS Import/Export"},
+ com.cognitect.aws/inspector {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon Inspector"},
+ com.cognitect.aws/iot {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS IoT"},
com.cognitect.aws/iot-data
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "AWS IoT Data Plane"},
+ {:mvn/version "801.2.695.0", :aws/serviceFullName "AWS IoT Data Plane"},
com.cognitect.aws/iot-jobs-data
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "AWS IoT Jobs Data Plane"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS IoT Jobs Data Plane"},
com.cognitect.aws/iot1click-projects
- {:mvn/version "712.2.427.0",
- :aws/serviceFullName "AWS IoT 1-Click Projects Service"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS IoT 1-Click Projects Service"},
com.cognitect.aws/iotanalytics
- {:mvn/version "722.2.466.0",
- :aws/serviceFullName "AWS IoT Analytics"},
- com.cognitect.aws/iotevents
- {:mvn/version "736.2.496.0", :aws/serviceFullName "AWS IoT Events"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS IoT Analytics"},
+ com.cognitect.aws/iotdeviceadvisor
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS IoT Core Device Advisor"},
+ com.cognitect.aws/iotevents {:mvn/version "796.2.667.0", :aws/serviceFullName "AWS IoT Events"},
com.cognitect.aws/iotevents-data
- {:mvn/version "726.2.479.0",
- :aws/serviceFullName "AWS IoT Events Data"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS IoT Events Data"},
+ com.cognitect.aws/iotfleethub
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS IoT Fleet Hub"},
+ com.cognitect.aws/iotsecuretunneling
+ {:mvn/version "809.2.797.0", :aws/serviceFullName "AWS IoT Secure Tunneling"},
+ com.cognitect.aws/iotsitewise
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS IoT SiteWise"},
com.cognitect.aws/iotthingsgraph
- {:mvn/version "722.2.470.0",
- :aws/serviceFullName "AWS IoT Things Graph"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS IoT Things Graph"},
+ com.cognitect.aws/iotwireless
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS IoT Wireless"},
+ com.cognitect.aws/ivs
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "Amazon Interactive Video Service"},
com.cognitect.aws/kafka
- {:mvn/version "722.2.466.0",
- :aws/serviceFullName "Managed Streaming for Kafka"},
- com.cognitect.aws/kinesis
- {:mvn/version "697.2.391.0", :aws/serviceFullName "Amazon Kinesis"},
+ {:mvn/version "810.2.805.0", :aws/serviceFullName "Managed Streaming for Kafka"},
+ com.cognitect.aws/kendra
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWSKendraFrontendService"},
+ com.cognitect.aws/kinesis {:mvn/version "809.2.784.0", :aws/serviceFullName "Amazon Kinesis"},
com.cognitect.aws/kinesis-video-archived-media
- {:mvn/version "729.2.490.0",
- :aws/serviceFullName "Amazon Kinesis Video Streams Archived Media"},
+ {:mvn/version "796.2.665.0", :aws/serviceFullName "Amazon Kinesis Video Streams Archived Media"},
com.cognitect.aws/kinesis-video-media
- {:mvn/version "726.2.480.0",
- :aws/serviceFullName "Amazon Kinesis Video Streams Media"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon Kinesis Video Streams Media"},
+ com.cognitect.aws/kinesis-video-signaling
+ {:mvn/version "781.2.585.0", :aws/serviceFullName "Amazon Kinesis Video Signaling Channels"},
com.cognitect.aws/kinesisanalytics
- {:mvn/version "718.2.452.0",
- :aws/serviceFullName "Amazon Kinesis Analytics"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon Kinesis Analytics"},
com.cognitect.aws/kinesisanalyticsv2
- {:mvn/version "718.2.452.0",
- :aws/serviceFullName "Amazon Kinesis Analytics"},
+ {:mvn/version "809.2.797.0", :aws/serviceFullName "Amazon Kinesis Analytics"},
com.cognitect.aws/kinesisvideo
- {:mvn/version "729.2.490.0",
- :aws/serviceFullName "Amazon Kinesis Video Streams"},
+ {:mvn/version "796.2.665.0", :aws/serviceFullName "Amazon Kinesis Video Streams"},
com.cognitect.aws/kms
- {:mvn/version "718.2.448.0",
- :aws/serviceFullName "AWS Key Management Service"},
- com.cognitect.aws/lambda
- {:mvn/version "718.2.454.0", :aws/serviceFullName "AWS Lambda"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS Key Management Service"},
+ com.cognitect.aws/lakeformation
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS Lake Formation"},
+ com.cognitect.aws/lambda {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS Lambda"},
com.cognitect.aws/lex-models
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon Lex Model Building Service"},
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon Lex Model Building Service"},
com.cognitect.aws/license-manager
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "AWS License Manager"},
- com.cognitect.aws/lightsail
- {:mvn/version "712.2.426.0", :aws/serviceFullName "Amazon Lightsail"},
+ {:mvn/version "810.2.805.0", :aws/serviceFullName "AWS License Manager"},
+ com.cognitect.aws/lightsail {:mvn/version "809.2.797.0", :aws/serviceFullName "Amazon Lightsail"},
+ com.cognitect.aws/location
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Location Service"},
com.cognitect.aws/logs
- {:mvn/version "722.2.470.0",
- :aws/serviceFullName "Amazon CloudWatch Logs"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "Amazon CloudWatch Logs"},
+ com.cognitect.aws/lookoutvision
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon Lookout for Vision"},
com.cognitect.aws/machinelearning
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon Machine Learning"},
- com.cognitect.aws/macie
- {:mvn/version "697.2.391.0", :aws/serviceFullName "Amazon Macie"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon Machine Learning"},
+ com.cognitect.aws/macie {:mvn/version "801.2.684.0", :aws/serviceFullName "Amazon Macie"},
+ com.cognitect.aws/macie2 {:mvn/version "811.2.824.0", :aws/serviceFullName "Amazon Macie 2"},
com.cognitect.aws/managedblockchain
- {:mvn/version "718.2.457.0",
- :aws/serviceFullName "Amazon Managed Blockchain"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Managed Blockchain"},
+ com.cognitect.aws/marketplace-catalog
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS Marketplace Catalog Service"},
com.cognitect.aws/marketplacecommerceanalytics
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "AWS Marketplace Commerce Analytics"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS Marketplace Commerce Analytics"},
com.cognitect.aws/mediaconnect
- {:mvn/version "722.2.470.0", :aws/serviceFullName "AWS MediaConnect"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS MediaConnect"},
com.cognitect.aws/mediaconvert
- {:mvn/version "718.2.449.0",
- :aws/serviceFullName "AWS Elemental MediaConvert"},
+ {:mvn/version "811.2.824.0", :aws/serviceFullName "AWS Elemental MediaConvert"},
com.cognitect.aws/medialive
- {:mvn/version "718.2.449.0",
- :aws/serviceFullName "AWS Elemental MediaLive"},
+ {:mvn/version "810.2.805.0", :aws/serviceFullName "AWS Elemental MediaLive"},
com.cognitect.aws/mediapackage
- {:mvn/version "726.2.480.0",
- :aws/serviceFullName "AWS Elemental MediaPackage"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS Elemental MediaPackage"},
com.cognitect.aws/mediapackage-vod
- {:mvn/version "722.2.470.0",
- :aws/serviceFullName "AWS Elemental MediaPackage VOD"},
+ {:mvn/version "801.2.690.0", :aws/serviceFullName "AWS Elemental MediaPackage VOD"},
com.cognitect.aws/mediastore
- {:mvn/version "726.2.487.0",
- :aws/serviceFullName "AWS Elemental MediaStore"},
+ {:mvn/version "796.2.650.0", :aws/serviceFullName "AWS Elemental MediaStore"},
com.cognitect.aws/mediastore-data
- {:mvn/version "719.2.463.0",
- :aws/serviceFullName "AWS Elemental MediaStore Data Plane"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS Elemental MediaStore Data Plane"},
com.cognitect.aws/mediatailor
- {:mvn/version "718.2.442.0", :aws/serviceFullName "AWS MediaTailor"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS MediaTailor"},
com.cognitect.aws/meteringmarketplace
- {:mvn/version "719.2.459.0",
- :aws/serviceFullName "AWSMarketplace Metering"},
- com.cognitect.aws/mobile
- {:mvn/version "697.2.391.0", :aws/serviceFullName "AWS Mobile"},
+ {:mvn/version "809.2.797.0", :aws/serviceFullName "AWSMarketplace Metering"},
+ com.cognitect.aws/migrationhub-config
+ {:mvn/version "796.2.656.0", :aws/serviceFullName "AWS Migration Hub Config"},
+ com.cognitect.aws/mobile {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS Mobile"},
com.cognitect.aws/mobileanalytics
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon Mobile Analytics"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon Mobile Analytics"},
com.cognitect.aws/monitoring
- {:mvn/version "729.2.490.0",
- :aws/serviceFullName "Amazon CloudWatch"},
- com.cognitect.aws/mq
- {:mvn/version "716.2.438.0", :aws/serviceFullName "AmazonMQ"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon CloudWatch"},
+ com.cognitect.aws/mq {:mvn/version "809.2.797.0", :aws/serviceFullName "AmazonMQ"},
com.cognitect.aws/mturk-requester
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon Mechanical Turk"},
- com.cognitect.aws/neptune
- {:mvn/version "726.2.477.0", :aws/serviceFullName "Amazon Neptune"},
- com.cognitect.aws/opsworks
- {:mvn/version "726.2.479.0", :aws/serviceFullName "AWS OpsWorks"},
- com.cognitect.aws/opsworkscm
- {:mvn/version "719.2.463.0",
- :aws/serviceFullName "AWS OpsWorks for Chef Automate"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon Mechanical Turk"},
+ com.cognitect.aws/mwaa {:mvn/version "810.2.801.0", :aws/serviceFullName "AmazonMWAA"},
+ com.cognitect.aws/neptune {:mvn/version "809.2.784.0", :aws/serviceFullName "Amazon Neptune"},
+ com.cognitect.aws/network-firewall
+ {:mvn/version "810.2.797.0", :aws/serviceFullName "AWS Network Firewall"},
+ com.cognitect.aws/networkmanager
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS Network Manager"},
+ com.cognitect.aws/opsworks {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS OpsWorks"},
+ com.cognitect.aws/opsworkscm {:mvn/version "801.2.701.0", :aws/serviceFullName "AWS OpsWorks CM"},
com.cognitect.aws/organizations
- {:mvn/version "726.2.486.0",
- :aws/serviceFullName "AWS Organizations"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS Organizations"},
+ com.cognitect.aws/outposts {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS Outposts"},
com.cognitect.aws/personalize
- {:mvn/version "723.2.476.0",
- :aws/serviceFullName "Amazon Personalize"},
+ {:mvn/version "807.2.729.0", :aws/serviceFullName "Amazon Personalize"},
com.cognitect.aws/personalize-events
- {:mvn/version "723.2.476.0",
- :aws/serviceFullName "Amazon Personalize Events"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "Amazon Personalize Events"},
com.cognitect.aws/personalize-runtime
- {:mvn/version "723.2.476.0",
- :aws/serviceFullName "Amazon Personalize Runtime"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Personalize Runtime"},
com.cognitect.aws/pi
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "AWS Performance Insights"},
- com.cognitect.aws/pinpoint
- {:mvn/version "726.2.484.0", :aws/serviceFullName "Amazon Pinpoint"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS Performance Insights"},
+ com.cognitect.aws/pinpoint {:mvn/version "809.2.784.0", :aws/serviceFullName "Amazon Pinpoint"},
com.cognitect.aws/pinpoint-email
- {:mvn/version "722.2.466.0",
- :aws/serviceFullName "Amazon Pinpoint Email Service"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon Pinpoint Email Service"},
com.cognitect.aws/pinpoint-sms-voice
- {:mvn/version "701.2.394.0",
- :aws/serviceFullName "Amazon Pinpoint SMS and Voice Service"},
- com.cognitect.aws/polly
- {:mvn/version "716.2.439.0", :aws/serviceFullName "Amazon Polly"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon Pinpoint SMS and Voice Service"},
+ com.cognitect.aws/polly {:mvn/version "809.2.797.0", :aws/serviceFullName "Amazon Polly"},
com.cognitect.aws/pricing
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "AWS Price List Service"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS Price List Service"},
+ com.cognitect.aws/qldb {:mvn/version "801.2.698.0", :aws/serviceFullName "Amazon QLDB"},
+ com.cognitect.aws/qldb-session
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon QLDB Session"},
com.cognitect.aws/quicksight
- {:mvn/version "729.2.491.0",
- :aws/serviceFullName "Amazon QuickSight"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon QuickSight"},
com.cognitect.aws/ram
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "AWS Resource Access Manager"},
+ {:mvn/version "796.2.662.0", :aws/serviceFullName "AWS Resource Access Manager"},
com.cognitect.aws/rds
- {:mvn/version "726.2.488.0",
- :aws/serviceFullName "Amazon Relational Database Service"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Relational Database Service"},
com.cognitect.aws/rds-data
- {:mvn/version "722.2.466.0",
- :aws/serviceFullName "AWS RDS DataService"},
- com.cognitect.aws/redshift
- {:mvn/version "726.2.485.0", :aws/serviceFullName "Amazon Redshift"},
+ {:mvn/version "795.2.645.0", :aws/serviceFullName "AWS RDS DataService"},
+ com.cognitect.aws/redshift {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Redshift"},
+ com.cognitect.aws/redshift-data
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "Redshift Data API Service"},
com.cognitect.aws/rekognition
- {:mvn/version "712.2.419.0",
- :aws/serviceFullName "Amazon Rekognition"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "Amazon Rekognition"},
com.cognitect.aws/resource-groups
- {:mvn/version "716.2.441.0",
- :aws/serviceFullName "AWS Resource Groups"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS Resource Groups"},
com.cognitect.aws/resourcegroupstaggingapi
- {:mvn/version "726.2.481.0",
- :aws/serviceFullName "AWS Resource Groups Tagging API"},
- com.cognitect.aws/robomaker
- {:mvn/version "736.2.493.0", :aws/serviceFullName "AWS RoboMaker"},
- com.cognitect.aws/route53
- {:mvn/version "718.2.442.0", :aws/serviceFullName "Amazon Route 53"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS Resource Groups Tagging API"},
+ com.cognitect.aws/robomaker {:mvn/version "809.2.797.0", :aws/serviceFullName "AWS RoboMaker"},
+ com.cognitect.aws/route53 {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Route 53"},
com.cognitect.aws/route53domains
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon Route 53 Domains"},
+ {:mvn/version "796.2.660.0", :aws/serviceFullName "Amazon Route 53 Domains"},
com.cognitect.aws/route53resolver
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon Route 53 Resolver"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Route 53 Resolver"},
com.cognitect.aws/runtime-lex
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon Lex Runtime Service"},
+ {:mvn/version "809.2.797.0", :aws/serviceFullName "Amazon Lex Runtime Service"},
com.cognitect.aws/runtime-sagemaker
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon SageMaker Runtime"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon SageMaker Runtime"},
com.cognitect.aws/s3
- {:mvn/version "726.2.488.0",
- :aws/serviceFullName "Amazon Simple Storage Service"},
- com.cognitect.aws/s3control
- {:mvn/version "718.2.446.0", :aws/serviceFullName "AWS S3 Control"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Simple Storage Service"},
+ com.cognitect.aws/s3control {:mvn/version "809.2.797.0", :aws/serviceFullName "AWS S3 Control"},
+ com.cognitect.aws/s3outposts
+ {:mvn/version "810.2.797.0", :aws/serviceFullName "Amazon S3 on Outposts"},
com.cognitect.aws/sagemaker
- {:mvn/version "723.2.473.0",
- :aws/serviceFullName "Amazon SageMaker Service"},
- com.cognitect.aws/sdb
- {:mvn/version "697.2.391.0", :aws/serviceFullName "Amazon SimpleDB"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon SageMaker Service"},
+ com.cognitect.aws/sagemaker-a2i-runtime
+ {:mvn/version "796.2.657.0", :aws/serviceFullName "Amazon Augmented AI Runtime"},
+ com.cognitect.aws/sagemaker-edge
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Sagemaker Edge Manager"},
+ com.cognitect.aws/sagemaker-featurestore-runtime
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon SageMaker Feature Store Runtime"},
+ com.cognitect.aws/savingsplans
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS Savings Plans"},
+ com.cognitect.aws/schemas {:mvn/version "809.2.784.0", :aws/serviceFullName "Schemas"},
+ com.cognitect.aws/sdb {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon SimpleDB"},
com.cognitect.aws/secretsmanager
- {:mvn/version "707.2.405.0",
- :aws/serviceFullName "AWS Secrets Manager"},
+ {:mvn/version "802.2.713.0", :aws/serviceFullName "AWS Secrets Manager"},
com.cognitect.aws/securityhub
- {:mvn/version "726.2.481.0", :aws/serviceFullName "AWS SecurityHub"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS SecurityHub"},
com.cognitect.aws/serverlessrepo
- {:mvn/version "712.2.420.0",
- :aws/serviceFullName "AWSServerlessApplicationRepository"},
+ {:mvn/version "794.2.637.0", :aws/serviceFullName "AWSServerlessApplicationRepository"},
com.cognitect.aws/service-quotas
- {:mvn/version "726.2.488.0", :aws/serviceFullName "Service Quotas"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Service Quotas"},
com.cognitect.aws/servicecatalog
- {:mvn/version "729.2.491.0",
- :aws/serviceFullName "AWS Service Catalog"},
+ {:mvn/version "811.2.824.0", :aws/serviceFullName "AWS Service Catalog"},
com.cognitect.aws/servicediscovery
- {:mvn/version "697.2.391.0", :aws/serviceFullName "AWS Cloud Map"},
- com.cognitect.aws/shield
- {:mvn/version "704.2.397.0", :aws/serviceFullName "AWS Shield"},
- com.cognitect.aws/signer
- {:mvn/version "697.2.391.0", :aws/serviceFullName "AWS Signer"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS Cloud Map"},
+ com.cognitect.aws/sesv2
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "Amazon Simple Email Service"},
+ com.cognitect.aws/shield {:mvn/version "809.2.797.0", :aws/serviceFullName "AWS Shield"},
+ com.cognitect.aws/signer {:mvn/version "810.2.801.0", :aws/serviceFullName "AWS Signer"},
com.cognitect.aws/sms
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "AWS Server Migration Service"},
+ {:mvn/version "807.2.729.0", :aws/serviceFullName "AWS Server Migration Service"},
com.cognitect.aws/snowball
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon Import/Export Snowball"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "Amazon Import/Export Snowball"},
com.cognitect.aws/sns
- {:mvn/version "718.2.444.0",
- :aws/serviceFullName "Amazon Simple Notification Service"},
+ {:mvn/version "809.2.797.0", :aws/serviceFullName "Amazon Simple Notification Service"},
com.cognitect.aws/sqs
- {:mvn/version "736.2.496.0",
- :aws/serviceFullName "Amazon Simple Queue Service"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Simple Queue Service"},
com.cognitect.aws/ssm
- {:mvn/version "726.2.481.0",
- :aws/serviceFullName "Amazon Simple Systems Manager (SSM)"},
- com.cognitect.aws/states
- {:mvn/version "707.2.409.0",
- :aws/serviceFullName "AWS Step Functions"},
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "Amazon Simple Systems Manager (SSM)"},
+ com.cognitect.aws/sso {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS Single Sign-On"},
+ com.cognitect.aws/sso-admin
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "AWS Single Sign-On Admin"},
+ com.cognitect.aws/sso-oidc {:mvn/version "770.2.568.0", :aws/serviceFullName "AWS SSO OIDC"},
+ com.cognitect.aws/states {:mvn/version "810.2.801.0", :aws/serviceFullName "AWS Step Functions"},
com.cognitect.aws/storagegateway
- {:mvn/version "722.2.468.0",
- :aws/serviceFullName "AWS Storage Gateway"},
+ {:mvn/version "809.2.797.0", :aws/serviceFullName "AWS Storage Gateway"},
com.cognitect.aws/streams-dynamodb
- {:mvn/version "697.2.391.0",
- :aws/serviceFullName "Amazon DynamoDB Streams"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "Amazon DynamoDB Streams"},
com.cognitect.aws/sts
- {:mvn/version "722.2.464.0",
- :aws/serviceFullName "AWS Security Token Service"},
- com.cognitect.aws/support
- {:mvn/version "697.2.391.0", :aws/serviceFullName "AWS Support"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS Security Token Service"},
+ com.cognitect.aws/support {:mvn/version "801.2.700.0", :aws/serviceFullName "AWS Support"},
com.cognitect.aws/swf
- {:mvn/version "726.2.488.0",
- :aws/serviceFullName "Amazon Simple Workflow Service"},
- com.cognitect.aws/textract
- {:mvn/version "718.2.442.0", :aws/serviceFullName "Amazon Textract"},
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon Simple Workflow Service"},
+ com.cognitect.aws/synthetics {:mvn/version "809.2.797.0", :aws/serviceFullName "Synthetics"},
+ com.cognitect.aws/textract {:mvn/version "809.2.797.0", :aws/serviceFullName "Amazon Textract"},
+ com.cognitect.aws/timestream-query
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon Timestream Query"},
+ com.cognitect.aws/timestream-write
+ {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon Timestream Write"},
com.cognitect.aws/transcribe
- {:mvn/version "722.2.464.0",
- :aws/serviceFullName "Amazon Transcribe Service"},
+ {:mvn/version "809.2.784.0", :aws/serviceFullName "Amazon Transcribe Service"},
com.cognitect.aws/transfer
- {:mvn/version "718.2.445.0",
- :aws/serviceFullName "AWS Transfer for SFTP"},
- com.cognitect.aws/translate
- {:mvn/version "697.2.391.0", :aws/serviceFullName "Amazon Translate"},
- com.cognitect.aws/waf
- {:mvn/version "729.2.490.0", :aws/serviceFullName "AWS WAF"},
+ {:mvn/version "811.2.824.0", :aws/serviceFullName "AWS Transfer Family"},
+ com.cognitect.aws/translate {:mvn/version "810.2.801.0", :aws/serviceFullName "Amazon Translate"},
+ com.cognitect.aws/waf {:mvn/version "796.2.666.0", :aws/serviceFullName "AWS WAF"},
com.cognitect.aws/waf-regional
- {:mvn/version "729.2.490.0", :aws/serviceFullName "AWS WAF Regional"},
- com.cognitect.aws/workdocs
- {:mvn/version "707.2.408.0", :aws/serviceFullName "Amazon WorkDocs"},
- com.cognitect.aws/worklink
- {:mvn/version "719.2.461.0", :aws/serviceFullName "Amazon WorkLink"},
- com.cognitect.aws/workmail
- {:mvn/version "718.2.449.0", :aws/serviceFullName "Amazon WorkMail"},
+ {:mvn/version "796.2.666.0", :aws/serviceFullName "AWS WAF Regional"},
+ com.cognitect.aws/wafv2 {:mvn/version "809.2.784.0", :aws/serviceFullName "AWS WAFV2"},
+ com.cognitect.aws/wellarchitected
+ {:mvn/version "810.2.817.0", :aws/serviceFullName "AWS Well-Architected Tool"},
+ com.cognitect.aws/workdocs {:mvn/version "793.2.629.0", :aws/serviceFullName "Amazon WorkDocs"},
+ com.cognitect.aws/worklink {:mvn/version "801.2.687.0", :aws/serviceFullName "Amazon WorkLink"},
+ com.cognitect.aws/workmail {:mvn/version "809.2.784.0", :aws/serviceFullName "Amazon WorkMail"},
+ com.cognitect.aws/workmailmessageflow
+ {:mvn/version "770.2.568.0", :aws/serviceFullName "Amazon WorkMail Message Flow"},
com.cognitect.aws/workspaces
- {:mvn/version "726.2.485.0",
- :aws/serviceFullName "Amazon WorkSpaces"},
- com.cognitect.aws/xray
- {:mvn/version "718.2.447.0", :aws/serviceFullName "AWS X-Ray"}}
+ {:mvn/version "810.2.805.0", :aws/serviceFullName "Amazon WorkSpaces"},
+ com.cognitect.aws/xray {:mvn/version "809.2.797.0", :aws/serviceFullName "AWS X-Ray"}}
diff --git a/pom.xml b/pom.xml
index e484ef29..e15121c2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,190 +1,189 @@
- 4.0.0
- com.cognitect.aws
- api
- DEV
- jar
- aws-api
- A Clojure API for the AWS API
- http://github.com/cognitect-labs/aws-api
-
-
- The Apache Software License, Version 2.0
- http://www.apache.org/licenses/LICENSE-2.0.txt
-
-
-
-
- Cognitect
- labs@cognitect.com
- Cognitect
- http://cognitect.com
-
-
-
- scm:git:git@github.com:cognitect-labs/aws-api.git
- scm:git:git@github.com:cognitect-labs/aws-api.git
- git@github.com:cognitect-labs/aws-api.git
-
-
+ 4.0.0
+ com.cognitect.aws
+ api
+ DEV
+ jar
+ aws-api
+ A Clojure API for the AWS API
+ http://github.com/cognitect-labs/aws-api
+
+
+ The Apache Software License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+
+
+
+
+ Cognitect
+ labs@cognitect.com
+ Cognitect
+ http://cognitect.com
+
+
+
+ scm:git:git@github.com:cognitect-labs/aws-api.git
+ scm:git:git@github.com:cognitect-labs/aws-api.git
+ git@github.com:cognitect-labs/aws-api.git
+
+
+
+ org.clojure
+ data.json
+ 1.0.0
+
+
+ org.clojure
+ clojure
+ 1.10.1
+
+
+ org.clojure
+ tools.logging
+ 1.1.0
+
+
+ com.cognitect
+ http-client
+ 0.1.105
+
+
+ org.clojure
+ data.xml
+ 0.2.0-alpha6
+
+
+ org.clojure
+ core.async
+ 1.3.610
+
+
+
+
+ autodoc
+
- org.clojure
- clojure
- 1.10.1
+ autodoc
+ autodoc
+ 0.9.0
+ test
-
- org.clojure
- core.async
- 0.4.490
-
-
- org.clojure
- tools.logging
- 0.4.0
-
-
- commons-codec
- commons-codec
- 1.11
-
-
- org.clojure
- data.json
- 0.2.6
-
-
- org.clojure
- data.xml
- 0.2.0-alpha6
-
-
- com.cognitect
- http-client
- 0.1.99
-
-
- autodoc
- autodoc
- 0.9.0
- test
-
-
-
-
-
- resources
-
-
- src
-
-
-
-
- dev-resources
-
-
- resources
-
-
- target
- target/classes
-
-
- com.theoryinpractise
- clojure-maven-plugin
- 1.7.1
- true
-
-
- src
-
-
- test
-
-
-
-
- org.sonatype.plugins
- nexus-staging-maven-plugin
- 1.6.2
- true
-
- ossrh
- https://oss.sonatype.org/
- true
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
- 2.9.1
-
-
- attach-javadocs
-
- jar
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
- 2.2.1
-
-
- attach-sources
-
- jar-no-fork
-
-
-
-
-
- org.apache.maven.plugins
- maven-gpg-plugin
- 1.6
-
-
- sign-artifacts
- verify
-
- sign
-
-
- gpg
-
- --pinentry-mode
- loopback
-
- ${gpg.passphrase}
-
-
-
-
-
-
-
- org.springframework.build
- aws-maven
- 5.0.0.RELEASE
-
-
- com.gkatzioura.maven.cloud
- s3-storage-wagon
- 1.0
-
-
- src
-
-
-
- clojars
- https://repo.clojars.org/
-
-
-
+
+
+
+
+
+
+ resources
+
+
+ src
+
+
+
+
+ dev-resources
+
+
+ resources
+
+
+ target
+ target/classes
+
+
+ com.theoryinpractise
+ clojure-maven-plugin
+ 1.7.1
+ true
+
+
+ src
+
+
+ test
+
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.2
+ true
+
+ ossrh
+ https://oss.sonatype.org/
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.9.1
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 2.2.1
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.6
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+ gpg
+
+ --pinentry-mode
+ loopback
+
+ ${gpg.passphrase}
+
+
+
+
+
+
+
+ org.springframework.build
+ aws-maven
+ 5.0.0.RELEASE
+
+
+ com.gkatzioura.maven.cloud
+ s3-storage-wagon
+ 1.0
+
+
+ src
+
+
+
+ clojars
+ https://repo.clojars.org/
+
+
diff --git a/src/cognitect/aws/client.clj b/src/cognitect/aws/client.clj
index 4be0dd3a..49c076da 100644
--- a/src/cognitect/aws/client.clj
+++ b/src/cognitect/aws/client.clj
@@ -5,11 +5,12 @@
"Impl, don't call directly."
(:require [clojure.core.async :as a]
[byte-streams :as byte-streams]
- [cognitect.aws
- [credentials :as credentials]
- [http :as http]
- [util :as util]
- [interceptors :as interceptors]]))
+ [cognitect.aws.http :as http]
+ [cognitect.aws.util :as util]
+ [cognitect.aws.interceptors :as interceptors]
+ [cognitect.aws.endpoint :as endpoint]
+ [cognitect.aws.region :as region]
+ [cognitect.aws.credentials :as credentials]))
(set! *warn-on-reflection* true)
@@ -36,7 +37,7 @@
(defmulti sign-http-request
"Sign the HTTP request."
- (fn [service region credentials http-request]
+ (fn [service endpoint credentials http-request]
(get-in service [:metadata :signatureVersion])))
;; TODO convey throwable back from impl
@@ -66,38 +67,66 @@
(defn http-request
"Creates a Ring request map that needs to be signed before being sent by `cognitect.http-client/submit`."
[client op-map]
- (let [{:keys [service endpoint]} (-get-info client)]
- (-> (build-http-request service op-map)
- (with-endpoint endpoint)
- (update :body #(some-> % byte-streams/to-byte-buffer))
- ((partial interceptors/modify-http-request service op-map)))))
+ (let [{:keys [service endpoint-provider region-provider]} (-get-info client)
+ region-ch (region/fetch-async region-provider)]
+ (a/go
+ (let [region (a/ (build-http-request service op-map)
+ (with-endpoint endpoint)
+ (update :body #(some-> % byte-streams/to-byte-buffer))
+ ((partial interceptors/modify-http-request service op-map))))))))
(defn sign-http-request-with-client
"Signs a request with a client and a request returned by `http-request`."
[client request]
- (let [{:keys [service region credentials]} (-get-info client)]
- (sign-http-request service region (credentials/fetch credentials) request)))
+ (let [{:keys [service region-provider credentials-provider]} (-get-info client)
+ creds-ch (credentials/fetch-async credentials-provider)
+ region-ch (region/fetch-async region-provider)]
+ (a/go
+ (let [region (a/ (handle-http-response service op-map %)
- with-meta? (with-meta (assoc @result-meta :http-response (dissoc % :body))))))]
- (swap! result-meta assoc :http-request req)
- (send-http req client op-map result-chan)
- result-chan)
- (catch Throwable t
- (let [err-ch (a/chan 1)]
- (a/put! err-ch (cond-> {:cognitect.anomalies/category :cognitect.anomalies/fault
- ::throwable t}
- with-meta? (with-meta @result-meta)))
- err-ch)))))
+ (let [{:keys [service http-client] :as client-info} (-get-info client)
+ response-meta (atom {})
+ result-ch (a/promise-chan (map #(cond-> (handle-http-response service op-map %)
+ with-meta? (with-meta (assoc @response-meta :http-response (dissoc % :body))))))
+ send-http (or (:send-http op-map)
+ (:send-http client-info))]
+
+ (a/go
+ (let [http-request (a/! result-ch http-request)
+ :else
+ (try
+ (swap! response-meta assoc :http-request http-request)
+ (send-http http-request http-client op-map result-ch)
+ result-ch
+ (catch Throwable t
+ (let [err-ch (a/promise-chan)]
+ (a/put! err-ch (cond-> {:cognitect.anomalies/category :cognitect.anomalies/fault
+ ::throwable t}
+ with-meta? (with-meta (swap! response-meta assoc :op-map op-map))))
+ err-ch))))))))
diff --git a/src/cognitect/aws/client/api.clj b/src/cognitect/aws/client/api.clj
index 4fc0015b..fdfb9f64 100644
--- a/src/cognitect/aws/client/api.clj
+++ b/src/cognitect/aws/client/api.clj
@@ -6,8 +6,10 @@
(:require [clojure.core.async :as async]
[clojure.tools.logging :as log]
[clojure.string :as str]
+ [cognitect.aws.dynaload :as dynaload]
[cognitect.aws.client :as client]
[cognitect.aws.retry :as retry]
+ [cognitect.aws.client.shared :as shared]
[cognitect.aws.credentials :as credentials]
[cognitect.aws.endpoint :as endpoint]
[cognitect.aws.http :as http]
@@ -37,9 +39,14 @@
:api - required, this or api-descriptor required, the name of the api
you want to interact with e.g. :s3, :cloudformation, etc
+ :http-client - optional, to share http-clients across aws-clients.
+ See default-http-client.
+ :region-provider - optional, implementation of aws-clojure.region/RegionProvider
+ protocol, defaults to cognitect.aws.region/default-region-provider.
+ Ignored if :region is also provided
:region - optional, the aws region serving the API endpoints you
want to interact with, defaults to region provided by
- by the default region provider (see `cognitect.aws.region`)
+ by the region-provider
:credentials-provider - optional, implementation of
`cognitect.aws.credentials/CredentialsProvider`
protocol, defaults to
@@ -76,6 +83,9 @@
(if the request is retriable?), or nil if it should stop.
Defaults to `cognitect.aws.retry/default-backoff`.
+ By default, all clients use shared http-client, credentials-provider, and
+ region-provider instances which use a small collection of daemon threads.
+
Alpha. Subject to change."
[{:keys [api region region-provider retriable? backoff http-client send-http credentials-provider endpoint-override]
:or {endpoint-override {}}
@@ -85,38 +95,38 @@
(format
"DEPRECATION NOTICE: :endpoint-override string is deprecated.\nUse {:endpoint-override {:hostname \"%s\"}} instead."
endpoint-override)))
- (let [service (service/service-description (name api))
- http-client (cond
- http-client http-client
- (not send-http) (http/resolve-http-client http-client))
- region (keyword
- (or region
- (region/fetch
- (or region-provider
- (region/default-region-provider (or http-client send-http))))))]
- (require (symbol (str "cognitect.aws.protocols." (get-in service [:metadata :protocol]))))
- (with-meta
- (client/->Client
- (atom {})
- {:service service
- :region region
- :endpoint (if-let [ep (endpoint/resolve (-> service :metadata :endpointPrefix keyword) region)]
- (merge ep (if (string? endpoint-override)
- {:hostname endpoint-override}
- endpoint-override))
- (throw (ex-info "No known endpoint." {:service api :region region})))
- :retriable? (or retriable? retry/default-retriable?)
- :backoff (or backoff retry/default-backoff)
- :send-http send-http
- :http-client http-client
- :credentials (or credentials-provider (credentials/global-provider (or send-http http-client)))})
- {'clojure.core.protocols/datafy (fn [c]
- (-> c
- client/-get-info
- (select-keys [:region :endpoint :service :send-http])
- (update :endpoint select-keys [:hostname :protocols :signatureVersions])
- (update :service select-keys [:metadata])
- (assoc :ops (ops c))))})))
+ (let [service (service/service-description (name api))
+ http-client (cond
+ http-client http-client
+ (not send-http) (shared/http-client))
+ region-provider (cond region (reify region/RegionProvider (fetch [_] region))
+ region-provider region-provider
+ :else (region/default-region-provider (or http-client send-http)))
+ credentials-provider (or credentials-provider (credentials/global-provider (or send-http http-client)))
+ endpoint-provider (endpoint/default-endpoint-provider
+ api
+ (get-in service [:metadata :endpointPrefix])
+ endpoint-override)]
+ (dynaload/load-ns (symbol (str "cognitect.aws.protocols." (get-in service [:metadata :protocol]))))
+ (client/->Client
+ (atom {'clojure.core.protocols/datafy (fn [c]
+ (let [i (client/-get-info c)]
+ (-> i
+ (select-keys [:service])
+ (assoc :region (-> i :region-provider region/fetch)
+ :endpoint (-> i :endpoint-provider endpoint/fetch))
+ (update :endpoint select-keys [:hostname :protocols :signatureVersions])
+ (update :service select-keys [:metadata])
+ (assoc :ops (ops c)))))})
+ {:service service
+ :retriable? (or retriable? retry/default-retriable?)
+ :backoff (or backoff retry/default-backoff)
+ :http-client http-client
+ :send-http send-http
+ :endpoint-provider endpoint-provider
+ :region-provider region-provider
+ :credentials-provider credentials-provider
+ :validate-requests? (atom nil)})))
(defn default-http-client
"Create an http-client to share across multiple aws-api clients."
@@ -148,14 +158,14 @@
Alpha. Subject to change."
[client op-map]
- (client/http-request client op-map))
+ (async/ client client/-get-info :service) op))
-(def ^:private pprint-ref (delay (util/dynaload 'clojure.pprint/pprint)))
+(def ^:private pprint-ref (delay (dynaload/load-var 'clojure.pprint/pprint)))
(defn ^:skip-wiki pprint
"For internal use. Don't call directly."
[& args]
@@ -202,13 +212,16 @@
representation.
Alpha. Subject to change."
- [{:keys [documentation request required response refs] :as doc}]
+ [{:keys [documentation documentationUrl request required response refs] :as doc}]
(when doc
(str/join "\n"
(cond-> ["-------------------------"
(:name doc)
""
documentation]
+ documentationUrl
+ (into [""
+ documentationUrl])
request
(into [""
"-------------------------"
@@ -240,15 +253,14 @@
(str "No docs for " (name operation)))))
(defn stop
- "Shuts down the underlying http-client, releasing resources.
+ "Has no effect when the underlying http-client is the shared
+ instance.
- NOTE: if you're sharing an http-client across aws-api clients,
- this will shut down the shared client for all aws-api clients
- that are using it.
+ If you explicitly provided any other instance of http-client, stops
+ it, releasing resources.
Alpha. Subject to change."
- [client]
- (some-> client
- client/-get-info
- :http-client
- http/stop))
+ [aws-client]
+ (let [{:keys [http-client]} (client/-get-info aws-client)]
+ (when-not (#'shared/shared-http-client? http-client)
+ (http/stop http-client))))
diff --git a/src/cognitect/aws/client/api/async.clj b/src/cognitect/aws/client/api/async.clj
index caa2c0e9..3f89c25d 100644
--- a/src/cognitect/aws/client/api/async.clj
+++ b/src/cognitect/aws/client/api/async.clj
@@ -7,29 +7,34 @@
[cognitect.aws.client :as client]
[cognitect.aws.retry :as retry]
[cognitect.aws.service :as service]
- [cognitect.aws.util :as util]))
+ [cognitect.aws.dynaload :as dynaload]))
-(def ^:private validate-requests? (atom {}))
+(set! *warn-on-reflection* true)
+
+(defn ^:skip-wiki validate-requests?
+ "For internal use. Don't call directly."
+ [client]
+ (some-> client client/-get-info :validate-requests? deref))
(defn ^:skip-wiki validate-requests
"For internal use. Don't call directly."
[client tf]
- (swap! validate-requests? assoc client tf)
+ (reset! (-> client client/-get-info :validate-requests?) tf)
(when tf
(service/load-specs (-> client client/-get-info :service)))
tf)
-(def ^:private registry-ref (delay (util/dynaload 'clojure.spec.alpha/registry)))
+(def ^:private registry-ref (delay (dynaload/load-var 'clojure.spec.alpha/registry)))
(defn ^:skip-wiki registry
"For internal use. Don't call directly."
[& args] (apply @registry-ref args))
-(def ^:private valid?-ref (delay (util/dynaload 'clojure.spec.alpha/valid?)))
+(def ^:private valid?-ref (delay (dynaload/load-var 'clojure.spec.alpha/valid?)))
(defn ^:skip-wiki valid?
"For internal use. Don't call directly."
[& args] (apply @valid?-ref args))
-(def ^:private explain-data-ref (delay (util/dynaload 'clojure.spec.alpha/explain-data)))
+(def ^:private explain-data-ref (delay (dynaload/load-var 'clojure.spec.alpha/explain-data)))
(defn ^:skip-wiki explain-data
"For internal use. Don't call directly."
[& args] (apply @explain-data-ref args))
@@ -55,18 +60,16 @@
[client op-map]
(let [result-chan (or (:ch op-map) (a/promise-chan))
{:keys [service retriable? backoff]} (client/-get-info client)
- validation-error (and (get @validate-requests? client)
+ validation-error (and (validate-requests? client)
(validate service op-map))]
(when-not (contains? (:operations service) (:op op-map))
(throw (ex-info "Operation not supported" {:service (keyword (service/service-name service))
:operation (:op op-map)})))
(if validation-error
- (do
- (a/put! result-chan validation-error)
- result-chan)
- (let [send #(client/send-request client op-map)
- retriable? (or (:retriable? op-map) retriable?)
- backoff (or (:backoff op-map) backoff)
- response-chan (retry/with-retry send (a/promise-chan) retriable? backoff)]
- (a/take! response-chan (partial a/put! result-chan))
- result-chan))))
+ (a/put! result-chan validation-error)
+ (retry/with-retry
+ #(client/send-request client op-map)
+ result-chan
+ (or (:retriable? op-map) retriable?)
+ (or (:backoff op-map) backoff)))
+ result-chan))
diff --git a/src/cognitect/aws/client/shared.clj b/src/cognitect/aws/client/shared.clj
new file mode 100644
index 00000000..46506637
--- /dev/null
+++ b/src/cognitect/aws/client/shared.clj
@@ -0,0 +1,49 @@
+(ns cognitect.aws.client.shared
+ (:require [cognitect.aws.http :as http]
+ [cognitect.aws.credentials :as credentials]
+ [cognitect.aws.region :as region]))
+
+(set! *warn-on-reflection* true)
+
+(declare http-client)
+
+(def ^:private shared-http-client
+ (delay (http/resolve-http-client nil)))
+
+(def ^:private shared-credentials-provider
+ (delay (credentials/default-credentials-provider (http-client))))
+
+(def ^:private shared-region-provider
+ (delay (region/default-region-provider (http-client))))
+
+(defn http-client
+ "Returns the globally shared instance of http-client (created on the
+ first call).
+
+ Alpha. Subject to change."
+ []
+ @shared-http-client)
+
+(defn credentials-provider
+ "Returns the globally shared instance of credentials-provider, which
+ uses the globally shared instance of http-client.
+
+ Alpha. Subject to change."
+ []
+ @shared-credentials-provider)
+
+(defn region-provider
+ "Returns the globally shared instance of region-provider, which
+ uses the globally shared instance of http-client.
+
+ Alpha. Subject to change."
+ []
+ @shared-region-provider)
+
+(defn ^:private shared-http-client?
+ "For internal use.
+
+ Alpha. Subject to change."
+ [candidate-http-client]
+ (identical? candidate-http-client
+ (and (realized? shared-http-client) @shared-http-client)))
diff --git a/src/cognitect/aws/credentials.clj b/src/cognitect/aws/credentials.clj
index 78d5924e..c72f8536 100644
--- a/src/cognitect/aws/credentials.clj
+++ b/src/cognitect/aws/credentials.clj
@@ -6,19 +6,22 @@
Alpha. Subject to change."
(:require [clojure.java.io :as io]
- [clojure.string :as str]
[clojure.tools.logging :as log]
+ [clojure.string :as str]
[cognitect.aws.util :as u]
[cognitect.aws.config :as config]
[cognitect.aws.ec2-metadata-utils :as ec2])
- (:import (java.util.concurrent Executors ScheduledExecutorService)
- (java.util.concurrent TimeUnit ThreadFactory)
+ (:import (java.util Date)
+ (java.util.concurrent Executors ExecutorService ScheduledExecutorService
+ ScheduledFuture TimeUnit ThreadFactory)
(java.io File)
(java.net URI)
(java.time Duration Instant)))
+(set! *warn-on-reflection* true)
+
(defprotocol CredentialsProvider
- (fetch [_]
+ (fetch [provider]
"Return the credentials found by this provider, or nil.
Credentials should be a map with the following keys:
@@ -37,59 +40,73 @@
;; Credentials subsystem
-(defn ^:skip-wiki auto-refresh-fn
- "For internal use. Don't call directly.
-
- Return the function to auto-refresh the `credentials` atom using the given `provider`.
-
- If the credentials return a ::ttl, schedule refresh after ::ttl seconds using `scheduler`.
-
- If the credentials returned by the provider are not valid, an error will be logged and
- the automatic refresh process will stop."
- [credentials provider scheduler]
- (fn refresh! []
- (try
- (let [{:keys [::ttl] :as new-creds} (fetch provider)]
- (reset! credentials new-creds)
- (when ttl
- (.schedule ^ScheduledExecutorService scheduler
- ^Runnable refresh!
- ^long ttl
- TimeUnit/SECONDS))
- new-creds)
- (catch Throwable t
- (log/error t "Error fetching the credentials.")))))
-
-(defn auto-refreshing-credentials
- "Create auto-refreshing credentials using the specified provider.
+(defonce ^:private scheduled-executor-service
+ (delay
+ (Executors/newScheduledThreadPool 1 (reify ThreadFactory
+ (newThread [_ r]
+ (doto (Thread. r)
+ (.setName "cognitect.aws-api.credentials-provider")
+ (.setDaemon true)))))))
- Return a derefable containing the credentials.
-
- Call `stop` to stop the auto-refreshing process.
+(defn ^:skip-wiki refresh!
+ "For internal use. Don't call directly.
- The default ScheduledExecutorService uses a ThreadFactory
- that spawns daemon threads. You can override this by
- providing your own ScheduledExecutorService.
+ Invokes `(fetch provider)`, resets the `credentials-atom` with and
+ returns the result.
+
+ If the result includes a ::ttl, schedules a refresh after ::ttl
+ seconds using `scheduler`, resetting `scheduled-refresh` with the
+ resulting `ScheduledFuture`.
+
+ If the credentials returned by the provider are not valid, resets
+ both atoms to nil and returns nil."
+ [credentials-atom scheduled-refresh-atom provider scheduler]
+ (try
+ (let [{:keys [::ttl] :as new-creds} (fetch provider)]
+ (reset! scheduled-refresh-atom
+ (when ttl
+ (.schedule ^ScheduledExecutorService scheduler
+ ^Runnable #(refresh! credentials-atom scheduled-refresh-atom provider scheduler)
+ ^long ttl
+ TimeUnit/SECONDS)))
+ (reset! credentials-atom new-creds))
+ (catch Throwable t
+ (reset! scheduled-refresh-atom nil)
+ (log/error t "Error fetching credentials."))))
+
+(defn cached-credentials-with-auto-refresh
+ "Returns a CredentialsProvider which wraps `provider`, caching
+ credentials returned by `fetch`, and auto-refreshing the cached
+ credentials in a background thread when the credentials include a
+ ::ttl.
+
+ Call `stop` to cancel future auto-refreshes.
+
+ The default ScheduledExecutorService uses a ThreadFactory that
+ spawns daemon threads. You can override this by providing your own
+ ScheduledExecutorService.
Alpha. Subject to change."
([provider]
- (auto-refreshing-credentials
- provider
- (Executors/newScheduledThreadPool 1 (reify ThreadFactory
- (newThread [_ r]
- (doto (Thread. r)
- (.setName "cognitect.aws-api.credentials.refresh")
- (.setDaemon true)))))))
+ (cached-credentials-with-auto-refresh provider @scheduled-executor-service))
([provider scheduler]
- (let [credentials (atom nil)
- auto-refresh! (auto-refresh-fn credentials provider scheduler)]
+ (let [credentials-atom (atom nil)
+ scheduled-refresh-atom (atom nil)]
(reify
CredentialsProvider
- (fetch [_] (or @credentials (auto-refresh!)))
+ (fetch [_]
+ (or @credentials-atom
+ (refresh! credentials-atom scheduled-refresh-atom provider scheduler)))
Stoppable
(-stop [_]
(-stop provider)
- (.shutdownNow ^ScheduledExecutorService scheduler))))))
+ (when-let [r @scheduled-refresh-atom]
+ (.cancel ^ScheduledFuture r true)))))))
+
+(defn ^:deprecated auto-refreshing-credentials
+ "Deprecated. Use cached-credentials-with-auto-refresh"
+ ([provider] (cached-credentials-with-auto-refresh provider))
+ ([provider scheduler] (cached-credentials-with-auto-refresh provider scheduler)))
(defn stop
"Stop auto-refreshing the credentials.
@@ -105,29 +122,24 @@
(valid-credentials credentials nil))
([{:keys [aws/access-key-id aws/secret-access-key] :as credentials}
credential-source]
- (cond (and (not (str/blank? access-key-id))
- (not (str/blank? secret-access-key)))
- credentials
-
- (or (str/blank? access-key-id) (str/blank? secret-access-key))
- (do
- (when-not (nil? credential-source)
- (log/debug (str "Unable to fetch credentials from " credential-source ".")))
- nil)
-
- :else
- nil)))
+ (if (and (not (str/blank? access-key-id))
+ (not (str/blank? secret-access-key)))
+ credentials
+ (when credential-source
+ (log/info (str "Unable to fetch credentials from " credential-source "."))
+ nil))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Providers
(defn chain-credentials-provider
- "Chain together multiple credentials provider.
+ "Returns a credentials-provider which chains together multiple
+ credentials providers.
- Calls each provider in order until one return a non-nil result. This
- provider is then cached for future calls to `fetch`.
+ `fetch` calls each provider in order until one returns a non-nil
+ result. This provider is then cached for future calls to `fetch`.
- Returns nil if none of the providers return credentials.
+ `fetch` returns nil if none of the providers return credentials.
Alpha. Subject to change."
[providers]
@@ -162,13 +174,14 @@
Alpha. Subject to change."
[]
- (reify CredentialsProvider
- (fetch [_]
- (valid-credentials
- {:aws/access-key-id (u/getenv "AWS_ACCESS_KEY_ID")
- :aws/secret-access-key (u/getenv "AWS_SECRET_ACCESS_KEY")
- :aws/session-token (u/getenv "AWS_SESSION_TOKEN")}
- "environment variables"))))
+ (cached-credentials-with-auto-refresh
+ (reify CredentialsProvider
+ (fetch [_]
+ (valid-credentials
+ {:aws/access-key-id (u/getenv "AWS_ACCESS_KEY_ID")
+ :aws/secret-access-key (u/getenv "AWS_SECRET_ACCESS_KEY")
+ :aws/session-token (u/getenv "AWS_SESSION_TOKEN")}
+ "environment variables")))))
(defn system-property-credentials-provider
"Return the credentials from the system properties.
@@ -184,12 +197,14 @@
Alpha. Subject to change. "
[]
- (reify CredentialsProvider
- (fetch [_]
- (valid-credentials
- {:aws/access-key-id (u/getProperty "aws.accessKeyId")
- :aws/secret-access-key (u/getProperty "aws.secretKey")}
- "system properties"))))
+ (cached-credentials-with-auto-refresh
+ (reify CredentialsProvider
+ (fetch [_]
+ (valid-credentials
+ {:aws/access-key-id (u/getProperty "aws.accessKeyId")
+ :aws/secret-access-key (u/getProperty "aws.secretKey")
+ :aws/session-token (u/getProperty "aws.sessionToken")}
+ "system properties")))))
(defn profile-credentials-provider
"Return credentials in an AWS configuration profile.
@@ -215,25 +230,35 @@
(profile-credentials-provider profile-name (or (io/file (u/getenv "AWS_CREDENTIAL_PROFILES_FILE"))
(io/file (u/getProperty "user.home") ".aws" "credentials"))))
([profile-name ^File f]
- (reify CredentialsProvider
- (fetch [_]
- (when (.exists f)
- (try
- (let [profile (get (config/parse f) profile-name)]
- (valid-credentials
- {:aws/access-key-id (get profile "aws_access_key_id")
- :aws/secret-access-key (get profile "aws_secret_access_key")
- :aws/session-token (get profile "aws_session_token")}
- "aws profiles file"))
- (catch Throwable t
- (log/error t "Error fetching credentials from aws profiles file"))))))))
-
-(defn ^:skip-wiki calculate-ttl
- "For internal use. Don't call directly."
- [credentials]
- (if-let [expiration (some-> credentials :Expiration Instant/parse)]
- (max (- (.getSeconds (Duration/between (Instant/now) ^Instant expiration)) 300)
- 60)
+ (cached-credentials-with-auto-refresh
+ (reify CredentialsProvider
+ (fetch [_]
+ (when (.exists f)
+ (try
+ (let [profile (get (config/parse f) profile-name)]
+ (valid-credentials
+ {:aws/access-key-id (get profile "aws_access_key_id")
+ :aws/secret-access-key (get profile "aws_secret_access_key")
+ :aws/session-token (get profile "aws_session_token")}
+ "aws profiles file"))
+ (catch Throwable t
+ (log/error t "Error fetching credentials from aws profiles file")))))))))
+
+(defn calculate-ttl
+ "Primarily for internal use, returns time to live (ttl, in seconds),
+ based on `:Expiration` in credentials. If `credentials` contains no
+ `:Expiration`, defaults to 3600.
+
+ `:Expiration` can be a string parsable by java.time.Instant/parse
+ (returned by ec2/ecs instance credentials) or a java.util.Date
+ (returned from :AssumeRole on aws sts client)."
+ [{:keys [Expiration] :as credentials}]
+ (if Expiration
+ (let [expiration (if (instance? Date Expiration)
+ (.toInstant ^Date Expiration)
+ (Instant/parse Expiration))]
+ (max (- (.getSeconds (Duration/between (Instant/now) ^Instant expiration)) 300)
+ 60))
3600))
(defn container-credentials-provider
@@ -245,7 +270,7 @@
Alpha. Subject to change."
[client-or-send-http]
- (auto-refreshing-credentials
+ (cached-credentials-with-auto-refresh
(reify CredentialsProvider
(fetch [_]
(when-let [creds (ec2/container-credentials client-or-send-http)]
@@ -266,7 +291,7 @@
Alpha. Subject to change."
[client-or-send-http]
- (auto-refreshing-credentials
+ (cached-credentials-with-auto-refresh
(reify CredentialsProvider
(fetch [_]
(when-let [creds (ec2/instance-credentials client-or-send-http)]
@@ -278,7 +303,7 @@
"ec2 instance"))))))
(defn default-credentials-provider
- "Return a chain-credentials-provider comprising, in order:
+ "Returns a chain-credentials-provider with (in order):
environment-credentials-provider
system-property-credentials-provider
@@ -311,3 +336,11 @@
(fetch [_]
{:aws/access-key-id access-key-id
:aws/secret-access-key secret-access-key})))
+
+(defn fetch-async
+ "Returns a channel that will produce the result of calling fetch on
+ the provider.
+
+ Alpha. Subject to change."
+ [provider]
+ (u/fetch-async fetch provider "credentials"))
diff --git a/src/cognitect/aws/dynaload.clj b/src/cognitect/aws/dynaload.clj
new file mode 100644
index 00000000..3d54ad47
--- /dev/null
+++ b/src/cognitect/aws/dynaload.clj
@@ -0,0 +1,17 @@
+(ns ^:skip-wiki cognitect.aws.dynaload)
+
+(set! *warn-on-reflection* true)
+
+(defonce ^:private dynalock (Object.))
+
+(defn load-ns [ns]
+ (locking dynalock
+ (require (symbol ns))))
+
+(defn load-var
+ [s]
+ (let [ns (namespace s)]
+ (assert ns)
+ (load-ns ns)
+ (or (resolve s)
+ (throw (RuntimeException. (str "Var " s " is not on the classpath"))))))
diff --git a/src/cognitect/aws/ec2_metadata_utils.clj b/src/cognitect/aws/ec2_metadata_utils.clj
index 59e8fe4a..caa6e6a6 100644
--- a/src/cognitect/aws/ec2_metadata_utils.clj
+++ b/src/cognitect/aws/ec2_metadata_utils.clj
@@ -11,6 +11,8 @@
[cognitect.aws.retry :as retry])
(:import (java.net URI)))
+(set! *warn-on-reflection* true)
+
(def ^:const ec2-metadata-service-override-system-property "com.amazonaws.sdk.ec2MetadataServiceEndpointOverride")
(def ^:const dynamic-data-root "/latest/dynamic/")
(def ^:const security-credentials-path "/latest/meta-data/iam/security-credentials/")
diff --git a/src/cognitect/aws/endpoint.clj b/src/cognitect/aws/endpoint.clj
index b744b585..e1e79404 100644
--- a/src/cognitect/aws/endpoint.clj
+++ b/src/cognitect/aws/endpoint.clj
@@ -7,9 +7,13 @@
(:require [clojure.string :as str]
[clojure.java.io :as io]
[clojure.edn :as edn]
+ [clojure.core.async :as a]
[cognitect.aws.service :as service]
+ [cognitect.aws.region :as region]
[cognitect.aws.util :as util]))
+(set! *warn-on-reflection* true)
+
(defn descriptor-resource-path [] (format "%s/endpoints.edn" service/base-resource-path))
(defn read-endpoints-description []
@@ -30,28 +34,28 @@
(defn service-resolve
"Resolve the endpoint for the given service."
- [partition service-name service endpoint-key]
- (let [endpoint (get-in service [:endpoints endpoint-key])
- endpoint-name (name endpoint-key)
- result (merge (:defaults partition)
- (:defaults service)
- endpoint
- {:partition (:partition partition)
- :endpoint-name endpoint-name
- :dnsSuffix (:dnsSuffix partition)})]
+ [partition service-name service region-key]
+ (let [endpoint (get-in service [:endpoints region-key])
+ region (name region-key)
+ result (merge (:defaults partition)
+ (:defaults service)
+ endpoint
+ {:partition (:partition partition)
+ :region region
+ :dnsSuffix (:dnsSuffix partition)})]
(util/map-vals #(render-template % {"service" service-name
- "region" endpoint-name
+ "region" region
"dnsSuffix" (:dnsSuffix partition)})
result
[:hostname :sslCommonName])))
(defn partition-resolve
[{:keys [services] :as partition} service-key region-key]
- (let [{:keys [partitionEndpoint isRegionalized] :as service} (get services service-key)
- endpoint-key (if (and partitionEndpoint (not isRegionalized))
- (keyword partitionEndpoint)
- region-key)]
- (when (contains? (-> partition :regions keys set) (keyword region-key))
+ (when (contains? (-> partition :regions keys set) region-key)
+ (let [{:keys [partitionEndpoint isRegionalized] :as service} (get services service-key)
+ endpoint-key (if (and partitionEndpoint (not isRegionalized))
+ (keyword partitionEndpoint)
+ region-key)]
(service-resolve partition (name service-key) service endpoint-key))))
(defn resolve*
@@ -63,14 +67,32 @@
Return a map with the following keys:
:partition The name of the partition.
- :endpoint-name The name of the endpoint.
+ :region The region of the endpoint.
:hostname The hostname to use.
- :ssl-common-name The ssl-common-name to use (optional).
- :credential-scope The Signature v4 credential scope (optional).
- :signature-versions A list of possible signature versions (optional).
+ :sslCommonName The sslCommonName to use (optional).
+ :credentialScope The Signature v4 credential scope (optional).
+ :signatureVersions A list of possible signature versions (optional).
:protocols A list of supported protocols."
- [service region]
- (some #(partition-resolve % service region)
+ [service-key region]
+ (some #(partition-resolve % service-key region)
(:partitions (resolver))))
(def resolve (memoize resolve*))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defprotocol EndpointProvider
+ (-fetch [provider region]))
+
+(defn default-endpoint-provider [api endpointPrefix endpoint-override]
+ (reify EndpointProvider
+ (-fetch [_ region]
+ (if-let [ep (resolve (keyword endpointPrefix) (keyword region))]
+ (merge ep (if (string? endpoint-override)
+ {:hostname endpoint-override}
+ endpoint-override))
+ {:cognitect.anomalies/category :cognitect.anomalies/fault
+ :cognitect.anomalies/message "No known endpoint."}))))
+
+(defn fetch [provider region]
+ (-fetch provider region))
diff --git a/src/cognitect/aws/http.clj b/src/cognitect/aws/http.clj
index a7cf3caf..adc15d0a 100644
--- a/src/cognitect/aws/http.clj
+++ b/src/cognitect/aws/http.clj
@@ -1,7 +1,10 @@
(ns ^:skip-wiki cognitect.aws.http
"Impl, don't call directly."
(:require [clojure.edn :as edn]
- [clojure.core.async :as a]))
+ [clojure.core.async :as a]
+ [cognitect.aws.dynaload :as dynaload]))
+
+(set! *warn-on-reflection* true)
(defprotocol HttpClient
(-submit [_ request channel]
@@ -42,6 +45,9 @@
(-submit client request channel)))
(defn stop
+ "Stops the client, releasing resources.
+
+ Alpha. Subject to change."
[client]
(-stop client))
@@ -53,18 +59,6 @@
[url]
(-> url slurp edn/read-string))
-(defonce ^:private dynalock (Object.))
-
-(defn- dynaload
- [s]
- (let [ns (namespace s)]
- (assert ns)
- (locking dynalock
- (require (symbol ns)))
- (if-let [v (resolve s)]
- @v
- (throw (RuntimeException. (str "Var " s " is not on the classpath"))))))
-
;; TODO consider providing config arguments to http constructor
(defn- configured-client
"If a single cognitect_aws_http.edn is found on the classpath,
@@ -84,9 +78,11 @@
(defn resolve-http-client
[http-client-or-sym]
(let [c (or (when (symbol? http-client-or-sym)
- ((dynaload http-client-or-sym)))
+ (let [ctor @(dynaload/load-var http-client-or-sym)]
+ (ctor)))
http-client-or-sym
- ((dynaload (configured-client))))]
+ (let [ctor @(dynaload/load-var (configured-client))]
+ (ctor)))]
(when-not (client? c)
(throw (ex-info "not an http client" {:provided http-client-or-sym
:resolved c})))
diff --git a/src/cognitect/aws/http/cognitect.clj b/src/cognitect/aws/http/cognitect.clj
index 6bb7d5ab..e9f40960 100644
--- a/src/cognitect/aws/http/cognitect.clj
+++ b/src/cognitect/aws/http/cognitect.clj
@@ -2,6 +2,8 @@
(:require [cognitect.http-client :as impl]
[cognitect.aws.http :as aws]))
+(set! *warn-on-reflection* true)
+
(defn create
[]
(let [c (impl/create {:trust-all true})] ;; FIX :trust-all
diff --git a/src/cognitect/aws/interceptors.clj b/src/cognitect/aws/interceptors.clj
index e4faed1a..61e494bf 100644
--- a/src/cognitect/aws/interceptors.clj
+++ b/src/cognitect/aws/interceptors.clj
@@ -6,6 +6,8 @@
(:require [cognitect.aws.service :as service]
[cognitect.aws.util :as util]))
+(set! *warn-on-reflection* true)
+
(defmulti modify-http-request (fn [service op-map http-request]
(service/service-name service)))
diff --git a/src/cognitect/aws/protocols/common.clj b/src/cognitect/aws/protocols/common.clj
index 77f15f97..5909ea9a 100644
--- a/src/cognitect/aws/protocols/common.clj
+++ b/src/cognitect/aws/protocols/common.clj
@@ -6,6 +6,8 @@
(:require [cognitect.aws.util :as util])
(:import (java.util Date)))
+(set! *warn-on-reflection* true)
+
(def status-codes->anomalies
{403 :cognitect.anomalies/forbidden
404 :cognitect.anomalies/not-found
diff --git a/src/cognitect/aws/protocols/ec2.clj b/src/cognitect/aws/protocols/ec2.clj
index 8f696f2e..5777b6ee 100644
--- a/src/cognitect/aws/protocols/ec2.clj
+++ b/src/cognitect/aws/protocols/ec2.clj
@@ -11,11 +11,13 @@
[cognitect.aws.protocols.common :as common]
[cognitect.aws.protocols.query :as query]))
+(set! *warn-on-reflection* true)
+
(defn serialized-name
[shape default]
(or (:queryName shape)
(when-let [name (:locationName shape)]
- (apply str (Character/toUpperCase (first name)) (rest name)))
+ (apply str (Character/toUpperCase ^Character (first name)) (rest name)))
default))
(defmulti serialize
diff --git a/src/cognitect/aws/protocols/json.clj b/src/cognitect/aws/protocols/json.clj
index e689d1e2..588d4258 100644
--- a/src/cognitect/aws/protocols/json.clj
+++ b/src/cognitect/aws/protocols/json.clj
@@ -9,6 +9,8 @@
[cognitect.aws.shape :as shape]
[cognitect.aws.protocols.common :as common]))
+(set! *warn-on-reflection* true)
+
(defmulti serialize
(fn [_ shape data] (:type shape)))
diff --git a/src/cognitect/aws/protocols/query.clj b/src/cognitect/aws/protocols/query.clj
index 948129b3..fb10cb21 100644
--- a/src/cognitect/aws/protocols/query.clj
+++ b/src/cognitect/aws/protocols/query.clj
@@ -10,6 +10,8 @@
[cognitect.aws.util :as util]
[cognitect.aws.protocols.common :as common]))
+(set! *warn-on-reflection* true)
+
; ----------------------------------------------------------------------------------------
;; Serializer
;; ----------------------------------------------------------------------------------------
diff --git a/src/cognitect/aws/protocols/rest.clj b/src/cognitect/aws/protocols/rest.clj
index d3780a9f..90a99ea1 100644
--- a/src/cognitect/aws/protocols/rest.clj
+++ b/src/cognitect/aws/protocols/rest.clj
@@ -14,6 +14,8 @@
[cognitect.aws.shape :as shape])
(:import java.util.Date))
+(set! *warn-on-reflection* true)
+
;; ----------------------------------------------------------------------------------------
;; Serializer
;; ----------------------------------------------------------------------------------------
@@ -27,13 +29,13 @@
[uri-template {:keys [required] :as input-shape} args]
(str/replace uri-template
#"\{([^}]+)\}"
- (fn [[_ param]]
+ (fn [[_ ^String param]]
(or (if (.endsWith param "+")
(some-> args
(get (keyword (.substring param 0 (dec (count param)))))
util/url-encode
- (.replace "%2F" "/")
- (.replace "%7E" "~")
+ (str/replace "%2F" "/")
+ (str/replace "%7E" "~")
remove-leading-slash)
(some-> args
(get (keyword param))
@@ -52,7 +54,7 @@
(defn append-querystring
"Append the map of arguments args to the uri's querystring."
- [uri shape args]
+ [^String uri shape args]
(if-let [qs (util/query-string (mapcat (fn [[k v]]
(when-let [member-shape (shape/member-shape shape k)]
(serialize-qs-args member-shape
@@ -194,10 +196,10 @@
:else data))
(defmethod parse-header-value "character" [_ data] (or data ""))
(defmethod parse-header-value "boolean" [_ data] (= data "true"))
-(defmethod parse-header-value "double" [_ data] (Double. data))
-(defmethod parse-header-value "float" [_ data] (Double. data))
-(defmethod parse-header-value "long" [_ data] (Long. data))
-(defmethod parse-header-value "integer" [_ data] (Long. data))
+(defmethod parse-header-value "double" [_ data] (Double/parseDouble ^String data))
+(defmethod parse-header-value "float" [_ data] (Double/parseDouble ^String data))
+(defmethod parse-header-value "long" [_ data] (Long/parseLong ^String data))
+(defmethod parse-header-value "integer" [_ data] (Long/parseLong ^String data))
(defmethod parse-header-value "blob" [_ data] (util/base64-decode data))
(defmethod parse-header-value "timestamp"
[shape data]
diff --git a/src/cognitect/aws/protocols/rest_json.clj b/src/cognitect/aws/protocols/rest_json.clj
index bf5115e9..94c0b96a 100644
--- a/src/cognitect/aws/protocols/rest_json.clj
+++ b/src/cognitect/aws/protocols/rest_json.clj
@@ -10,6 +10,8 @@
[cognitect.aws.protocols.common :as common]
[cognitect.aws.protocols.rest :as rest]))
+(set! *warn-on-reflection* true)
+
(defmulti serialize
(fn [_ shape data] (:type shape)))
diff --git a/src/cognitect/aws/protocols/rest_xml.clj b/src/cognitect/aws/protocols/rest_xml.clj
index 4f0b97f9..0e4b7879 100644
--- a/src/cognitect/aws/protocols/rest_xml.clj
+++ b/src/cognitect/aws/protocols/rest_xml.clj
@@ -8,6 +8,8 @@
[cognitect.aws.protocols.common :as common]
[cognitect.aws.protocols.rest :as rest]))
+(set! *warn-on-reflection* true)
+
(defmethod client/build-http-request "rest-xml"
[{:keys [shapes operations metadata] :as service} op-map]
(rest/build-http-request service
diff --git a/src/cognitect/aws/region.clj b/src/cognitect/aws/region.clj
index 42452e4a..d7264d2c 100644
--- a/src/cognitect/aws/region.clj
+++ b/src/cognitect/aws/region.clj
@@ -6,10 +6,13 @@
(:require [clojure.string :as str]
[clojure.java.io :as io]
[clojure.tools.logging :as log]
+ [clojure.core.async :as a]
[cognitect.aws.util :as u]
[cognitect.aws.config :as config]
[cognitect.aws.ec2-metadata-utils :as ec2])
- (:import [java.io File]))
+ (:import (java.io File)))
+
+(set! *warn-on-reflection* true)
(defn ^:skip-wiki valid-region
"For internal use. Don't call directly.
@@ -25,9 +28,8 @@
(defn chain-region-provider
"Chain together multiple region providers.
- Calls each provider in order until one return a non-nil result.
-
- Returns nil if none of the providers return a region.
+ `fetch` calls each provider in order until one returns a non-nil result,
+ or returns nil.
Alpha. Subject to change."
[providers]
@@ -38,7 +40,7 @@
{:providers (map class providers)}))))))
(defn environment-region-provider
- "Return the region from the AWS_REGION env var, or nil if not present.
+ "Returns the region from the AWS_REGION env var, or nil if not present.
Alpha. Subject to change."
[]
@@ -46,7 +48,7 @@
(fetch [_] (valid-region (u/getenv "AWS_REGION")))))
(defn system-property-region-provider
- "Return the region from the aws.region system property, or nil if not present.
+ "Returns the region from the aws.region system property, or nil if not present.
Alpha. Subject to change."
[]
@@ -54,7 +56,7 @@
(fetch [_] (valid-region (u/getProperty "aws.region")))))
(defn profile-region-provider
- "Return the region in a AWS configuration profile.
+ "Returns the region from an AWS configuration profile.
Arguments:
@@ -84,17 +86,19 @@
(log/error t "Unable to fetch region from the AWS config file " (str f)))))))))
(defn instance-region-provider
- "Return the region from the ec2 instance's metadata service,
+ "Returns the region from the ec2 instance's metadata service,
or nil if the service can not be found.
Alpha. Subject to change."
[http-client]
- (reify RegionProvider
- (fetch [_] (valid-region (ec2/get-ec2-instance-region http-client)))))
-
+ (let [cached-region (atom nil)]
+ (reify RegionProvider
+ (fetch [_]
+ (or @cached-region
+ (reset! cached-region (valid-region (ec2/get-ec2-instance-region http-client))))))))
(defn default-region-provider
- "Return a chain-region-provider comprising, in order:
+ "Returns a chain-region-provider with, in order:
environment-region-provider
system-property-region-provider
@@ -108,3 +112,11 @@
(system-property-region-provider)
(profile-region-provider)
(instance-region-provider http-client)]))
+
+(defn fetch-async
+ "Returns a channel that will produce the result of calling fetch on
+ the provider.
+
+ Alpha. Subject to change."
+ [provider]
+ (u/fetch-async fetch provider "region"))
diff --git a/src/cognitect/aws/retry.clj b/src/cognitect/aws/retry.clj
index dcf34e70..33ca919b 100644
--- a/src/cognitect/aws/retry.clj
+++ b/src/cognitect/aws/retry.clj
@@ -4,13 +4,15 @@
(ns cognitect.aws.retry
(:require [clojure.core.async :as a]))
+(set! *warn-on-reflection* true)
+
(defn ^:skip-wiki with-retry
"For internal use. Do not call directly.
- Calls req-fn, a function that wraps some operation and returns a
- channel. When the response to req-fn is retriable? and backoff
- returns an int, waits backoff ms and retries, otherwise puts
- response on resp-chan."
+ Calls req-fn, a *non-blocking* function that wraps some operation
+ and returns a channel. When the response to req-fn is retriable?
+ and backoff returns an int, waits backoff ms and retries, otherwise
+ puts response on resp-chan."
[req-fn resp-chan retriable? backoff]
(a/go-loop [retries 0]
(let [resp (a/> formats
+ (map #(try (util/parse-date % d) (catch java.text.ParseException _ nil)))
+ (filter identity)
+ first))
+
(defn parse-date
- [shape data]
- (condp = (:timestampFormat shape)
- "rfc822" (util/parse-date util/rfc822-date-format data)
- "iso8601" (util/parse-date util/iso8601-date-format data)
- (cond (int? data)
- (java.util.Date. (* 1000 data))
+ [{:keys [timestampFormat]} data]
+ (when data
+ (cond (= "rfc822" timestampFormat)
+ (parse-date* data util/rfc822-date-format)
+ (= "iso8601" timestampFormat)
+ (parse-date* data
+ util/iso8601-date-format
+ util/iso8601-msecs-date-format)
+ (int? data)
+ (java.util.Date. (* 1000 ^int data))
(double? data)
(java.util.Date. (* 1000 (long data)))
(re-matches #"^\d+$" data)
- (java.util.Date. (* 1000 (read-string data)))
+ (java.util.Date. (* 1000 (long (read-string data))))
:else
- (->> [util/iso8601-date-format
- util/iso8601-msecs-date-format
- util/rfc822-date-format]
- (map #(try (util/parse-date % data) (catch java.text.ParseException _ nil)))
- (filter identity)
- first))))
+ (parse-date* data
+ util/iso8601-date-format
+ util/iso8601-msecs-date-format
+ util/rfc822-date-format))))
;; ----------------------------------------------------------------------------------------
;; JSON Parser & Serializer
@@ -396,10 +406,10 @@
(defmethod xml-parse* "string" [_ nodes] (or (data nodes) ""))
(defmethod xml-parse* "character" [_ nodes] (or (data nodes) ""))
(defmethod xml-parse* "boolean" [_ nodes] (= (data nodes) "true"))
-(defmethod xml-parse* "double" [_ nodes] (Double. (data nodes)))
-(defmethod xml-parse* "float" [_ nodes] (Double. (data nodes)))
-(defmethod xml-parse* "long" [_ nodes] (Long. (data nodes)))
-(defmethod xml-parse* "integer" [_ nodes] (Long. (data nodes)))
+(defmethod xml-parse* "double" [_ nodes] (Double/parseDouble ^String (data nodes)))
+(defmethod xml-parse* "float" [_ nodes] (Double/parseDouble ^String (data nodes)))
+(defmethod xml-parse* "long" [_ nodes] (Long/parseLong ^String (data nodes)))
+(defmethod xml-parse* "integer" [_ nodes] (Long/parseLong ^String (data nodes)))
(defmethod xml-parse* "blob" [_ nodes] (util/base64-decode (data nodes)))
(defmethod xml-parse* "timestamp"
[shape nodes]
diff --git a/src/cognitect/aws/signers.clj b/src/cognitect/aws/signers.clj
index ff5ef6b3..89fd5c55 100644
--- a/src/cognitect/aws/signers.clj
+++ b/src/cognitect/aws/signers.clj
@@ -138,16 +138,14 @@
(string-to-sign request auth-info))))
(defn v4-sign-http-request
- [service region credentials http-request & {:keys [content-sha256-header?]}]
+ [service endpoint credentials http-request & {:keys [content-sha256-header?]}]
(let [{:keys [:aws/access-key-id :aws/secret-access-key :aws/session-token]} credentials
auth-info {:access-key-id access-key-id
:secret-access-key secret-access-key
:service (or (service/signing-name service)
(service/endpoint-prefix service))
- :region (if (and (-> service :metadata :globalEndpoint)
- (not= "s3" (service/service-name service)))
- "us-east-1"
- (name region))}
+ :region (or (get-in endpoint [:credentialScope :region])
+ (:region endpoint))}
req (cond-> http-request
session-token (assoc-in [:headers "x-amz-security-token"] session-token)
content-sha256-header? (assoc-in [:headers "x-amz-content-sha256"] (hashed-body http-request)))]
@@ -160,13 +158,13 @@
(signature auth-info req)))))
(defmethod client/sign-http-request "v4"
- [service region credentials http-request]
- (v4-sign-http-request service region credentials http-request))
+ [service endpoint credentials http-request]
+ (v4-sign-http-request service endpoint credentials http-request))
(defmethod client/sign-http-request "s3"
- [service region credentials http-request]
- (v4-sign-http-request service region credentials http-request :content-sha256-header? true))
+ [service endpoint credentials http-request]
+ (v4-sign-http-request service endpoint credentials http-request :content-sha256-header? true))
(defmethod client/sign-http-request "s3v4"
- [service region credentials http-request]
- (v4-sign-http-request service region credentials http-request :content-sha256-header? true))
+ [service endpoint credentials http-request]
+ (v4-sign-http-request service endpoint credentials http-request :content-sha256-header? true))
diff --git a/src/cognitect/aws/util.clj b/src/cognitect/aws/util.clj
index fb87c827..4b4b6cca 100644
--- a/src/cognitect/aws/util.clj
+++ b/src/cognitect/aws/util.clj
@@ -7,14 +7,15 @@
[clojure.data.xml :as xml]
[jsonista.core :as json]
[byte-streams :as byte-streams]
+ [clojure.core.async :as a]
[clojure.java.io :as io])
- (:import [java.text SimpleDateFormat]
+ (:import [java.util.concurrent Executors ExecutorService ThreadFactory]
+ [java.text SimpleDateFormat]
[java.util Date TimeZone]
[java.util UUID]
[java.io InputStream]
[java.nio.charset Charset]
[java.security MessageDigest]
- [org.apache.commons.codec.binary Hex]
[javax.crypto Mac]
[javax.crypto.spec SecretKeySpec]
[java.nio ByteBuffer]
@@ -64,9 +65,19 @@
(def ^ThreadLocal rfc822-date-format
(date-format "EEE, dd MMM yyyy HH:mm:ss z"))
-(defn hex-encode
- [^bytes bytes]
- (String. (Hex/encodeHex bytes true)))
+(let [hex-chars (char-array [\0 \1 \2 \3 \4 \5 \6 \7 \8 \9 \a \b \c \d \e \f])]
+ (defn hex-encode
+ [^bytes bytes]
+ (let [bl (alength bytes)
+ ca (char-array (* 2 bl))]
+ (loop [i (int 0)
+ c (int 0)]
+ (if (< i bl)
+ (let [b (long (bit-and (long (aget bytes i)) 255))]
+ (aset ca c ^char (aget hex-chars (unsigned-bit-shift-right b 4)))
+ (aset ca (unchecked-inc-int c) (aget hex-chars (bit-and b 15)))
+ (recur (unchecked-inc-int i) (unchecked-add-int c 2)))
+ (String. ca))))))
(defn sha-256
"Returns the sha-256 digest (bytes) of data, which can be a
@@ -229,19 +240,25 @@
(or data {})
(:members shape)))
-(defonce ^:private dynalock (Object.))
-
-(defn dynaload
- [s]
- (let [ns (namespace s)]
- (assert ns)
- (locking dynalock
- (require (symbol ns)))
- (let [v (resolve s)]
- (if v
- @v
- (throw (RuntimeException. (str "Var " s " is not on the classpath")))))))
-
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; used to fetch creds and region
+
+(defn fetch-async
+ "Internal use. Do not call directly."
+ [fetch provider item]
+ (a/thread
+ (try
+ ;; lock on the provider to avoid redundant concurrent requests
+ ;; before the provider has a chance to cache the results of the
+ ;; first fetch.
+ (or (locking provider
+ (fetch provider))
+ {:cognitect.anomalies/category :cognitect.anomalies/fault
+ :cognitect.anomalies/message (format "Unable to fetch %s. See log for more details." item)})
+ (catch Throwable t
+ {:cognitect.anomalies/category :cognitect.anomalies/fault
+ ::throwable t
+ :cognitect.anomalies/message (format "Unable to fetch %s." item)}))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Wrappers - here to support testing with-redefs since
diff --git a/test/resources/cognitect/protocols/output/rest-xml.json b/test/resources/cognitect/protocols/output/rest-xml.json
index 0c846334..1a777bae 100644
--- a/test/resources/cognitect/protocols/output/rest-xml.json
+++ b/test/resources/cognitect/protocols/output/rest-xml.json
@@ -32,5 +32,40 @@
}
}
]
+ },
+ {
+ "description": "Single string in payload",
+ "metadata": {"protocol": "rest-xml"},
+ "shapes": {
+ "OutputShape": {
+ "type": "structure",
+ "members": {
+ "Data": {
+ "shape": "DataShape"
+ }
+ },
+ "payload" : "Data"
+ },
+ "DataShape": {
+ "type": "string"
+ }
+ },
+ "cases": [
+ {
+ "given": {
+ "output": {
+ "shape": "OutputShape"
+ },
+ "name": "OperationName"
+ },
+ "result": {
+ "Data": "{\"a\":1}"
+ },
+ "response": {
+ "status_code": 200,
+ "body": "{\"a\":1}"
+ }
+ }
+ ]
}
]
diff --git a/test/src/cognitect/aws/api_test.clj b/test/src/cognitect/aws/api_test.clj
new file mode 100644
index 00000000..ab250830
--- /dev/null
+++ b/test/src/cognitect/aws/api_test.clj
@@ -0,0 +1,33 @@
+(ns cognitect.aws.api-test
+ (:require [clojure.test :as t :refer [deftest testing is]]
+ [cognitect.aws.client :as client]
+ [cognitect.aws.http :as http]
+ [cognitect.aws.client.api :as aws]
+ [cognitect.aws.client.shared :as shared]))
+
+(deftest test-underlying-http-client
+ (testing "defaults to shared client"
+ (let [clients (repeatedly 5 #(aws/client {:api :s3 :region "us-east-1"}))]
+ (is (= #{(shared/http-client)}
+ (into #{(shared/http-client)}
+ (->> clients (map (fn [c] (-> c client/-get-info :http-client))))))))))
+
+(deftest test-stop
+ (let [call-count (atom 0)
+ default (aws/client {:api :s3 :region "us-east-1"})
+ supplied-shared (aws/client {:api :s3 :region "us-east-1"
+ :http-client (shared/http-client)})
+ supplied-unshared (aws/client {:api :s3 :region "us-east-1"
+ :http-client (http/resolve-http-client nil)})]
+ (with-redefs [http/stop (fn [_] (swap! call-count inc))]
+ (testing "has no effect when aws-client uses the default shared http-client"
+ (aws/stop default)
+ (is (zero? @call-count)))
+ (testing "has no effect when user supplies the shared http-client"
+ (aws/stop supplied-shared)
+ (is (zero? @call-count)))
+ (testing "forwards to http/stop when user supplies a different http-client"
+ (aws/stop supplied-unshared)
+ (is (= 1 @call-count))))
+ ;; now actually stop the aws-client with the non-shared http-client
+ (aws/stop supplied-unshared)))
diff --git a/test/src/cognitect/aws/client_test.clj b/test/src/cognitect/aws/client_test.clj
new file mode 100644
index 00000000..bf670698
--- /dev/null
+++ b/test/src/cognitect/aws/client_test.clj
@@ -0,0 +1,94 @@
+(ns cognitect.aws.client-test
+ (:require [clojure.test :as t :refer [deftest testing is]]
+ [cognitect.aws.client.api :as aws]
+ [cognitect.aws.client :as client]
+ [cognitect.aws.client.api.async :as api.async]
+ [cognitect.aws.http :as http]
+ [cognitect.aws.region :as region]
+ [cognitect.aws.credentials :as creds]
+ [clojure.core.async :as a]))
+
+(defn stub-http-client [result]
+ (reify http/HttpClient
+ (-submit [_ _ ch]
+ (a/go (a/>! ch result))
+ ch)
+ (-stop [_])))
+
+(defn stub-credentials-provider [creds]
+ (reify creds/CredentialsProvider
+ (fetch [_] creds)))
+
+(defn stub-region-provider [region]
+ (reify region/RegionProvider
+ (fetch [_] region)))
+
+(def params {:api :s3
+ ;; use an anomaly to bypass parsing http-response
+ :http-client (stub-http-client {:cognitect.anomalies/category :cognitect.aws/test
+ :cognitect.anomalies/message "test"})
+ :region-provider (stub-region-provider :us-east-1)
+ :credentials-provider (stub-credentials-provider
+ {:access-key-id "a"
+ :secret-access-key "b"})})
+
+(deftest test-handle-http-response
+ (testing "returns http-response if it is an anomaly"
+ (is (= {:cognitect.anomalies/category :does-not-matter}
+ (#'client/handle-http-response {} {} {:cognitect.anomalies/category :does-not-matter})))))
+
+(deftest test-meta
+ (let [res (aws/invoke (aws/client params) {:op :ListBuckets})]
+ (testing "request meta includes :http-request"
+ (is (= {:uri "/"
+ :server-name "s3.amazonaws.com"
+ :body nil}
+ (select-keys (:http-request (meta res)) [:uri :server-name :body]))))
+ (testing "request meta includes raw response"
+ (is (= {:cognitect.anomalies/category :cognitect.aws/test,
+ :cognitect.anomalies/message "test",
+ :body nil}
+ (:http-response (meta res)))))))
+
+(deftest test-providers
+ (testing "base case"
+ (let [aws-client (aws/client params)]
+ (is (= "test"
+ (:cognitect.anomalies/message
+ (aws/invoke aws-client {:op :ListBuckets}))))))
+ (testing "nil creds (regression test - should not hang)"
+ (let [aws-client (aws/client (assoc params
+ :credentials-provider
+ (stub-credentials-provider nil)))]
+ (is (re-find #"^Unable to fetch credentials"
+ (:cognitect.anomalies/message
+ (aws/invoke aws-client {:op :ListBuckets}))))))
+ (testing "empty creds (regression test - should not hang)"
+ (let [aws-client (aws/client (assoc params
+ :credentials-provider
+ (stub-credentials-provider {})))]
+ (is (= "test"
+ (:cognitect.anomalies/message
+ (aws/invoke aws-client {:op :ListBuckets}))))))
+ (testing "nil region (regression test - should not hang)"
+ (let [aws-client (aws/client (assoc params
+ :region-provider
+ (stub-region-provider nil)))]
+ (is (re-find #"^Unable to fetch region"
+ (:cognitect.anomalies/message
+ (aws/invoke aws-client {:op :ListBuckets}))))))
+ (testing "empty region (regression test - should not hang)"
+ (let [aws-client (aws/client (assoc params
+ :region-provider
+ (stub-region-provider "")))]
+ (is (re-find #"^No known endpoint."
+ (:cognitect.anomalies/message
+ (aws/invoke aws-client {:op :ListBuckets})))))))
+
+(deftest validate-requests?
+ (let [aws-client (aws/client params)]
+ (is (not (api.async/validate-requests? aws-client)))
+ (api.async/validate-requests aws-client true)
+ (is (api.async/validate-requests? aws-client))
+ (api.async/validate-requests aws-client false)
+ (is (not (api.async/validate-requests? aws-client)))))
diff --git a/test/src/cognitect/aws/credentials_test.clj b/test/src/cognitect/aws/credentials_test.clj
index 7b514901..b6806a12 100644
--- a/test/src/cognitect/aws/credentials_test.clj
+++ b/test/src/cognitect/aws/credentials_test.clj
@@ -2,16 +2,14 @@
;; All rights reserved.
(ns cognitect.aws.credentials-test
- (:require [cognitect.aws.credentials :as credentials]
+ (:require [clojure.test :as t :refer [deftest testing use-fixtures is]]
+ [clojure.java.io :as io]
+ [cognitect.aws.credentials :as credentials]
[cognitect.aws.util :as u]
[cognitect.aws.test.utils :as tu]
[cognitect.aws.ec2-metadata-utils :as ec2-metadata-utils]
- [cognitect.aws.ec2-metadata-utils-test :as ec2-metadata-utils-test]
- [clojure.spec.alpha :as s]
- [clojure.spec.test.alpha :as stest]
- [clojure.spec.gen.alpha :as gen]
- [clojure.test :refer :all]
- [clojure.java.io :as io]))
+ [cognitect.aws.ec2-metadata-utils-test :as ec2-metadata-utils-test])
+ (:import (java.time Instant)))
(use-fixtures :once ec2-metadata-utils-test/test-server)
@@ -58,20 +56,36 @@
(is (nil? (credentials/fetch p)))))))))
(deftest system-properites-credentials-provider-test
+ (testing "all vars present"
+ (with-redefs [u/getProperty (tu/stub-getProperty {"aws.accessKeyId" "foo"
+ "aws.secretKey" "bar"
+ "aws.sessionToken" "baz"})]
+ (is (= {:aws/access-key-id "foo"
+ :aws/secret-access-key "bar"
+ :aws/session-token "baz"}
+ (credentials/fetch
+ (credentials/system-property-credentials-provider))))))
(testing "required vars present"
(with-redefs [u/getProperty (tu/stub-getProperty {"aws.accessKeyId" "foo"
- "aws.secretKey" "bar"})]
- (is (map? (credentials/fetch
- (credentials/system-property-credentials-provider))))))
+ "aws.secretKey" "bar"})]
+ (is (= {:aws/access-key-id "foo"
+ :aws/secret-access-key "bar"
+ :aws/session-token nil}
+ (credentials/fetch
+ (credentials/system-property-credentials-provider))))))
(testing "required vars blank"
(doall
(for [props [{}
{"aws.accessKeyId" "foo"}
{"aws.secretKey" "bar"}
{"aws.accessKeyId" ""
- "aws.secretKey" "bar"}
+ "aws.secretKey" "bar"}
+ {"aws.accessKeyId" " "
+ "aws.secretKey" "bar"}
{"aws.accessKeyId" "foo"
- "aws.secretKey" ""}]]
+ "aws.secretKey" ""}
+ {"aws.accessKeyId" "foo"
+ "aws.secretKey" " "}]]
(with-redefs [u/getProperty (tu/stub-getProperty props)]
(let [p (credentials/system-property-credentials-provider)]
(is (nil? (credentials/fetch p)))))))))
@@ -148,13 +162,13 @@
{:aws/access-key-id "id"
:aws/secret-access-key "secret"
::credentials/ttl 1}))
- creds (credentials/auto-refreshing-credentials p)]
+ creds (credentials/cached-credentials-with-auto-refresh p)]
(credentials/fetch creds)
- (Thread/sleep 5000)
+ (Thread/sleep 2500)
(let [refreshed @cnt]
(credentials/stop creds)
- (Thread/sleep 2000)
- (is (<= 3 refreshed) "The credentials have been refreshed.")
+ (Thread/sleep 1000)
+ (is (= 3 refreshed) "The credentials have been refreshed.")
(is (= refreshed @cnt) "We stopped the auto-refreshing process."))))
(deftest basic-credentials-provider
@@ -166,7 +180,7 @@
(defn minutes-from-now
[m]
- (-> (java.time.Instant/now)
+ (-> (Instant/now)
(.plusSeconds (* m 60))
(.with java.time.temporal.ChronoField/NANO_OF_SECOND 0)
str))
@@ -176,14 +190,17 @@
(is (= 3600 (credentials/calculate-ttl {}))))
(testing "refreshes in exp - 5 minutes"
(let [c {:Expiration (minutes-from-now 60)}]
- (is (< (- (* 55 60) 5)
+ (is (< (- (* 55 60) (* 5 60))
(credentials/calculate-ttl c)
- (+ (* 55 60) 5)))))
+ (+ (* 55 60) (* 5 60))))))
(testing "short expiration minimum is one minute"
(let [c {:Expiration (minutes-from-now 3)}]
+ (is (= 60 (credentials/calculate-ttl c)))))
+ (testing "supports java.util.Date (return value from sts :AssumeRole)"
+ (let [c {:Expiration (java.util.Date/from (Instant/parse (minutes-from-now 3)))}]
(is (= 60 (credentials/calculate-ttl c))))))
(comment
- (run-tests)
+ (t/run-tests)
)
diff --git a/test/src/cognitect/aws/ec2_metadata_utils_test.clj b/test/src/cognitect/aws/ec2_metadata_utils_test.clj
index 3a504950..9d70025d 100644
--- a/test/src/cognitect/aws/ec2_metadata_utils_test.clj
+++ b/test/src/cognitect/aws/ec2_metadata_utils_test.clj
@@ -5,6 +5,7 @@
(:require [clojure.test :refer :all]
[clojure.core.async :as a]
[cognitect.aws.http :as http]
+ [cognitect.aws.client.shared :as shared]
[cognitect.aws.test.ec2-metadata-utils-server :as ec2-metadata-utils-server]
[cognitect.aws.ec2-metadata-utils :as ec2-metadata-utils]
[byte-streams :as byte-streams]))
@@ -15,15 +16,14 @@
(defn test-server
[f]
;; NOTE: starting w/ 0 generates a random port
- (let [server-stop-fn (ec2-metadata-utils-server/start 0)
+ (let [server-stop-fn (ec2-metadata-utils-server/start 0)
test-server-port (-> server-stop-fn meta :local-port)]
(try
(System/setProperty ec2-metadata-utils/ec2-metadata-service-override-system-property
(str "http://localhost:" test-server-port))
(binding [*test-server-port* test-server-port
- *http-client* (http/resolve-http-client 'cognitect.aws.http.cognitect/create)]
- (f)
- (http/stop *http-client*))
+ *http-client* (shared/http-client)]
+ (f))
(finally
(server-stop-fn)
(System/clearProperty ec2-metadata-utils/ec2-metadata-service-override-system-property)))))
diff --git a/test/src/cognitect/aws/region_test.clj b/test/src/cognitect/aws/region_test.clj
index 269c972e..b87f1223 100644
--- a/test/src/cognitect/aws/region_test.clj
+++ b/test/src/cognitect/aws/region_test.clj
@@ -4,6 +4,7 @@
(ns cognitect.aws.region-test
(:require [clojure.test :refer :all]
[clojure.java.io :as io]
+ [clojure.core.async :as a]
[cognitect.aws.region :as region]
[cognitect.aws.util :as u]
[cognitect.aws.test.utils :as tu]
@@ -40,8 +41,23 @@
(is (= "us-west-1" (region/fetch (region/profile-region-provider))))))))
(deftest instance-region-provider-test
- (testing "The provider obtains the region from the instance metadata correctly."
- (is (= "us-east-1" (region/fetch (region/instance-region-provider ec2-metadata-utils-test/*http-client*))))))
+ (testing "provider caches the fetched value"
+ (let [orig-get-region-fn cognitect.aws.ec2-metadata-utils/get-ec2-instance-region
+ request-counter (atom 0)
+ fetch-counter (atom 0)]
+ (with-redefs [cognitect.aws.ec2-metadata-utils/get-ec2-instance-region
+ (fn [http]
+ (swap! fetch-counter inc)
+ (orig-get-region-fn http))]
+ (let [num-requests 10
+ p (region/instance-region-provider ec2-metadata-utils-test/*http-client*)
+ chans (repeatedly num-requests
+ #(do
+ (swap! request-counter inc)
+ (region/fetch-async p)))]
+ (is (apply = "us-east-1" (map #(a/ parsed :content last :content))))
(is (re-matches #"\n\s+inner-value\s+" (-> parsed :content last :content first))))))
+(deftest hex-encode
+ (is (= (util/hex-encode (byte-array (range -128 128)))
+ "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f")))
+
(comment
(run-tests)