From aff8c816f023e56fff4d4f64ef2cb9fa73f74111 Mon Sep 17 00:00:00 2001 From: Liam White Date: Fri, 2 Aug 2019 07:00:26 +0100 Subject: [PATCH] Implement functional options Signed-off-by: Liam White --- pkg/binary/getenvoy/run_test.go | 58 +++++++++++++++--------------- pkg/binary/getenvoy/runtime.go | 10 ++++-- pkg/binary/getenvoy/termination.go | 43 +++++++++++----------- pkg/cmd/run.go | 5 +-- 4 files changed, 59 insertions(+), 57 deletions(-) diff --git a/pkg/binary/getenvoy/run_test.go b/pkg/binary/getenvoy/run_test.go index f3442c8..ca57b9f 100644 --- a/pkg/binary/getenvoy/run_test.go +++ b/pkg/binary/getenvoy/run_test.go @@ -55,15 +55,12 @@ func TestRuntime_RunPath(t *testing.T) { for _, tt := range tests { tc := tt t.Run(tc.name, func(t *testing.T) { - r, _ := New() + // This ensures functions are called in the correct order + r, preStartCalled, preTerminationCalled := newRuntimeWithMockFunctions(t) tmpDir, _ := ioutil.TempDir("", "getenvoy-test-") defer os.RemoveAll(tmpDir) r.local = tmpDir - // These will t.Error if not called in correct order - preStartCalled := registerPreStart(t, r) - preTerminationCalled := registerPreTermination(t, r) - wg := &sync.WaitGroup{} wg.Add(1) go func() { @@ -88,29 +85,32 @@ func waitForProcessStart(r *Runtime) { } } -func registerPreStart(t *testing.T, r *Runtime) *bool { - called := false - r.registerPreStart(func() error { - if r.cmd != nil && r.cmd.Process != nil { - t.Error("preStart was called after process has started") - } - called = true - return nil - }) - return &called -} +// This ensures functions are called in the correct order +func newRuntimeWithMockFunctions(t *testing.T) (*Runtime, *bool, *bool) { + preStartCalled := false + preStart := func(r *Runtime) { + r.registerPreStart(func() error { + if r.cmd != nil && r.cmd.Process != nil { + t.Error("preStart was called after process has started") + } + preStartCalled = true + return nil + }) + } -func registerPreTermination(t *testing.T, r *Runtime) *bool { - called := false - r.registerPreTermination(func() error { - if r.cmd != nil && r.cmd.Process == nil { - t.Error("preTermination was called before process was started") - } - if r.cmd != nil && r.cmd.ProcessState != nil { - t.Error("preTermination was called after process was terminated") - } - called = true - return nil - }) - return &called + preTerminationCalled := false + preTermination := func(r *Runtime) { + r.registerPreTermination(func() error { + if r.cmd != nil && r.cmd.Process == nil { + t.Error("preTermination was called before process was started") + } + if r.cmd != nil && r.cmd.ProcessState != nil { + t.Error("preTermination was called after process was terminated") + } + preTerminationCalled = true + return nil + }) + } + runtime, _ := New(preStart, preTermination) + return runtime, &preStartCalled, &preTerminationCalled } diff --git a/pkg/binary/getenvoy/runtime.go b/pkg/binary/getenvoy/runtime.go index 12d62b4..19d1f54 100644 --- a/pkg/binary/getenvoy/runtime.go +++ b/pkg/binary/getenvoy/runtime.go @@ -24,16 +24,20 @@ import ( ) // New creates a new GetEnvoy binary.Runtime with the local file storage set to the home directory -func New() (*Runtime, error) { +func New(options ...func(*Runtime)) (*Runtime, error) { usrDir, err := homedir.Dir() local := filepath.Join(usrDir, ".getenvoy") - return &Runtime{ + runtime := &Runtime{ local: local, wg: &sync.WaitGroup{}, signals: make(chan os.Signal), preStart: make([]preStartFunc, 0), preTermination: make([]preTerminationFunc, 0), - }, err + } + for _, option := range options { + option(runtime) + } + return runtime, err } // Runtime implements the GetEnvoy binary.Runtime diff --git a/pkg/binary/getenvoy/termination.go b/pkg/binary/getenvoy/termination.go index df413ea..28fdc7e 100644 --- a/pkg/binary/getenvoy/termination.go +++ b/pkg/binary/getenvoy/termination.go @@ -62,28 +62,25 @@ var adminAPIPaths = map[string]string{ "runtime": "runtime.json", } -// EnvoyAdminDataCollection registers collection of Envoy Admin API information -// TODO: Test this (Liam) -func (r *Runtime) EnvoyAdminDataCollection(enable bool) { - if enable { - r.registerPreTermination(func() error { - var multiErr *multierror.Error - for path, file := range adminAPIPaths { - resp, err := http.Get(fmt.Sprintf("http://0.0.0.0:15001/%v", path)) - if err != nil { - multiErr = multierror.Append(multiErr, err) - } - f, err := os.OpenFile(filepath.Join(r.debugDir, file), os.O_CREATE|os.O_WRONLY, 0600) - if err != nil { - multiErr = multierror.Append(multiErr, err) - } - defer func() { _ = f.Close() }() - defer func() { _ = resp.Body.Close() }() - if _, err := io.Copy(f, resp.Body); err != nil { - multiErr = multierror.Append(multiErr, err) - } +// EnableEnvoyAdminDataCollection registers collection of Envoy Admin API information +var EnableEnvoyAdminDataCollection = func(r *Runtime) { + r.registerPreTermination(func() error { + var multiErr *multierror.Error + for path, file := range adminAPIPaths { + resp, err := http.Get(fmt.Sprintf("http://0.0.0.0:15001/%v", path)) + if err != nil { + multiErr = multierror.Append(multiErr, err) } - return multiErr.ErrorOrNil() - }) - } + f, err := os.OpenFile(filepath.Join(r.debugDir, file), os.O_CREATE|os.O_WRONLY, 0600) + if err != nil { + multiErr = multierror.Append(multiErr, err) + } + defer func() { _ = f.Close() }() + defer func() { _ = resp.Body.Close() }() + if _, err := io.Copy(f, resp.Body); err != nil { + multiErr = multierror.Append(multiErr, err) + } + } + return multiErr.ErrorOrNil() + }) } diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go index ffa89a6..d398744 100644 --- a/pkg/cmd/run.go +++ b/pkg/cmd/run.go @@ -48,11 +48,12 @@ getenvoy run standard:1.10.1 -- --help return nil }, RunE: func(cmd *cobra.Command, args []string) error { - runtime, err := getenvoy.New() + runtime, err := getenvoy.New( + getenvoy.EnableEnvoyAdminDataCollection, + ) if err != nil { return err } - runtime.EnvoyAdminDataCollection(true) key, manifestErr := manifest.NewKey(args[0]) if manifestErr != nil {