diff options
-rw-r--r-- | README.org | 38 | ||||
-rw-r--r-- | aws/base.scm | 32 | ||||
-rw-r--r-- | language/aws/spec.scm | 4 |
3 files changed, 50 insertions, 24 deletions
@@ -1,13 +1,12 @@ Guile AWS is pre-alpha software. At the very least it’s yet another demonstration that Guile’s compiler tower can be used to generate an embedded domain specific language from JSON specifications. -The DSL Guile AWS produces is unpolished and thus pretty repetitive and ugly. Here is an example session to create an EFS and make it ready for mounting on an EC2 instance: +Here is an example session to create an EFS and make it ready for mounting on an EC2 instance: #+begin_src scheme (import (aws api elasticfilesystem-2015-02-01)) (CreateFileSystem - (CreateFileSystemRequest - #:CreationToken (CreationToken "my-guile-aws-filesystem"))) + #:CreationToken "my-guile-aws-filesystem") #; (("ThroughputMode" . "bursting") ("Tags" . #()) @@ -35,9 +34,8 @@ The DSL Guile AWS produces is unpolished and thus pretty repetitive and ugly. H ("AvailabilityZoneId" . null)) (CreateAccessPoint - (CreateAccessPointRequest - #:ClientToken (ClientToken "my-guile-aws-filesystem") - #:FileSystemId (FileSystemId "fs-8bee03d0"))) + #:ClientToken "my-guile-aws-filesystem" + #:FileSystemId "fs-8bee03d0") #; (("Tags" . #()) @@ -57,9 +55,8 @@ The DSL Guile AWS produces is unpolished and thus pretty repetitive and ugly. H ;; Use the same subnet identifier as your EC2 instances. (CreateMountTarget - (CreateMountTargetRequest - #:FileSystemId (FileSystemId "fs-8bee03d0") - #:SubnetId (SubnetId "subnet-7f6a7102"))) + #:FileSystemId "fs-8bee03d0" + #:SubnetId "subnet-7f6a7102") #; (("VpcId" . "vpc-8e31f4e4") @@ -75,25 +72,34 @@ The DSL Guile AWS produces is unpolished and thus pretty repetitive and ugly. H ;; Tear down (DeleteMountTarget - (DeleteMountTargetRequest - #:MountTargetId (MountTargetId "fsmt-284b4e71"))) + #:MountTargetId "fsmt-284b4e71") #; #t (DeleteAccessPoint - (DeleteAccessPointRequest - #:AccessPointId (AccessPointId "fsap-0d9a986284d086526"))) + #:AccessPointId "fsap-0d9a986284d086526") #; #t (DeleteFileSystem - (DeleteFileSystemRequest - #:FileSystemId (FileSystemId "fs-8bee03d0"))) + #:FileSystemId "fs-8bee03d0") #; #t #+end_src -The output is pretty bad as it is currently unprocessed SXML or JSON. It may not even work at all, because the AWS APIs are all a little different. +You can also separate the request definition from submitting the request. This is useful if you want your requests type-checked well before even getting near to submission: + +#+begin_src scheme +;; This is type-checked right away, so any errors will show up here. +(define req + (DeleteFileSystemRequest + #:FileSystemId "fs-8bee03d0")) + +;; Actually submit the request +(DeleteFileSystem req) +#+end_src + +As you can see, the output is pretty bad as it is currently unprocessed SXML or JSON. It may not even work at all, because the AWS APIs are all a little different. Considering all these caveats there are a couple of obvious things to work on: diff --git a/aws/base.scm b/aws/base.scm index 21a55b9..676fdd1 100644 --- a/aws/base.scm +++ b/aws/base.scm @@ -1,5 +1,5 @@ ;;; guile-aws --- Scheme DSL for the AWS APIs -;;; Copyright © 2019 Ricardo Wurmus <rekado@elephly.net> +;;; Copyright © 2019, 2021 Ricardo Wurmus <rekado@elephly.net> ;;; ;;; Guile-AWS is free software: you can redistribute it and/or modify ;;; it under the terms of the GNU General Public License as published @@ -137,14 +137,30 @@ value type)))) -(define* (aws-operation requester #:key name input-type output-type http documentation) +(define* (aws-operation requester + #:key + name + input-constructor + input-type + output-type + http documentation) (let ((proc - (lambda* (#:optional input) - (unless (eq? (aws-name input) input-type) - (error (format #f "~a: input must be of type ~a: ~a~%" - name input-type input))) - ;; TODO: do something with the response! - (requester #:http http #:operation-name name #:input input)))) + (lambda args + (let ((input* + (match args + ;; Accept a keyword list and pass it to the + ;; appropriate constructor. + (((? keyword?) . rest) + (apply input-constructor args)) + ;; Otherwise type check the input + ((input) + (unless (eq? (aws-name input) input-type) + (error (format #f "~a: input must be of type ~a: ~a~%" + name input-type input))) + input) + (() #false)))) + ;; TODO: do something with the response! + (requester #:http http #:operation-name name #:input input*))))) (set-procedure-property! proc 'documentation documentation) (set-procedure-property! proc 'name name) proc)) diff --git a/language/aws/spec.scm b/language/aws/spec.scm index c40367b..f271d27 100644 --- a/language/aws/spec.scm +++ b/language/aws/spec.scm @@ -200,6 +200,10 @@ if this is not a primitive data type." (aws-operation operation->request #:name ,name + #:input-constructor + ,(and=> (assoc-ref spec "input") + (lambda (input) + (and=> (assoc-ref input "shape") string->symbol))) #:input-type ',(and=> (assoc-ref spec "input") (lambda (input) |