Fork me on GitHub
#portkey
<
2018-05-27
>
baptiste-from-paris07:05:16

hello friends, I am working on the POC

baptiste-from-paris08:05:10

I don’t see how I can go from input -> spec which validate input ->

baptiste-from-paris08:05:18

then we generate the operation

baptiste-from-paris08:05:43

but how can we manage to call all the ser* from the input

baptiste-from-paris08:05:56

for example, let’s take this operation from lambda

baptiste-from-paris08:05:04

{"TagResource"
   {"name" "TagResource",
    "http"
    {"method" "POST",
     "requestUri" "/2017-03-31/tags/{ARN}",
     "responseCode" 204},
    "input" {"shape" "TagResourceRequest"},
    "errors"
    [{"shape" "ServiceException"}
     {"shape" "ResourceNotFoundException"}
     {"shape" "InvalidParameterValueException"}
     {"shape" "TooManyRequestsException"}]}}

baptiste-from-paris08:05:08

from this operation we generate specs for every shape like before

baptiste-from-paris08:05:34

then the gen-operationmakes the defn & fspec

baptiste-from-paris08:05:19

the idea is to split specfrom ser & deser

baptiste-from-paris08:05:54

so we map into a sets all input-roots and inputsshape

baptiste-from-paris08:05:16

now, once spec validate my TagResourceRequest

baptiste-from-paris08:05:29

how can I pass all the ser function ?

baptiste-from-paris08:05:36

"TagResourceRequest"
  {"type" "structure",
   "required" ["Resource" "Tags"],
   "members"
   {"Resource"
    {"shape" "FunctionArn", "location" "uri", "locationName" "ARN"},
    "Tags" {"shape" "Tags"}}}

baptiste-from-paris08:05:55

which should be an entry map like that

baptiste-from-paris08:05:18

{:resource “some string” :tags “some tags type”}

baptiste-from-paris17:05:29

So I’ve been working today on this problem and here is some code that might go in the right direction (help me god)

baptiste-from-paris17:05:51

(defn shape-name->ser-name
    "Given a shape name, transorm it to a ser-* name."
    [shape-name]
    (->> shape-name (str "ser-") portkey.aws/dashed symbol))

  
  (defmulti gen-ser-input (fn [shape-name api _]
                            [(get-in api ["metadata" "protocol"]) (get-in api ["shapes" shape-name "type"])]))


  (defmethod gen-ser-input :default [shape-name api _]
    (let [mess [(get-in api ["metadata" "protocol"]) (get-in api ["shapes" shape-name "type"])]]
      (throw
       (ex-info (str "unsupported protocol/type for shape : " shape-name)
                {:shape mess}))))


  (defmethod gen-ser-input ["rest-json" "integer"] [shape-name api input] input)
  

  (defmethod gen-ser-input ["rest-json" "structure"] [shape-name api input]
    (let [shape (get-in api ["shapes" shape-name])
          keep-keys-args (into {}
                               (mapcat #(vec [[(-> % portkey.aws/dashed keyword) %]]))
                               (keys (shape "members")))]
      `(let [vv-fn# ~(into {}
                           (map (fn [[k# v#]]
                                  [k# (shape-name->ser-name (v# "shape"))]))
                           (shape "members"))]
         (into {}
               (comp (keep (fn [[k# v#]] (when-some [k# (~keep-keys-args k#)] [k# v#])))
                     (map (fn [[k# v#]]
                            (let [ser-fn# (vv-fn# k#)]
                              [k# (ser-fn# v#)]))))
               ~input))))


  (defmethod gen-ser-input ["rest-json" "string"] [shape-name api input]
    (let [{:strs [enum] :as shape} (get-in api ["shapes" shape-name])]
      (if enum
        `(let [m# ~(into {} (mapcat #(vector [% %] [(-> % aws/dashed keyword) %])) enum)]
           (m# input))
        input)))

  (defmethod gen-ser-input ["rest-json" "map"] [shape-name api input] input)

  (defmethod gen-ser-input ["rest-json" "boolean"] [shape-name api input] input)

  (defmethod gen-ser-input ["rest-json" "timestamp"] [shape-name api input] input)

  (defmethod gen-ser-input ["rest-json" "list"] [shape-name api input] input)

  (defmethod gen-ser-input ["rest-json" "blob"] [shape-name api input]
    `(aws/base64-encode ~input))
  
  (defn ser-fn-fn
    "Fonction tu lui donne un input et il t'appelle les fn de ser qui
  on été généré pour faire le confirming."
    [input]
    {})

  

  
  (let [{:keys [inputs]} (shapes-by-usage api)
        f (fn [shape-name api]
            (let [varname (shape-name->ser-name shape-name)
                  input# (symbol "shape-input")]
              `(defn ~varname
                 [~input#]
                 ~(gen-ser-input shape-name api input#))))]
    (map (fn [in]
           (f in api))
         inputs))

baptiste-from-paris17:05:35

which generate stuff like that =>

baptiste-from-paris17:05:41

(clojure.core/defn
  ser-reserved-concurrent-executions
  [shape-input]
  shape-input)
 (clojure.core/defn
  ser-tracing-config
  [shape-input]
  (clojure.core/let
   [vv-fn__53839__auto__ {“Mode” ser-tracing-mode}]
   (clojure.core/into
    {}
    (clojure.core/comp
     (clojure.core/keep
      (clojure.core/fn
       [[k__53840__auto__ v__53841__auto__]]
       (clojure.core/when-some
        [k__53840__auto__ ({:mode “Mode”} k__53840__auto__)]
        [k__53840__auto__ v__53841__auto__])))
     (clojure.core/map
      (clojure.core/fn
       [[k__53840__auto__ v__53841__auto__]]
       (clojure.core/let
        [ser-fn__53842__auto__
         (vv-fn__53839__auto__ k__53840__auto__)]
        [k__53840__auto__
         (ser-fn__53842__auto__ v__53841__auto__)]))))
    shape-input)))

baptiste-from-paris17:05:25

What I’ve done is to rebase wip stuff on master

baptiste-from-paris17:05:40

then I generate defn fors ser-*

baptiste-from-paris18:05:02

I think I now understand the purpose of the resp but I think one fn should do the trick for each protocol