Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow entrypoint binary to wait for multiple files #1430

Merged
merged 1 commit into from
Oct 15, 2019
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
5 changes: 3 additions & 2 deletions cmd/entrypoint/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"log"
"os"
"os/exec"
"strings"
"syscall"
"time"

Expand All @@ -29,7 +30,7 @@ import (

var (
ep = flag.String("entrypoint", "", "Original specified entrypoint to execute")
waitFile = flag.String("wait_file", "", "If specified, file to wait for")
waitFiles = flag.String("wait_file", "", "Comma-separated list of paths to wait for")
waitFileContent = flag.Bool("wait_file_content", false, "If specified, expect wait_file to have content")
postFile = flag.String("post_file", "", "If specified, file to write upon completion")

Expand All @@ -41,7 +42,7 @@ func main() {

e := entrypoint.Entrypointer{
Entrypoint: *ep,
WaitFile: *waitFile,
WaitFiles: strings.Split(*waitFiles, ","),
WaitFileContent: *waitFileContent,
PostFile: *postFile,
Args: flag.Args(),
Expand Down
12 changes: 6 additions & 6 deletions pkg/entrypoint/entrypointer.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ type Entrypointer struct {
Entrypoint string
// Args are the original specified args, if any.
Args []string
// WaitFile is the file to wait for. If not specified, execution begins
// immediately.
WaitFile string
// WaitFiles is the set of files to wait for. If empty, execution
// begins immediately.
WaitFiles []string
// WaitFileContent indicates the WaitFile should have non-zero size
// before continuing with execution.
WaitFileContent bool
Expand Down Expand Up @@ -65,10 +65,10 @@ type PostWriter interface {
// Go optionally waits for a file, runs the command, and writes a
// post file.
func (e Entrypointer) Go() error {
if e.WaitFile != "" {
if err := e.Waiter.Wait(e.WaitFile, e.WaitFileContent); err != nil {
for _, f := range e.WaitFiles {
if err := e.Waiter.Wait(f, e.WaitFileContent); err != nil {
// An error happened while waiting, so we bail
// *but* we write postfile to make next steps bail too
// *but* we write postfile to make next steps bail too.
e.WritePostFile(e.PostFile, err)
return err
}
Expand Down
46 changes: 25 additions & 21 deletions pkg/entrypoint/entrypointer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ import (

func TestEntrypointerFailures(t *testing.T) {
for _, c := range []struct {
desc, waitFile, postFile string
waiter Waiter
runner Runner
expectedError string
desc, postFile string
waitFiles []string
waiter Waiter
runner Runner
expectedError string
}{{
desc: "failing runner with no postFile",
runner: &fakeErrorRunner{},
Expand All @@ -41,12 +42,12 @@ func TestEntrypointerFailures(t *testing.T) {
postFile: "foo",
}, {
desc: "failing waiter with no postFile",
waitFile: "foo",
waitFiles: []string{"foo"},
waiter: &fakeErrorWaiter{},
expectedError: "waiter failed",
}, {
desc: "failing waiter with postFile",
waitFile: "foo",
waitFiles: []string{"foo"},
waiter: &fakeErrorWaiter{},
expectedError: "waiter failed",
postFile: "bar",
Expand All @@ -63,7 +64,7 @@ func TestEntrypointerFailures(t *testing.T) {
fpw := &fakePostWriter{}
err := Entrypointer{
Entrypoint: "echo",
WaitFile: c.waitFile,
WaitFiles: c.waitFiles,
PostFile: c.postFile,
Args: []string{"some", "args"},
Waiter: fw,
Expand Down Expand Up @@ -93,8 +94,8 @@ func TestEntrypointerFailures(t *testing.T) {

func TestEntrypointer(t *testing.T) {
for _, c := range []struct {
desc, entrypoint, waitFile, postFile string
args []string
desc, entrypoint, postFile string
waitFiles, args []string
}{{
desc: "do nothing",
}, {
Expand All @@ -107,22 +108,25 @@ func TestEntrypointer(t *testing.T) {
desc: "just args",
args: []string{"just", "args"},
}, {
desc: "wait file",
waitFile: "waitforme",
desc: "wait file",
waitFiles: []string{"waitforme"},
}, {
desc: "post file",
postFile: "writeme",
}, {
desc: "all together now",
entrypoint: "echo", args: []string{"some", "args"},
waitFile: "waitforme",
postFile: "writeme",
waitFiles: []string{"waitforme"},
postFile: "writeme",
}, {
desc: "multiple wait files",
waitFiles: []string{"waitforme", "metoo", "methree"},
}} {
t.Run(c.desc, func(t *testing.T) {
fw, fr, fpw := &fakeWaiter{}, &fakeRunner{}, &fakePostWriter{}
err := Entrypointer{
Entrypoint: c.entrypoint,
WaitFile: c.waitFile,
WaitFiles: c.waitFiles,
PostFile: c.postFile,
Args: c.args,
Waiter: fw,
Expand All @@ -133,14 +137,14 @@ func TestEntrypointer(t *testing.T) {
t.Fatalf("Entrypointer failed: %v", err)
}

if c.waitFile != "" {
if len(c.waitFiles) > 0 {
if fw.waited == nil {
t.Error("Wanted waited file, got nil")
} else if *fw.waited != c.waitFile {
t.Errorf("Waited for %q, want %q", *fw.waited, c.waitFile)
} else if !reflect.DeepEqual(fw.waited, c.waitFiles) {
t.Errorf("Waited for %v, want %v", fw.waited, c.waitFiles)
}
}
if c.waitFile == "" && fw.waited != nil {
if len(c.waitFiles) == 0 && fw.waited != nil {
t.Errorf("Waited for file when not required")
}

Expand Down Expand Up @@ -173,10 +177,10 @@ func TestEntrypointer(t *testing.T) {
}
}

type fakeWaiter struct{ waited *string }
type fakeWaiter struct{ waited []string }

func (f *fakeWaiter) Wait(file string, expectContent bool) error {
f.waited = &file
func (f *fakeWaiter) Wait(file string, _ bool) error {
f.waited = append(f.waited, file)
return nil
}

Expand Down