blob: 65093182f7cfa2d64b4d7e5bd56d476d3efc3416 [file] [log] [blame]
Tim Windelschmidt6d33a432025-02-04 14:34:25 +01001// Copyright The Monogon Project Authors.
2// SPDX-License-Identifier: Apache-2.0
3
Serge Bazanski7d1a0de2023-07-05 01:17:15 +02004package main
5
6import (
Serge Bazanski568c38c2024-02-05 14:40:39 +01007 "context"
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +02008 "fmt"
Serge Bazanski7d1a0de2023-07-05 01:17:15 +02009 "log"
10 "os"
11 "os/exec"
Tim Windelschmidtb765f242024-05-08 01:40:02 +020012 "os/signal"
Serge Bazanski7d1a0de2023-07-05 01:17:15 +020013
14 "github.com/spf13/cobra"
15
16 "source.monogon.dev/metropolis/cli/metroctl/core"
17)
18
19var k8sCommand = &cobra.Command{
20 Short: "Manages kubernetes-specific functionality in Metropolis.",
21 Use: "k8s",
22}
23
24var 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)
28to connect to a Metropolis cluster. A cluster endpoint must be provided with the
29--endpoints parameter.`,
Tim Windelschmidtfc6e1cf2024-09-18 17:34:07 +020030 Args: PrintUsageOnWrongArgs(cobra.ExactArgs(0)),
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020031 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 Bazanski7d1a0de2023-07-05 01:17:15 +020035 }
Tim Windelschmidt0b4fb8c2024-09-18 17:34:23 +020036
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 Bazanski7d1a0de2023-07-05 01:17:15 +020060}
61
62func init() {
Tim Windelschmidt2f842372024-05-07 00:07:11 +020063 k8sConfigureCommand.Flags().String("context", "metroctl", "The name for the kubernetes context to configure")
Serge Bazanski7d1a0de2023-07-05 01:17:15 +020064 k8sCommand.AddCommand(k8sConfigureCommand)
Serge Bazanski7d1a0de2023-07-05 01:17:15 +020065 rootCmd.AddCommand(k8sCommand)
66}