Skip to content

Commit

Permalink
Add support for --no-start push option
Browse files Browse the repository at this point in the history
`cf push` supports a `--no-start` option. The CF Concourse Resource
should support this as well.

Unfortunately this option is unsupported by the `zero-downtime-push`
feature of `autopilot`, which complicates the implementation and tests a
bit.

Signed-off-by: Navdeep Pama <npama@pivotal.io>
  • Loading branch information
klakin-pivotal authored and navdeep-pama committed May 15, 2018
1 parent 4f3721b commit e3ebea6
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 12 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ be specified.
* `docker_username`: *Optional.* This is used as the username to authenticate against a protected docker registry.
* `docker_password`: *Optional.* This should be the users password when authenticating against a protected docker registry.
* `show_app_log`: *Optional.* Tails the app log during startup, useful to debug issues when using blue/green deploys together with the `current_app_name` option.
* `no_start`: *Optional.* Deploys the app but does not start it. This parameter is ignored when `current_app_name` is specified.

## Pipeline example

Expand Down
7 changes: 5 additions & 2 deletions out/cloud_foundry.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
type PAAS interface {
Login(api string, username string, password string, clientID string, clientSecret string, insecure bool) error
Target(organization string, space string) error
PushApp(manifest string, path string, currentAppName string, dockerUser string, showLogs bool) error
PushApp(manifest string, path string, currentAppName string, dockerUser string, showLogs bool, noStart bool) error
}

type CloudFoundry struct {
Expand Down Expand Up @@ -41,11 +41,14 @@ func (cf *CloudFoundry) Target(organization string, space string) error {
return cf.cf("target", "-o", organization, "-s", space).Run()
}

func (cf *CloudFoundry) PushApp(manifest string, path string, currentAppName string, dockerUser string, showLogs bool) error {
func (cf *CloudFoundry) PushApp(manifest string, path string, currentAppName string, dockerUser string, showLogs bool, noStart bool) error {
args := []string{}

if currentAppName == "" {
args = append(args, "push", "-f", manifest)
if noStart {
args = append(args, "--no-start")
}
} else {
args = append(args, "zero-downtime-push", currentAppName, "-f", manifest)
if showLogs {
Expand Down
1 change: 1 addition & 0 deletions out/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ func (command *Command) Run(request Request) (Response, error) {
request.Params.CurrentAppName,
request.Params.DockerUsername,
request.Params.ShowAppLog,
request.Params.NoStart,
)
if err != nil {
return Response{}, err
Expand Down
23 changes: 20 additions & 3 deletions out/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,13 @@ var _ = Describe("Out Command", func() {
By("pushing the app")
Expect(cloudFoundry.PushAppCallCount()).To(Equal(1))

manifest, path, currentAppName, dockerUser, showAppLog := cloudFoundry.PushAppArgsForCall(0)
manifest, path, currentAppName, dockerUser, showAppLog, noStart := cloudFoundry.PushAppArgsForCall(0)
Expect(manifest).To(Equal(request.Params.ManifestPath))
Expect(path).To(Equal(""))
Expect(currentAppName).To(Equal(""))
Expect(dockerUser).To(Equal(""))
Expect(showAppLog).To(Equal(false))
Expect(noStart).To(Equal(false))
})

Describe("handling any errors", func() {
Expand Down Expand Up @@ -118,6 +119,22 @@ var _ = Describe("Out Command", func() {
})
})

Describe("no_start handling", func() {
Context("when no_start is specified", func() {
BeforeEach(func() {
request.Params.NoStart = true
})

It("sets noStart to true", func() {
_, err := command.Run(request)
Expect(err).NotTo(HaveOccurred())

_, _, _, _, _, noStart := cloudFoundry.PushAppArgsForCall(0)
Expect(noStart).To(Equal(true))
})
})
})

Context("setting environment variables provided as params", func() {
var err error
var tempFile *os.File
Expand Down Expand Up @@ -251,7 +268,7 @@ var _ = Describe("Out Command", func() {
By("pushing the app")
Expect(cloudFoundry.PushAppCallCount()).To(Equal(1))

_, _, currentAppName, _, _ := cloudFoundry.PushAppArgsForCall(0)
_, _, currentAppName, _, _, _ := cloudFoundry.PushAppArgsForCall(0)
Expect(currentAppName).To(Equal("cool-app-name"))
})

Expand All @@ -277,7 +294,7 @@ var _ = Describe("Out Command", func() {
By("pushing the app")
Expect(cloudFoundry.PushAppCallCount()).To(Equal(1))

_, _, _, dockerUser, _ := cloudFoundry.PushAppArgsForCall(0)
_, _, _, dockerUser, _, _ := cloudFoundry.PushAppArgsForCall(0)
Expect(dockerUser).To(Equal("DOCKER_USER"))
})

Expand Down
70 changes: 70 additions & 0 deletions out/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,4 +284,74 @@ var _ = Describe("Out", func() {
Expect(session.Err).To(gbytes.Say("CF_DOCKER_PASSWORD=DOCKER_PASSWORD"))
})
})
Context("when doing an ordinary cf push", func() {
BeforeEach(func() {
request.Params.CurrentAppName = ""
})
Context("when no_start is not specified", func() {
It("pushes an application to cloud foundry", func() {
session, err := gexec.Start(
cmd,
GinkgoWriter,
GinkgoWriter,
)
Expect(err).NotTo(HaveOccurred())

Eventually(session).Should(gexec.Exit(0))

var response out.Response
err = json.Unmarshal(session.Out.Contents(), &response)
Expect(err).NotTo(HaveOccurred())

Expect(response.Version.Timestamp).To(BeTemporally("~", time.Now(), time.Second))

// shim outputs arguments
Expect(session.Err).To(gbytes.Say("cf api https://api.run.pivotal.io --skip-ssl-validation"))
Expect(session.Err).To(gbytes.Say("cf auth awesome@example.com hunter2"))
Expect(session.Err).To(gbytes.Say("cf target -o org -s space"))
Expect(session.Err).To(gbytes.Say("cf push -f %s",
filepath.Join(tmpDir, "project/manifest.yml"),
))
Expect(session.Err).To(gbytes.Say(filepath.Join(tmpDir, "another-project")))

// color should be always
Eventually(session.Err).Should(gbytes.Say("CF_COLOR=true"))
Eventually(session.Err).Should(gbytes.Say("CF_TRACE=/dev/stderr"))
})
})
Context("when no_start is specified", func() {
BeforeEach(func() {
request.Params.NoStart = true
})
It("pushes an application to cloud foundry with --no-start", func() {
session, err := gexec.Start(
cmd,
GinkgoWriter,
GinkgoWriter,
)
Expect(err).NotTo(HaveOccurred())

Eventually(session).Should(gexec.Exit(0))

var response out.Response
err = json.Unmarshal(session.Out.Contents(), &response)
Expect(err).NotTo(HaveOccurred())

Expect(response.Version.Timestamp).To(BeTemporally("~", time.Now(), time.Second))

// shim outputs arguments
Expect(session.Err).To(gbytes.Say("cf api https://api.run.pivotal.io --skip-ssl-validation"))
Expect(session.Err).To(gbytes.Say("cf auth awesome@example.com hunter2"))
Expect(session.Err).To(gbytes.Say("cf target -o org -s space"))
Expect(session.Err).To(gbytes.Say("cf push -f %s --no-start",
filepath.Join(tmpDir, "project/manifest.yml"),
))
Expect(session.Err).To(gbytes.Say(filepath.Join(tmpDir, "another-project")))

// color should be always
Eventually(session.Err).Should(gbytes.Say("CF_COLOR=true"))
Eventually(session.Err).Should(gbytes.Say("CF_TRACE=/dev/stderr"))
})
})
})
})
1 change: 1 addition & 0 deletions out/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type Params struct {
DockerUsername string `json:"docker_username"`
DockerPassword string `json:"docker_password"`
ShowAppLog bool `json:"show_app_log"`
NoStart bool `json:"no_start"`
}

type Response struct {
Expand Down
16 changes: 9 additions & 7 deletions out/outfakes/fake_paas.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit e3ebea6

Please sign in to comment.