config.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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. // If no flagsProfile and flagsConfig are provided, this will follow the above precendence order to find values.
  47. func InitAndLoadConfig(ctx context.Context, flagsProfile string, flagsConfig CLIConfig) (CLIConfig, string, error) {
  48. var config CLIConfig
  49. err := ensurePorterConfigDirectoryExists()
  50. if err != nil {
  51. return config, "", fmt.Errorf("unable to get or create porter directory: %w", err)
  52. }
  53. err = ensurePorterConfigFileExists()
  54. if err != nil {
  55. return config, "", fmt.Errorf("unable to get or create porter config file: %w", err)
  56. }
  57. defaultConfig := defaultCLIConfig()
  58. currentProfile := defaultProfileName
  59. if currentProfile != "" {
  60. currentProfile = flagsProfile
  61. }
  62. currentProfileConfig, configFileProfile, err := configForProfileFromConfigFile(currentProfile, porterConfigFilePath)
  63. if err != nil {
  64. return config, currentProfile, fmt.Errorf("unable to read profile variables from config file")
  65. }
  66. if currentProfile != "" {
  67. currentProfile = flagsProfile
  68. }
  69. envProfile := os.Getenv("PORTER_PROFILE")
  70. if envProfile != "" {
  71. currentProfile = envProfile
  72. }
  73. if flagsProfile != "" {
  74. currentProfile = flagsProfile
  75. }
  76. overlayedCurrentProfileConfig, err := overlayProfiles(defaultConfig, currentProfileConfig)
  77. if err != nil {
  78. return config, currentProfile, fmt.Errorf("unable to overlay profile onto default values")
  79. }
  80. fmt.Println(currentProfile, configFileProfile, flagsProfile, overlayedCurrentProfileConfig.Host, currentProfileConfig.Host)
  81. envVarsConfig, err := profileConfigFromEnvVars(ctx)
  82. if err != nil {
  83. return config, currentProfile, fmt.Errorf("unable to read profile variables from env vars")
  84. }
  85. overlayedEnvVarsConfig, err := overlayProfiles(overlayedCurrentProfileConfig, envVarsConfig)
  86. if err != nil {
  87. return config, currentProfile, fmt.Errorf("unable to overlay env vars profile onto values in porter config file")
  88. }
  89. configWithAllOverlays, err := overlayProfiles(overlayedEnvVarsConfig, flagsConfig)
  90. if err != nil {
  91. return config, currentProfile, fmt.Errorf("unable to overlay onto env vars config values onto flag values values")
  92. }
  93. return configWithAllOverlays, currentProfile, nil
  94. }