diff --git a/cmd/entrypoint/main.go b/cmd/entrypoint/main.go index 22df0332688..4030acf840e 100644 --- a/cmd/entrypoint/main.go +++ b/cmd/entrypoint/main.go @@ -18,6 +18,11 @@ package main import ( "flag" + "log" + "os" + "os/exec" + "syscall" + "time" "github.com/knative/build-pipeline/pkg/entrypoint" ) @@ -36,10 +41,75 @@ func main() { WaitFile: *waitFile, PostFile: *postFile, Args: flag.Args(), - Waiter: &entrypoint.RealWaiter{}, - Runner: &entrypoint.RealRunner{}, - PostWriter: &entrypoint.RealPostWriter{}, + Waiter: &RealWaiter{}, + Runner: &RealRunner{}, + PostWriter: &RealPostWriter{}, }.Go() } -// TODO(jasonhall): Test that original exit code is propagated and that stdout/stderr are collected -- needs e2e tests. +// TODO(jasonhall): Test that original exit code is propagated and that +// stdout/stderr are collected -- needs e2e tests. + +// RealWaiter actually waits for files, by polling. +type RealWaiter struct{ waitFile string } + +var _ entrypoint.Waiter = (*RealWaiter)(nil) + +func (*RealWaiter) Wait(file string) { + if file == "" { + return + } + for ; ; time.Sleep(time.Second) { + if _, err := os.Stat(file); err == nil { + return + } else if !os.IsNotExist(err) { + log.Fatalf("Waiting for %q: %v", file, err) + } + } +} + +// RealRunner actually runs commands. +type RealRunner struct{} + +var _ entrypoint.Runner = (*RealRunner)(nil) + +func (*RealRunner) Run(args ...string) { + if len(args) == 0 { + return + } + name, args := args[0], args[1:] + + cmd := exec.Command(name, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + if err := cmd.Run(); err != nil { + if exiterr, ok := err.(*exec.ExitError); ok { + // Copied from https://stackoverflow.com/questions/10385551/get-exit-code-go + // This works on both Unix and Windows. Although + // package syscall is generally platform dependent, + // WaitStatus is defined for both Unix and Windows and + // in both cases has an ExitStatus() method with the + // same signature. + if status, ok := exiterr.Sys().(syscall.WaitStatus); ok { + os.Exit(status.ExitStatus()) + } + log.Fatalf("Error executing command (ExitError): %v", err) + } + log.Fatalf("Error executing command: %v", err) + } +} + +// RealPostWriter actually writes files. +type RealPostWriter struct{} + +var _ entrypoint.PostWriter = (*RealPostWriter)(nil) + +func (*RealPostWriter) Write(file string) { + if file == "" { + return + } + if _, err := os.Create(file); err != nil { + log.Fatalf("Creating %q: %v", file, err) + } +} diff --git a/pkg/entrypoint/entrypointer.go b/pkg/entrypoint/entrypointer.go index 957520a3179..d6f701f8279 100644 --- a/pkg/entrypoint/entrypointer.go +++ b/pkg/entrypoint/entrypointer.go @@ -38,6 +38,23 @@ type Entrypointer struct { PostWriter PostWriter } +// Waiter encapsulates waiting for files to exist. +type Waiter interface { + // Wait blocks until the specified file exists. + Wait(file string) +} + +// Runner encapsulates running commands. +type Runner interface { + Run(args ...string) +} + +// PostWriter encapsulates writing a file when complete. +type PostWriter interface { + // Write writes to the path when complete. + Write(file string) +} + // Go optionally waits for a file, runs the command, and writes a // post file. func (e Entrypointer) Go() { diff --git a/pkg/entrypoint/postwriter.go b/pkg/entrypoint/postwriter.go deleted file mode 100644 index d6b57e88954..00000000000 --- a/pkg/entrypoint/postwriter.go +++ /dev/null @@ -1,42 +0,0 @@ -/* -Copyright 2019 The Knative 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 - - http://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 entrypoint - -import ( - "log" - "os" -) - -// PostWriter encapsulates writing a file when complete. -type PostWriter interface { - // Write writes to the path when complete. - Write(file string) -} - -// RealPostWriter actually writes files. -type RealPostWriter struct{} - -var _ PostWriter = (*RealPostWriter)(nil) - -func (*RealPostWriter) Write(file string) { - if file == "" { - return - } - if _, err := os.Create(file); err != nil { - log.Fatalf("Creating %q: %v", file, err) - } -} diff --git a/pkg/entrypoint/runner.go b/pkg/entrypoint/runner.go deleted file mode 100644 index 1b454cdb02b..00000000000 --- a/pkg/entrypoint/runner.go +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2019 The Knative 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 - - http://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 entrypoint - -import ( - "log" - "os" - "os/exec" - "syscall" -) - -// Runner encapsulates running commands. -type Runner interface { - Run(args ...string) -} - -// RealRunner actually runs commands. -type RealRunner struct{} - -var _ Runner = (*RealRunner)(nil) - -func (*RealRunner) Run(args ...string) { - if len(args) == 0 { - return - } - name, args := args[0], args[1:] - - cmd := exec.Command(name, args...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - if err := cmd.Run(); err != nil { - if exiterr, ok := err.(*exec.ExitError); ok { - // Copied from https://stackoverflow.com/questions/10385551/get-exit-code-go - // This works on both Unix and Windows. Although - // package syscall is generally platform dependent, - // WaitStatus is defined for both Unix and Windows and - // in both cases has an ExitStatus() method with the - // same signature. - if status, ok := exiterr.Sys().(syscall.WaitStatus); ok { - os.Exit(status.ExitStatus()) - } - log.Fatalf("Error executing command (ExitError): %v", err) - } - log.Fatalf("Error executing command: %v", err) - } -} diff --git a/pkg/entrypoint/waiter.go b/pkg/entrypoint/waiter.go deleted file mode 100644 index 89de4c18a3a..00000000000 --- a/pkg/entrypoint/waiter.go +++ /dev/null @@ -1,47 +0,0 @@ -/* -Copyright 2019 The Knative 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 - - http://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 entrypoint - -import ( - "log" - "os" - "time" -) - -// Waiter encapsulates waiting for files to exist. -type Waiter interface { - // Wait blocks until the specified file exists. - Wait(file string) -} - -// RealWaiter actually waits for files, by polling. -type RealWaiter struct{ waitFile string } - -var _ Waiter = (*RealWaiter)(nil) - -func (*RealWaiter) Wait(file string) { - if file == "" { - return - } - for ; ; time.Sleep(time.Second) { - if _, err := os.Stat(file); err == nil { - return - } else if !os.IsNotExist(err) { - log.Fatalf("Waiting for %q: %v", file, err) - } - } -}