config.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package config
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "k8s.io/client-go/util/homedir"
  8. )
  9. var (
  10. // These values are globals to reduce the size of the refactor.
  11. // These should be passed around
  12. home = homedir.HomeDir()
  13. defaultPorterConfigFileName string = "porter.yaml"
  14. defaultPorterConfigDir string = filepath.Join(home, ".porter")
  15. porterConfigFilePath string = filepath.Clean(filepath.Join(defaultPorterConfigDir, defaultPorterConfigFileName))
  16. // currentProfile is used to set the profile for which any applied setting should be read or set
  17. currentProfile string = "default"
  18. )
  19. // CLIConfig is the set of shared configuration options for the CLI commands.
  20. // This config is used by viper: calling Set() function for any parameter will
  21. // update the corresponding field in the viper config file.
  22. type CLIConfig struct {
  23. // Driver can be either "docker" or "local", and represents which driver is
  24. // used to run an instance of the server.
  25. Driver string `yaml:"driver" env:"PORTER_DRIVER"`
  26. Host string `yaml:"host" env:"PORTER_HOST"`
  27. Project uint `yaml:"project" env:"PORTER_PROJECT"`
  28. Cluster uint `yaml:"cluster" env:"PORTER_CLUSTER"`
  29. Token string `yaml:"token" env:"PORTER_TOKEN"`
  30. Registry uint `yaml:"registry" env:"PORTER_REGISTRY"`
  31. HelmRepo uint `yaml:"helm_repo" env:"PORTER_HELM_REPO"`
  32. Kubeconfig string `yaml:"kubeconfig" env:"PORTER_KUBECONFIG"`
  33. }
  34. // FeatureFlags are any flags that are relevant to the feature set of the CLI. This should not include all feature flags, only those relevant to client-side CLI operations
  35. type FeatureFlags struct {
  36. // ValidateApplyV2Enabled is a project-wide flag for checking if `porter apply` with porter.yaml is enabled
  37. ValidateApplyV2Enabled bool
  38. }
  39. // InitAndLoadConfig populates the config object with the following precedence rules:
  40. // 1. flag
  41. // 2. env
  42. // 3. config
  43. // 4. default
  44. // If flagsConfig and envConfig are empty, then the default values or config file values will be preferred.
  45. // This returns the config which should be applied to all subsequent requests, as well as the current profile that the command was run with
  46. func InitAndLoadConfig(ctx context.Context, flagsProfile string, flagsConfig CLIConfig) (CLIConfig, string, error) {
  47. var config CLIConfig
  48. currentProfile := defaultProfileName
  49. err := ensurePorterConfigDirectoryExists()
  50. if err != nil {
  51. return config, currentProfile, fmt.Errorf("unable to get or create porter directory: %w", err)
  52. }
  53. err = ensurePorterConfigFileExists()
  54. if err != nil {
  55. return config, currentProfile, fmt.Errorf("unable to get or create porter config file: %w", err)
  56. }
  57. defaultConfig := defaultCLIConfig()
  58. envProfile := os.Getenv("PORTER_PROFILE")
  59. if envProfile != "" {
  60. currentProfile = envProfile
  61. }
  62. if flagsProfile != "" {
  63. currentProfile = flagsProfile
  64. }
  65. currentProfileConfig, err := configForProfileFromConfigFile(currentProfile, porterConfigFilePath)
  66. if err != nil {
  67. return config, currentProfile, fmt.Errorf("unable to read profile variables from config file")
  68. }
  69. overlayedCurrentProfileConfig, err := overlayProfiles(defaultConfig, currentProfileConfig)
  70. if err != nil {
  71. return config, currentProfile, fmt.Errorf("unable to overlay profile onto default values")
  72. }
  73. envVarsConfig, err := profileConfigFromEnvVars(ctx)
  74. if err != nil {
  75. return config, currentProfile, fmt.Errorf("unable to read profile variables from env vars")
  76. }
  77. overlayedEnvVarsConfig, err := overlayProfiles(overlayedCurrentProfileConfig, envVarsConfig)
  78. if err != nil {
  79. return config, currentProfile, fmt.Errorf("unable to overlay env vars profile onto values in porter config file")
  80. }
  81. configWithAllOverlays, err := overlayProfiles(overlayedEnvVarsConfig, flagsConfig)
  82. if err != nil {
  83. return config, currentProfile, fmt.Errorf("unable to overlay onto env vars config values onto flag values values")
  84. }
  85. return configWithAllOverlays, currentProfile, nil
  86. }
  87. // ValidateCLIEnvironment checks that all required variables are present for running the CLI
  88. func (c *CLIConfig) ValidateCLIEnvironment() error {
  89. if c.Token == "" {
  90. return fmt.Errorf("no auth token present, please run 'porter auth login' to authenticate")
  91. }
  92. if c.Project == 0 {
  93. return fmt.Errorf("no project selected, please run 'porter config set-project' to select a project")
  94. }
  95. if c.Cluster == 0 {
  96. return fmt.Errorf("no cluster selected, please run 'porter config set-cluster' to select a cluster")
  97. }
  98. return nil
  99. }