summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRicardo Wurmus <rekado@elephly.net>2021-03-07 13:03:30 +0100
committerRicardo Wurmus <rekado@elephly.net>2021-03-07 13:08:10 +0100
commitb76ae8c42a2198fa206b472c2a6a5dbef257925b (patch)
treec17caaa00eafa37ac15e90c1150eaa34c6a2ef94
parent54b59f500d4b45a3879b2a7bfc489fb53ba2b3c3 (diff)
base: aws-operation: Pass request arguments to request constructor.
Instead of expecting a single input of the required type, the procedure returned by AWS-OPERATION now accepts keyword arguments intended for the request constructor. This makes for a much less verbose DSL. Compare the explicit style (DeleteFileSystem (DeleteFileSystemRequest #:FileSystemId "fs-cabba9e")) with the new implicit style: (DeleteFileSystem #:FileSystemId "fs-cabba9e") * aws/base.scm (aws-operation): Accept an input-constructor; apply it to a provided list of keyword arguments. * language/aws/spec.scm (compile-operation): Generate code that specifies the input constructor. * README.org: Update examples.
-rw-r--r--README.org38
-rw-r--r--aws/base.scm32
-rw-r--r--language/aws/spec.scm4
3 files changed, 50 insertions, 24 deletions
diff --git a/README.org b/README.org
index dcebd48..c2e20a1 100644
--- a/README.org
+++ b/README.org
@@ -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)