Managing Pantheon Sites with Terminus
In the previous post we looked into Pantheon hosting and how we can use it to easily create a suite of similar websites without having to build them individually each time. Often the requirement isn’t only easily creating new sites, but having to maintain them easily as well. When you have dozens or hundreds of websites that need changes applied to them, managing each one individually through Pantheon’s dashboard becomes a bottleneck. Fortunately Pantheon offers a command line interface that allows developers to automate much of that maintenance. In this post we’ll take a look at using Terminus to manage our sites.
Understanding Pantheon’s Framework
Before we can start rolling out features to multiple sites, it is helpful to understand how Pantheon groups the websites it hosts. Websites can be first grouped into an Organization. Within that, they can be tagged in any manner that makes sense for your needs. Both the organization and the tags can be used to filter sites into more targeted groups.
Each site then gets three environments; dev
, test
, and live
are their machine names. Those machine names are important, as we’ll need to know which environment we’re targeting when we do our deployments. A single site also gets a machine name, like my-awesome-site
. The combination of site name and environment name create a single instance identifier, which we use in our Terminus commands. For example, to clear Drupal’s cache on a live environment we’d run:
terminus remote:drush my-awesome-site.live -- cache-rebuild
A deployment on Pantheon has to follow a specific process, whether done via the dashboard or through Terminus. First, code must be deployed to the dev
environment. Normally this is done with Git by pushing new code into the master
branch on Pantheon’s repo. For features we’re deploying to multiple sites, the code must be pushed to the Upstream and then pulled from there. In the dashboard, this takes the form of a button that appears to alert you to new changes. In Terminus, you’d run the following command. Note, the --updatedb
flag ensures any Drupal database updates get run as well.
terminus upstream:updates:apply my-awesome-site.dev --updatedb
Second, we have to move those updates to testing and then to production. Again, the dashboard provides a button on those environments when there are updates that can be made to them. In Terminus, this is done with:
terminus env:deploy my-awesome-site.test --updatedb --cc --note=”Deployed new feature.”
As before --updatedb
runs the database updates, --cc
rebuilds Drupal’s cache, and --note
is the description of the updates that gets added to the Pantheon dashboard.
There are many other actions you can handle with Terminus. Their documentation covers the full list. However, out of the box Terminus has the same limitation that the dashboard has. You can only run a command on one site at a time. Thankfully, Terminus has additional plugins that solve this problem for us.
New Commands with Terminus Plugins
Terminus is built on PHP and managed with Composer. This allows for new commands to be built and distributed on Pantheon’s Terminus Plugin Library. We’ll need to install two plugins to run Terminus commands on multiple sites at once: Terminus Mass Update and Terminus Mass Run. Mass Update is created by Pantheon and runs the upstream:updates:apply
command on a list of sites that get piped into it. Mass Run builds on that idea, by using the same piping logic and implements it onto more commands. With it you can run Drush commands, create site backups, and deploy code among other things.
To get the list of sites, we’ll use the org:site:list
command. We could also use site:list
, however since Custom Upstreams are an Organization level feature we’ll more than likely want to filter by Organization; org:site:list
takes the name of the organization we want to filter by. To get a list of the Organizations you have access to, run terminus org:list
. This returns both the machine name and the ID number of the Organizations, either will work for org:site:list
.
Running terminus org:site:list aten
will return a table of all sites in Aten’s Organization account. However, we still might only want a subset of those sites. This is where tagging comes in. Adding the --tag
flag to our command lets us get only sites we’ve tagged with whatever is passed in. To see all sites tagged with “US” our command becomes terminus org:site:list aten --tag=US
. This gets us closer, however it still returns a table of all site information. We only need the site ID numbers as a list for our Mass Run and Mass Update commands. To get this list we’ll add --format=list
to our command, making the entire thing:
terminus org:site:list aten --tag=US --format=list
Now that we have a list of the site IDs we want to update, all we need to do is pipe that list into our plugin commands. To deploy a new feature from our upstream, we’d run:
terminus org:site:list aten --tag=US --format=list | terminus site:mass-update:apply --updatedb
Moving that feature through Pantheon’s environments is:
terminus org:site:list aten --tag=US --format=list | terminus env:mass:deploy --sync-content --cc --updatedb --env=test --note="Updated Drupal Core."
Removing a user from all sites they exist on becomes:
terminus org:site:list aten --tag=US --format=list | terminus remote:mass:drush --env=live -- ucan bad-user
Long Commands, Amazing Results
At this point you’ve probably noticed the commands we’re using have become very verbose. This is one downside of this approach: the commands themselves are not intuitive at first glance. For common tasks creating aliases can help simplify this. Leveraging the terminal’s history to bring up past commands and then modifying them speeds up more one-off tasks. But the ability to manage our websites en masse becomes a huge time saver over clicking our way through the dashboard for dozens of sites.