From 2f63e4e79d2b1cd4ef7890812c8a477d0ddb2d6f Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Fri, 8 May 2020 12:05:14 +0200 Subject: [PATCH] refactor term interrupts & have RunContext take a conf struct now --- command/build.go | 40 +++++++++------------------------------- command/cli.go | 8 ++++---- command/signal.go | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 35 deletions(-) create mode 100644 command/signal.go diff --git a/command/build.go b/command/build.go index 7a835707f..40130ac52 100644 --- a/command/build.go +++ b/command/build.go @@ -6,12 +6,9 @@ import ( "fmt" "log" "math" - "os" - "os/signal" "strconv" "strings" "sync" - "syscall" "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hclparse" @@ -29,30 +26,15 @@ type BuildCommand struct { } func (c *BuildCommand) Run(args []string) int { - buildCtx, cancelBuildCtx := context.WithCancel(context.Background()) - // Handle interrupts for this build - sigCh := make(chan os.Signal, 1) - signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM) - defer func() { - cancelBuildCtx() - signal.Stop(sigCh) - close(sigCh) - }() - go func() { - select { - case sig := <-sigCh: - if sig == nil { - // context got cancelled and this closed chan probably - // triggered first - return - } - c.Ui.Error(fmt.Sprintf("Cancelling build after receiving %s", sig)) - cancelBuildCtx() - case <-buildCtx.Done(): - } - }() + buildCtx, cleanup := handleTermInterrupt(c.Ui) + defer cleanup() - return c.RunContext(buildCtx, args) + cfg, ret := c.ParseArgs(args) + if ret != 0 { + return ret + } + + return c.RunContext(buildCtx, cfg) } // Config is the command-configuration parsed from the command line. @@ -207,11 +189,7 @@ func (m *Meta) GetConfigFromJSON(path string) (BuildStarter, int) { }, ret } -func (c *BuildCommand) RunContext(buildCtx context.Context, args []string) int { - cfg, ret := c.ParseArgs(args) - if ret != 0 { - return ret - } +func (c *BuildCommand) RunContext(buildCtx context.Context, cfg Config) int { packerStarter, ret := c.GetConfig(cfg.Path) if ret != 0 { diff --git a/command/cli.go b/command/cli.go index 02ec5973f..e1af60a22 100644 --- a/command/cli.go +++ b/command/cli.go @@ -71,7 +71,7 @@ func (ba *BuildArgs) AddFlagSets(flags *flag.FlagSet) { func (ba *BuildArgs) ParseArgvs(args []string) int { flags := flag.NewFlagSet("build", flag.ContinueOnError) - flags.Usage = func() { ba.Ui.Say(ba.Help()) } + // flags.Usage = func() { ba.Ui.Say(ba.Help()) } ba.AddFlagSets(flags) err := flags.Parse(args) if err != nil { @@ -96,7 +96,7 @@ type BuildArgs struct { func (ca *ConsoleArgs) ParseArgvs(args []string) int { flags := flag.NewFlagSet("console", flag.ContinueOnError) - flags.Usage = func() { ca.Ui.Say(ca.Help()) } + // flags.Usage = func() { ca.Ui.Say(ca.Help()) } ca.AddFlagSets(flags) err := flags.Parse(args) if err != nil { @@ -118,7 +118,7 @@ func (fa *FixArgs) AddFlagSets(flags *flag.FlagSet) { func (fa *FixArgs) ParseArgvs(args []string) int { flags := flag.NewFlagSet("fix", flag.ContinueOnError) - flags.Usage = func() { fa.Ui.Say(fa.Help()) } + // flags.Usage = func() { fa.Ui.Say(fa.Help()) } fa.AddFlagSets(flags) err := flags.Parse(args) if err != nil { @@ -143,7 +143,7 @@ func (va *ValidateArgs) AddFlagSets(flags *flag.FlagSet) { func (va *ValidateArgs) ParseArgvs(args []string) int { flags := flag.NewFlagSet("validate", flag.ContinueOnError) - flags.Usage = func() { va.Ui.Say(va.Help()) } + // flags.Usage = func() { va.Ui.Say(va.Help()) } va.AddFlagSets(flags) err := flags.Parse(args) if err != nil { diff --git a/command/signal.go b/command/signal.go new file mode 100644 index 000000000..5fcbacae7 --- /dev/null +++ b/command/signal.go @@ -0,0 +1,37 @@ +package command + +import ( + "context" + "fmt" + "os" + "os/signal" + "syscall" + + "github.com/hashicorp/packer/packer" +) + +func handleTermInterrupt(ui packer.Ui) (context.Context, func()) { + ctx, cancelCtx := context.WithCancel(context.Background()) + // Handle interrupts for this build + sigCh := make(chan os.Signal, 1) + signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM) + cleanup := func() { + cancelCtx() + signal.Stop(sigCh) + close(sigCh) + } + go func() { + select { + case sig := <-sigCh: + if sig == nil { + // context got cancelled and this closed chan probably + // triggered first + return + } + ui.Error(fmt.Sprintf("Cancelling build after receiving %s", sig)) + cancelCtx() + case <-ctx.Done(): + } + }() + return ctx, cleanup +}