Skip to content

Commit

Permalink
Merge pull request #12 from HappyTobi/docker_support
Browse files Browse the repository at this point in the history
Docker support
  • Loading branch information
HappyTobi authored Nov 21, 2019
2 parents 54e0771 + 698c471 commit 02d3e94
Show file tree
Hide file tree
Showing 19 changed files with 503 additions and 223 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- refactor environment parsing
- clean code
- documentation update
- back port "--no-route" and "--route-only" option to "--legacy-push" (v2).
- docker support was available again
- vendor-option droped

### Fixed

Expand Down
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,30 @@
[![APACHE-2 License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://github.com/HappyTobi/cf-puppeteer/blob/master/LICENSE)
[![Github All Releases](https://img.shields.io/github/downloads/HappyTobi/cf-puppeteer/total.svg)](https://github.com/HappyTobi/cf-puppeteer/releases)
[![Github All Releases](https://img.shields.io/github/v/release/HappyTobi/cf-puppeteer?include_prereleases)](https://github.com/HappyTobi/cf-puppeteer/releases)
[![Documentation](https://img.shields.io/badge/Documentation-visit-green)](https://cf-puppeteer.happytobi.com)

*cf plugin for hands-off, zero downtime application deploys*

## notice
## Documentation / Website
[CF-Puppeteer Website](https://cf-puppeteer.happytobi.com).

### Notice

This project was forked from [contraband](https://github.com/contraband/autopilot).

It was renamed to *cf-puppeteer* and is being further developed under the new name.

# changelog
# Changelog

To get an overview of the changes between versions, read the [changelog](CHANGELOG.md).

## version
## Version

The latest version of *CF-Puppeteer* is *1.1.2*. It works with and is based on Cloud Foundry CLI version 6.43.0.

For more details on the most recent release, check out the [changelog](CHANGELOG.md).

## cf installation
## Cf installation

Download the latest version from the [releases][releases] page and make it executable.

Expand All @@ -33,7 +37,7 @@ $ cf install-plugin path/to/downloaded/binary

[releases]: https://github.com/happytobi/cf-puppeteer/releases

## usage
## Usage

```
$ cf zero-downtime-push \
Expand All @@ -44,7 +48,7 @@ $ cf zero-downtime-push \

To get more information go to [CF-Puppeteer homepage](https://cf-puppeteer.happytobi.com/)

### passing an application name
### Passing an application name

To override the application name from the manifest, specify it as command line argument. For example:

Expand All @@ -55,7 +59,7 @@ $ cf zero-downtime-push application-to-replace \
-t 120
```

### changing the health check settings
### Changing the health check settings

To have more control over the health checks of your application, *CF-Puppeteer* supports additional parameters. For example:

Expand All @@ -71,7 +75,7 @@ $ cf zero-downtime-push application-to-replace \

While *CF-Puppeteer* gives precedence to command line parameters, you can also specify `health-check-type` and `health-check-http-endpoint` in the application manifest. However, Cloud Foundry currently does not support `invocation-timeout` in application manifests. Therefore, if you want to set it, always use the command line.

## method
## Method

*CF-Puppeteer* takes a different approach compared to other zero-downtime plugins. It
does not perform any [complex route re-mappings][indiana-jones]. Instead it uses the manifest feature of the Cloud Foundry CLI. The method also has the advantage of treating a manifest as the source of truth and will converge the
Expand All @@ -90,5 +94,5 @@ delivery environments.

[indiana-jones]: https://www.youtube.com/watch?v=0gU35Tgtlmg

## local development
## Local development
for local development you need to install [govendor](https://github.com/kardianos/govendor)
35 changes: 15 additions & 20 deletions arguments/arguments.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"fmt"
"github.com/happytobi/cf-puppeteer/cf/utils/env"
"github.com/happytobi/cf-puppeteer/manifest"
"github.com/happytobi/cf-puppeteer/ui"
"os"
"regexp"
"strings"
)
Expand All @@ -22,7 +22,6 @@ type ParserArguments struct {
InvocationTimeout int
Process string
StackName string
VendorAppOption string
VenerableAction string
Envs map[string]string
ShowLogs bool
Expand Down Expand Up @@ -56,6 +55,8 @@ var (
ErrWrongEnvFormat = errors.New("--var would be in wrong format, use the vars like key=value")
//ErrWrongCombination error when legacy push is used with health check options
ErrWrongCombination = errors.New("--legacy-push and health check options couldn't be combined")
//ErrWrongDockerCombination error when private docker image repo will be pushed without a pass
ErrWrongPrivateDockerRepoCombination = errors.New("--docker-username have to be used in combination with env CF_DOCKER_PASSWORD and --docker-image")
)

// ParseArgs parses the command line arguments
Expand All @@ -72,20 +73,19 @@ func ParseArgs(args []string) (*ParserArguments, error) {
flags.StringVar(&pta.HealthCheckHTTPEndpoint, "health-check-http-endpoint", "", "endpoint for the 'http' health check type")
flags.IntVar(&pta.Timeout, "t", 0, "push timeout in seconds (defaults to 60 seconds)")
flags.IntVar(&pta.InvocationTimeout, "invocation-timeout", -1, "health check invocation timeout in seconds")
flags.StringVar(&pta.Process, "process", "", "application process to update")
flags.StringVar(&pta.Process, "process", "", "use health check type process")
flags.BoolVar(&pta.ShowLogs, "show-app-log", false, "tail and show application log during application start")
flags.BoolVar(&pta.ShowCrashLogs, "show-crash-log", false, "Show recent logs when applications crashes while the deployment")
flags.StringVar(&pta.VendorAppOption, "vendor-option", "delete", "option to delete,stop,none application action on vendor app- default is delete")
flags.StringVar(&pta.VenerableAction, "venerable-action", "delete", "option to delete,stop,none application action on vendor app- default is delete")
flags.Var(&envs, "env", "Variable key value pair for adding dynamic environment variables; can specify multiple times")
flags.BoolVar(&pta.LegacyPush, "legacy-push", false, "use legacy push instead of new v3 api")
flags.BoolVar(&pta.NoRoute, "no-route", false, "deploy new application without adding routes")
flags.BoolVar(&pta.AddRoutes, "route-only", false, "only add routes from manifest to the application")
flags.BoolVar(&pta.NoStart, "no-start", false, "don't start application after deployment")
flags.BoolVar(&pta.NoStart, "no-start", false, "don't start application after deployment; venerable action is none")
//flags.BoolVar(&pta.ShowLogs, "show-app-log", false, "tail and show application log during application start")
//flags.StringVar(&pta.DockerImage, "docker-image", "", "url to docker image")
//flags.StringVar(&pta.DockerUserName, "docker-username", "", "pass docker username if image came from private repository")
//dockerPass := os.Getenv("CF_DOCKER_PASSWORD")
flags.StringVar(&pta.DockerImage, "docker-image", "", "docker image url")
flags.StringVar(&pta.DockerUserName, "docker-username", "", "docker repository username; used with password from env CF_DOCKER_PASSWORD")
dockerPass := os.Getenv("CF_DOCKER_PASSWORD")

//first check if argument was passed
if len(args) < 2 {
Expand Down Expand Up @@ -117,9 +117,10 @@ func ParseArgs(args []string) (*ParserArguments, error) {
}
pta.Manifest = parsedManifest

/*if *dockerImage != "" && *dockerUserName != "" && dockerPass != "" {
//TODO use dockerImage stuff and pass to push command
}*/
//check if a docker image shouldbe pushed and verify passed args combination
if len(pta.DockerUserName) > 0 && (len(dockerPass) == 0 || len(pta.DockerImage) == 0) {
return nil, ErrWrongPrivateDockerRepoCombination
}

//set timeout
manifestTimeout := parsedManifest.ApplicationManifests[0].Timeout
Expand All @@ -136,12 +137,12 @@ func ParseArgs(args []string) (*ParserArguments, error) {
}

//check that health check works without legacy push only
if pta.LegacyPush && (pta.HealthCheckType != "" || pta.HealthCheckHTTPEndpoint != "") {
if pta.LegacyPush && ((argPassed(flags, "health-check-type") && pta.HealthCheckType != "") || (argPassed(flags, "health-check-http-endpoint") && pta.HealthCheckHTTPEndpoint != "")) {
return nil, ErrWrongCombination
}

// get health check settings from manifest if nothing else was specified in the command line
if pta.HealthCheckType == "" {
if argPassed(flags, "health-check-type") == false {
if parsedManifest.ApplicationManifests[0].HealthCheckType == "" {
pta.HealthCheckType = "port"
} else {
Expand All @@ -164,14 +165,8 @@ func ParseArgs(args []string) (*ParserArguments, error) {
pta.Envs = env.Convert(envs)
}

//print waring for deprecated arguments
if strings.ToLower(pta.VendorAppOption) != "delete" {
ui.Warn("deprecated argument used, please use --venerable-action instead - argument will dropped in next version")
pta.VenerableAction = pta.VendorAppOption
}

//no-route set venerable-action to delete as default - but can be overwritten
if pta.NoRoute && argPassed(flags, "venerable-action") == false {
if (pta.NoRoute || pta.NoStart) && argPassed(flags, "venerable-action") == false {
pta.VenerableAction = "none"
}

Expand Down
5 changes: 2 additions & 3 deletions arguments/arguments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ var _ = Describe("Flag Parsing", func() {
Expect(parsedArguments.AppPath).To(Equal("app-path"))
Expect(parsedArguments.StackName).To(Equal("stack-name"))
Expect(parsedArguments.Envs).To(Equal(map[string]string{"foo": "bar", "baz": "bob"}))
Expect(parsedArguments.VenerableAction).Should(Equal("delete"))
Expect(parsedArguments.VenerableAction).Should(Equal("none"))
Expect(parsedArguments.ShowLogs).To(Equal(true))
Expect(parsedArguments.ShowCrashLogs).To(Equal(false))
Expect(parsedArguments.Timeout).To(Equal(120))
Expand Down Expand Up @@ -223,13 +223,12 @@ var _ = Describe("Deprecated flag parsing", func() {
"appname",
"-f", "../fixtures/manifest.yml",
"-p", "app-path",
"--vendor-option", "stop",
"--venerable-action", "stop",
},
)
Expect(err).ToNot(HaveOccurred())
Expect(arg.AppName).To(Equal("appname"))
Expect(arg.ManifestPath).To(Equal("../fixtures/manifest.yml"))
Expect(arg.VenerableAction).Should(Equal("stop"))
Expect(arg.VendorAppOption).Should(Equal("stop"))
})
})
10 changes: 5 additions & 5 deletions cf/cli/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@ import (
"os/exec"
)

type Executor interface {
type CfExecutor interface {
Execute(arguments []string) (err error)
}

//HttpConnection
type executor struct {
type Executor struct {
traceLogging bool
}

func NewExecutor(traceLogging bool) Executor {
return executor{
func NewExecutor(traceLogging bool) CfExecutor {
return Executor{
traceLogging: traceLogging,
}
}

func (ec executor) Execute(arguments []string) (err error) {
func (ec Executor) Execute(arguments []string) (err error) {
cfCmdToolPath, err := exec.LookPath("cf")
if err != nil {
return err
Expand Down
32 changes: 32 additions & 0 deletions cf/cli/fakeExcecutor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cli

//Test struct for executro
type FakeExecutor struct {
traceLogging bool
counter int
argumentsOutput map[int][]string
}

func (tx *FakeExecutor) NewFakeExecutor() CfExecutor {
return tx
}

func (tx *FakeExecutor) Execute(arguments []string) (err error) {
tx.counter++
size := len(tx.argumentsOutput)
if tx.argumentsOutput == nil {
//init lazy - only for fake executor
tx.argumentsOutput = map[int][]string{0: arguments}
} else {
tx.argumentsOutput[size] = arguments
}
return nil
}
func (tx *FakeExecutor) ExecutorCallCount() int {
return tx.counter
}

func (tx *FakeExecutor) ExecutorArgumentsOutput() map[int][]string {
return tx.argumentsOutput
}

7 changes: 5 additions & 2 deletions cf/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type ApplicationPushData struct {

//PuppeteerPush push application interface
type PuppeteerPush interface {
PushApplication(venAppName string, spaceGUID string, parsedArguments *arguments.ParserArguments) error
PushApplication(venAppName string, venAppExists bool, spaceGUID string, parsedArguments *arguments.ParserArguments) error
}

var cliCalls cli.Calls
Expand All @@ -39,7 +39,7 @@ func NewApplicationPush(conn plugin.CliConnection, traceLogging bool) *Applicati
}

//PushApplication push application to cf
func (adp *ApplicationPushData) PushApplication(venAppName, spaceGUID string, parsedArguments *arguments.ParserArguments) error {
func (adp *ApplicationPushData) PushApplication(venAppName string, venAppExists bool, spaceGUID string, parsedArguments *arguments.ParserArguments) error {
v3Push, err := useV3Push()
if err != nil {
//fatal exit
Expand All @@ -57,6 +57,9 @@ func (adp *ApplicationPushData) PushApplication(venAppName, spaceGUID string, pa
}

var legacyPush v2.Push = v2.NewV2LegacyPush(adp.Connection, adp.TraceLogging)
if parsedArguments.AddRoutes {
return legacyPush.SwitchRoutesOnly(venAppName, venAppExists, parsedArguments.AppName, parsedArguments.Manifest.ApplicationManifests[0].Routes)
}
return legacyPush.PushApplication(venAppName, spaceGUID, parsedArguments)
}

Expand Down
Loading

0 comments on commit 02d3e94

Please sign in to comment.