env.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package commands
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "github.com/fatih/color"
  7. api "github.com/porter-dev/porter/api/client"
  8. "github.com/porter-dev/porter/api/types"
  9. "github.com/porter-dev/porter/cli/cmd/config"
  10. "github.com/spf13/cobra"
  11. )
  12. var (
  13. appName string
  14. envGroupName string
  15. envFilePath string
  16. )
  17. type envVariables struct {
  18. Variables map[string]string `json:"variables"`
  19. Secrets map[string]string `json:"secrets"`
  20. }
  21. func registerCommand_Env(cliConf config.CLIConfig) *cobra.Command {
  22. envCmd := &cobra.Command{
  23. Use: "env",
  24. Args: cobra.MinimumNArgs(1),
  25. Short: "Manage environment variables for a project",
  26. RunE: func(cmd *cobra.Command, args []string) error {
  27. return cmd.Help()
  28. },
  29. }
  30. pullCommand := &cobra.Command{
  31. Use: "pull",
  32. Short: "Pull environment variables for an app or environment group",
  33. Long: `Pull environment variables for an app or environment group.
  34. Optionally, specify a file to write the environment variables to. Otherwise the environment variables will be written to stdout.`,
  35. Args: cobra.NoArgs,
  36. RunE: func(cmd *cobra.Command, args []string) error {
  37. return checkLoginAndRunWithConfig(cmd, cliConf, args, pullEnv)
  38. },
  39. }
  40. pullCommand.Flags().StringVarP(&appName, "app", "a", "", "app name")
  41. pullCommand.Flags().StringVarP(&envGroupName, "group", "g", "", "environment group name")
  42. pullCommand.Flags().StringVarP(&envFilePath, "file", "f", "", "file to write environment variables to")
  43. pullCommand.Flags().StringVarP(&deploymentTargetName, "target", "x", "", "the name of the deployment target for the app")
  44. envCmd.AddCommand(pullCommand)
  45. return envCmd
  46. }
  47. func pullEnv(ctx context.Context, user *types.GetAuthenticatedUserResponse, client api.Client, cliConf config.CLIConfig, featureFlags config.FeatureFlags, cmd *cobra.Command, args []string) error {
  48. if appName == "" && envGroupName == "" {
  49. return fmt.Errorf("must specify either --app or --group")
  50. }
  51. if appName != "" && envGroupName != "" {
  52. return fmt.Errorf("only one of --app or --group can be specified")
  53. }
  54. var envVars envVariables
  55. if appName != "" {
  56. color.New(color.FgGreen).Printf("Pulling environment variables for app %s...\n", appName) // nolint:errcheck,gosec
  57. envVarsResp, err := client.GetAppEnvVariables(ctx, cliConf.Project, cliConf.Cluster, appName, deploymentTargetName)
  58. if err != nil {
  59. return fmt.Errorf("could not get app env variables: %w", err)
  60. }
  61. if envVarsResp == nil {
  62. return fmt.Errorf("could not get app env variables: response was nil")
  63. }
  64. envVars = envVariables{
  65. Variables: envVarsResp.EnvVariables.Variables,
  66. Secrets: envVarsResp.EnvVariables.Secrets,
  67. }
  68. }
  69. if envGroupName != "" {
  70. color.New(color.FgGreen).Printf("Pulling environment variables for environment group %s...\n", envGroupName) // nolint:errcheck,gosec
  71. envVarsResp, err := client.GetLatestEnvGroupVariables(ctx, cliConf.Project, cliConf.Cluster, envGroupName)
  72. if err != nil {
  73. return fmt.Errorf("could not get env group env variables: %w", err)
  74. }
  75. if envVarsResp == nil {
  76. return fmt.Errorf("could not get env group variables: response was nil")
  77. }
  78. envVars = envVariables{
  79. Variables: envVarsResp.Variables,
  80. Secrets: envVarsResp.Secrets,
  81. }
  82. }
  83. if envFilePath != "" {
  84. err := writeEnvFile(envFilePath, envVars)
  85. if err != nil {
  86. return fmt.Errorf("could not write env file: %w", err)
  87. }
  88. color.New(color.FgGreen).Printf("Wrote environment variables to %s\n", envFilePath) // nolint:errcheck,gosec
  89. }
  90. if envFilePath == "" {
  91. err := exportEnvVars(envVars)
  92. if err != nil {
  93. return fmt.Errorf("could not export env vars: %w", err)
  94. }
  95. }
  96. return nil
  97. }
  98. func writeEnvFile(envFilePath string, envVars envVariables) error {
  99. // open existing file or create new file: https://pkg.go.dev/os#example-OpenFile-Append
  100. envFile, err := os.OpenFile(envFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) // nolint:gosec
  101. if err != nil {
  102. return err
  103. }
  104. defer envFile.Close() // nolint:errcheck
  105. _, err = envFile.WriteString("# Generated by Porter CLI\n")
  106. if err != nil {
  107. return err
  108. }
  109. for k, v := range envVars.Variables {
  110. _, err := envFile.WriteString(fmt.Sprintf("%s=%s\n", k, v))
  111. if err != nil {
  112. return err
  113. }
  114. }
  115. for k, v := range envVars.Secrets {
  116. _, err := envFile.WriteString(fmt.Sprintf("%s=%s\n", k, v))
  117. if err != nil {
  118. return err
  119. }
  120. }
  121. return nil
  122. }
  123. func exportEnvVars(envVars envVariables) error {
  124. for k, v := range envVars.Variables {
  125. _, err := os.Stdout.WriteString(fmt.Sprintf("%s=%s\n", k, v))
  126. if err != nil {
  127. return err
  128. }
  129. }
  130. for k, v := range envVars.Secrets {
  131. _, err := os.Stdout.WriteString(fmt.Sprintf("%s=%s\n", k, v))
  132. if err != nil {
  133. return err
  134. }
  135. }
  136. return nil
  137. }