sup

package module
v0.0.0-...-8dad1ef Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 5, 2016 License: MIT Imports: 15 Imported by: 0

README

Stack Up

Stack Up is a simple deployment tool that performs given set of commands on multiple hosts in parallel. It reads Supfile, a YAML configuration file, which defines networks (groups of hosts), commands and targets.

Demo

Demo using the following Supfile:

Sup

Installation

$ go get -u github.com/pressly/sup/cmd/sup

Usage

$ sup [OPTIONS] NETWORK TARGET/COMMAND [...]
Options
Option Description
--help, -h Print help/usage
--version, -v Print version
-f Supfile Location of Supfile
--only REGEXP Filter NETWORK hosts using regexp string
--except REGEXP Filter out NETWORK hosts using regexp string
Network

A group of hosts on which COMMAND will be invoked in parallel.

# Supfile

networks:
    production:
        hosts:
            - api1.example.com
            - api2.example.com
            - api3.example.com
    staging:
        hosts:
            - stg1.example.com

$ sup production COMMAND will invoke COMMAND on all production hosts in parallel.

$ sup staging TARGET will invoke TARGET on the staging host.

Target

An alias to run multiple COMMANDS.

# Supfile

targets:
    deploy:
        - build
        - pull
        - migrate-db-up
        - stop-rm-run
        - health
        - slack-notify
        - airbrake-notify

$ sup production deploy will invoke build, pull, migrate-db-up, stop-rm-run and slack-notify commands sequentially on all production hosts.

Command

A shell command (or set of commands) to be run remotely.

# Supfile

commands:
    restart:
        desc: Restart example Docker container
        run: sudo docker restart example
    tail-logs:
        desc: Watch tail of Docker logs from all hosts
        run: sudo docker logs --tail=20 -f example
    exec:
        desc: Exec into Docker container on all hosts
        stdin: true
        run: sudo docker exec -i example bash
    bash:
        desc: Interactive Bash on all hosts
        stdin: true
        run: bash

$ sup production restart will restart all production example Docker containers in parallel.

$ sup production tail-logs will tail Docker logs from all production example containers in parallel.

$ sup production exec will Docker Exec into all production Docker containers and run interactive shell.

$ sup production bash will run interactive shell on all production hosts.

Supfile

See example Supfile.

Basic structure
# Supfile
---
version: 0.3

# Global environment variables
env:
  NAME: api
  IMAGE: example/api

networks:
  local:
    hosts:
      - localhost
  staging:
    hosts:
      - stg1.example.com
  production:
    hosts:
      - api1.example.com
      - api2.example.com

commands:
  echo:
    desc: Print some env vars
    run: echo $NAME $IMAGE $SUP_NETWORK
  date:
    desc: Print OS name and current date/time
    run: uname -a; date

targets:
  all:
    - echo
    - date
Default environment variables
  • $SUP_NETWORK - Name of the NETWORK that the command was originally issued against.
  • $SUP_USER - Name of user who issued the command.
  • $SUP_TIME - Date and time of the original command line invocation.

Development

fork it..

$ make tools
$ make build

License

Licensed under the MIT License.

Documentation

Index

Constants

View Source
const VERSION = "0.3"

Variables

View Source
var (
	Colors = []string{
		"\033[32m",
		"\033[33m",
		"\033[36m",
		"\033[35m",
		"\033[31m",
		"\033[34m",
	}
	ResetColor = "\033[0m"
)

Functions

func LocalTarCommand

func LocalTarCommand(path, exclude string) string

func NewTarStreamReader

func NewTarStreamReader(path, exclude, env string) io.Reader

NewTarStreamReader creates a tar stream reader from a local path. TODO: Refactor. Use "archive/tar" instead.

func RemoteTarCommand

func RemoteTarCommand(dir string) string

RemoteTarCommand returns command to be run on remote SSH host to properly receive the created TAR stream. TODO: Check for relative directory.

Types

type Client

type Client interface {
	Connect(host string) error
	Run(task *Task) error
	Wait() error
	Close() error
	Prefix() (string, int)
	Write(p []byte) (n int, err error)
	WriteClose() error
	Stdin() io.WriteCloser
	Stderr() io.Reader
	Stdout() io.Reader
}

type Command

type Command struct {
	Name   string   `yaml:"-"`      // Command name.
	Desc   string   `yaml:"desc"`   // Command description.
	Local  string   `yaml:"local"`  // Command(s) to be run locally.
	Run    string   `yaml:"run"`    // Command(s) to be run remotelly.
	Script string   `yaml:"script"` // Load command(s) from script and run it remotelly.
	Upload []Upload `yaml:"upload"` // See Upload struct.
	Stdin  bool     `yaml:"stdin"`  // Attach localhost STDOUT to remote commands' STDIN?
	Once   bool     `yaml:"once"`   // The command should be run "once" (on one host only).
	Serial int      `yaml:"serial"` // Max number of clients processing a task in parallel.

	// API backward compatibility. Will be deprecated in v1.0.
	RunOnce bool `yaml:"run_once"` // The command should be run once only.
}

Command represents command(s) to be run remotely.

type EnvList

type EnvList []EnvVar

EnvList is a list of environment variables that maps to a YAML map, but maintains order, enabling late variables to reference early variables.

func (*EnvList) Set

func (e *EnvList) Set(key, value string)

Set key to be equal value in this list.

func (*EnvList) UnmarshalYAML

func (e *EnvList) UnmarshalYAML(unmarshal func(interface{}) error) error

type EnvVar

type EnvVar struct {
	Key   string
	Value string
}

EnvVar represents an environment variable

func (EnvVar) AsExport

func (e EnvVar) AsExport() string

AsExport returns the environment variable as a bash export statement

func (EnvVar) String

func (e EnvVar) String() string

type ErrConnect

type ErrConnect struct {
	User   string
	Host   string
	Reason string
}

func (ErrConnect) Error

func (e ErrConnect) Error() string

type ErrTask

type ErrTask struct {
	Task   *Task
	Reason string
}

func (ErrTask) Error

func (e ErrTask) Error() string

type LocalhostClient

type LocalhostClient struct {
	// contains filtered or unexported fields
}

Client is a wrapper over the SSH connection/sessions.

func (*LocalhostClient) Close

func (c *LocalhostClient) Close() error

func (*LocalhostClient) Connect

func (c *LocalhostClient) Connect(_ string) error

func (*LocalhostClient) Prefix

func (c *LocalhostClient) Prefix() (string, int)

func (*LocalhostClient) Run

func (c *LocalhostClient) Run(task *Task) error

func (*LocalhostClient) Stderr

func (c *LocalhostClient) Stderr() io.Reader

func (*LocalhostClient) Stdin

func (c *LocalhostClient) Stdin() io.WriteCloser

func (*LocalhostClient) Stdout

func (c *LocalhostClient) Stdout() io.Reader

func (*LocalhostClient) Wait

func (c *LocalhostClient) Wait() error

func (*LocalhostClient) Write

func (c *LocalhostClient) Write(p []byte) (n int, err error)

func (*LocalhostClient) WriteClose

func (c *LocalhostClient) WriteClose() error

type Network

type Network struct {
	Env       EnvList  `yaml:"env"`
	Inventory string   `yaml:"inventory"`
	Hosts     []string `yaml:"hosts"`
	Bastion   string   `yaml:"bastion"` // Jump host for the environment
}

Network is group of hosts with extra custom env vars.

func (Network) ParseInventory

func (n Network) ParseInventory() ([]string, error)

ParseInventory runs the inventory command, if provided, and appends the command's output lines to the manually defined list of hosts.

type SSHClient

type SSHClient struct {
	// contains filtered or unexported fields
}

Client is a wrapper over the SSH connection/sessions.

func (*SSHClient) Close

func (c *SSHClient) Close() error

Close closes the underlying SSH connection and session.

func (*SSHClient) Connect

func (c *SSHClient) Connect(host string) error

Connect creates SSH connection to a specified host. It expects the host of the form "[ssh://]host[:port]".

func (*SSHClient) ConnectWith

func (c *SSHClient) ConnectWith(host string, dialer SSHDialFunc) error

ConnectWith creates a SSH connection to a specified host. It will use dialer to establish the connection. TODO: Split Signers to its own method.

func (*SSHClient) DialThrough

func (sc *SSHClient) DialThrough(net, addr string, config *ssh.ClientConfig) (*ssh.Client, error)

DialThrough will create a new connection from the ssh server sc is connected to. DialThrough is an SSHDialer.

func (*SSHClient) Prefix

func (c *SSHClient) Prefix() (string, int)

func (*SSHClient) Run

func (c *SSHClient) Run(task *Task) error

Run runs the task.Run command remotely on c.host.

func (*SSHClient) Stderr

func (c *SSHClient) Stderr() io.Reader

func (*SSHClient) Stdin

func (c *SSHClient) Stdin() io.WriteCloser

func (*SSHClient) Stdout

func (c *SSHClient) Stdout() io.Reader

func (*SSHClient) Wait

func (c *SSHClient) Wait() error

Wait waits until the remote command finishes and exits. It closes the SSH session.

func (*SSHClient) Write

func (c *SSHClient) Write(p []byte) (n int, err error)

func (*SSHClient) WriteClose

func (c *SSHClient) WriteClose() error

type SSHDialFunc

type SSHDialFunc func(net, addr string, config *ssh.ClientConfig) (*ssh.Client, error)

SSHDialFunc can dial an ssh server and return a client

type Stackup

type Stackup struct {
	// contains filtered or unexported fields
}

func New

func New(conf *Supfile) (*Stackup, error)

func (*Stackup) Run

func (sup *Stackup) Run(network *Network, commands ...*Command) error

Run runs set of commands on multiple hosts defined by network sequentially. TODO: This megamoth method needs a big refactor and should be split

to multiple smaller methods.

type Supfile

type Supfile struct {
	Networks map[string]Network  `yaml:"networks"`
	Commands map[string]Command  `yaml:"commands"`
	Targets  map[string][]string `yaml:"targets"`
	Env      EnvList             `yaml:"env"`
	Version  string              `yaml:"version"`
}

Supfile represents the Stack Up configuration YAML file.

func NewSupfile

func NewSupfile(file string) (*Supfile, error)

NewSupfile parses configuration file and returns Supfile or error.

type Task

type Task struct {
	Run     string
	Input   io.Reader
	Clients []Client
}

Task represents a set of commands to be run.

func CreateTasks

func CreateTasks(cmd *Command, clients []Client, env string) ([]*Task, error)

type Upload

type Upload struct {
	Src string `yaml:"src"`
	Dst string `yaml:"dst"`
	Exc string `yaml:"exclude"`
}

Upload represents file copy operation from localhost Src path to Dst path of every host in a given Network.

Directories

Path Synopsis
cmd
sup command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL