visit
“The advantage of feature branching is that each developer can work on their own feature and be isolated from changes going on elsewhere.” ()
Feature branches have been around for a long time and are a common practice among dev teams. I couldn’t imagine development in a team without them. It would seem ludicrous if someone asked me to share a branch with a colleague who is working on a different feature. Just the thought makes me uncomfortable. It’s easy to see how the isolation that feature-branches provide, is also needed for testing the application. And more specifically — testing its integrations.
Keeping your running code isolated used to be much easier — you could run everything locally. I’ve had MySQL and Redis installed on almost every computer I’ve worked on. But as our applications grew to rely on managed services — like Cognito and BigQuery — running 100% locally became an issue. It’s possible to mock or mimic these services, but they never act exactly like their original counterparts. Furthermore — these integrations should be tested frequently and early — as the boundaries of our application tend to be the places we get surprised in, and where things break.
This actually works on a small scale. For example — each developer runs his code locally, and everyone works with a dedicated S3 bucket that has different folders to isolate usage. But you don’t have to think far to get to a point where this breaks. What if we’re using an SQS Queue? My local application would push a message into that queue, only to have a colleague’s local application pulling that message. That’s exactly the type of interruption we’d like to avoid. We should each use our own queue — and to extrapolate from there — our own environment.
Running an environment for every feature branch, or every pull request, is firstly a matter of how you perceive your CD pipeline. Don’t think of it as ‘this deploys the environment’, but as ‘this deploys an environment’. You just need to give it a name. That could be ‘production’ or ‘staging’, but it could also be ‘pr1017’ of ‘feature-blue-button’. Your CD process needs to work for existing environments, as well as for new ones. This is where Terraform really shines.
Because Terraform uses a declarative approach, it is in charge of figuring out if the environment is new and needs to be created, or if it exists and needs to be updated. Another key feature of Terraform is , which isolate state between different environments (it was even called “environments” in previous versions). Your Terraform code will need to use the variable ${terraform.workspace} in order to make sure your resources are specific for the environment you are in.locals {
environment_name = terraform.workspace
}
resource “aws_s3_bucket” “website_bucket” {
bucket = “${local.environment_name}.feature.environment.blog.com”
acl = “public-read”
force_destroy = true
website {
index_document = “index.html”
}
}
Notice how we create a local variable from the Terraform workspace name, and that we use that variable in order to give the bucket a unique-per-environment name.
Our “CD Process” will be a simple bash file, that accepts the environment name as a parameter:echo “Deploying environment $ENVIRONMENT”
echo “Injecting env vars”
sed ‘s/!!!ENVIRONMENT!!!/’”$ENVIRONMENT”’/g’ index.template.html > $ENVIRONMENT.index.html
echo “Applying Terraform”
terraform init
echo “Selecting/creating workspace”
terraform workspace select $ENVIRONMENT || terraform workspace new $ENVIRONMENT
terraform apply
(You can find the complete example in)
Running
./apply.sh env1
will deploy an environment called env1. Terraform will initialise, show us what actions are going to be performed (the Terraform plan), and after deploying everything, will output the endpoint of the website. If we go into that website — we’ll see something like this -Let’s try running that again, for a different environment this time. We’ll run
./apply.sh my-other-env
, and we’ll get a link to a website that looks like this —> terraform workspace select $ENVIRONMENT
> terraform destroy
I would like to ask you to take all of the above with a grain of salt — this code is really an oversimplified example, meant to illustrate a workflow. As software often goes — making it work “in the wild’’ is often much more complex. Automating Terraform and managing cloud environments isn’t a trivial thing, and most CI/CD tools are built to run one time tasks, and not manage “environments”, that have a longer lifecycle.
That’s why we created , a complete Environment-as-a-service solution, that is built to give your developers the dynamic infrastructure they need, without compromising on the organization’s needs to control and govern how cloud resources are used. Give it a go at .Thanks for reading!
Previously published at //medium.com/env0/from-feature-branches-to-feature-environments-with-terraform-652c0fdf0e78