kubectl.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package commands
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "os/exec"
  7. "strings"
  8. api "github.com/porter-dev/porter/api/client"
  9. "github.com/porter-dev/porter/api/types"
  10. "github.com/porter-dev/porter/cli/cmd/config"
  11. "github.com/spf13/cobra"
  12. )
  13. func registerCommand_Kubectl(cliConf config.CLIConfig) *cobra.Command {
  14. depMsg := `This command is no longer available. Please consult documentation of the respective cloud provider to get access to the kubeconfig of the cluster.
  15. Note that any change made directly on the kubernetes cluster under the hood can degrade the performance and reliability of the cluster, and Porter will
  16. automatically reconcile any changes that pose a threat to the uptime of the cluster to its original state. Porter is not responsible for the issues that
  17. arise due to the change implemented directly on the Kubernetes cluster via kubectl.`
  18. kubectlCmd := &cobra.Command{
  19. Use: "kubectl",
  20. Short: "Use kubectl to interact with a Porter cluster",
  21. Deprecated: depMsg,
  22. Run: func(cmd *cobra.Command, args []string) {
  23. err := checkLoginAndRunWithConfig(cmd, cliConf, args, runKubectl)
  24. if err != nil {
  25. os.Exit(1)
  26. }
  27. },
  28. }
  29. var printKubeconfig bool
  30. kubectlCmd.Flags().BoolVar(&printKubeconfig, "print-kubeconfig", false, "Print an authenticated kubeconfig to the console with a 15 minute expiry")
  31. return kubectlCmd
  32. }
  33. func runKubectl(ctx context.Context, _ *types.GetAuthenticatedUserResponse, client api.Client, cliConf config.CLIConfig, featureFlags config.FeatureFlags, cmd *cobra.Command, args []string) error {
  34. // this will never error because it just ran
  35. user, _ := client.AuthCheck(ctx)
  36. project, err := client.GetProject(ctx, cliConf.Project)
  37. if err != nil {
  38. return fmt.Errorf("could not retrieve project from Porter API. Please contact support@porter.run: %w", err)
  39. }
  40. if project == nil {
  41. return fmt.Errorf("project [%d] not found", cliConf.Project)
  42. }
  43. if !strings.HasSuffix(user.Email, "@porter.run") && project.ValidateApplyV2 {
  44. return fmt.Errorf("Forbidden")
  45. }
  46. _, err = exec.LookPath("kubectl")
  47. if err != nil {
  48. return fmt.Errorf("error finding kubectl: %w", err)
  49. }
  50. printKubeconfig, err := cmd.Flags().GetBool("print-kubeconfig")
  51. if err != nil {
  52. return fmt.Errorf("error when retrieving print-kubeconfig flag")
  53. }
  54. tmpFile, err := downloadTempKubeconfig(ctx, client, cliConf)
  55. if err != nil {
  56. return err
  57. }
  58. defer func() {
  59. os.Remove(tmpFile)
  60. }()
  61. if printKubeconfig {
  62. kc, err := os.ReadFile(tmpFile) //nolint:gosec
  63. if err != nil {
  64. return fmt.Errorf("erro reading downloaded kubeconfig for printing: %w", err)
  65. }
  66. fmt.Println(string(kc))
  67. return nil
  68. }
  69. err = os.Setenv("KUBECONFIG", tmpFile)
  70. if err != nil {
  71. return fmt.Errorf("unable to set KUBECONFIG env var: %w", err)
  72. }
  73. execCommand := exec.Command("kubectl", args...)
  74. execCommand.Stdin = os.Stdin
  75. execCommand.Stdout = os.Stdout
  76. execCommand.Stderr = os.Stderr
  77. err = execCommand.Run()
  78. if err != nil {
  79. return fmt.Errorf("error running kubectl: %w", err)
  80. }
  81. return nil
  82. }
  83. func downloadTempKubeconfig(ctx context.Context, client api.Client, cliConf config.CLIConfig) (string, error) {
  84. tmpFile, err := os.CreateTemp("", "porter_kubeconfig_*.yaml")
  85. if err != nil {
  86. return "", fmt.Errorf("error creating temp file for kubeconfig: %w", err)
  87. }
  88. defer tmpFile.Close()
  89. resp, err := client.GetKubeconfig(ctx, cliConf.Project, cliConf.Cluster, cliConf.Kubeconfig)
  90. if err != nil {
  91. return "", fmt.Errorf("error fetching kubeconfig for cluster: %w", err)
  92. }
  93. _, err = tmpFile.Write(resp.Kubeconfig)
  94. if err != nil {
  95. return "", fmt.Errorf("error writing kubeconfig to temp file: %w", err)
  96. }
  97. return tmpFile.Name(), nil
  98. }