From 2345831b82dbc02ce6733b71a44f2087188c58cf Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Wed, 20 Mar 2019 11:27:55 -0700 Subject: [PATCH] kubectl: Removes dependency on util/interrupt by copying this code into kubectl --- pkg/kubectl/cmd/exec/BUILD | 2 +- pkg/kubectl/cmd/exec/exec.go | 2 +- pkg/kubectl/cmd/get/BUILD | 2 +- pkg/kubectl/cmd/get/get.go | 2 +- pkg/kubectl/cmd/rollout/BUILD | 2 +- pkg/kubectl/cmd/rollout/rollout_status.go | 2 +- pkg/kubectl/cmd/run/BUILD | 2 +- pkg/kubectl/cmd/run/run.go | 2 +- pkg/kubectl/util/BUILD | 1 + pkg/kubectl/util/interrupt/BUILD | 22 +++++ pkg/kubectl/util/interrupt/interrupt.go | 104 ++++++++++++++++++++++ pkg/kubectl/util/term/BUILD | 2 +- pkg/kubectl/util/term/term.go | 2 +- 13 files changed, 137 insertions(+), 10 deletions(-) create mode 100644 pkg/kubectl/util/interrupt/BUILD create mode 100644 pkg/kubectl/util/interrupt/interrupt.go diff --git a/pkg/kubectl/cmd/exec/BUILD b/pkg/kubectl/cmd/exec/BUILD index 00411d528f..1b827ab5e3 100644 --- a/pkg/kubectl/cmd/exec/BUILD +++ b/pkg/kubectl/cmd/exec/BUILD @@ -9,9 +9,9 @@ go_library( "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/scheme:go_default_library", "//pkg/kubectl/util/i18n:go_default_library", + "//pkg/kubectl/util/interrupt:go_default_library", "//pkg/kubectl/util/templates:go_default_library", "//pkg/kubectl/util/term:go_default_library", - "//pkg/util/interrupt:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/cli-runtime/pkg/genericclioptions:go_default_library", diff --git a/pkg/kubectl/cmd/exec/exec.go b/pkg/kubectl/cmd/exec/exec.go index e7f40e3f71..d448bf804d 100644 --- a/pkg/kubectl/cmd/exec/exec.go +++ b/pkg/kubectl/cmd/exec/exec.go @@ -33,9 +33,9 @@ import ( cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" + "k8s.io/kubernetes/pkg/kubectl/util/interrupt" "k8s.io/kubernetes/pkg/kubectl/util/templates" "k8s.io/kubernetes/pkg/kubectl/util/term" - "k8s.io/kubernetes/pkg/util/interrupt" ) var ( diff --git a/pkg/kubectl/cmd/get/BUILD b/pkg/kubectl/cmd/get/BUILD index 609c3c329f..b45f7e95b9 100644 --- a/pkg/kubectl/cmd/get/BUILD +++ b/pkg/kubectl/cmd/get/BUILD @@ -32,11 +32,11 @@ go_library( "//pkg/kubectl/cmd/util/openapi:go_default_library", "//pkg/kubectl/scheme:go_default_library", "//pkg/kubectl/util/i18n:go_default_library", + "//pkg/kubectl/util/interrupt:go_default_library", "//pkg/kubectl/util/printers:go_default_library", "//pkg/kubectl/util/templates:go_default_library", "//pkg/printers:go_default_library", "//pkg/printers/internalversion:go_default_library", - "//pkg/util/interrupt:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", diff --git a/pkg/kubectl/cmd/get/get.go b/pkg/kubectl/cmd/get/get.go index 092fda391b..ab842e5171 100644 --- a/pkg/kubectl/cmd/get/get.go +++ b/pkg/kubectl/cmd/get/get.go @@ -45,9 +45,9 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/util/i18n" + "k8s.io/kubernetes/pkg/kubectl/util/interrupt" utilprinters "k8s.io/kubernetes/pkg/kubectl/util/printers" "k8s.io/kubernetes/pkg/kubectl/util/templates" - "k8s.io/kubernetes/pkg/util/interrupt" ) // GetOptions contains the input to the get command. diff --git a/pkg/kubectl/cmd/rollout/BUILD b/pkg/kubectl/cmd/rollout/BUILD index 9d56043dfb..8f73ec1b96 100644 --- a/pkg/kubectl/cmd/rollout/BUILD +++ b/pkg/kubectl/cmd/rollout/BUILD @@ -25,8 +25,8 @@ go_library( "//pkg/kubectl/polymorphichelpers:go_default_library", "//pkg/kubectl/scheme:go_default_library", "//pkg/kubectl/util/i18n:go_default_library", + "//pkg/kubectl/util/interrupt:go_default_library", "//pkg/kubectl/util/templates:go_default_library", - "//pkg/util/interrupt:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", diff --git a/pkg/kubectl/cmd/rollout/rollout_status.go b/pkg/kubectl/cmd/rollout/rollout_status.go index 5e520e4d4e..3c42f7cbfd 100644 --- a/pkg/kubectl/cmd/rollout/rollout_status.go +++ b/pkg/kubectl/cmd/rollout/rollout_status.go @@ -40,8 +40,8 @@ import ( "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" + "k8s.io/kubernetes/pkg/kubectl/util/interrupt" "k8s.io/kubernetes/pkg/kubectl/util/templates" - "k8s.io/kubernetes/pkg/util/interrupt" ) var ( diff --git a/pkg/kubectl/cmd/run/BUILD b/pkg/kubectl/cmd/run/BUILD index 1fb98519b9..8bc0a365e8 100644 --- a/pkg/kubectl/cmd/run/BUILD +++ b/pkg/kubectl/cmd/run/BUILD @@ -17,8 +17,8 @@ go_library( "//pkg/kubectl/polymorphichelpers:go_default_library", "//pkg/kubectl/scheme:go_default_library", "//pkg/kubectl/util/i18n:go_default_library", + "//pkg/kubectl/util/interrupt:go_default_library", "//pkg/kubectl/util/templates:go_default_library", - "//pkg/util/interrupt:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", diff --git a/pkg/kubectl/cmd/run/run.go b/pkg/kubectl/cmd/run/run.go index c89457b4cd..5a544f31b2 100644 --- a/pkg/kubectl/cmd/run/run.go +++ b/pkg/kubectl/cmd/run/run.go @@ -51,8 +51,8 @@ import ( "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" + "k8s.io/kubernetes/pkg/kubectl/util/interrupt" "k8s.io/kubernetes/pkg/kubectl/util/templates" - "k8s.io/kubernetes/pkg/util/interrupt" uexec "k8s.io/utils/exec" ) diff --git a/pkg/kubectl/util/BUILD b/pkg/kubectl/util/BUILD index fc010ff599..48d783ade6 100644 --- a/pkg/kubectl/util/BUILD +++ b/pkg/kubectl/util/BUILD @@ -72,6 +72,7 @@ filegroup( "//pkg/kubectl/util/fieldpath:all-srcs", "//pkg/kubectl/util/hash:all-srcs", "//pkg/kubectl/util/i18n:all-srcs", + "//pkg/kubectl/util/interrupt:all-srcs", "//pkg/kubectl/util/logs:all-srcs", "//pkg/kubectl/util/podutils:all-srcs", "//pkg/kubectl/util/printers:all-srcs", diff --git a/pkg/kubectl/util/interrupt/BUILD b/pkg/kubectl/util/interrupt/BUILD new file mode 100644 index 0000000000..8d2d54edb8 --- /dev/null +++ b/pkg/kubectl/util/interrupt/BUILD @@ -0,0 +1,22 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["interrupt.go"], + importpath = "k8s.io/kubernetes/pkg/kubectl/util/interrupt", + visibility = ["//visibility:public"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/pkg/kubectl/util/interrupt/interrupt.go b/pkg/kubectl/util/interrupt/interrupt.go new file mode 100644 index 0000000000..0265b9fb17 --- /dev/null +++ b/pkg/kubectl/util/interrupt/interrupt.go @@ -0,0 +1,104 @@ +/* +Copyright 2016 The Kubernetes 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 interrupt + +import ( + "os" + "os/signal" + "sync" + "syscall" +) + +// terminationSignals are signals that cause the program to exit in the +// supported platforms (linux, darwin, windows). +var terminationSignals = []os.Signal{syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT} + +// Handler guarantees execution of notifications after a critical section (the function passed +// to a Run method), even in the presence of process termination. It guarantees exactly once +// invocation of the provided notify functions. +type Handler struct { + notify []func() + final func(os.Signal) + once sync.Once +} + +// Chain creates a new handler that invokes all notify functions when the critical section exits +// and then invokes the optional handler's notifications. This allows critical sections to be +// nested without losing exactly once invocations. Notify functions can invoke any cleanup needed +// but should not exit (which is the responsibility of the parent handler). +func Chain(handler *Handler, notify ...func()) *Handler { + if handler == nil { + return New(nil, notify...) + } + return New(handler.Signal, append(notify, handler.Close)...) +} + +// New creates a new handler that guarantees all notify functions are run after the critical +// section exits (or is interrupted by the OS), then invokes the final handler. If no final +// handler is specified, the default final is `os.Exit(1)`. A handler can only be used for +// one critical section. +func New(final func(os.Signal), notify ...func()) *Handler { + return &Handler{ + final: final, + notify: notify, + } +} + +// Close executes all the notification handlers if they have not yet been executed. +func (h *Handler) Close() { + h.once.Do(func() { + for _, fn := range h.notify { + fn() + } + }) +} + +// Signal is called when an os.Signal is received, and guarantees that all notifications +// are executed, then the final handler is executed. This function should only be called once +// per Handler instance. +func (h *Handler) Signal(s os.Signal) { + h.once.Do(func() { + for _, fn := range h.notify { + fn() + } + if h.final == nil { + os.Exit(1) + } + h.final(s) + }) +} + +// Run ensures that any notifications are invoked after the provided fn exits (even if the +// process is interrupted by an OS termination signal). Notifications are only invoked once +// per Handler instance, so calling Run more than once will not behave as the user expects. +func (h *Handler) Run(fn func() error) error { + ch := make(chan os.Signal, 1) + signal.Notify(ch, terminationSignals...) + defer func() { + signal.Stop(ch) + close(ch) + }() + go func() { + sig, ok := <-ch + if !ok { + return + } + h.Signal(sig) + }() + defer h.Close() + return fn() +} diff --git a/pkg/kubectl/util/term/BUILD b/pkg/kubectl/util/term/BUILD index 18fbe9fc43..204c47f3c9 100644 --- a/pkg/kubectl/util/term/BUILD +++ b/pkg/kubectl/util/term/BUILD @@ -17,7 +17,7 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/kubectl/util/term", deps = [ - "//pkg/util/interrupt:go_default_library", + "//pkg/kubectl/util/interrupt:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/client-go/tools/remotecommand:go_default_library", "//vendor/github.com/docker/docker/pkg/term:go_default_library", diff --git a/pkg/kubectl/util/term/term.go b/pkg/kubectl/util/term/term.go index 58baee8310..d1e32dac6f 100644 --- a/pkg/kubectl/util/term/term.go +++ b/pkg/kubectl/util/term/term.go @@ -22,7 +22,7 @@ import ( "github.com/docker/docker/pkg/term" - "k8s.io/kubernetes/pkg/util/interrupt" + "k8s.io/kubernetes/pkg/kubectl/util/interrupt" ) // SafeFunc is a function to be invoked by TTY.