Skip to content

Commit

Permalink
Adds 'stacks' command for inspecting available stacks
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew Meyer <ameyer@pivotal.io>
Signed-off-by: Emily Casey <ecasey@pivotal.io>
  • Loading branch information
ameyer-pivotal authored and ekcasey committed Dec 17, 2018
1 parent 0878c58 commit 5ccae5a
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 127 deletions.
21 changes: 2 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,29 +252,12 @@ $ pack set-default-stack org.example.my-stack

### Listing stacks

To inspect available stacks and their IDs (denoted by `id`), run:
To inspect available stacks and their associated images, run:

```bash
$ cat ~/.pack/config.toml

...

[[stacks]]
id = "io.buildpacks.stacks.bionic"
build-image = "packs/build"
run-images = ["packs/run"]

[[stacks]]
id = "org.example.my-stack"
build-image = "my-stack/build"
run-images = ["my-stack/run"]

...
$ pack stacks
```

> Note that this method of inspecting available stacks will soon be replaced by a new command. The format of
> `config.toml` is subject to change at any time.
## Resources

- [Buildpack & Platform Specifications](https://github.com/buildpack/spec)
Expand Down
131 changes: 31 additions & 100 deletions acceptance/acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,20 @@ func TestPack(t *testing.T) {
func testPack(t *testing.T, when spec.G, it spec.S) {
var packHome string

var packCmd = func(name string, args ...string) *exec.Cmd {
cmdArgs := append([]string{
name,
"--verbose",
"--no-color",
}, args...)
cmd := exec.Command(
pack,
cmdArgs...,
)
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
return cmd
}

it.Before(func() {
if _, err := os.Stat(pack); os.IsNotExist(err) {
t.Fatal("No file found at PACK_PATH environment variable:", pack)
Expand All @@ -84,7 +98,6 @@ func testPack(t *testing.T, when spec.G, it spec.S) {
when("subcommand is invalid", func() {
it("prints usage", func() {
cmd := packCmd("some-bad-command")
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
output, _ := cmd.CombinedOutput()
if !strings.Contains(string(output), `unknown command "some-bad-command" for "pack"`) {
t.Fatal("Failed to print usage", string(output))
Expand Down Expand Up @@ -122,7 +135,6 @@ func testPack(t *testing.T, when spec.G, it spec.S) {
when("'--publish' flag is not specified'", func() {
it("builds and exports an image", func() {
cmd := packCmd("build", repoName, "-p", sourceCodePath)
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
output := h.Run(t, cmd)
h.AssertContains(t, output, fmt.Sprintf("Successfully built image '%s'", repoName))
runDockerImageExposePort(t, containerName, repoName)
Expand All @@ -144,7 +156,6 @@ func testPack(t *testing.T, when spec.G, it spec.S) {
runPackBuild := func() string {
t.Helper()
cmd := packCmd("build", repoName, "-p", sourceCodePath, "--publish")
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
return h.Run(t, cmd)
}
output := runPackBuild()
Expand Down Expand Up @@ -207,7 +218,6 @@ func testPack(t *testing.T, when spec.G, it spec.S) {
it("starts an image", func() {
var buf bytes.Buffer
cmd := packCmd("run", "--port", "3000", "-p", sourceCodePath)
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
cmd.Stdout = &buf
cmd.Stderr = &buf
cmd.Dir = sourceCodePath
Expand Down Expand Up @@ -249,7 +259,6 @@ func testPack(t *testing.T, when spec.G, it spec.S) {
"--build-image", h.DefaultBuildImage(t, registryPort),
"--run-image", runImage,
)
cmd.Env = []string{"PACK_HOME=" + packHome}
h.Run(t, cmd)
}
rootContents1 = func() string {
Expand Down Expand Up @@ -281,7 +290,6 @@ func testPack(t *testing.T, when spec.G, it spec.S) {
buildAndSetRunImage(runBefore, "contents-before-1", "contents-before-2")

cmd := packCmd("build", repoName, "-p", "testdata/node_app/", "--no-pull")
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
h.Run(t, cmd)
origID = h.ImageID(t, repoName)
})
Expand All @@ -297,7 +305,6 @@ func testPack(t *testing.T, when spec.G, it spec.S) {
buildAndSetRunImage(runAfter, "contents-after-1", "contents-after-2")

cmd := packCmd("rebase", repoName, "--no-pull")
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
output := h.Run(t, cmd)

h.AssertContains(t, output, fmt.Sprintf("Successfully rebased image '%s'", repoName))
Expand All @@ -315,7 +322,6 @@ func testPack(t *testing.T, when spec.G, it spec.S) {
h.AssertNil(t, pushImage(dockerCli, runBefore))

cmd := packCmd("build", repoName, "-p", "testdata/node_app/", "--publish")
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
h.Run(t, cmd)

h.AssertNil(t, h.PullImage(dockerCli, repoName))
Expand All @@ -328,7 +334,6 @@ func testPack(t *testing.T, when spec.G, it spec.S) {
h.AssertNil(t, pushImage(dockerCli, runAfter))

cmd := packCmd("rebase", repoName, "--publish")
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
output := h.Run(t, cmd)

h.AssertContains(t, output, fmt.Sprintf("Successfully rebased image '%s'", repoName))
Expand Down Expand Up @@ -363,13 +368,11 @@ func testPack(t *testing.T, when spec.G, it spec.S) {

t.Log("create builder image")
cmd := packCmd("create-builder", builderRepoName, "-b", builderTOML)
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
output := h.Run(t, cmd)
h.AssertContains(t, output, fmt.Sprintf("Successfully created builder image '%s'", builderRepoName))

t.Log("build uses order defined in builder.toml")
cmd = packCmd("build", repoName, "--builder", builderRepoName, "--path", sourceCodePath, "--no-pull")
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
buildOutput, err := cmd.CombinedOutput()
h.AssertNil(t, err)
defer func(origID string) { h.AssertNil(t, h.DockerRmi(dockerCli, origID)) }(h.ImageID(t, repoName))
Expand Down Expand Up @@ -404,7 +407,6 @@ func testPack(t *testing.T, when spec.G, it spec.S) {
"--path", sourceCodePath,
"--no-pull",
)
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
buildOutput, err = cmd.CombinedOutput()
h.AssertNil(t, err)
defer func(origID string) { h.AssertNil(t, h.DockerRmi(dockerCli, origID)) }(h.ImageID(t, repoName))
Expand Down Expand Up @@ -436,40 +438,19 @@ func testPack(t *testing.T, when spec.G, it spec.S) {
when("pack add-stack", func() {
it("adds a custom stack to ~/.pack/config.toml", func() {
cmd := packCmd("add-stack", "my.custom.stack", "--run-image", "my-org/run", "--build-image", "my-org/build")
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
output := h.Run(t, cmd)

h.AssertEq(t, string(output), "Stack 'my.custom.stack' added\n")

var config struct {
Stacks []struct {
ID string `toml:"id"`
BuildImage string `toml:"build-image"`
RunImages []string `toml:"run-images"`
} `toml:"stacks"`
}
_, err := toml.DecodeFile(filepath.Join(packHome, "config.toml"), &config)
h.AssertNil(t, err)

stack := config.Stacks[len(config.Stacks)-1]
h.AssertEq(t, stack.ID, "my.custom.stack")
h.AssertEq(t, stack.BuildImage, "my-org/build")
h.AssertEq(t, stack.RunImages, []string{"my-org/run"})
cmd = packCmd("stacks")
output = h.Run(t, cmd)
h.AssertMatch(t, output, `(?m)^\Qmy.custom.stack\E\s+\Qmy-org/build\E\s+\Qmy-org/run\E\n`)
})
}, spec.Parallel(), spec.Report(report.Terminal{}))

when("pack update-stack", func() {
type config struct {
Stacks []struct {
ID string `toml:"id"`
BuildImage string `toml:"build-image"`
RunImages []string `toml:"run-images"`
} `toml:"stacks"`
}

it.Before(func() {
cmd := packCmd("add-stack", "my.custom.stack", "--run-image", "my-org/run", "--build-image", "my-org/build")
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
output, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("add-stack command failed: %s: %s", output, err)
Expand All @@ -483,32 +464,21 @@ func testPack(t *testing.T, when spec.G, it spec.S) {
"--run-image", "my-org/run-3",
"--build-image", "my-org/build-2",
)
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
output, err := cmd.CombinedOutput()
updateOutput, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("update-stack command failed: %s: %s", output, err)
t.Fatalf("update-stack command failed: %s: %s", updateOutput, err)
}
h.AssertEq(t, string(output), "Stack 'my.custom.stack' updated\n")

var config config
_, err = toml.DecodeFile(filepath.Join(packHome, "config.toml"), &config)
h.AssertNil(t, err)
h.AssertEq(t, string(updateOutput), "Stack 'my.custom.stack' updated\n")

stack := config.Stacks[len(config.Stacks)-1]
h.AssertEq(t, stack.ID, "my.custom.stack")
h.AssertEq(t, stack.BuildImage, "my-org/build-2")
h.AssertEq(t, stack.RunImages, []string{"my-org/run-2", "my-org/run-3"})
cmd = packCmd("stacks")
stacksOutput := h.Run(t, cmd)
h.AssertMatch(t, stacksOutput, `(?m)^\Qmy.custom.stack\E\s+\Qmy-org/build-2\E\s+\Qmy-org/run-2, my-org/run-3\E\n`)
})
}, spec.Parallel(), spec.Report(report.Terminal{}))

when("pack set-default-stack", func() {
type config struct {
DefaultStackID string `toml:"default-stack-id"`
}

it.Before(func() {
cmd := packCmd("add-stack", "my.custom.stack", "--run-image", "my-org/run", "--build-image", "my-org/build")
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
output, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("add-stack command failed: %s: %s", output, err)
Expand All @@ -517,65 +487,40 @@ func testPack(t *testing.T, when spec.G, it spec.S) {

it("sets the default-stack-id in ~/.pack/config.toml", func() {
cmd := packCmd("set-default-stack", "my.custom.stack")
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
output, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("set-default-stack command failed: %s: %s", output, err)
}
h.AssertEq(t, string(output), "Stack 'my.custom.stack' is now the default stack\n")

var config config
_, err = toml.DecodeFile(filepath.Join(packHome, "config.toml"), &config)
h.AssertNil(t, err)
h.AssertEq(t, config.DefaultStackID, "my.custom.stack")
cmd = packCmd("stacks")
stacksOutput := h.Run(t, cmd)
h.AssertMatch(t, stacksOutput, `(?m)^\Qmy.custom.stack (default)\E\s+\Qmy-org/build\E\s+\Qmy-org/run\E\n`)
})
}, spec.Parallel(), spec.Report(report.Terminal{}))

when("pack delete-stack", func() {
type config struct {
Stacks []struct {
ID string `toml:"id"`
BuildImage string `toml:"build-image"`
RunImages []string `toml:"run-images"`
} `toml:"stacks"`
}
containsStack := func(c config, stackID string) bool {
for _, s := range c.Stacks {
if s.ID == stackID {
return true
}
}
return false
}

it.Before(func() {
cmd := packCmd("add-stack", "my.custom.stack", "--run-image", "my-org/run", "--build-image", "my-org/build")
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
output, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("add-stack command failed: %s: %s", output, err)
}
})

it("deletes a custom stack from ~/.pack/config.toml", func() {
var config config
_, err := toml.DecodeFile(filepath.Join(packHome, "config.toml"), &config)
h.AssertNil(t, err)
numStacks := len(config.Stacks)
h.AssertEq(t, containsStack(config, "my.custom.stack"), true)

cmd := packCmd("delete-stack", "my.custom.stack")
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
output, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("add-stack command failed: %s: %s", output, err)
}
h.AssertEq(t, string(output), "Stack 'my.custom.stack' deleted\n")

_, err = toml.DecodeFile(filepath.Join(packHome, "config.toml"), &config)
h.AssertNil(t, err)
h.AssertEq(t, len(config.Stacks), numStacks-1)
h.AssertEq(t, containsStack(config, "my.custom.stack"), false)
cmd = packCmd("stacks")
stacksOutput := h.Run(t, cmd)
if strings.Contains(stacksOutput, "my.custom.stack") {
t.Fatalf("stacks output '%s' contains deleted stack 'my.custom.stack'", stacksOutput)
}
})
}, spec.Parallel(), spec.Report(report.Terminal{}))

Expand All @@ -586,7 +531,6 @@ func testPack(t *testing.T, when spec.G, it spec.S) {

it("sets the default-stack-id in ~/.pack/config.toml", func() {
cmd := packCmd("set-default-builder", "some/builder")
cmd.Env = append(os.Environ(), "PACK_HOME="+packHome)
output, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("set-default-builder command failed: %s: %s", output, err)
Expand All @@ -601,19 +545,6 @@ func testPack(t *testing.T, when spec.G, it spec.S) {
}, spec.Parallel(), spec.Report(report.Terminal{}))
}

func packCmd(name string, args ...string) *exec.Cmd {
cmdArgs := append([]string{
name,
"--verbose",
"--no-color",
}, args...)

return exec.Command(
pack,
cmdArgs...,
)
}

func fetchHostPort(t *testing.T, dockerID string) string {
t.Helper()

Expand Down
Loading

0 comments on commit 5ccae5a

Please sign in to comment.