-
Notifications
You must be signed in to change notification settings - Fork 359
Fun with Revisions
With the release of CAPI 1.79.0, we introduced the Revisions feature MVP. When you enable Revisions for your app, Cloud Controller will create a new Revision any time new code, environment variables, or process commands are changed and deployed. Previously, Cloud Foundry did not keep a record of an application's history. With Revisions, you can now see what changed with your application, and when. Perhaps more importantly, if you find that your most recent deployment contained a serious bug, you can now rollback to a previous "good" version [version].
In this article, we will explore in-depth the functionality of Revisions in Cloud Foundry, including what exactly they track, how to view your Revision history, and how to revert to a previous Revision.
For this tutorial, we will be using this sample app: CF Ruby Sample App [TODO: Get this on cloudfoundry-samples]. If you would like to follow along, you can clone this repository, or use your own test application.
Let’s start by creating our application. In the app’s root directory, let’s run:
cf v3-create-app sample-app
Currently, Revisions are enabled on a per-app basis. To enable revisions for our sample application, let’s add enable the feature flag via the Cloud Controller API:
cf curl /v3/apps/$(cf app sample-app --guid)/features/revisions -X PATCH -d '{ "enabled": true }'
Now that we have created our app and enabled Revisions, we can poll the v3/revisions
endpoint to watch the new Revisions being created as we deploy different versions of our application.
In a separate terminal, run:
watch 'cf curl /v3/apps/$(cf app sample-app --guid)/revisions | grep description'
(For the purposes of this tutorial, we are only extracting the description
of the revisions, as the raw API results would be too verbose).
To begin with, we won’t see any results, as we haven’t deployed our app yet. So let’s try it! In your app directory, run:
cf v3-push sample-app
Partway through the push process, you should see a description of your app’s first revision appear:
"description": "Initial revision."
Our first revision!
Because this is the very first one, its description is not too informative. But let’s try changing an environment variable:
cf set-env sample-app FOO BAR
cf v3-restart sample-app
You’ll see a new revision is created, explaining the change:
"description": "Initial revision.",
"description": "New environment variables deployed.",
This description is a little more helpful.
Now, let’s try re-pushing the app without any changes:
cf v3-push sample-app
You might expect that would be no revision, as we didn’t make any changes, right? But you will see that a new Revision was created:
“description": "Initial revision.",
“description": "New environment variables deployed.",
“description": "New droplet deployed.",
That’s because pushing always creates a new droplet, even if there are no changes.
Now let’s take a detailed look at the app’s current revision. Conveniently, we can fetch the currently deployed revisions by calling a special endpoint, v3/apps/:app_guid/revisions/deployed
:
cf curl v3/apps/$(cf app sample-app --guid)/revisions/deployed
Your revision will look something like this:
{
"guid": "ac8f9f3b-ddd1-4385-8960-c464e2c3feb9",
"version": 5,
"droplet": {
"guid": "0ae58601-5687-4afd-9b73-97759e651a3d"
},
"processes": {
"web": {
"command": null
}
},
"description": "New droplet deployed.",
"created_at": "2019-05-20T23:36:35Z",
"updated_at": "2019-05-20T23:36:35Z",
"links": {
"environment_variables": {
"href": "https://api.moor-cap.capi.land/v3/revisions/ac8f9f3b-ddd1-4385-8960-c464e2c3feb9/environment_variables"
}
}
...
}
As you can see, revisions track droplet's and process commands, as well as its environment variables. The “web” process’s command being set to null
means that it defaults to the start command defined in that droplet’s Procfile. But we can override that command using the V3 API. Let’s try it!
First we get the app’s web process:
cf curl v3/apps/$(cf app sample-app --guid)/processes/web
The result will look something like this:
{
"guid": "MY_GUID",
"type": "web",
"command": "bundle exec rackup config.ru -p $PORT",
"instances": 1,
"memory_in_mb": 256,
"disk_in_mb": 1024,
"health_check": {
"type": "port",
"data": {
"timeout": null,
"invocation_timeout": null
}
},
...
Let’s take the guid from the top of the payload and alter the process’s start command slightly by PATCHing it:
cf curl /v3/processes/MY_GUID -X PATCH -d '{ "command": "FOO=test ruby app.rb" }'
cf v3-push sample-app
You should see yet another revision description appear:
"description": "Initial revision.",
"description": "New environment variables deployed.",
“description": "New droplet deployed.",
“description": "Custom start command updated for 'web' process. New droplet deployed.",
If you curl the deployed revision again, you’ll see that the revision has recorded the custom start command.
But let’s say we decide we want to undo the changes we’ve made, and revert to our first revision. We can query for our first revision of the app using the version
query parameter.
cf curl /v3/apps/$(cf app sample-app --guid)/revisions?versions=1
Grab the revision's GUID, and then create a new deployment via the V3 API:
(you'll also need to grab the app's guid with cf app sample-app --guid
)
cf curl /v3/deployments -X POST -d '{
"revision": {
"guid": "REVISION_GUID"
},
"relationships": {
"app": {
"data": {
"guid": "APP_GUID"
}
}
}
}'
You should see yet another description appear in your other terminal:
"description": "Initial revision.",
"description": "New environment variables deployed.",
“description": "New droplet deployed.",
“description": "Custom start command updated for 'web' process. New droplet deployed.",
"description": "Custom start command removed for 'web' process. New droplet deployed. New environment variables deployed. Rolled back to revision 1.",
As you can see, all the changes we made were undone, and we've reverted our application back to our initial state!
NOTE: There are some limitations on rolling back to previous revisions. Most notably, by default Cloud Controller will only store the five most recent droplets for an app. This can be configured with the cc.droplets.max_staged_droplets_stored
property. Otherwise, by default CC will only store the last 100 revisions. However, this can be configured with the cc.max_retained_revisions_per_app
property.
For more information about Revisions, please refer to the Dev Guide and the V3 API. Please note this feature is still considered experimental and not yet recommended for production environments. Please let us know your thoughts and feedback, and we hope you are excited to use Revisions in your deployment process!
-
Pipelines
-
Contributing
- Tips and Tricks
- Cloud Controller API v3 Style Guide
- Playbooks
- Development configuration
- Testing
-
Architectural Details
-
CC Resources
- Apps
- Audit Events
- Deployments
- Labels
- Services
- Sidecars
-
Dependencies
-
Troubleshooting
- Ruby Console Script to Find Fields that Cannot Be Decrypted
- Logging database queries in unit tests
- Inspecting blobstore cc resources and cc packages(webdav)
- How to Use USR1 Trap for Diagnostics
- How to Perf: Finding and Fixing Bottlenecks
- How to get access to mysql database
- How To Get a Ruby Heap Dumps & GC Stats from CC
- How to curl v4 internal endpoints with mtls
- How to access Bosh Director console and restore an outdated Cloud Config
- Analyzing Cloud Controller's NGINX logs using the toplogs script
-
k8s
-
Archive