Introduction#
At this point, we have a number of primitives that can be used to manage resources on AWS and a composition module that uses the primitives to build a website using Cloudfront/S3/ACM/Route53. It’s basically a single command like “I want a website called test1.dxaws.com in account #123 in region us-least-6” and away it goes. The whole process takes about five minutes, which seems pretty good, not great but there are some ways to optimize it even further by creating resource pools.
But before we can really start digging in on optimizing this workflow, we really need a way to manage it. WHo owns it? Where are the components? Who can create/view/edit/delete the thing.
My philosophy is to spend some time at the pie in the sky requirements and then pull them back into a narrow set up intial requirements. This gives me a direction for future development and means that I’m not going to have to drop and rebuild everything if I stay on that path. This is not to say that the long term requirements are being set in stone - I’m not using a waterfall approach but I’m also not going to hit the ground running writing code and see what comes out. Waterfall has use cases as does pure agile ‘we will know when we are done when we get there’ approach. I use something I call a Dependency Gravity Model
Discussion / Requirements#
Let’s start with what the high level requirements are:
- inventory: what exists
- location: which account and region does it live in
- tenancy: who owns or is assigned to it
- authority: who may act on it
We have to keep in mind that resources can live in our own plaform accounts, in different workload accounts, in different AWS regions and maybe even in our customer accounts. We can potoentially have resources that are not located on AWS. While this last one may seem out of scope, planning for it now is easy compared to trying to shoehorn that stuff in later on. If a client has storage on Azure or GCP, it should not be that hard for use to index it from AWS…but yes, generally this is out of scope right now.
Objects#
This all over the placedness is going to mean that we are probably going to want to create a general object registry that does not really care what the actual object are. So, in a way this is similar to an ARN on aws. ARNs tell you what things are, where they live and even what namespace they belong to. We don’t want to exactly copy this but some the requirements for our system will be:
- globally unique with the dxaws environment
- readable
- structured
- parsable
- stable over time
But we don’t really want to encode things in the ids like region or account because we may want to move these resources around. If I build a website object in ca-central-1, I may want to move it to a different account in a different region like eu-south-2 BUT I don’t want to change the object-id. If we use the AWS ARN scheme then moving the site actually changes it’s identity which means that other resources that are attached to our website object would also have to be updated. In a sense, we need a global identifier that can be used to track resources anywhere on the internet. So what we get is ids that look like this which are stable forever:
- dxaws:website:0001
- dxaws:bucket:001
- dxaws:distribution:0001
- dxaws:surface:0001
- dxaws:principal:tenant:acme
and then add metadata which is changeable:
- provider: aws
- account_id: 123456789012
- region: ca-central-1
- provider_id: E123ABCXYZ
- provider_arn: aws:aws:cloudfront:123456789012:distribution/E123ABCXYZ
Now, we can do something like:
dxaws:website:0001@aws/123456789012/ca-central-1which is a website with id 0001 on aws in account 123456789012 in region ca-central-1. Easy to read and we keep the stable part of the id separate from the changeable location data. This is handy as it gives us a lot of information in a single glance.
Classes#
There are really two classes of objects in the system
Platform Managed Objects
These are pretty straight forward - these are resources built and controlled by the system:
- prebuilt site buckets
- platform cloudfront distributions
- route53 records
- ACM certs
Externally located or Customer-Owned Objects
These are not fully owned by the platform but are still part of the system graph. This can be things like:
- a customer S3 bucket in their AWS account
- a bucket transferred out on exit
- maybe customer owned route53 zones
- apis or storage assets the platform reads but does not own
So we can’t assume that every object is platform-owned. We need to track both:
- ownership
- control level
So we may want to have a field like control_mode which tracks:
platform_managedcustomer_managedsharedexternal_reference
A client config might look something like this:
- bucket:customer-archive-123
- located in account 123456789012
- region us-west-2
- owned by tenant:acme
- control mode customer_managed
- linked to site:0001 with relation uses
That is very different from:
- site:0001 owns bucket:platform-bucket-0001
We are doing quite a bit more than just saying owns. We need to define a number of different relationships like:
- owns
- assigned_to
- uses
- hosted_in
and all of this is going to matter when we start talking about
- permissions
- billing
- cleanup
- exit workflows
- what automation is allowed to touch
The Other Stuff#
What a weird day:
- MacOS laptop screen suddenly went black for about a minute and I found myself back at the login screen
- When I got back online, Webstorm and Pycharm refused to start up again. I checked in with Athena and she said to remove some cache files and whatnot. So I did only to get a more mysterious message from Webstorm. Apparently what happened is that Webstorm was running and it was just the frontend that was missing. So I kill nined (or probably just killed) the old process and Webstorm worked again. Unfortunately, it lost almost all of it’s settings. I was editing a file (this file in fact) and suddenly realized that the soft wrap was not on. I fixed that and then found that I was not in
vimso I had random control commands all over the place. The only thing harder than quitting vim is trying to quit vim when you are not using vim. - I’m using a different laptop for dev right now and hugo was not displaying shortcodes from my custom library. No warnings or errors, just no displaying. Turns out I was missing a dependency and some set up stuff. The cool part is that I had documented the install steps for the plugin, and it actually told me exactly how to fix it. I keep pounding on stuff like writing unit tests and documentation, well these docs saved me a shit ton of time. Even Athena (my trusty LLM) seemed a bit flummoxed.
- finally, Github actions simply decided not to publish the dev site for this site. There was a flag that told it to skip building the infra if it already existed and somehow (not naming any names but Athena) extended that flag so no content would be published. Fortunately she fixed that error pretty quickly and the new content was published shortly after. It’s nice when your CI/CD just works without really thinking about it.
It’s finally warming up here after a freak snowstorm on Monday. I still went out with a scarf and the puffer jacket, but I was definitely a bit warm when I got home. I kind of like these 15c to 20c degree days. Grad a sweater, don’t need gloves - all good.