Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ require (
github.com/go-git/go-git/v5 v5.16.5
github.com/google/go-github/v50 v50.2.0
github.com/jfrog/jfrog-client-go v1.52.0
github.com/hashicorp/go-version v1.8.0
github.com/julienschmidt/httprouter v1.3.0
github.com/masterminds/sprig v2.22.0+incompatible
github.com/maxbrunsfeld/counterfeiter/v6 v6.12.1
Expand Down Expand Up @@ -110,7 +111,6 @@ require (
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-memdb v1.3.5 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/go-version v1.8.0 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/huandu/xstrings v1.5.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
Expand Down
200 changes: 200 additions & 0 deletions internal/acceptance/carvel/carvel_bake_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
package acceptance_test

import (
"archive/zip"
"os"
"os/exec"
"path/filepath"
"testing"
"time"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
"github.com/onsi/gomega/gexec"
)

var pathToMain string

func TestCarvelAcceptance(t *testing.T) {
SetDefaultEventuallyTimeout(time.Minute)
RegisterFailHandler(Fail)
RunSpecs(t, "carvel acceptance")
}

var _ = BeforeSuite(func() {
if _, err := exec.LookPath("bosh"); err != nil {
Skip("bosh CLI not installed - skipping carvel acceptance tests")
}

var err error
pathToMain, err = gexec.Build("github.com/pivotal-cf/kiln")
Expect(err).NotTo(HaveOccurred())
})

var _ = AfterSuite(func() {
gexec.CleanupBuildArtifacts()
})

var _ = Describe("carvel bake command", func() {
var (
outputFile string
tmpDir string
inputPath string
commandWithArgs []string
)

const (
sampleTileFixture = "fixtures/sample-tile"
)

BeforeEach(func() {
var err error
tmpDir, err = os.MkdirTemp("", "kiln-carvel-test")
Expect(err).NotTo(HaveOccurred())

// Copy the sample-tile fixture to a temp directory
inputPath = filepath.Join(tmpDir, "tile")
err = os.CopyFS(inputPath, os.DirFS(sampleTileFixture))
Expect(err).NotTo(HaveOccurred())

// Initialize git repo (required by kiln for metadata)
gitCommands := []*exec.Cmd{
exec.Command("git", "init"),
exec.Command("git", "config", "user.email", "test@test.com"),
exec.Command("git", "config", "user.name", "Test"),
exec.Command("git", "add", "."),
exec.Command("git", "commit", "-m", "initial commit"),
}
for _, cmd := range gitCommands {
cmd.Dir = inputPath
out, err := cmd.CombinedOutput()
Expect(err).NotTo(HaveOccurred(), "error invoking git: "+string(out))
}

outputFile = filepath.Join(tmpDir, "k8s-tile-test-0.0.1.pivotal")

commandWithArgs = []string{
"carvel", "bake",
"--source-directory", inputPath,
"--output-file", outputFile,
}
})

AfterEach(func() {
_ = os.RemoveAll(tmpDir)
})

It("generates a tile with the correct structure", func() {
commandWithArgs = append(commandWithArgs, "--verbose")

command := exec.Command(pathToMain, commandWithArgs...)

session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())

Eventually(session, "60s").Should(gexec.Exit(0))

archive, err := os.Open(outputFile)
Expect(err).NotTo(HaveOccurred())
defer func() { _ = archive.Close() }()

archiveInfo, err := archive.Stat()
Expect(err).NotTo(HaveOccurred())

bakedTile, err := zip.NewReader(archive, archiveInfo.Size())
Expect(err).NotTo(HaveOccurred())

// Verify metadata exists
_, err = bakedTile.Open("metadata/metadata.yml")
Expect(err).NotTo(HaveOccurred())

// Verify releases directory contains a tgz
var foundRelease bool
for _, f := range bakedTile.File {
if filepath.Dir(f.Name) == "releases" && filepath.Ext(f.Name) == ".tgz" {
foundRelease = true
break
}
}
Expect(foundRelease).To(BeTrue(), "releases/*.tgz should be in the tile")

// Verify migrations directory exists (even if empty)
var foundMigrations bool
for _, f := range bakedTile.File {
if filepath.Dir(f.Name) == "migrations" || f.Name == "migrations/v1/" {
foundMigrations = true
break
}
}
Expect(foundMigrations).To(BeTrue(), "migrations directory should be in the tile")

Eventually(session.Out).Should(gbytes.Say("Baked"))
Eventually(session.Out).Should(gbytes.Say("k8s-tile-test"))
})

It("produces a valid zip archive", func() {
command := exec.Command(pathToMain, commandWithArgs...)

session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())

Eventually(session, "60s").Should(gexec.Exit(0))

// Verify using unzip -t
verifyCmd := exec.Command("unzip", "-t", outputFile)
verifySession, err := gexec.Start(verifyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())

Eventually(verifySession, "10s").Should(gexec.Exit(0))
Eventually(verifySession.Out).Should(gbytes.Say("No errors detected"))
})

Context("failure cases", func() {
Context("when the output-file flag is not provided", func() {
It("prints an error and exits 1", func() {
command := exec.Command(pathToMain, "carvel", "bake",
"--source-directory", inputPath,
)

session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())

Eventually(session).Should(gexec.Exit(1))
Eventually(session.Err).Should(gbytes.Say("output-file"))
})
})

Context("when the source directory does not exist", func() {
It("prints an error and exits 1", func() {
command := exec.Command(pathToMain, "carvel", "bake",
"--source-directory", "/non/existent/path",
"--output-file", outputFile,
)

session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())

Eventually(session).Should(gexec.Exit(1))
})
})

Context("when the source directory is missing base.yml", func() {
It("prints an error and exits 1", func() {
emptyDir, err := os.MkdirTemp(tmpDir, "empty-tile")
Expect(err).NotTo(HaveOccurred())

command := exec.Command(pathToMain, "carvel", "bake",
"--source-directory", emptyDir,
"--output-file", outputFile,
)

session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())

Eventually(session).Should(gexec.Exit(1))
Eventually(session.Err).Should(gbytes.Say("base.yml"))
})
})
})
})
Loading
Loading