Skip to content
This repository has been archived by the owner on Jul 24, 2024. It is now read-only.
/ deployadactyl Public archive
forked from slota/deployadactyl

Make deployment downtime extinct

License

Notifications You must be signed in to change notification settings

rmeharg/deployadactyl

 
 

Repository files navigation

Release CircleCI Go Report Card codecov Stories in Ready Gitter GoDoc

Deployadactyl is a Go library for managing applications across multiple Cloud Foundry instances. Deployadactyl utilizes blue green deployments and if it's unable to execute the requested operation it will rollback to the previous state. It also utilizes Go channels for concurrent deployments across the multiple Cloud Foundry instances.

Check out our stories on Pivotal Tracker!

How It Works

Deployadactyl works by utilizing the Cloud Foundry CLI to manage applications. The general flow is to get a list of Cloud Foundry instances, check that the instances are available, log into each instance, and concurrently execute the requested operation on each instance. If the requested operation fails, Deployadactyl will automatically revert the application back to the previous state. For example, in the case of deploying an application, the specified artifact will be downloaded and cf push will be called concurrently in the deploying applications directory on each CF instance. If the push fails on any instance, the application will be reverted to the version that was previously deployed on all instances.

Why Use Deployadactyl?

As an application grows, it will have multiple foundations for each environment. These scaling foundations make managing an application time consuming and difficult to manage. Deployment errors can greatly increase downtime and result in inconsistent state of the application across all foundations..

Deployadactyl makes the process easy and efficient with:

  • Management of multiple environment configurations
  • Concurrent deployments and running state management across environment foundations
  • Automatic rollbacks for failures or errors
  • Prechecking foundation availablity before managing applicaiton state
  • Event handlers for third-party services

Installation Requirements

Dependencies

Deployadactyl has the following dependencies within the environment:

We use Godeps to vendor our GO dependencies. To grab the dependencies and save them to the vendor folder, run the following commands:

$ go get -u github.com/tools/godep
$ godep restore                       // updates local packages to required versions
$ rm -rf Godeps
$ godep save ./...                    // creates ./vendor folder with dependencies

or

$ make dependencies

Configuration File

Deployadactyl needs a yml configuration file to specify available environments for managing applications. At a minimum, each environment has a name and a list of foundations.

The configuration file can be placed anywhere within the Deployadactyl directory, or outside, as long as the location is specified when running the server.

Param Necessity Type Description
name Required string Used in the deploy when the users are sending a request to Deployadactyl to specify which environment from the config they want to use.
foundations Required []string A list of Cloud Foundry Cloud Controller URLs.
domain Optional string Used to specify a load balanced URL that has previously been created on the Cloud Foundry instances.
authenticate Optional bool Used to specify if basic authentication is required for users. See the authentication section for more details
skip_ssl Optional bool Used to skip SSL verification when Deployadactyl logs into Cloud Foundry.
instances Optional int Used to set the number of instances an application is deployed with. If the number of instances is specified in a Cloud Foundry manifest, that will be used instead.

Example Configuration yml

---
environments:
  - name: preproduction
    domain: preproduction.example.com
    foundations:
    - https://api.foundation-1.example.com
    - https://api.foundation-2.example.com
    authenticate: false
    skip_ssl: true
    instances: 2

  - name: production
    domain: production.example.com
    foundations:
    - https://production.foundation-1.example.com
    - https://production.foundation-2.example.com
    - https://production.foundation-3.example.com
    - https://production.foundation-4.example.com
    authenticate: true
    skip_ssl: false
    instances: 4

Environment Variables

Authentication is optional as long as CF_USERNAME and CF_PASSWORD environment variables are exported. We recommend making a generic user account that is able to push to each Cloud Foundry instance.

$ export CF_USERNAME=some-username
$ export CF_PASSWORD=some-password

Optional: The log level can be changed by defining DEPLOYADACTYL_LOGLEVEL. DEBUG is the default log level.

Installing Deployadactyl

Local Installation

After a configuration file has been created and environment variables have been set, the server can be run using the following commands:

$ cd ~/go/src/github.com/compozed/deployadactyl && go run server.go

or

$ cd ~/go/src/github.com/compozed/deployadactyl && go build && ./deployadactyl

Cloud Foundry Installation

To push Deployadactyl to Cloud Foundry, edit the manifest.yml to include the CF_USERNAME and CF_PASSWORD environment variables. In addition, be sure to create a config.yml. Then you can push to Cloud Foundry like normal:

$ cf login
$ cf push

or

$ make push

Available Installation Flags

Flag Usage
-config location of the config file (default "./config.yml")
-envvar turns on the environment variable handler that will bind environment variables to your application at deploy time
-health-check turns on the health check handler that confirms an application is up and running before finishing a push
-route-mapper turns on the route mapper handler that will map additional routes to an application during a deployment. see the Cloud Foundry manifest documentation here for more information

API

A deployment can be executed or modified by hitting the API using curl or other means. For more information on using the Deployadactyl API visit the API documentation in the wiki.

Example Push Curl

curl -X POST \
     -u your_username:your_password \
     -H "Accept: application/json" \
     -H "Content-Type: application/json" \
     -d '{ "artifact_url": "https://example.com/lib/release/my_artifact.jar", "health_check_endpoint": "/health" }' \
     https://preproduction.example.com/v3/deploy/environment/org/space/t-rex

Example Stop Curl

curl -X PUT \
     -u your_username:your_password \
     -H "Accept: application/json" \
     -H "Content-Type: application/json" \
     -d '{ "state": "stopped" }' \
     https://preproduction.example.com/v3/deploy/environment/org/space/t-rex

Event Handling

With Deployadactyl you can optionally register event handlers to perform any additional actions your deployment flow may require. For example, you may want to do an additional health check before the new application overwrites the old application.

NOTE The event handling framework for Deployadactyl has been reworked in version 3 to allow for strongly typed binding between event handler functions and the events on which those functions operate. See more info below and in the wiki

Event Handler Example

Attach an event handler to a specific event by creating a binding between the desired event and your handler function and add it to the EventManager:

myHandler := func(event PushStartedEvent) error {
   mylog.Debug("A push has started with manifest: " + event.Manifest)
   ...
   return nil
}

eventManager.AddBinding(NewPushStartedEventBinding(myHandler))

Custom events can be created by implementing the Binding and IEvent interfaces.

Deprecated Event Handling

Prior to version 3, events were registered the following way:

type Handler struct {...}

func (h Handler) OnEvent(event interfaces.Event) error {
   if event.Type == "push.started" {
      deploymentInfo := event.Data.(*DS.DeployEventData).DeploymentInfo
      mylog.Debug("A push has started with manifest: " + deploymentInfo.Manifest
      ...
      return nil
   } else ...
}

eventManager.AddHandler(Handler{...}, "push.started")

This method of event handling is still supported for push related events and creating custom events, but is deprecated and can be expected to be removed in the future.

Contributing

See our CONTRIBUTING section for more information.

About

Make deployment downtime extinct

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 99.9%
  • Other 0.1%