-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #72 from platform-acceleration-lab/master
Replace autopilot zero down time deploys with own implementation.
- Loading branch information
Showing
9 changed files
with
425 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#!/bin/bash | ||
|
||
./$(dirname $0)/cf $* | ||
|
||
exit 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -112,15 +112,17 @@ var _ = Describe("Out", func() { | |
Expect(session.Err).To(gbytes.Say("cf api https://api.run.pivotal.io --skip-ssl-validation")) | ||
Expect(session.Err).To(gbytes.Say("cf auth [email protected] hunter2")) | ||
Expect(session.Err).To(gbytes.Say("cf target -o org -s space")) | ||
Expect(session.Err).To(gbytes.Say("cf zero-downtime-push awesome-app -f %s", | ||
Expect(session.Err).To(gbytes.Say("cf rename awesome-app awesome-app-venerable")) | ||
Expect(session.Err).To(gbytes.Say("cf push awesome-app -f %s", | ||
filepath.Join(tmpDir, "project/manifest.yml"), | ||
)) | ||
Expect(session.Err).To(gbytes.Say(filepath.Join(tmpDir, "another-project"))) | ||
Expect(session.Err).To(gbytes.Say("cf delete -f awesome-app-venerable")) | ||
|
||
// color should be always | ||
output := string(session.Err.Contents()) | ||
Expect(strings.Count(output, "CF_COLOR=true")).To(Equal(4)) | ||
Expect(strings.Count(output, "CF_TRACE=/dev/stderr")).To(Equal(4)) | ||
Expect(strings.Count(output, "CF_COLOR=true")).To(Equal(7)) | ||
Expect(strings.Count(output, "CF_TRACE=true")).To(Equal(7)) | ||
}) | ||
}) | ||
|
||
|
@@ -150,15 +152,18 @@ var _ = Describe("Out", func() { | |
Expect(session.Err).To(gbytes.Say("cf api https://api.run.pivotal.io --skip-ssl-validation")) | ||
Expect(session.Err).To(gbytes.Say("cf auth [email protected] hunter2")) | ||
Expect(session.Err).To(gbytes.Say("cf target -o org -s space")) | ||
Expect(session.Err).To(gbytes.Say("cf zero-downtime-push awesome-app -f %s --var foo=bar --vars-file vars.yml", | ||
|
||
Expect(session.Err).To(gbytes.Say("cf rename awesome-app awesome-app-venerable")) | ||
Expect(session.Err).To(gbytes.Say("cf push awesome-app -f %s --var foo=bar --vars-file vars.yml", | ||
filepath.Join(tmpDir, "project/manifest.yml"), | ||
)) | ||
Expect(session.Err).To(gbytes.Say(filepath.Join(tmpDir, "another-project"))) | ||
Expect(session.Err).To(gbytes.Say("cf delete -f awesome-app-venerable")) | ||
|
||
// color should be always | ||
output := string(session.Err.Contents()) | ||
Expect(strings.Count(output, "CF_COLOR=true")).To(Equal(4)) | ||
Expect(strings.Count(output, "CF_TRACE=/dev/stderr")).To(Equal(4)) | ||
Expect(strings.Count(output, "CF_COLOR=true")).To(Equal(7)) | ||
Expect(strings.Count(output, "CF_TRACE=true")).To(Equal(7)) | ||
}) | ||
}) | ||
|
||
|
@@ -199,10 +204,12 @@ var _ = Describe("Out", func() { | |
Expect(session.Err).To(gbytes.Say("cf api https://api.run.pivotal.io --skip-ssl-validation")) | ||
Expect(session.Err).To(gbytes.Say("cf auth [email protected] hunter2")) | ||
Expect(session.Err).To(gbytes.Say("cf target -o org -s space")) | ||
Expect(session.Err).To(gbytes.Say("cf zero-downtime-push awesome-app -f %s -p %s", | ||
Expect(session.Err).To(gbytes.Say("cf rename awesome-app awesome-app-venerable")) | ||
Expect(session.Err).To(gbytes.Say("cf push awesome-app -f %s -p %s", | ||
tmpFileManifest.Name(), | ||
tmpFileSearch.Name(), | ||
)) | ||
Expect(session.Err).To(gbytes.Say("cf delete -f awesome-app-venerable")) | ||
|
||
// color should be always | ||
Eventually(session.Err).Should(gbytes.Say("CF_COLOR=true")) | ||
|
@@ -316,10 +323,12 @@ var _ = Describe("Out", func() { | |
Expect(session.Err).To(gbytes.Say("cf api https://api.run.pivotal.io --skip-ssl-validation")) | ||
Expect(session.Err).To(gbytes.Say("cf auth [email protected] hunter2")) | ||
Expect(session.Err).To(gbytes.Say("cf target -o org -s space")) | ||
Expect(session.Err).To(gbytes.Say("cf zero-downtime-push awesome-app -f %s --docker-username %s", | ||
Expect(session.Err).To(gbytes.Say("cf rename awesome-app awesome-app-venerable")) | ||
Expect(session.Err).To(gbytes.Say("cf push awesome-app -f %s --docker-username %s", | ||
filepath.Join(tmpDir, "project/manifest.yml"), | ||
request.Params.DockerUsername, | ||
)) | ||
Expect(session.Err).To(gbytes.Say("cf delete -f awesome-app-venerable")) | ||
Expect(session.Err).To(gbytes.Say("CF_DOCKER_PASSWORD=DOCKER_PASSWORD")) | ||
}) | ||
}) | ||
|
@@ -348,15 +357,15 @@ var _ = Describe("Out", func() { | |
Expect(session.Err).To(gbytes.Say("cf api https://api.run.pivotal.io --skip-ssl-validation")) | ||
Expect(session.Err).To(gbytes.Say("cf auth [email protected] hunter2")) | ||
Expect(session.Err).To(gbytes.Say("cf target -o org -s space")) | ||
Expect(session.Err).To(gbytes.Say("cf push -f %s", | ||
Expect(session.Err).To(gbytes.Say("cf push -f %s -p .", | ||
filepath.Join(tmpDir, "project/manifest.yml"), | ||
)) | ||
Expect(session.Err).To(gbytes.Say(filepath.Join(tmpDir, "another-project"))) | ||
|
||
// color should be always | ||
output := string(session.Err.Contents()) | ||
Expect(strings.Count(output, "CF_COLOR=true")).To(Equal(4)) | ||
Expect(strings.Count(output, "CF_TRACE=/dev/stderr")).To(Equal(4)) | ||
Expect(strings.Count(output, "CF_TRACE=true")).To(Equal(4)) | ||
}) | ||
}) | ||
Context("when no_start is specified", func() { | ||
|
@@ -391,7 +400,7 @@ var _ = Describe("Out", func() { | |
// color should be always | ||
output := string(session.Err.Contents()) | ||
Expect(strings.Count(output, "CF_COLOR=true")).To(Equal(4)) | ||
Expect(strings.Count(output, "CF_TRACE=/dev/stderr")).To(Equal(4)) | ||
Expect(strings.Count(output, "CF_TRACE=true")).To(Equal(4)) | ||
}) | ||
}) | ||
}) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package zdt | ||
|
||
import ( | ||
"fmt" | ||
"os/exec" | ||
) | ||
|
||
func CanPush( | ||
cf func(args ...string) *exec.Cmd, | ||
currentAppName string, | ||
) bool { | ||
|
||
if currentAppName == "" { | ||
return false | ||
} | ||
|
||
findErr := cf("app", currentAppName).Run() | ||
appExists := findErr == nil | ||
|
||
return appExists | ||
} | ||
|
||
func Push( | ||
cf func(args ...string) *exec.Cmd, | ||
currentAppName string, | ||
pushFunction func() error, | ||
showLogs bool, | ||
) error { | ||
|
||
venerableAppName := fmt.Sprintf("%s-venerable", currentAppName) | ||
|
||
actions := []Action{ | ||
{ | ||
Forward: cf("rename", currentAppName, venerableAppName).Run, | ||
}, | ||
{ | ||
Forward: pushFunction, | ||
ReversePrevious: func() error { | ||
if showLogs { | ||
_ = cf("logs", currentAppName, "--recent").Run() | ||
} | ||
_ = cf("delete", "-f", currentAppName).Run() | ||
return cf("rename", venerableAppName, currentAppName).Run() | ||
}, | ||
}, | ||
{ | ||
Forward: cf("delete", "-f", venerableAppName).Run, | ||
}, | ||
} | ||
|
||
return Actions{ | ||
Actions: actions, | ||
RewindFailureMessage: "Oh no. Something's gone wrong. I've tried to roll back but you should check to see if everything is OK.", | ||
}.Execute() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package zdt_test | ||
|
||
import ( | ||
"errors" | ||
"os/exec" | ||
|
||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
"github.com/onsi/gomega/gbytes" | ||
|
||
"github.com/concourse/cf-resource/out/zdt" | ||
) | ||
|
||
var stdout *gbytes.Buffer | ||
|
||
func cli(path string) func(args ...string) *exec.Cmd { | ||
return func(args ...string) *exec.Cmd { | ||
cmd := exec.Command(path, args...) | ||
cmd.Stdout = stdout | ||
return cmd | ||
} | ||
} | ||
|
||
var _ = Describe("CanPush", func() { | ||
cf := cli("assets/cf") | ||
errCf := cli("assets/erroringCf") | ||
|
||
BeforeEach(func() { | ||
stdout = gbytes.NewBuffer() | ||
}) | ||
|
||
It("needs a currentAppName", func() { | ||
Expect(zdt.CanPush(cf, "")).To(BeFalse()) | ||
Expect(stdout.Contents()).To(BeEmpty()) | ||
}) | ||
|
||
It("needs the app to exist", func() { | ||
Expect(zdt.CanPush(errCf, "my-app")).To(BeFalse()) | ||
Expect(stdout).To(gbytes.Say("cf app my-app")) | ||
}) | ||
|
||
It("is ok when app exists", func() { | ||
Expect(zdt.CanPush(cf, "my-app")).To(BeTrue()) | ||
Expect(stdout).To(gbytes.Say("cf app my-app")) | ||
}) | ||
}) | ||
|
||
var _ = Describe("Push", func() { | ||
cf := cli("assets/cf") | ||
|
||
BeforeEach(func() { | ||
stdout = gbytes.NewBuffer() | ||
}) | ||
|
||
It("pushes an app with zero downtime", func() { | ||
pushFunction := func() error { return cf("push", "my-app").Run() } | ||
err := zdt.Push(cf, "my-app", pushFunction, false) | ||
|
||
Expect(err).NotTo(HaveOccurred()) | ||
Expect(stdout).To(gbytes.Say("cf rename my-app my-app-venerable")) | ||
Expect(stdout).To(gbytes.Say("cf push my-app")) | ||
Expect(stdout).To(gbytes.Say("cf delete -f my-app-venerable")) | ||
}) | ||
|
||
It("rolls back on failed push", func() { | ||
pushErr := errors.New("push failed") | ||
pushFunction := func() error { | ||
_ = cf("push", "my-app").Run() | ||
return pushErr | ||
} | ||
err := zdt.Push(cf, "my-app", pushFunction, false) | ||
|
||
Expect(err).To(Equal(pushErr)) | ||
Expect(stdout).To(gbytes.Say("cf rename my-app my-app-venerable")) | ||
Expect(stdout).To(gbytes.Say("cf push my-app")) | ||
Expect(stdout).ToNot(gbytes.Say("cf logs")) | ||
Expect(stdout).To(gbytes.Say("cf delete -f my-app")) | ||
Expect(stdout).To(gbytes.Say("cf rename my-app-venerable my-app")) | ||
}) | ||
|
||
It("shows logs on failure when flag is set", func() { | ||
pushFunction := func() error { | ||
_ = cf("push", "my-app").Run() | ||
return errors.New("push failed") | ||
} | ||
err := zdt.Push(cf, "my-app", pushFunction, true) | ||
|
||
Expect(err).To(HaveOccurred()) | ||
Expect(stdout).To(gbytes.Say("cf rename my-app my-app-venerable")) | ||
Expect(stdout).To(gbytes.Say("cf push my-app")) | ||
Expect(stdout).To(gbytes.Say("cf logs my-app --recent")) | ||
Expect(stdout).To(gbytes.Say("cf delete -f my-app")) | ||
Expect(stdout).To(gbytes.Say("cf rename my-app-venerable my-app")) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package zdt | ||
|
||
import "fmt" | ||
|
||
type Actions struct { | ||
Actions []Action | ||
|
||
RewindFailureMessage string | ||
} | ||
|
||
func (actions Actions) Execute() error { | ||
for _, action := range actions.Actions { | ||
err := action.Forward() | ||
if err != nil { | ||
if action.ReversePrevious == nil { | ||
return err | ||
} | ||
|
||
reverseError := action.ReversePrevious() | ||
if reverseError != nil { | ||
if actions.RewindFailureMessage != "" { | ||
return fmt.Errorf("%s: %s", actions.RewindFailureMessage, reverseError) | ||
} else { | ||
return reverseError | ||
} | ||
} | ||
|
||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
type Action struct { | ||
Forward func() error | ||
ReversePrevious func() error | ||
} |
Oops, something went wrong.