metropolis/cli/pkg/context: replace with signal.NotifyContext

Change-Id: I457ccb83c7e25988755bb9463a8c83fc328a722b
Reviewed-on: https://review.monogon.dev/c/monogon/+/3081
Tested-by: Jenkins CI
Reviewed-by: Serge Bazanski <serge@monogon.tech>
diff --git a/cloud/bmaas/scruffy/cmd/BUILD.bazel b/cloud/bmaas/scruffy/cmd/BUILD.bazel
index 1a372e7..1d919b4 100644
--- a/cloud/bmaas/scruffy/cmd/BUILD.bazel
+++ b/cloud/bmaas/scruffy/cmd/BUILD.bazel
@@ -5,10 +5,7 @@
     srcs = ["main.go"],
     importpath = "source.monogon.dev/cloud/bmaas/scruffy/cmd",
     visibility = ["//visibility:private"],
-    deps = [
-        "//cloud/bmaas/scruffy",
-        "//metropolis/cli/pkg/context",
-    ],
+    deps = ["//cloud/bmaas/scruffy"],
 )
 
 go_binary(
diff --git a/cloud/bmaas/scruffy/cmd/main.go b/cloud/bmaas/scruffy/cmd/main.go
index e838834..b675fda 100644
--- a/cloud/bmaas/scruffy/cmd/main.go
+++ b/cloud/bmaas/scruffy/cmd/main.go
@@ -3,9 +3,10 @@
 import (
 	"context"
 	"flag"
+	"os"
+	"os/signal"
 
 	"source.monogon.dev/cloud/bmaas/scruffy"
-	clicontext "source.monogon.dev/metropolis/cli/pkg/context"
 )
 
 func main() {
@@ -13,7 +14,7 @@
 	s.Config.RegisterFlags()
 	flag.Parse()
 
-	ctx := clicontext.WithInterrupt(context.Background())
+	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 	s.Start(ctx)
 	<-ctx.Done()
 }
diff --git a/cloud/bmaas/server/cmd/BUILD.bazel b/cloud/bmaas/server/cmd/BUILD.bazel
index 958f2c4..9f3ce58 100644
--- a/cloud/bmaas/server/cmd/BUILD.bazel
+++ b/cloud/bmaas/server/cmd/BUILD.bazel
@@ -8,7 +8,6 @@
     visibility = ["//visibility:private"],
     deps = [
         "//cloud/bmaas/server",
-        "//metropolis/cli/pkg/context",
         "@io_k8s_klog_v2//:klog",
     ],
 )
diff --git a/cloud/bmaas/server/cmd/main.go b/cloud/bmaas/server/cmd/main.go
index dd99205..8dbb7f8 100644
--- a/cloud/bmaas/server/cmd/main.go
+++ b/cloud/bmaas/server/cmd/main.go
@@ -3,11 +3,12 @@
 import (
 	"context"
 	"flag"
+	"os"
+	"os/signal"
 
 	"k8s.io/klog/v2"
 
 	"source.monogon.dev/cloud/bmaas/server"
-	clicontext "source.monogon.dev/metropolis/cli/pkg/context"
 )
 
 func main() {
@@ -18,7 +19,7 @@
 		klog.Exitf("unexpected positional arguments: %v", flag.Args())
 	}
 
-	ctx := clicontext.WithInterrupt(context.Background())
+	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 	s.Start(ctx)
 	select {}
 }
diff --git a/cloud/equinix/cli/BUILD.bazel b/cloud/equinix/cli/BUILD.bazel
index da94d95..d10fdeb 100644
--- a/cloud/equinix/cli/BUILD.bazel
+++ b/cloud/equinix/cli/BUILD.bazel
@@ -13,7 +13,6 @@
     visibility = ["//visibility:private"],
     deps = [
         "//cloud/equinix/wrapngo",
-        "//metropolis/cli/pkg/context",
         "@com_github_packethost_packngo//:packngo",
         "@com_github_spf13_cobra//:cobra",
         "@io_k8s_klog_v2//:klog",
diff --git a/cloud/equinix/cli/cmd_delete.go b/cloud/equinix/cli/cmd_delete.go
index 056956e..97eb26f 100644
--- a/cloud/equinix/cli/cmd_delete.go
+++ b/cloud/equinix/cli/cmd_delete.go
@@ -2,6 +2,8 @@
 
 import (
 	"context"
+	"os"
+	"os/signal"
 	"time"
 
 	"github.com/packethost/packngo"
@@ -9,7 +11,6 @@
 	"k8s.io/klog/v2"
 
 	"source.monogon.dev/cloud/equinix/wrapngo"
-	clicontext "source.monogon.dev/metropolis/cli/pkg/context"
 )
 
 var deleteCmd = &cobra.Command{
@@ -24,7 +25,7 @@
 }
 
 func doDelete(cmd *cobra.Command, args []string) {
-	ctx := clicontext.WithInterrupt(context.Background())
+	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 	api := wrapngo.New(&c)
 
 	klog.Infof("Listing devices for %q", args[0])
diff --git a/cloud/equinix/cli/cmd_move.go b/cloud/equinix/cli/cmd_move.go
index 770e480..ec32071 100644
--- a/cloud/equinix/cli/cmd_move.go
+++ b/cloud/equinix/cli/cmd_move.go
@@ -2,12 +2,13 @@
 
 import (
 	"context"
+	"os"
+	"os/signal"
 
 	"github.com/spf13/cobra"
 	"k8s.io/klog/v2"
 
 	"source.monogon.dev/cloud/equinix/wrapngo"
-	clicontext "source.monogon.dev/metropolis/cli/pkg/context"
 )
 
 var moveCmd = &cobra.Command{
@@ -22,7 +23,7 @@
 }
 
 func doMove(cmd *cobra.Command, args []string) {
-	ctx := clicontext.WithInterrupt(context.Background())
+	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 	api := wrapngo.New(&c)
 
 	klog.Infof("Listing reservations for %q", args[0])
diff --git a/cloud/equinix/cli/cmd_reboot.go b/cloud/equinix/cli/cmd_reboot.go
index 7fcd35c..e788f01 100644
--- a/cloud/equinix/cli/cmd_reboot.go
+++ b/cloud/equinix/cli/cmd_reboot.go
@@ -2,12 +2,13 @@
 
 import (
 	"context"
+	"os"
+	"os/signal"
 
 	"github.com/spf13/cobra"
 	"k8s.io/klog/v2"
 
 	"source.monogon.dev/cloud/equinix/wrapngo"
-	clicontext "source.monogon.dev/metropolis/cli/pkg/context"
 )
 
 var rebootCmd = &cobra.Command{
@@ -22,7 +23,7 @@
 }
 
 func doReboot(cmd *cobra.Command, args []string) {
-	ctx := clicontext.WithInterrupt(context.Background())
+	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 	api := wrapngo.New(&c)
 
 	klog.Infof("Requesting device list...")
diff --git a/cloud/equinix/cli/cmd_yoink.go b/cloud/equinix/cli/cmd_yoink.go
index bda9e82..c351d47 100644
--- a/cloud/equinix/cli/cmd_yoink.go
+++ b/cloud/equinix/cli/cmd_yoink.go
@@ -4,6 +4,7 @@
 	"bufio"
 	"context"
 	"os"
+	"os/signal"
 	"sort"
 	"strconv"
 	"strings"
@@ -13,7 +14,6 @@
 	"k8s.io/klog/v2"
 
 	"source.monogon.dev/cloud/equinix/wrapngo"
-	clicontext "source.monogon.dev/metropolis/cli/pkg/context"
 )
 
 var yoinkCmd = &cobra.Command{
@@ -73,7 +73,7 @@
 		klog.Exitf("missing metro flag")
 	}
 
-	ctx := clicontext.WithInterrupt(context.Background())
+	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 	api := wrapngo.New(&c)
 
 	klog.Infof("Listing reservations for %q", srcProject)
diff --git a/cloud/shepherd/mini/BUILD.bazel b/cloud/shepherd/mini/BUILD.bazel
index 5fad3c2..f8a5e72 100644
--- a/cloud/shepherd/mini/BUILD.bazel
+++ b/cloud/shepherd/mini/BUILD.bazel
@@ -17,7 +17,6 @@
         "//cloud/shepherd",
         "//cloud/shepherd/manager",
         "//go/net/ssh",
-        "//metropolis/cli/pkg/context",
         "@io_k8s_klog_v2//:klog",
         "@org_golang_x_crypto//ssh",
     ],
diff --git a/cloud/shepherd/mini/main.go b/cloud/shepherd/mini/main.go
index b35c09e..0d7b11f 100644
--- a/cloud/shepherd/mini/main.go
+++ b/cloud/shepherd/mini/main.go
@@ -10,6 +10,7 @@
 	"net/http"
 	"net/url"
 	"os"
+	"os/signal"
 	"strings"
 
 	"k8s.io/klog/v2"
@@ -20,7 +21,6 @@
 	"source.monogon.dev/cloud/lib/component"
 	"source.monogon.dev/cloud/shepherd"
 	"source.monogon.dev/cloud/shepherd/manager"
-	clicontext "source.monogon.dev/metropolis/cli/pkg/context"
 )
 
 type Config struct {
@@ -133,7 +133,7 @@
 	registry := c.Component.PrometheusRegistry()
 	c.BMDB.EnableMetrics(registry)
 
-	ctx := clicontext.WithInterrupt(context.Background())
+	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 	c.Component.StartPrometheus(ctx)
 
 	conn, err := c.BMDB.Open(true)
diff --git a/cloud/shepherd/provider/equinix/BUILD.bazel b/cloud/shepherd/provider/equinix/BUILD.bazel
index 4214f16..ef1ab53 100644
--- a/cloud/shepherd/provider/equinix/BUILD.bazel
+++ b/cloud/shepherd/provider/equinix/BUILD.bazel
@@ -21,7 +21,6 @@
         "//cloud/shepherd",
         "//cloud/shepherd/manager",
         "//go/net/ssh",
-        "//metropolis/cli/pkg/context",
         "@com_github_packethost_packngo//:packngo",
         "@io_k8s_klog_v2//:klog",
         "@org_golang_x_crypto//ssh",
diff --git a/cloud/shepherd/provider/equinix/main.go b/cloud/shepherd/provider/equinix/main.go
index 7faee9d..0fb28e1 100644
--- a/cloud/shepherd/provider/equinix/main.go
+++ b/cloud/shepherd/provider/equinix/main.go
@@ -6,6 +6,7 @@
 	"flag"
 	"fmt"
 	"os"
+	"os/signal"
 
 	"golang.org/x/crypto/ssh"
 	"k8s.io/klog/v2"
@@ -16,7 +17,6 @@
 	"source.monogon.dev/cloud/lib/component"
 	"source.monogon.dev/cloud/shepherd/manager"
 	ssh2 "source.monogon.dev/go/net/ssh"
-	clicontext "source.monogon.dev/metropolis/cli/pkg/context"
 )
 
 type Config struct {
@@ -72,7 +72,7 @@
 	registry := c.Component.PrometheusRegistry()
 	c.BMDB.EnableMetrics(registry)
 
-	ctx := clicontext.WithInterrupt(context.Background())
+	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 	c.Component.StartPrometheus(ctx)
 
 	if c.API.APIKey == "" || c.API.User == "" {
diff --git a/metropolis/cli/metroctl/BUILD.bazel b/metropolis/cli/metroctl/BUILD.bazel
index a84ae03..9eb0aa4 100644
--- a/metropolis/cli/metroctl/BUILD.bazel
+++ b/metropolis/cli/metroctl/BUILD.bazel
@@ -43,7 +43,6 @@
     deps = [
         "//go/clitable",
         "//metropolis/cli/metroctl/core",
-        "//metropolis/cli/pkg/context",
         "//metropolis/node/core/identity",
         "//metropolis/node/core/rpc",
         "//metropolis/node/core/rpc/resolver",
diff --git a/metropolis/cli/metroctl/cmd_install.go b/metropolis/cli/metroctl/cmd_install.go
index fdc51b0..fc463b4 100644
--- a/metropolis/cli/metroctl/cmd_install.go
+++ b/metropolis/cli/metroctl/cmd_install.go
@@ -7,6 +7,7 @@
 	_ "embed"
 	"log"
 	"os"
+	"os/signal"
 	"strings"
 
 	"github.com/bazelbuild/rules_go/go/runfiles"
@@ -16,7 +17,6 @@
 	cpb "source.monogon.dev/metropolis/proto/common"
 
 	"source.monogon.dev/metropolis/cli/metroctl/core"
-	clicontext "source.monogon.dev/metropolis/cli/pkg/context"
 	"source.monogon.dev/metropolis/pkg/blkio"
 	"source.monogon.dev/metropolis/pkg/fat32"
 )
@@ -63,7 +63,7 @@
 		log.Fatalf("Invalid --bootstrap-storage-security (must be one of: permissive, needs-encryption, needs-encryption-and-authentication, needs-insecure)")
 	}
 
-	ctx := clicontext.WithInterrupt(context.Background())
+	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 
 	if err := os.MkdirAll(flags.configPath, 0700); err != nil && !os.IsExist(err) {
 		log.Fatalf("Failed to create config directory: %v", err)
diff --git a/metropolis/cli/metroctl/cmd_k8s_configure.go b/metropolis/cli/metroctl/cmd_k8s_configure.go
index 7e8d771..c238cdf 100644
--- a/metropolis/cli/metroctl/cmd_k8s_configure.go
+++ b/metropolis/cli/metroctl/cmd_k8s_configure.go
@@ -5,11 +5,11 @@
 	"log"
 	"os"
 	"os/exec"
+	"os/signal"
 
 	"github.com/spf13/cobra"
 
 	"source.monogon.dev/metropolis/cli/metroctl/core"
-	clicontext "source.monogon.dev/metropolis/cli/pkg/context"
 )
 
 var k8sCommand = &cobra.Command{
@@ -28,7 +28,7 @@
 }
 
 func doK8sConfigure(cmd *cobra.Command, _ []string) {
-	ctx := clicontext.WithInterrupt(context.Background())
+	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 	if len(flags.clusterEndpoints) < 1 {
 		log.Fatalf("k8s configure requires at least one cluster endpoint to be provided with the --endpoints parameter.")
 	}
diff --git a/metropolis/cli/metroctl/cmd_node.go b/metropolis/cli/metroctl/cmd_node.go
index ebfaa25..19440b6 100644
--- a/metropolis/cli/metroctl/cmd_node.go
+++ b/metropolis/cli/metroctl/cmd_node.go
@@ -7,6 +7,7 @@
 	"io"
 	"log"
 	"os"
+	"os/signal"
 	"strings"
 	"sync"
 	"time"
@@ -16,7 +17,6 @@
 
 	"source.monogon.dev/go/clitable"
 	"source.monogon.dev/metropolis/cli/metroctl/core"
-	clicontext "source.monogon.dev/metropolis/cli/pkg/context"
 	"source.monogon.dev/metropolis/node/core/identity"
 	"source.monogon.dev/version"
 
@@ -33,7 +33,7 @@
 	Use:     "describe [node-id] [--filter] [--output] [--format]",
 	Example: "metroctl node describe metropolis-c556e31c3fa2bf0a36e9ccb9fd5d6056",
 	Run: func(cmd *cobra.Command, args []string) {
-		ctx := clicontext.WithInterrupt(context.Background())
+		ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 		cc := dialAuthenticated(ctx)
 		mgmt := apb.NewManagementClient(cc)
 
@@ -52,7 +52,7 @@
 	Use:     "list [node-id] [--filter] [--output] [--format]",
 	Example: "metroctl node list --filter node.status.external_address==\"10.8.0.2\"",
 	Run: func(cmd *cobra.Command, args []string) {
-		ctx := clicontext.WithInterrupt(context.Background())
+		ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 		cc := dialAuthenticated(ctx)
 		mgmt := apb.NewManagementClient(cc)
 
@@ -106,7 +106,7 @@
 		}
 		unavailableSemaphore := semaphore.NewWeighted(int64(maxUnavailable))
 
-		ctx := clicontext.WithInterrupt(context.Background())
+		ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 
 		cacert, err := core.GetClusterCAWithTOFU(ctx, connectOptions())
 		if err != nil {
@@ -234,7 +234,7 @@
 			return err
 		}
 
-		ctx := clicontext.WithInterrupt(context.Background())
+		ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 		mgmt := apb.NewManagementClient(dialAuthenticated(ctx))
 
 		nodes, err := core.GetNodes(ctx, mgmt, fmt.Sprintf("node.id==%q", args[0]))
diff --git a/metropolis/cli/metroctl/cmd_node_approve.go b/metropolis/cli/metroctl/cmd_node_approve.go
index 41c6f24..62ab7bd 100644
--- a/metropolis/cli/metroctl/cmd_node_approve.go
+++ b/metropolis/cli/metroctl/cmd_node_approve.go
@@ -4,11 +4,12 @@
 	"context"
 	"fmt"
 	"log"
+	"os"
+	"os/signal"
 
 	"github.com/spf13/cobra"
 
 	"source.monogon.dev/metropolis/cli/metroctl/core"
-	clicontext "source.monogon.dev/metropolis/cli/pkg/context"
 	"source.monogon.dev/metropolis/node/core/identity"
 	"source.monogon.dev/metropolis/proto/api"
 )
@@ -35,7 +36,7 @@
 }
 
 func doApprove(cmd *cobra.Command, args []string) {
-	ctx := clicontext.WithInterrupt(context.Background())
+	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 	cc := dialAuthenticated(ctx)
 	mgmt := api.NewManagementClient(cc)
 
diff --git a/metropolis/cli/metroctl/cmd_node_set.go b/metropolis/cli/metroctl/cmd_node_set.go
index b0bfaf5..5d465f5 100644
--- a/metropolis/cli/metroctl/cmd_node_set.go
+++ b/metropolis/cli/metroctl/cmd_node_set.go
@@ -3,11 +3,12 @@
 import (
 	"context"
 	"log"
+	"os"
+	"os/signal"
 	"strings"
 
 	"github.com/spf13/cobra"
 
-	clicontext "source.monogon.dev/metropolis/cli/pkg/context"
 	"source.monogon.dev/metropolis/proto/api"
 )
 
@@ -46,7 +47,7 @@
 }
 
 func doAdd(cmd *cobra.Command, args []string) {
-	ctx := clicontext.WithInterrupt(context.Background())
+	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 	cc := dialAuthenticated(ctx)
 	mgmt := api.NewManagementClient(cc)
 
@@ -84,7 +85,7 @@
 }
 
 func doRemove(cmd *cobra.Command, args []string) {
-	ctx := clicontext.WithInterrupt(context.Background())
+	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 	cc := dialAuthenticated(ctx)
 	mgmt := api.NewManagementClient(cc)
 
diff --git a/metropolis/cli/metroctl/cmd_takeownership.go b/metropolis/cli/metroctl/cmd_takeownership.go
index 5161dc9..30b9f08 100644
--- a/metropolis/cli/metroctl/cmd_takeownership.go
+++ b/metropolis/cli/metroctl/cmd_takeownership.go
@@ -6,12 +6,12 @@
 	"log"
 	"os"
 	"os/exec"
+	"os/signal"
 
 	"github.com/spf13/cobra"
 	"google.golang.org/grpc"
 
 	"source.monogon.dev/metropolis/cli/metroctl/core"
-	clicontext "source.monogon.dev/metropolis/cli/pkg/context"
 	"source.monogon.dev/metropolis/node/core/rpc"
 	"source.monogon.dev/metropolis/node/core/rpc/resolver"
 	apb "source.monogon.dev/metropolis/proto/api"
@@ -29,7 +29,7 @@
 }
 
 func doTakeOwnership(cmd *cobra.Command, _ []string) {
-	ctx := clicontext.WithInterrupt(context.Background())
+	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 	if len(flags.clusterEndpoints) != 1 {
 		log.Fatalf("takeownership requires a single cluster endpoint to be provided with the --endpoints parameter.")
 	}
diff --git a/metropolis/cli/pkg/context/BUILD.bazel b/metropolis/cli/pkg/context/BUILD.bazel
deleted file mode 100644
index 2418a82..0000000
--- a/metropolis/cli/pkg/context/BUILD.bazel
+++ /dev/null
@@ -1,8 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_library")
-
-go_library(
-    name = "context",
-    srcs = ["context.go"],
-    importpath = "source.monogon.dev/metropolis/cli/pkg/context",
-    visibility = ["//visibility:public"],
-)
diff --git a/metropolis/cli/pkg/context/context.go b/metropolis/cli/pkg/context/context.go
deleted file mode 100644
index bad24ea..0000000
--- a/metropolis/cli/pkg/context/context.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package clicontext
-
-import (
-	"context"
-	"os"
-	"os/signal"
-)
-
-// WithInterrupt returns a context for use in a command-line utility. It gets
-// cancelled if the user interrupts the command, for example by pressing
-// Ctrl+C.
-func WithInterrupt(parent context.Context) context.Context {
-	ctx, cancel := context.WithCancel(parent)
-	c := make(chan os.Signal, 1)
-	signal.Notify(c, os.Interrupt)
-	go func() {
-		<-c
-		cancel()
-	}()
-	return ctx
-}
diff --git a/metropolis/test/launch/cli/launch-cluster/BUILD.bazel b/metropolis/test/launch/cli/launch-cluster/BUILD.bazel
index 974258a..2c673c5 100644
--- a/metropolis/test/launch/cli/launch-cluster/BUILD.bazel
+++ b/metropolis/test/launch/cli/launch-cluster/BUILD.bazel
@@ -8,7 +8,6 @@
     visibility = ["//visibility:private"],
     deps = [
         "//metropolis/cli/metroctl/core",
-        "//metropolis/cli/pkg/context",
         "//metropolis/test/launch/cluster",
     ],
 )
diff --git a/metropolis/test/launch/cli/launch-cluster/main.go b/metropolis/test/launch/cli/launch-cluster/main.go
index e5959f3..c9b9dec 100644
--- a/metropolis/test/launch/cli/launch-cluster/main.go
+++ b/metropolis/test/launch/cli/launch-cluster/main.go
@@ -19,14 +19,15 @@
 import (
 	"context"
 	"log"
+	"os"
+	"os/signal"
 
 	metroctl "source.monogon.dev/metropolis/cli/metroctl/core"
-	clicontext "source.monogon.dev/metropolis/cli/pkg/context"
 	"source.monogon.dev/metropolis/test/launch/cluster"
 )
 
 func main() {
-	ctx := clicontext.WithInterrupt(context.Background())
+	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 	cl, err := cluster.LaunchCluster(ctx, cluster.ClusterOptions{
 		NumNodes:        3,
 		NodeLogsToFiles: true,
diff --git a/metropolis/test/launch/cli/launch/BUILD.bazel b/metropolis/test/launch/cli/launch/BUILD.bazel
index 2e58632..cfbf93a 100644
--- a/metropolis/test/launch/cli/launch/BUILD.bazel
+++ b/metropolis/test/launch/cli/launch/BUILD.bazel
@@ -7,7 +7,6 @@
     importpath = "source.monogon.dev/metropolis/test/launch/cli/launch",
     visibility = ["//visibility:private"],
     deps = [
-        "//metropolis/cli/pkg/context",
         "//metropolis/proto/api",
         "//metropolis/test/launch",
         "//metropolis/test/launch/cluster",
diff --git a/metropolis/test/launch/cli/launch/main.go b/metropolis/test/launch/cli/launch/main.go
index ea856a1..53b65f9 100644
--- a/metropolis/test/launch/cli/launch/main.go
+++ b/metropolis/test/launch/cli/launch/main.go
@@ -20,8 +20,8 @@
 	"context"
 	"log"
 	"os"
+	"os/signal"
 
-	clicontext "source.monogon.dev/metropolis/cli/pkg/context"
 	apb "source.monogon.dev/metropolis/proto/api"
 	"source.monogon.dev/metropolis/test/launch"
 	"source.monogon.dev/metropolis/test/launch/cluster"
@@ -47,7 +47,7 @@
 	for _, p := range cluster.NodePorts {
 		ports = append(ports, uint16(p))
 	}
-	ctx := clicontext.WithInterrupt(context.Background())
+	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
 	doneC := make(chan error)
 	err = cluster.LaunchNode(ctx, ld, sd, &cluster.NodeOptions{
 		Name:       "test-node",