Skip to content

Commit

Permalink
Moves toward a more generic "build-plan" buildpack
Browse files Browse the repository at this point in the history
- brings in occam in the integration suite
  • Loading branch information
Ryan Moran committed May 7, 2020
1 parent 028925c commit 73a1ae1
Show file tree
Hide file tree
Showing 279 changed files with 34,992 additions and 13,231 deletions.
File renamed without changes.
4 changes: 2 additions & 2 deletions cmd/detect/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

func main() {
environmentParser := noapp.NewEnvironmentParser()
planParser := noapp.NewBuildPlanParser()

packit.Detect(noapp.Detect(environmentParser))
packit.Detect(noapp.Detect(planParser))
}
12 changes: 7 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ go 1.13

require (
github.com/BurntSushi/toml v0.3.1
github.com/cloudfoundry/dagger v0.0.0-20191217204304-b24bb745729d
github.com/cloudfoundry/libcfbuildpack v1.91.13 // indirect
github.com/cloudfoundry/packit v0.0.0-20191220164501-d7f225fefe2c
github.com/onsi/gomega v1.8.1
github.com/cloudfoundry/dagger v0.0.0-20200424213418-5178da286b3e
github.com/cloudfoundry/occam v0.0.2
github.com/cloudfoundry/packit v0.0.5
github.com/golang/protobuf v1.4.1 // indirect
github.com/onsi/gomega v1.9.0
github.com/sclevine/spec v1.4.0
golang.org/x/sys v0.0.0-20191220220014-0732a990476f // indirect
golang.org/x/net v0.0.0-20200505041828-1ed23360d12c // indirect
google.golang.org/appengine v1.6.6 // indirect
)
146 changes: 95 additions & 51 deletions go.sum

Large diffs are not rendered by default.

60 changes: 60 additions & 0 deletions integration/default_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package integration_test

import (
"path/filepath"
"testing"

"github.com/cloudfoundry/occam"
"github.com/sclevine/spec"

. "github.com/cloudfoundry/occam/matchers"
. "github.com/onsi/gomega"
)

func testDefault(t *testing.T, context spec.G, it spec.S) {
var (
Expect = NewWithT(t).Expect
Eventually = NewWithT(t).Eventually

pack occam.Pack
docker occam.Docker

image occam.Image
container occam.Container
name string
)

it.Before(func() {
pack = occam.NewPack()
docker = occam.NewDocker()

var err error
name, err = occam.RandomName()
Expect(err).NotTo(HaveOccurred())
})

it.After(func() {
Expect(docker.Container.Remove.Execute(container.ID)).To(Succeed())
Expect(docker.Image.Remove.Execute(image.ID)).To(Succeed())
Expect(docker.Volume.Remove.Execute(occam.CacheVolumeNames(name))).To(Succeed())
})

it("should build a working OCI image for a simple app with aspnet dependencies", func() {
var err error
image, _, err = pack.WithNoColor().Build.
WithNoPull().
WithBuildpacks(pythonRuntimeBuildpack, buildpack).
Execute(name, filepath.Join("testdata", "python-env"))
Expect(err).ToNot(HaveOccurred())

container, err = docker.Container.Run.WithCommand("python --version && python -m http.server $PORT").Execute(image.ID)
Expect(err).NotTo(HaveOccurred())

Eventually(container).Should(BeAvailable(), ContainerLogs(container.ID))

logs, err := docker.Container.Logs.Execute(container.ID)
Expect(err).NotTo(HaveOccurred())

Expect(logs).To(MatchRegexp(`Python \d+\.\d+\.\d+`))
})
}
55 changes: 55 additions & 0 deletions integration/init_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package integration_test

import (
"fmt"
"testing"
"time"

"github.com/cloudfoundry/dagger"
"github.com/cloudfoundry/occam"
"github.com/sclevine/spec"
"github.com/sclevine/spec/report"

. "github.com/onsi/gomega"
)

var (
buildpack string
pythonRuntimeBuildpack string
)

func TestIntegration(t *testing.T) {
Expect := NewWithT(t).Expect

root, err := dagger.FindBPRoot()
Expect(err).ToNot(HaveOccurred())

buildpack, err = dagger.PackageBuildpack(root)
Expect(err).NotTo(HaveOccurred())

pythonRuntimeBuildpack, err = dagger.GetLatestBuildpack("python-runtime-cnb")
Expect(err).ToNot(HaveOccurred())

// HACK: we need to fix dagger and the package.sh scripts so that this isn't required
buildpack = fmt.Sprintf("%s.tgz", buildpack)

defer func() {
dagger.DeleteBuildpack(buildpack)
dagger.DeleteBuildpack(pythonRuntimeBuildpack)
}()

SetDefaultEventuallyTimeout(10 * time.Second)

suite := spec.New("Integration", spec.Report(report.Terminal{}))
suite("Default", testDefault, spec.Parallel())
suite.Run(t)
}

func ContainerLogs(id string) func() string {
docker := occam.NewDocker()

return func() string {
logs, _ := docker.Container.Logs.Execute(id)
return logs.String()
}
}
72 changes: 0 additions & 72 deletions integration/integration_test.go

This file was deleted.

1 change: 0 additions & 1 deletion integration/testdata/python-env/env.toml

This file was deleted.

5 changes: 5 additions & 0 deletions integration/testdata/python-env/plan.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[[requires]]
name = "python"

[requires.metadata]
launch = true
36 changes: 36 additions & 0 deletions noapp/build_plan_parser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package noapp

import (
"errors"
"fmt"
"os"

"github.com/BurntSushi/toml"
"github.com/cloudfoundry/packit"
)

type BuildPlanParser struct{}

func NewBuildPlanParser() BuildPlanParser {
return BuildPlanParser{}
}

func (p BuildPlanParser) Parse(path string) ([]packit.BuildPlanRequirement, error) {
file, err := os.Open(path)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return nil, nil
}

return nil, fmt.Errorf("failed to read plan.toml: %w", err)
}
defer file.Close()

var plan packit.BuildPlan
_, err = toml.DecodeReader(file, &plan)
if err != nil {
return nil, fmt.Errorf("failed to decode plan.toml: %w", err)
}

return plan.Requires, nil
}
110 changes: 110 additions & 0 deletions noapp/build_plan_parser_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package noapp_test

import (
"io/ioutil"
"os"
"path/filepath"
"testing"

"github.com/cloudfoundry/no-app-cnb/noapp"
"github.com/cloudfoundry/packit"

. "github.com/onsi/gomega"
"github.com/sclevine/spec"
)

func testEnvironmentParser(t *testing.T, context spec.G, it spec.S) {
var (
Expect = NewWithT(t).Expect
workingDir string

planParser noapp.BuildPlanParser
)

it.Before(func() {
var err error
workingDir, err = ioutil.TempDir("", "working-dir")
Expect(err).NotTo(HaveOccurred())

planParser = noapp.NewBuildPlanParser()
})

it.After(func() {
Expect(os.RemoveAll(workingDir)).To(Succeed())
})

context("Parse", func() {
it.Before(func() {
Expect(ioutil.WriteFile(filepath.Join(workingDir, "plan.toml"), []byte(`
[[requires]]
name = "python"
[requires.metadata]
build = true
[[requires]]
name = "ruby"
[requires.metadata]
launch = true
`), os.ModePerm)).To(Succeed())
})

it("returns a list of strings", func() {
requirements, err := planParser.Parse(filepath.Join(workingDir, "plan.toml"))
Expect(err).NotTo(HaveOccurred())
Expect(requirements).To(Equal([]packit.BuildPlanRequirement{
{
Name: "python",
Metadata: map[string]interface{}{
"build": true,
},
},
{
Name: "ruby",
Metadata: map[string]interface{}{
"launch": true,
},
},
}))
})

context("there is no plan.toml", func() {
it.Before(func() {
Expect(os.Remove(filepath.Join(workingDir, "plan.toml"))).To(Succeed())
})

it("returns an empty list of requirements", func() {
requirements, err := planParser.Parse(filepath.Join(workingDir, "plan.toml"))
Expect(err).NotTo(HaveOccurred())
Expect(requirements).To(BeEmpty())
})
})

context("failure cases", func() {
context("when the plan.toml cannot be opened", func() {
it.Before(func() {
Expect(os.Chmod(filepath.Join(workingDir, "plan.toml"), 0000)).To(Succeed())
})

it("returns an error", func() {
_, err := planParser.Parse(filepath.Join(workingDir, "plan.toml"))
Expect(err).To(MatchError(ContainSubstring("failed to read plan.toml:")))
Expect(err).To(MatchError(ContainSubstring("permission denied")))
})
})

context("the plan.toml is malformed", func() {
it.Before(func() {
Expect(ioutil.WriteFile(filepath.Join(workingDir, "plan.toml"), []byte("%%%"), os.ModePerm)).To(Succeed())
})

it("returns an error", func() {
_, err := planParser.Parse(filepath.Join(workingDir, "plan.toml"))
Expect(err).To(MatchError(ContainSubstring("failed to decode plan.toml:")))
Expect(err).To(MatchError(ContainSubstring("bare keys cannot contain '%'")))
})
})
})
})
}
2 changes: 1 addition & 1 deletion noapp/constants.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package noapp

const (
Name = "no-app"
DependencyName = "no-app"
)
Loading

0 comments on commit 73a1ae1

Please sign in to comment.