Since 2016 I have worked on AWS library. On 2021-09-30, AWS released something comparable, AWS Cloud Control API. If it’s comparable, let’s compare. I hope the reader will find this unique perspective interesting.
AWS Cloud Control provides uniform API to Create, Read, Update, Delete and List different resources. In short, CRUDL.
My library aims to provide uniform simplified declarative interface where the main functionality is to converge to desired state.
Cloud Control supports much more resources. My library supports very few, the ones that I needed the most for my work. It’s just how experimental library by one person in spare time compares with a product from AWS.
Mode of Operation
Operates on one resource at a time.
Cloud Control provides relatively low level API, CRUDL. The advantage of Cloud Control over existing APIs is the uniformity, not achieving a desired state. You either create or update, and you need to know which one you are doing. (Deletion is a different story).
I am amazed that somebody at AWS was able to pull this off… where different services don’t agree on naming conventions for tagging resources, how and what can be tagged, and don’t have a convention for naming pagination fields. (Which by the way is nightmare for the users but typically abstracted by Terraform or CloudFormation). Sorry for the rant.
The operations are performed asynchronously. You have an API to query the status: GetResourceRequestStatus. This approach is better for advanced use cases, where multiple resources are being created simultaneously. (Like CloudFormation?)
The operations are idempotent. This is achieved using client token, as in other AWS services.
Operates either on one resource or a set of resources of the same type at a time. Edit: … from default, specified , or all regions.
The library looks up the resources and either creates or updates them, depending on whether they exist or not.
The operations are performed synchronously. The library throws exception if anything goes wrong. I find this approach much more user friendly for basic use cases.
Idempotency is out of the picture. Should it be in? Probably. Looks like omission on my side. How to best shield the user of the library from this issue? Don’t know yet. Need to think.
Describing Desired State
The “create” API has desired state parameter: DesiredState.
The “update” API doesn’t, which I find very strange. I thought that desired state is something to be achieved no matter what the current state is. Desired state is only used in the “create” API so from my perspective it could have been called “properties” or whatever.
The “update” API has PatchDocument parameter, which I find not user friendly for the following reasons:
- Who actually works with JSON patch format? It’s the first time I see that I need to use it.
- I think it is less mentally challenging to describe … desired state and not the delta. This is typically done by IaC tools, including CloudFormation: calculate the diff between current and desired state for the user, so that the user would not need to get into this.
- It makes the update inconsistent with create.
There is no separate create and update. The user specifies the desired state as a parameter to the “converge” function. Converge then either creates or updates the resource / resources. The (non existent) “create” and “update” are therefore completely uniform in the library.
Search / Filtering
Search is not supported. In practice it means listing all the resources and filtering the result on the client side. Typically that can be done in AWS CLI with the
--query flag which is supported globally, for any AWS CLI command. Unfortunately I don’t see a way to make it work in this situation. The returned result has
ResourceDescriptions field, an array where each item has
Properties field, the
Properties field is a string (JSON). Apparently JMESPath does not support parsing JSON in this situation. This means that the output of Cloud Control AWS CLI will be piped to
jq or maybe a programming language for filtering and/or further processing.
While the number of supported resources and filters is low, the library supports filtering. The filtering is done on the server or on the client, completely transparent to the users of the library. What’s done on the server and what’s on the client? Simple – when filtering a given property is supported on the server side, it’s done there.
Desired State Format
Cloud Control uses CloudFormation syntax. This makes sense.
My library uses the same format as you would see when using AWS CLI to describe the resource. It allows access to properties that CloudFormation does not have, and is unlikely to have, so for example this works:
instance = AWS::Instance(...).converge(State = 'running')— which creates or turns on the specified EC2 instance / instances. Turning on or off EC2 instances is not supported in CloudFormation.
vpc = AWS::Vpc(IsDefault=true).expect(1)— get a reference to default VPC (to use in further operations).
- Cloud Control looks like a step in the right direction.
Propertiesas a string is a major ergonomic issue.
- JSON patch for update is a huge ergonomic issue.
- Search (filtering in List) functionality is missing.
- “Desired state” naming is unjustified.
Cloud Control is a big effort, therefore let’s give the team some slack and see how the API is improved with time? Hopefully soon 🙂
Have a nice day, evening, or night! Mornings are just statistically less nice…