package commands import ( "context" "fmt" "os" "github.com/fatih/color" api "github.com/porter-dev/porter/api/client" "github.com/porter-dev/porter/api/types" "github.com/porter-dev/porter/cli/cmd/config" "github.com/spf13/cobra" ) var ( appName string envGroupName string envFilePath string ) type envVariables struct { Variables map[string]string `json:"variables"` Secrets map[string]string `json:"secrets"` } func registerCommand_Env(cliConf config.CLIConfig) *cobra.Command { envCmd := &cobra.Command{ Use: "env", Args: cobra.MinimumNArgs(1), Short: "Manage environment variables for a project", RunE: func(cmd *cobra.Command, args []string) error { return cmd.Help() }, } pullCommand := &cobra.Command{ Use: "pull", Short: "Pull environment variables for an app or environment group", Long: `Pull environment variables for an app or environment group. Optionally, specify a file to write the environment variables to. Otherwise the environment variables will be written to stdout.`, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { return checkLoginAndRunWithConfig(cmd, cliConf, args, pullEnv) }, } pullCommand.Flags().StringVarP(&appName, "app", "a", "", "app name") pullCommand.Flags().StringVarP(&envGroupName, "group", "g", "", "environment group name") pullCommand.Flags().StringVarP(&envFilePath, "file", "f", "", "file to write environment variables to") pullCommand.Flags().StringVarP(&deploymentTargetName, "target", "x", "", "the name of the deployment target for the app") envCmd.AddCommand(pullCommand) return envCmd } func pullEnv(ctx context.Context, user *types.GetAuthenticatedUserResponse, client api.Client, cliConf config.CLIConfig, featureFlags config.FeatureFlags, cmd *cobra.Command, args []string) error { if appName == "" && envGroupName == "" { return fmt.Errorf("must specify either --app or --group") } if appName != "" && envGroupName != "" { return fmt.Errorf("only one of --app or --group can be specified") } var envVars envVariables if appName != "" { color.New(color.FgGreen).Printf("Pulling environment variables for app %s...\n", appName) // nolint:errcheck,gosec envVarsResp, err := client.GetAppEnvVariables(ctx, cliConf.Project, cliConf.Cluster, appName, deploymentTargetName) if err != nil { return fmt.Errorf("could not get app env variables: %w", err) } if envVarsResp == nil { return fmt.Errorf("could not get app env variables: response was nil") } envVars = envVariables{ Variables: envVarsResp.EnvVariables.Variables, Secrets: envVarsResp.EnvVariables.Secrets, } } if envGroupName != "" { color.New(color.FgGreen).Printf("Pulling environment variables for environment group %s...\n", envGroupName) // nolint:errcheck,gosec envVarsResp, err := client.GetLatestEnvGroupVariables(ctx, cliConf.Project, cliConf.Cluster, envGroupName) if err != nil { return fmt.Errorf("could not get env group env variables: %w", err) } if envVarsResp == nil { return fmt.Errorf("could not get env group variables: response was nil") } envVars = envVariables{ Variables: envVarsResp.Variables, Secrets: envVarsResp.Secrets, } } if envFilePath != "" { err := writeEnvFile(envFilePath, envVars) if err != nil { return fmt.Errorf("could not write env file: %w", err) } color.New(color.FgGreen).Printf("Wrote environment variables to %s\n", envFilePath) // nolint:errcheck,gosec } if envFilePath == "" { err := exportEnvVars(envVars) if err != nil { return fmt.Errorf("could not export env vars: %w", err) } } return nil } func writeEnvFile(envFilePath string, envVars envVariables) error { // open existing file or create new file: https://pkg.go.dev/os#example-OpenFile-Append envFile, err := os.OpenFile(envFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) // nolint:gosec if err != nil { return err } defer envFile.Close() // nolint:errcheck _, err = envFile.WriteString("# Generated by Porter CLI\n") if err != nil { return err } for k, v := range envVars.Variables { _, err := envFile.WriteString(fmt.Sprintf("%s=%s\n", k, v)) if err != nil { return err } } for k, v := range envVars.Secrets { _, err := envFile.WriteString(fmt.Sprintf("%s=%s\n", k, v)) if err != nil { return err } } return nil } func exportEnvVars(envVars envVariables) error { for k, v := range envVars.Variables { _, err := os.Stdout.WriteString(fmt.Sprintf("%s=%s\n", k, v)) if err != nil { return err } } for k, v := range envVars.Secrets { _, err := os.Stdout.WriteString(fmt.Sprintf("%s=%s\n", k, v)) if err != nil { return err } } return nil }