Skip to content
This repository was archived by the owner on Oct 25, 2023. It is now read-only.

Commit d81f39c

Browse files
committed
chore(tests): Add python layer contributor tests
Signed-off-by: Andrew Meyer <[email protected]>
1 parent b86d88d commit d81f39c

19 files changed

+734
-52
lines changed

buildpacks/python/go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.19
44

55
require (
66
github.com/buildpacks/libcnb v1.26.0
7+
github.com/golang/mock v1.6.0
78
github.com/onsi/gomega v1.20.2
89
github.com/paketo-buildpacks/libpak v1.61.0
910
github.com/sclevine/spec v1.4.0

buildpacks/python/mock_python/command_runner.go

+50
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

buildpacks/python/mock_python/layer.go

+48
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

buildpacks/python/python/build.go

+8-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import (
1313
)
1414

1515
type Build struct {
16-
Logger bard.Logger
16+
Logger bard.Logger
17+
CommandRunner CommandRunner
1718
}
1819

1920
func (b Build) Build(context libcnb.BuildContext) (libcnb.BuildResult, error) {
@@ -49,12 +50,12 @@ func (b Build) Build(context libcnb.BuildContext) (libcnb.BuildResult, error) {
4950
return libcnb.BuildResult{}, fmt.Errorf("unable to find dependency\n%w", err)
5051
}
5152

52-
invokerDepCacheLayer := NewInvokerDependencyCache(invokerDeps, dependencyCache)
53+
invokerDepCacheLayer := NewInvokerDependencyCache(invokerDeps, dependencyCache, b.CommandRunner)
5354
invokerDepCacheLayer.Logger = b.Logger
54-
result.Layers = append(result.Layers, &invokerDepCacheLayer)
55+
result.Layers = append(result.Layers, invokerDepCacheLayer)
5556

5657
invokerLayer := NewInvoker(invoker, dependencyCache)
57-
result.Layers = append(result.Layers, &invokerLayer)
58+
result.Layers = append(result.Layers, invokerLayer)
5859

5960
functionPlan, ok, err := planResolver.Resolve("python-function")
6061
if err != nil {
@@ -74,8 +75,9 @@ func (b Build) Build(context libcnb.BuildContext) (libcnb.BuildResult, error) {
7475

7576
validationLayer := NewFunctionValidationLayer(
7677
context.Application.Path,
77-
&invokerLayer,
78-
&invokerDepCacheLayer,
78+
invokerLayer,
79+
invokerDepCacheLayer,
80+
b.CommandRunner,
7981
WithValidationLogger(b.Logger),
8082
WithValidationFunctionClass(functionClass, isFuncDefDefault),
8183
WithValidationFunctionEnvs(functionPlan.Metadata["func_yaml_envs"].(map[string]any)),
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2021-2022 VMware, Inc.
2+
// SPDX-License-Identifier: BSD-2-Clause
3+
4+
package python
5+
6+
import (
7+
"os/exec"
8+
)
9+
10+
//go:generate mockgen -destination ../mock_python/command_runner.go . CommandRunner
11+
type CommandRunner interface {
12+
Run(cmd *exec.Cmd) (output string, err error)
13+
}
14+
15+
type DefaultCommandRunner struct{}
16+
17+
func NewDefaultCommandRunner() *DefaultCommandRunner {
18+
return &DefaultCommandRunner{}
19+
}
20+
21+
func (dcr *DefaultCommandRunner) Run(cmd *exec.Cmd) (output string, err error) {
22+
buff, err := cmd.CombinedOutput()
23+
return string(buff), err
24+
}

buildpacks/python/python/function.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ type Function struct {
2727
funcYamlEnvs map[string]string
2828
}
2929

30-
func NewFunction(opts ...FunctionOpt) Function {
31-
f := Function{}
30+
func NewFunction(opts ...FunctionOpt) *Function {
31+
f := &Function{}
3232
meta := map[string]string{}
3333

3434
for _, opt := range opts {
35-
opt(&f, meta)
35+
opt(f, meta)
3636
}
3737

3838
f.layerContributor = libpak.NewLayerContributor(
@@ -46,7 +46,7 @@ func NewFunction(opts ...FunctionOpt) Function {
4646
return f
4747
}
4848

49-
func (f Function) Contribute(layer libcnb.Layer) (libcnb.Layer, error) {
49+
func (f *Function) Contribute(layer libcnb.Layer) (libcnb.Layer, error) {
5050
f.layerContributor.Logger = f.logger
5151

5252
return f.layerContributor.Contribute(layer, func() (libcnb.Layer, error) {
@@ -70,7 +70,7 @@ func (f Function) Contribute(layer libcnb.Layer) (libcnb.Layer, error) {
7070
})
7171
}
7272

73-
func (f Function) Name() string {
73+
func (f *Function) Name() string {
7474
return f.layerContributor.Name
7575
}
7676

buildpacks/python/python/invoker.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ type Invoker struct {
2020
pythonPath string
2121
}
2222

23-
func NewInvoker(dependency libpak.BuildpackDependency, cache libpak.DependencyCache) Invoker {
23+
func NewInvoker(dependency libpak.BuildpackDependency, cache libpak.DependencyCache) *Invoker {
2424
contributor := libpak.NewDependencyLayerContributor(dependency, cache, libcnb.LayerTypes{
2525
Launch: true,
2626
Cache: true,
2727
})
28-
return Invoker{LayerContributor: contributor}
28+
return &Invoker{LayerContributor: contributor}
2929
}
3030

3131
func (i *Invoker) Contribute(layer libcnb.Layer) (libcnb.Layer, error) {

buildpacks/python/python/invoker_dependency_cache.go

+14-9
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package python
55

66
import (
7-
"bytes"
87
"fmt"
98
"os"
109
"os/exec"
@@ -20,16 +19,24 @@ type InvokerDependencyCache struct {
2019
LayerContributor libpak.DependencyLayerContributor
2120
Logger bard.Logger
2221

23-
pythonPath string
22+
pythonPath string
23+
commandRunner CommandRunner
2424
}
2525

26-
func NewInvokerDependencyCache(dependency libpak.BuildpackDependency, cache libpak.DependencyCache) InvokerDependencyCache {
26+
func NewInvokerDependencyCache(
27+
dependency libpak.BuildpackDependency,
28+
cache libpak.DependencyCache,
29+
commandRunner CommandRunner,
30+
) *InvokerDependencyCache {
2731
contributor := libpak.NewDependencyLayerContributor(dependency, cache, libcnb.LayerTypes{
2832
Launch: true,
2933
Cache: true,
3034
})
3135

32-
return InvokerDependencyCache{LayerContributor: contributor}
36+
return &InvokerDependencyCache{
37+
LayerContributor: contributor,
38+
commandRunner: commandRunner,
39+
}
3340
}
3441

3542
func (i *InvokerDependencyCache) Contribute(layer libcnb.Layer) (libcnb.Layer, error) {
@@ -53,7 +60,7 @@ func (i *InvokerDependencyCache) Contribute(layer libcnb.Layer) (libcnb.Layer, e
5360

5461
args := []string{
5562
"install",
56-
"--target=" + i.PythonPath(),
63+
"--target", i.PythonPath(),
5764
"--no-index",
5865
"--find-links", depsDir,
5966
"--compile",
@@ -69,12 +76,10 @@ func (i *InvokerDependencyCache) Contribute(layer libcnb.Layer) (libcnb.Layer, e
6976

7077
args = append(args, files...)
7178

72-
var stderr bytes.Buffer
7379
cmd := exec.Command("pip", args...)
74-
cmd.Stderr = &stderr
7580

76-
if err := cmd.Run(); err != nil {
77-
i.Logger.Body("failed to install dependencies: %s", stderr.String())
81+
if output, err := i.commandRunner.Run(cmd); err != nil {
82+
i.Logger.Body("failed to install dependencies: %s", output)
7883
return layer, err
7984
}
8085

buildpacks/python/python/validation.go

+21-23
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package python
55

66
import (
7-
"bytes"
87
"fmt"
98
"os"
109
"os/exec"
@@ -18,6 +17,7 @@ import (
1817
type FunctionValidationLayer struct {
1918
layerContributor libpak.LayerContributor
2019
logger bard.Logger
20+
commandRunner CommandRunner
2121

2222
module string
2323
function string
@@ -31,20 +31,22 @@ type FunctionValidationLayer struct {
3131

3232
type FunctionValidationOpts func(*FunctionValidationLayer, map[string]string)
3333

34+
//go:generate mockgen -destination ../mock_python/layer.go . Layer
3435
type Layer interface {
3536
PythonPath() string
3637
}
3738

38-
func NewFunctionValidationLayer(appPath string, invoker Layer, InvokerDepLayer Layer, opts ...FunctionValidationOpts) FunctionValidationLayer {
39-
fvl := FunctionValidationLayer{
39+
func NewFunctionValidationLayer(appPath string, invoker Layer, InvokerDepLayer Layer, commandRunner CommandRunner, opts ...FunctionValidationOpts) *FunctionValidationLayer {
40+
fvl := &FunctionValidationLayer{
4041
applicationPath: appPath,
4142
Invoker: invoker,
4243
InvokerDep: InvokerDepLayer,
44+
commandRunner: commandRunner,
4345
}
4446
meta := map[string]string{}
4547

4648
for _, opt := range opts {
47-
opt(&fvl, meta)
49+
opt(fvl, meta)
4850
}
4951

5052
fvl.layerContributor = libpak.NewLayerContributor("validation", meta, libcnb.LayerTypes{
@@ -54,44 +56,40 @@ func NewFunctionValidationLayer(appPath string, invoker Layer, InvokerDepLayer L
5456
return fvl
5557
}
5658

57-
func (i FunctionValidationLayer) Contribute(layer libcnb.Layer) (libcnb.Layer, error) {
58-
i.layerContributor.Logger = i.logger
59+
func (f *FunctionValidationLayer) Contribute(layer libcnb.Layer) (libcnb.Layer, error) {
60+
f.layerContributor.Logger = f.logger
5961

60-
return i.layerContributor.Contribute(layer, func() (libcnb.Layer, error) {
61-
i.logger.Body("Validating function")
62+
return f.layerContributor.Contribute(layer, func() (libcnb.Layer, error) {
63+
f.logger.Body("Validating function")
6264

6365
var pythonPath []string
64-
if i.Invoker.PythonPath() != "" {
65-
pythonPath = append(pythonPath, i.Invoker.PythonPath())
66+
if f.Invoker.PythonPath() != "" {
67+
pythonPath = append(pythonPath, f.Invoker.PythonPath())
6668
}
6769

68-
if i.InvokerDep.PythonPath() != "" {
69-
pythonPath = append(pythonPath, i.InvokerDep.PythonPath())
70+
if f.InvokerDep.PythonPath() != "" {
71+
pythonPath = append(pythonPath, f.InvokerDep.PythonPath())
7072
}
7173

7274
if env, found := os.LookupEnv("PYTHONPATH"); found {
7375
pythonPath = append(pythonPath, env)
7476
}
7577

76-
buffer := bytes.NewBuffer(nil)
77-
cmd := exec.Command("python", "-m", "pyfunc", "check", "-s", i.applicationPath)
78-
// cmd := exec.Command("env")
78+
cmd := exec.Command("python", "-m", "pyfunc", "check", "-s", f.applicationPath)
7979
cmd.Env = append(os.Environ(), fmt.Sprintf("PYTHONPATH=%s", strings.Join(pythonPath, string(os.PathListSeparator))))
80-
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", EnvModuleName, i.module), fmt.Sprintf("%s=%s", EnvFunctionName, i.function))
81-
cmd.Stderr = buffer
82-
cmd.Stdout = buffer
80+
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", EnvModuleName, f.module), fmt.Sprintf("%s=%s", EnvFunctionName, f.function))
8381

84-
if err := cmd.Run(); err != nil {
85-
return layer, fmt.Errorf("%v: %v", buffer.String(), err)
82+
if output, err := f.commandRunner.Run(cmd); err != nil {
83+
return layer, fmt.Errorf("%v: %v", output, err)
8684
}
8785

88-
i.logger.Debug("Function was successfully parsed")
86+
f.logger.Debug("Function was successfully parsed")
8987
return layer, nil
9088
})
9189
}
9290

93-
func (i FunctionValidationLayer) Name() string {
94-
return i.layerContributor.Name
91+
func (f *FunctionValidationLayer) Name() string {
92+
return f.layerContributor.Name
9593
}
9694

9795
func WithValidationLogger(logger bard.Logger) FunctionValidationOpts {

buildpacks/python/tests/build_test.go

-4
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,6 @@ func testBuild(t *testing.T, when spec.G, it spec.S) {
7070
Expect(err).NotTo(HaveOccurred())
7171
})
7272

73-
it.After(func() {
74-
Expect(os.Unsetenv("BP_FUNCTION"))
75-
})
76-
7773
it("adds expected layers", func() {
7874
var layers []string
7975
for _, l := range result.Layers {

0 commit comments

Comments
 (0)