summaryrefslogtreecommitdiff
path: root/README.org
blob: 25d12991776dc5d6121d790b987af02cce0f7206 (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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.

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))

(setenv "AWS_DEFAULT_REGION" "eu-central-1")
(setenv "AWS_SECRET_ACCESS_KEY" "…")
(setenv "AWS_ACCESS_KEY_ID" "AKIA…")

;; Create a file system with this unique creation token.
(CreateFileSystem
 #:CreationToken "my-guile-aws-filesystem"
 #:Tags (list (Tag #:Key "project" #:Value "guile-aws")
              (Tag #:Key "type" #:Value "test")))

#;
(("ThroughputMode" . "bursting")
 ("Tags"
  .
  #((("Value" . "guile-aws") ("Key" . "project"))
    (("Value" . "test") ("Key" . "type"))))
 ("SizeInBytes"
  ("ValueInStandard" . 0)
  ("ValueInIA" . 0)
  ("Value" . 0)
  ("Timestamp" . null))
 ("ReplicationPolicies" . null)
 ("ProvisionedThroughputInMibps" . null)
 ("PerformanceMode" . "generalPurpose")
 ("OwnerId" . "439516136713")
 ("NumberOfMountTargets" . 0)
 ("Name" . null)
 ("LifeCycleState" . "creating")
 ("KmsKeyId" . null)
 ("FileSystemId" . "fs-8bee03d0")
 ("FileSystemArn"
  .
  "arn:aws:elasticfilesystem:eu-central-1:439516136713:file-system/fs-8bee03d0")
 ("Encrypted" . #f)
 ("CreationToken" . "my-guile-aws-filesystem")
 ("CreationTime" . 1615285393.0)
 ("AvailabilityZoneName" . null)
 ("AvailabilityZoneId" . null))

;; Save costs by transitioning to the Infrequent Access
;; storage class as soon as possible.
(PutLifecycleConfiguration
 #:FileSystemId "fs-8bee03d0"
 #:LifecyclePolicies
 (list (LifecyclePolicy
        #:TransitionToIA "AFTER_7_DAYS")))

#;
(("LifecyclePolicies"
  .
  #((("TransitionToIA" . "AFTER_7_DAYS")))))

(CreateAccessPoint
 #:ClientToken "my-guile-aws-filesystem"
 #:FileSystemId "fs-8bee03d0")

#;
(("Tags" . #())
 ("RootDirectory"
  ("Path" . "/")
  ("CreationInfo" . null))
 ("PosixUser" . null)
 ("OwnerId" . "439516136713")
 ("Name" . null)
 ("LifeCycleState" . "creating")
 ("FileSystemId" . "fs-8bee03d0")
 ("ClientToken" . "my-guile-aws-filesystem")
 ("AccessPointId" . "fsap-0d9a986284d086526")
 ("AccessPointArn"
  .
  "arn:aws:elasticfilesystem:eu-central-1:439516136713:access-point/fsap-0d9a986284d086526"))

;; Use the same subnet identifier as your EC2 instances.
(CreateMountTarget
 #:FileSystemId "fs-8bee03d0"
 #:SubnetId "subnet-7f6a7102")

#;
(("VpcId" . "vpc-8e31f4e4")
 ("SubnetId" . "subnet-7f6a7102")
 ("OwnerId" . "439516136713")
 ("NetworkInterfaceId" . "eni-08df70c51f2ecbc33")
 ("MountTargetId" . "fsmt-023b3e5b")
 ("LifeCycleState" . "creating")
 ("IpAddress" . "172.31.44.41")
 ("FileSystemId" . "fs-8bee03d0")
 ("AvailabilityZoneName" . "eu-central-1b")
 ("AvailabilityZoneId" . "euc1-az3"))

;; Tear down
(DeleteMountTarget
 #:MountTargetId "fsmt-023b3e5b")

#; #t

(DeleteAccessPoint
 #:AccessPointId "fsap-0d9a986284d086526")

#; #t

(DeleteFileSystem
 #:FileSystemId "fs-8bee03d0")

#; #t
#+end_src

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:

** Extend requestUri formatting
   The =(aws request)= module interprets the =requestUri= field and substitutes placeholders. However, this was only tested with the EFS API.  The S3 API uses fancier placeholders such as ="/{Bucket}/{Key+}?restore"= — it is not clear yet how to interpret the plus.
** Create aliases
  The S3 API (for example) defines aliases for some operations, such as “PostObjectRestore” for “RestoreObject”.  The compiler should process the “alias” field.
** Record possible errors
The S3 API and the EFS API (for example) define possible error names.  While their shape is not specified anywhere we should generate values for these error conditions.
** Process output shapes
   We generate types for all defined shapes — including output shapes — but we don’t mashall the output SXML into appropriate Scheme values yet.
** Turn errors into Scheme conditions
This is easier said than done because different APIs return different kinds of errors.
** TODO Respect “location” and “locationName”
In the S3 API some values have a “location” property with value “header”, others with “querystring”.  These values must appear in the headers or the querystring, respectively, and should not be added to the body.