From f6770ebcaca911b89ec391b824535af014c8f075 Mon Sep 17 00:00:00 2001 From: Ben Hale Date: Fri, 13 Nov 2020 11:03:09 -0800 Subject: [PATCH] Helper Helpers This change adds some more helper functions to sherpa that are particularly useful in the environment that exec.d's run in. Signed-off-by: Ben Hale --- bindings/resolve.go | 30 +++++++++++ bindings/resolve_test.go | 56 +++++++++++++++++++++ sherpa/env_var.go | 52 +++++++++++++++++++ sherpa/env_var_test.go | 106 +++++++++++++++++++++++++++++++++++++++ sherpa/init_test.go | 1 + 5 files changed, 245 insertions(+) create mode 100644 sherpa/env_var.go create mode 100644 sherpa/env_var_test.go diff --git a/bindings/resolve.go b/bindings/resolve.go index 61b1a5a..99e4077 100644 --- a/bindings/resolve.go +++ b/bindings/resolve.go @@ -26,6 +26,36 @@ import ( // Predicate should return true if it matches a given binding. type Predicate func(bind libcnb.Binding) bool +// And combines multiple predicates logical and-ing their results together. +func And(predicates ...Predicate) Predicate { + return func(bind libcnb.Binding) bool { + if len(predicates) < 1 { + return false + } + + v := predicates[0](bind) + for _, p := range predicates[1:] { + v = v && p(bind) + } + return v + } +} + +// Or combines multiple predicates logical or-ing their results together. +func Or(predicates ...Predicate) Predicate { + return func(bind libcnb.Binding) bool { + if len(predicates) < 1 { + return false + } + + v := predicates[0](bind) + for _, p := range predicates[1:] { + v = v || p(bind) + } + return v + } +} + // OfType returns a Predicate that returns true if a given binding has Type that matches t. The comparison is // case-insensitive. func OfType(t string) Predicate { diff --git a/bindings/resolve_test.go b/bindings/resolve_test.go index c200235..ab8943e 100644 --- a/bindings/resolve_test.go +++ b/bindings/resolve_test.go @@ -53,6 +53,62 @@ func testResolve(t *testing.T, context spec.G, it spec.S) { } }) + context("And", func() { + var ( + tr = func(bind libcnb.Binding) bool { + return true + } + + fa = func(bind libcnb.Binding) bool { + return false + } + ) + + it("returns false with no predicates", func() { + Expect(bindings.And()(libcnb.Binding{})).To(BeFalse()) + }) + + it("returns value of single predicate", func() { + Expect(bindings.And(tr)(libcnb.Binding{})).To(BeTrue()) + Expect(bindings.And(fa)(libcnb.Binding{})).To(BeFalse()) + }) + + it("returns and-ed value of multiple predicates", func() { + Expect(bindings.And(tr, tr)(libcnb.Binding{})).To(BeTrue()) + Expect(bindings.And(tr, fa)(libcnb.Binding{})).To(BeFalse()) + Expect(bindings.And(fa, tr)(libcnb.Binding{})).To(BeFalse()) + Expect(bindings.And(fa, fa)(libcnb.Binding{})).To(BeFalse()) + }) + }) + + context("Or", func() { + var ( + tr = func(bind libcnb.Binding) bool { + return true + } + + fa = func(bind libcnb.Binding) bool { + return false + } + ) + + it("returns false with no predicates", func() { + Expect(bindings.Or()(libcnb.Binding{})).To(BeFalse()) + }) + + it("returns value of single predicate", func() { + Expect(bindings.Or(tr)(libcnb.Binding{})).To(BeTrue()) + Expect(bindings.Or(fa)(libcnb.Binding{})).To(BeFalse()) + }) + + it("returns or-ed value of multiple predicates", func() { + Expect(bindings.Or(tr, tr)(libcnb.Binding{})).To(BeTrue()) + Expect(bindings.Or(tr, fa)(libcnb.Binding{})).To(BeTrue()) + Expect(bindings.Or(fa, tr)(libcnb.Binding{})).To(BeTrue()) + Expect(bindings.Or(fa, fa)(libcnb.Binding{})).To(BeFalse()) + }) + }) + context("Resolve", func() { context("no predicate", func() { it("returns all bindings", func() { diff --git a/sherpa/env_var.go b/sherpa/env_var.go new file mode 100644 index 0000000..a39bbc5 --- /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 varible if it exists, otherwire 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)