env.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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. envCmd.AddCommand(pullCommand)
  44. return envCmd
  45. }
  46. func pullEnv(ctx context.Context, user *types.GetAuthenticatedUserResponse, client api.Client, cliConf config.CLIConfig, featureFlags config.FeatureFlags, cmd *cobra.Command, args []string) error {
  47. if appName == "" && envGroupName == "" {
  48. return fmt.Errorf("must specify either --app or --group")
  49. }
  50. if appName != "" && envGroupName != "" {
  51. return fmt.Errorf("only one of --app or --group can be specified")
  52. }
  53. var envVars envVariables
  54. if appName != "" {
  55. color.New(color.FgGreen).Printf("Pulling environment variables for app %s...\n", appName) // nolint:errcheck,gosec
  56. envVarsResp, err := client.GetAppEnvVariables(ctx, cliConf.Project, cliConf.Cluster, appName)
  57. if err != nil {
  58. return fmt.Errorf("could not get app env variables: %w", err)
  59. }
  60. if envVarsResp == nil {
  61. return fmt.Errorf("could not get app env variables: response was nil")
  62. }
  63. envVars = envVariables{
  64. Variables: envVarsResp.EnvVariables.Variables,
  65. Secrets: envVarsResp.EnvVariables.Secrets,
  66. }
  67. }
  68. if envGroupName != "" {
  69. color.New(color.FgGreen).Printf("Pulling environment variables for environment group %s...\n", envGroupName) // nolint:errcheck,gosec
  70. envVarsResp, err := client.GetLatestEnvGroupVariables(ctx, cliConf.Project, cliConf.Cluster, envGroupName)
  71. if err != nil {
  72. return fmt.Errorf("could not get env group env variables: %w", err)
  73. }
  74. if envVarsResp == nil {
  75. return fmt.Errorf("could not get env group variables: response was nil")
  76. }
  77. envVars = envVariables{
  78. Variables: envVarsResp.Variables,
  79. Secrets: envVarsResp.Secrets,
  80. }
  81. }
  82. if envFilePath != "" {
  83. err := writeEnvFile(envFilePath, envVars)
  84. if err != nil {
  85. return fmt.Errorf("could not write env file: %w", err)
  86. }
  87. color.New(color.FgGreen).Printf("Wrote environment variables to %s\n", envFilePath) // nolint:errcheck,gosec
  88. }
  89. if envFilePath == "" {
  90. err := exportEnvVars(envVars)
  91. if err != nil {
  92. return fmt.Errorf("could not export env vars: %w", err)
  93. }
  94. }
  95. return nil
  96. }
  97. func writeEnvFile(envFilePath string, envVars envVariables) error {
  98. // open existing file or create new file: https://pkg.go.dev/os#example-OpenFile-Append
  99. envFile, err := os.OpenFile(envFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) // nolint:gosec
  100. if err != nil {
  101. return err
  102. }
  103. defer envFile.Close() // nolint:errcheck
  104. _, err = envFile.WriteString("# Generated by Porter CLI\n")
  105. if err != nil {
  106. return err
  107. }
  108. for k, v := range envVars.Variables {
  109. _, err := envFile.WriteString(fmt.Sprintf("%s=%s\n", k, v))
  110. if err != nil {
  111. return err
  112. }
  113. }
  114. for k, v := range envVars.Secrets {
  115. _, err := envFile.WriteString(fmt.Sprintf("%s=%s\n", k, v))
  116. if err != nil {
  117. return err
  118. }
  119. }
  120. return nil
  121. }
  122. func exportEnvVars(envVars envVariables) error {
  123. for k, v := range envVars.Variables {
  124. _, err := os.Stdout.WriteString(fmt.Sprintf("%s=%s\n", k, v))
  125. if err != nil {
  126. return err
  127. }
  128. }
  129. for k, v := range envVars.Secrets {
  130. _, err := os.Stdout.WriteString(fmt.Sprintf("%s=%s\n", k, v))
  131. if err != nil {
  132. return err
  133. }
  134. }
  135. return nil
  136. }