portkey

Portkey: from REPL to Serverless in one call
cgrand 2017-09-08T09:17:11.000204Z

=> (binding [*credentials* {:access-key "XXXX"
                            :secret-key "YYYY"} 
             *region* "eu-central-1"]
     (lambda/list-functions {}))
[:result {:functions [{:role "arn:aws:iam::238568392557:role/portkey", :description "", :code-size 5826344, :function-arn "arn:aws:lambda:eu-central-1:238568392557:function:user_Iflatter", :dead-letter-config {}, :master-arn nil, :last-modified "2017-07-13T10:08:40.196+0000", :code-sha256 "Nx3nojHfJakr8w5EVS6ZhbGq+vQ6uq0z0BRGBPpcFPg=", :runtime :java8, :memory-size 1536, :vpc-config {}, :environment {}, :tracing-config {:mode :pass-through}, :timeout 30, :version "$LATEST", :kmskey-arn nil, :handler "portkey.LambdaStub", :function-name "user_Iflatter"}], :next-marker nil}]

🎆 1
cgrand 2017-09-08T09:17:21.000255Z

🍾

🍾 2
viesti 2017-09-08T09:21:47.000158Z

whoa 🙂

viesti 2017-09-08T09:22:18.000004Z

hmm, where’s the tweet? 🙂

viesti 2017-09-08T09:27:12.000020Z

:kmskey-arn nil actually brings to my mind that I did’t specify that on function creation/configuration update

viesti 2017-09-08T09:27:30.000134Z

since environment variables can be encrypted (passwords etc)

cgrand 2017-09-08T10:23:24.000306Z

Ok. Now, unless explicitly dynamically bound, credentials and region are fetched from the same usual locations (env vars, properties, profile files).

cgrand 2017-09-08T10:23:40.000397Z

Now it’s just:

=> (require '[portkey.aws.lambda :as lambda])
=> (lambda/list-functions {})
{:functions [{:role "arn:aws:iam::238568392557:role/portkey", :description "", :code-size 5826344, :function-arn "arn:aws:lambda:eu-central-1:238568392557:function:user_Iflatter", :dead-letter-config {}, :master-arn nil, :last-modified "2017-07-13T10:08:40.196+0000", :code-sha256 "Nx3nojHfJakr8w5EVS6ZhbGq+vQ6uq0z0BRGBPpcFPg=", :runtime :java8, :memory-size 1536, :vpc-config {}, :environment {}, :tracing-config {:mode :pass-through}, :timeout 30, :version "$LATEST", :kmskey-arn nil, :handler "portkey.LambdaStub", :function-name "user_Iflatter"}], :next-marker nil}

cgrand 2017-09-08T10:35:23.000200Z

aws-clj-sdk can now be tested for the following services (rest-json protocol) “AWS Batch” “AWS Greengrass” “AWS IoT” “AWS IoT Data Plane” “AWS Lambda” “AWS X-Ray” “Amazon API Gateway” “Amazon CloudDirectory” “Amazon CloudSearch Domain” “Amazon Cognito Sync” “Amazon Elastic File System” “Amazon Elastic Transcoder” “Amazon Elasticsearch Service” “Amazon Glacier” “Amazon Lex Model Building Service” “Amazon Lex Runtime Service” “Amazon Pinpoint” “Amazon Polly” “Amazon WorkDocs See example above for a simple invocation. doc doesn’t return a docstring at the moment but at least displays specs:

=> (doc lambda/list-functions)
-------------------------
portkey.aws.lambda/list-functions
([input__8278__auto__])
Spec
  args: (tuple :portkey.aws.lambda/list-functions-request)
  ret: (and :portkey.aws.lambda/list-functions-response)

cgrand 2017-09-08T14:59:09.000194Z

the elusive s3v4 signature is v4 + special rules for payalod hashing (unsigned, chunked, normal) and the additional payload hash header

cgrand 2017-09-08T14:59:43.000235Z

fun fact: it seems like the root element of xml responses is not specified 🤷

cgrand 2017-09-08T15:15:17.000359Z

@richiardiandrea abstracting over json and http client libs.

cgrand 2017-09-08T15:17:24.000609Z

There is provision for async support in the current design. By binding http-client one can have functions returning promises or chans instead of values.

viesti 2017-09-08T15:23:32.000200Z

ah-haa

viesti 2017-09-08T15:23:34.000282Z

the async

cgrand 2017-09-08T15:42:16.000437Z

@viesti async was such a low hanging fruit

cgrand 2017-09-08T15:42:51.000117Z

=> (binding [aws/*http-client* aws/async-http-client]
     (lambda/list-functions))
#object[clojure.core.async.impl.channels.ManyToManyChannel 0x7975d4aa "clojure.core.async.impl.channels.ManyToManyChannel@7975d4aa"]
=> (async/<!! *1)
[:result {:functions [{:role "arn:aws:iam::238568392557:role/portkey", :description "", :code-size 5826344, :function-arn "arn:aws:lambda:eu-central-1:238568392557:function:user_Iflatter", :dead-letter-config {}, :master-arn nil, :last-modified "2017-07-13T10:08:40.196+0000", :code-sha256 "Nx3nojHfJakr8w5EVS6ZhbGq+vQ6uq0z0BRGBPpcFPg=", :runtime :java8, :memory-size 1536, :vpc-config {}, :environment {}, :tracing-config {:mode :pass-through}, :timeout 30, :version "$LATEST", :kmskey-arn nil, :handler "portkey.LambdaStub", :function-name "user_Iflatter"}], :next-marker nil}]

viesti 2017-09-08T15:47:20.000747Z

nice!

viesti 2017-09-08T15:48:34.000177Z

for some reason was thinking about binding conveyance, but channels fit well

richiardiandrea 2017-09-08T15:50:05.000299Z

Very nice, would be super interested in a lumo port given I am using the JS aws SDK quite extensively. So if it's only an abstraction over http, it should be quite easy to achieve that

viesti 2017-09-08T15:50:05.000329Z

have to learn to use binding as a choice for structuring a library

cgrand 2017-09-08T15:57:02.000060Z

@richiardiandrea I have good hopes that all generated files could be pure cljc.

richiardiandrea 2017-09-08T16:04:46.000241Z

@cgrand will explore, thanks everything looks good

viesti 2017-09-08T16:38:52.000089Z

awesome work, didn’t image what reach this project would have when we started on it 🙂

đź‘Ť 2
cgrand 2017-09-08T21:23:47.000153Z

Bindings are conveyed through go blocks in Clojure (not in Clojurescript obviously)

cgrand 2017-09-08T21:24:35.000161Z

If you prefer another async flavor you just have to provide a new http-client