| Tim Windelschmidt | 6d33a43 | 2025-02-04 14:34:25 +0100 | [diff] [blame^] | 1 | // Copyright The Monogon Project Authors. |
| 2 | // SPDX-License-Identifier: Apache-2.0 |
| 3 | |
| Serge Bazanski | 7d1a0de | 2023-07-05 01:17:15 +0200 | [diff] [blame] | 4 | package main |
| 5 | |
| 6 | import ( |
| Serge Bazanski | 568c38c | 2024-02-05 14:40:39 +0100 | [diff] [blame] | 7 | "context" |
| Tim Windelschmidt | 0b4fb8c | 2024-09-18 17:34:23 +0200 | [diff] [blame] | 8 | "fmt" |
| Serge Bazanski | 7d1a0de | 2023-07-05 01:17:15 +0200 | [diff] [blame] | 9 | "log" |
| 10 | "os" |
| 11 | "os/exec" |
| Tim Windelschmidt | b765f24 | 2024-05-08 01:40:02 +0200 | [diff] [blame] | 12 | "os/signal" |
| Serge Bazanski | 7d1a0de | 2023-07-05 01:17:15 +0200 | [diff] [blame] | 13 | |
| 14 | "github.com/spf13/cobra" |
| 15 | |
| 16 | "source.monogon.dev/metropolis/cli/metroctl/core" |
| 17 | ) |
| 18 | |
| 19 | var k8sCommand = &cobra.Command{ |
| 20 | Short: "Manages kubernetes-specific functionality in Metropolis.", |
| 21 | Use: "k8s", |
| 22 | } |
| 23 | |
| 24 | var k8sConfigureCommand = &cobra.Command{ |
| 25 | Use: "configure", |
| 26 | Short: "Configures local `kubectl` for use with a Metropolis cluster.", |
| 27 | Long: `Configures a local kubectl instance (or any other Kubernetes application) |
| 28 | to connect to a Metropolis cluster. A cluster endpoint must be provided with the |
| 29 | --endpoints parameter.`, |
| Tim Windelschmidt | fc6e1cf | 2024-09-18 17:34:07 +0200 | [diff] [blame] | 30 | Args: PrintUsageOnWrongArgs(cobra.ExactArgs(0)), |
| Tim Windelschmidt | 0b4fb8c | 2024-09-18 17:34:23 +0200 | [diff] [blame] | 31 | RunE: func(cmd *cobra.Command, _ []string) error { |
| 32 | ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt) |
| 33 | if len(flags.clusterEndpoints) < 1 { |
| 34 | return fmt.Errorf("k8s configure requires at least one cluster endpoint to be provided with the --endpoints parameter") |
| Serge Bazanski | 7d1a0de | 2023-07-05 01:17:15 +0200 | [diff] [blame] | 35 | } |
| Tim Windelschmidt | 0b4fb8c | 2024-09-18 17:34:23 +0200 | [diff] [blame] | 36 | |
| 37 | contextName, err := cmd.Flags().GetString("context") |
| 38 | if err != nil || contextName == "" { |
| 39 | return fmt.Errorf("k8s configure requires a valid context name to be provided with the --context parameter") |
| 40 | } |
| 41 | |
| 42 | // If the user has metroctl in their path, use the metroctl from path as |
| 43 | // a credential plugin. Otherwise use the path to the currently-running |
| 44 | // metroctl. |
| 45 | metroctlPath := "metroctl" |
| 46 | if _, err := exec.LookPath("metroctl"); err != nil { |
| 47 | metroctlPath, err = os.Executable() |
| 48 | if err != nil { |
| 49 | return fmt.Errorf("failed to create kubectl entry as metroctl is neither in PATH nor can its absolute path be determined: %w", err) |
| 50 | } |
| 51 | } |
| 52 | // TODO(q3k, issues/144): this only works as long as all nodes are kubernetes controller |
| 53 | // nodes. This won't be the case for too long. Figure this out. |
| 54 | if err := core.InstallKubeletConfig(ctx, metroctlPath, connectOptions(), contextName, flags.clusterEndpoints[0]); err != nil { |
| 55 | return fmt.Errorf("failed to install metroctl/k8s integration: %w", err) |
| 56 | } |
| 57 | log.Printf("Success! kubeconfig is set up. You can now run kubectl --context=%s ... to access the Kubernetes cluster.", contextName) |
| 58 | return nil |
| 59 | }, |
| Serge Bazanski | 7d1a0de | 2023-07-05 01:17:15 +0200 | [diff] [blame] | 60 | } |
| 61 | |
| 62 | func init() { |
| Tim Windelschmidt | 2f84237 | 2024-05-07 00:07:11 +0200 | [diff] [blame] | 63 | k8sConfigureCommand.Flags().String("context", "metroctl", "The name for the kubernetes context to configure") |
| Serge Bazanski | 7d1a0de | 2023-07-05 01:17:15 +0200 | [diff] [blame] | 64 | k8sCommand.AddCommand(k8sConfigureCommand) |
| Serge Bazanski | 7d1a0de | 2023-07-05 01:17:15 +0200 | [diff] [blame] | 65 | rootCmd.AddCommand(k8sCommand) |
| 66 | } |