Declarative Config
I get confused with the difference between imperative and declarative configuration. This post is a quick reminder for myself with a simple Terraform example.
Summary
Declarative configuration is the one we like the most because we declare what we want the result of our configuration to be, and we leave it to the tooling to get us there. An imperative configuration requires us to provide all the steps necessary to create our desired configuration (much like a recipe) and it’s up to us to keep track of the state/result of the configuration.
S3 Bucket Example
The Terraform and AWS CLI examples here create a trivial S3 bucket configuration for use as a static website. These examples assume the tooling has been configured with the keys and permissions required to create the resources.
Declarative - Terraform
provider aws {
region = "us-east-2"
}
resource aws_s3_bucket website {
bucket = "web.example.com"
acl = "public-read"
}
resource aws_s3_bucket_website_configuration {
bucket = aws_s3_bucket.website.bucket
index_document {
suffix = "index.html"
}
error_document {
key = "error.html"
}
}
Running terraform apply
with this configuration should result in the same configuration every time. The first time it will create the necessary resources and after that (assuming no changes), it will leave everything alone and exit without errors.
Imperative - AWS CLI
Using the AWS CLI, we call the create-bucket and put-bucket-website commands. The put-bucket-website
command requires the following JSON file as input.
website.json
{
"IndexDocument": {
"Suffix": "index.html"
},
"ErrorDocument": {
"Key": "error.html"
}
}
aws s3api create-bucket \
--bucket web.example.com \
--region us-east-2
aws s3api put-bucket-website \
--bucket web.example.com \
--website-configuration file://website.json \
--regions us-east-2
These CLI commands can only be run once because they have not concept of state. If we run them again, we’ll get an error stating that the bucket name is taken. This becomes brittle as the infrastructure evolves, and you need to make changes and don’t want to start from scratch.
Conclusion
Declarative configuration relies on the tools to understand the current state of the system, and how to get from the current state to the desired state. We really need to trust these tools (ideally by reviewing their source) because they’re doing a lot of heavy lifting for us and require root-like permissions.