diff --git a/buildpack.go b/buildpack.go index e6584e6..124fb80 100644 --- a/buildpack.go +++ b/buildpack.go @@ -20,6 +20,7 @@ import ( "fmt" "os" "sort" + "strconv" "strings" "github.com/Masterminds/semver/v3" @@ -345,6 +346,18 @@ func (c *ConfigurationResolver) Resolve(name string) (string, bool) { return "", false } +// ResolveBool resolves a boolean value for a configuration option. Returns true for 1, t, T, TRUE, true, True. Returns +// false for all other values or unset. +func (c *ConfigurationResolver) ResolveBool(name string) bool { + s, _ := c.Resolve(name) + t, err := strconv.ParseBool(s) + if err != nil { + return false + } + + return t +} + // DependencyResolver provides functionality for resolving a dependency given a collection of constraints. type DependencyResolver struct { diff --git a/buildpack_test.go b/buildpack_test.go index fc69f6b..3160f85 100644 --- a/buildpack_test.go +++ b/buildpack_test.go @@ -130,16 +130,23 @@ func testBuildpack(t *testing.T, context spec.G, it spec.S) { Configurations: []libpak.BuildpackConfiguration{ {Name: "TEST_KEY_1", Default: "test-default-value-1"}, {Name: "TEST_KEY_2", Default: "test-default-value-2"}, + {Name: "TEST_BOOL_3", Default: "true"}, + {Name: "TEST_BOOL_4", Default: "false"}, + {Name: "TEST_BOOL_6", Default: "test-value"}, }, } ) it.Before(func() { Expect(os.Setenv("TEST_KEY_1", "test-value-1")).To(Succeed()) + Expect(os.Setenv("TEST_BOOL_1", "true")).To(Succeed()) + Expect(os.Setenv("TEST_BOOL_2", "false")).To(Succeed()) }) it.After(func() { Expect(os.Unsetenv("TEST_KEY_1")).To(Succeed()) + Expect(os.Unsetenv("TEST_BOOL_1")).To(Succeed()) + Expect(os.Unsetenv("TEST_BOOL_2")).To(Succeed()) }) it("returns configured value", func() { @@ -159,6 +166,24 @@ func testBuildpack(t *testing.T, context spec.G, it spec.S) { Expect(v).To(Equal("")) Expect(ok).To(BeFalse()) }) + + it("returns configured bool", func() { + Expect(resolver.ResolveBool("TEST_BOOL_1")).To(BeTrue()) + Expect(resolver.ResolveBool("TEST_BOOL_2")).To(BeFalse()) + }) + + it("returns default bool", func() { + Expect(resolver.ResolveBool("TEST_BOOL_3")).To(BeTrue()) + Expect(resolver.ResolveBool("TEST_BOOL_4")).To(BeFalse()) + }) + + it("returns false for unset", func() { + Expect(resolver.ResolveBool("TEST_BOOL_5")).To(BeFalse()) + }) + + it("return false for invalid", func() { + Expect(resolver.ResolveBool("TEST_BOOL_6")).To(BeFalse()) + }) }) context("DependencyResolver", func() { diff --git a/sherpa/env_var.go b/sherpa/env_var.go new file mode 100644 index 0000000..ff2b7c2 --- /dev/null +++ b/sherpa/env_var.go @@ -0,0 +1,52 @@ +/* + * Copyright 2018-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sherpa + +import ( + "fmt" + "os" + "strings" +) + +// AppendToEnvVar appends a collection of values to an env var separated by a delimiter. If the env var does not already +// exist, joins the values with the delimiter and returns the result. +func AppendToEnvVar(name string, delimiter string, values ...string) string { + var e []string + if s, ok := os.LookupEnv(name); ok { + e = append(e, s) + } + e = append(e, values...) + return strings.Join(e, delimiter) +} + +// GetEnvRequired returns the value of an environment variable if it exists, otherwise returns an error with a +// predictable message. +func GetEnvRequired(name string) (string, error) { + if s, ok := os.LookupEnv(name); ok { + return s, nil + } + + return "", fmt.Errorf("$%s must be set", name) +} + +// GetEnvWithWithDefault returns the value of an environment variable if it exists, otherwise returns the default. +func GetEnvWithDefault(name string, def string) string { + if s, ok := os.LookupEnv(name); ok { + return s + } + return def +} diff --git a/sherpa/env_var_test.go b/sherpa/env_var_test.go new file mode 100644 index 0000000..62c6db3 --- /dev/null +++ b/sherpa/env_var_test.go @@ -0,0 +1,106 @@ +/* + * Copyright 2018-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sherpa_test + +import ( + "os" + "testing" + + . "github.com/onsi/gomega" + "github.com/sclevine/spec" + + "github.com/paketo-buildpacks/libpak/sherpa" +) + +func testEnvVar(t *testing.T, context spec.G, it spec.S) { + var ( + Expect = NewWithT(t).Expect + ) + + context("AppendToEnvVar", func() { + + context("No Existing", func() { + + it("append one", func() { + Expect(sherpa.AppendToEnvVar("TEST_KEY", "|", "test-value-2")). + To(Equal("test-value-2")) + }) + + it("appends multiple", func() { + Expect(sherpa.AppendToEnvVar("TEST_KEY", "|", "test-value-2", "test-value-3")). + To(Equal("test-value-2|test-value-3")) + }) + }) + + context("With Existing", func() { + it.Before(func() { + Expect(os.Setenv("TEST_KEY", "test-value-1")).To(Succeed()) + }) + + it.After(func() { + Expect(os.Unsetenv("TEST_KEY")).To(Succeed()) + }) + + it("append one", func() { + Expect(sherpa.AppendToEnvVar("TEST_KEY", "|", "test-value-2")). + To(Equal("test-value-1|test-value-2")) + }) + + it("appends multiple", func() { + Expect(sherpa.AppendToEnvVar("TEST_KEY", "|", "test-value-2", "test-value-3")). + To(Equal("test-value-1|test-value-2|test-value-3")) + }) + }) + }) + + context("GetEnvRequired", func() { + it.Before(func() { + Expect(os.Setenv("TEST_KEY", "test-value")).To(Succeed()) + }) + + it.After(func() { + Expect(os.Unsetenv("TEST_KEY")).To(Succeed()) + }) + + it("returns value if set", func() { + Expect(sherpa.GetEnvRequired("TEST_KEY")).To(Equal("test-value")) + }) + + it("returns error if not set", func() { + _, err := sherpa.GetEnvRequired("ANOTHER_KEY") + Expect(err).To(MatchError("$ANOTHER_KEY must be set")) + }) + }) + + context("GetEnvWithDefault", func() { + it.Before(func() { + Expect(os.Setenv("TEST_KEY", "test-value")).To(Succeed()) + }) + + it.After(func() { + Expect(os.Unsetenv("TEST_KEY")).To(Succeed()) + }) + + it("returns value if set", func() { + Expect(sherpa.GetEnvWithDefault("TEST_KEY", "default-value")).To(Equal("test-value")) + }) + + it("returns default value if not set", func() { + Expect(sherpa.GetEnvWithDefault("ANOTHER_KEY", "default-value")).To(Equal("default-value")) + }) + }) +} diff --git a/sherpa/init_test.go b/sherpa/init_test.go index c90dccd..f524e5d 100644 --- a/sherpa/init_test.go +++ b/sherpa/init_test.go @@ -26,6 +26,7 @@ import ( func TestUnit(t *testing.T) { suite := spec.New("libpak/sherpa", spec.Report(report.Terminal{})) suite("CopyFile", testCopyFile) + suite("EnvVar", testEnvVar) suite("FileListing", testFileListing) suite("NodeJS", testNodeJS) suite("Sherpa", testSherpa)