config.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. package commands
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "os"
  7. "path/filepath"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "github.com/briandowns/spinner"
  12. "github.com/fatih/color"
  13. api "github.com/porter-dev/porter/api/client"
  14. "github.com/porter-dev/porter/api/types"
  15. "github.com/porter-dev/porter/cli/cmd/config"
  16. "github.com/porter-dev/porter/cli/cmd/utils"
  17. "github.com/spf13/cobra"
  18. )
  19. // func registerCommand_Config() *cobra.Command {
  20. func registerCommand_Config() *cobra.Command {
  21. configCmd := &cobra.Command{
  22. Use: "config",
  23. Short: "Commands that control local configuration settings",
  24. Run: func(cmd *cobra.Command, args []string) {
  25. if err := printConfig(); err != nil {
  26. _, _ = color.New(color.FgRed).Fprintf(os.Stderr, "An error occurred: %v\n", err)
  27. os.Exit(1)
  28. }
  29. },
  30. }
  31. configSetProjectCmd := &cobra.Command{
  32. Use: "set-project [id]",
  33. Args: cobra.MaximumNArgs(1),
  34. Short: "Saves the project id in the default configuration",
  35. RunE: func(cmd *cobra.Command, args []string) error {
  36. if len(args) == 0 {
  37. err := checkLoginAndRunWithConfig(cmd, args, listAndSetProject)
  38. if err != nil {
  39. if errors.Is(err, errCreatingPorterAPIClient) {
  40. return errors.New("error creating porter API client. Please ensure you are logged in")
  41. }
  42. return fmt.Errorf("error checking login and setting project: %w", err)
  43. }
  44. return nil
  45. }
  46. err := checkLoginAndRunWithConfig(cmd, args, setProjectAndCluster)
  47. if err != nil {
  48. if errors.Is(err, errCreatingPorterAPIClient) {
  49. return errors.New("error creating porter API client. Please ensure you are logged in")
  50. }
  51. return fmt.Errorf("error checking login and setting project with cluster: %w", err)
  52. }
  53. return nil
  54. },
  55. }
  56. configSetClusterCmd := &cobra.Command{
  57. Use: "set-cluster [id]",
  58. Args: cobra.MaximumNArgs(1),
  59. Short: "Saves the cluster id in the default configuration",
  60. RunE: func(cmd *cobra.Command, args []string) error {
  61. if len(args) == 0 {
  62. err := checkLoginAndRunWithConfig(cmd, args, listAndSetCluster)
  63. if err != nil {
  64. if errors.Is(err, errCreatingPorterAPIClient) {
  65. return errors.New("error creating porter API client. Please ensure you are logged in")
  66. }
  67. return fmt.Errorf("error checking login and setting project: %w", err)
  68. }
  69. return nil
  70. }
  71. _, currentProfile, err := currentProfileIncludingFlags(cmd)
  72. if err != nil {
  73. return fmt.Errorf("error whilst initialising config: %w", err)
  74. }
  75. clusterID, err := strconv.ParseUint(args[0], 10, 64)
  76. if err != nil {
  77. _, _ = color.New(color.FgRed).Fprintf(os.Stderr, "An error occurred: %v\n", err)
  78. os.Exit(1)
  79. }
  80. err = config.SetCluster(uint(clusterID), currentProfile)
  81. if err != nil {
  82. _, _ = color.New(color.FgRed).Fprintf(os.Stderr, "An error occurred: %v\n", err)
  83. os.Exit(1)
  84. }
  85. return nil
  86. },
  87. }
  88. configSetRegistryCmd := &cobra.Command{
  89. Use: "set-registry [id]",
  90. Args: cobra.MaximumNArgs(1),
  91. Short: "Saves the registry id in the default configuration",
  92. Run: func(cmd *cobra.Command, args []string) {
  93. if len(args) == 0 {
  94. err := checkLoginAndRunWithConfig(cmd, args, listAndSetRegistry)
  95. if err != nil {
  96. os.Exit(1)
  97. }
  98. } else {
  99. registryID, err := strconv.ParseUint(args[0], 10, 64)
  100. if err != nil {
  101. _, _ = color.New(color.FgRed).Fprintf(os.Stderr, "An error occurred: %v\n", err)
  102. os.Exit(1)
  103. }
  104. err = config.SetRegistry(uint(registryID))
  105. if err != nil {
  106. _, _ = color.New(color.FgRed).Fprintf(os.Stderr, "An error occurred: %v\n", err)
  107. os.Exit(1)
  108. }
  109. }
  110. },
  111. }
  112. configSetHelmRepoCmd := &cobra.Command{
  113. Use: "set-helmrepo [id]",
  114. Args: cobra.ExactArgs(1),
  115. Short: "Saves the helm repo id in the default configuration",
  116. Run: func(cmd *cobra.Command, args []string) {
  117. hrID, err := strconv.ParseUint(args[0], 10, 64)
  118. if err != nil {
  119. _, _ = color.New(color.FgRed).Fprintf(os.Stderr, "An error occurred: %v\n", err)
  120. os.Exit(1)
  121. }
  122. err = config.SetHelmRepo(uint(hrID))
  123. if err != nil {
  124. _, _ = color.New(color.FgRed).Fprintf(os.Stderr, "An error occurred: %v\n", err)
  125. os.Exit(1)
  126. }
  127. },
  128. }
  129. configSetHostCmd := &cobra.Command{
  130. Use: "set-host [host]",
  131. Args: cobra.ExactArgs(1),
  132. Short: "Saves the host in the default configuration",
  133. RunE: func(cmd *cobra.Command, args []string) error {
  134. _, currentProfile, err := currentProfileIncludingFlags(cmd)
  135. if err != nil {
  136. return fmt.Errorf("error whilst initialising config: %w", err)
  137. }
  138. err = config.SetHost(args[0], currentProfile)
  139. if err != nil {
  140. _, _ = color.New(color.FgRed).Fprintf(os.Stderr, "An error occurred: %s\n", err.Error())
  141. return err
  142. }
  143. return nil
  144. },
  145. }
  146. configSetKubeconfigCmd := &cobra.Command{
  147. Use: "set-kubeconfig [kubeconfig-path]",
  148. Args: cobra.ExactArgs(1),
  149. Short: "Saves the path to kubeconfig in the default configuration",
  150. Run: func(cmd *cobra.Command, args []string) {
  151. err := config.SetKubeconfig(args[0])
  152. if err != nil {
  153. _, _ = color.New(color.FgRed).Fprintf(os.Stderr, "An error occurred: %s\n", err.Error())
  154. os.Exit(1)
  155. }
  156. },
  157. }
  158. configSetProfileCmd := &cobra.Command{
  159. Use: "set-profile [profile-name]",
  160. Args: cobra.ExactArgs(1),
  161. Short: "Saves the path to kubeconfig in the default configuration",
  162. RunE: func(cmd *cobra.Command, args []string) error {
  163. return config.SetProfile(args[0])
  164. },
  165. }
  166. configCmd.AddCommand(configSetProjectCmd)
  167. configCmd.AddCommand(configSetClusterCmd)
  168. configCmd.AddCommand(configSetHostCmd)
  169. configCmd.AddCommand(configSetRegistryCmd)
  170. configCmd.AddCommand(configSetHelmRepoCmd)
  171. configCmd.AddCommand(configSetKubeconfigCmd)
  172. configCmd.AddCommand(configSetProfileCmd)
  173. return configCmd
  174. }
  175. func printConfig() error {
  176. config, err := os.ReadFile(filepath.Join(home, ".porter", "porter.yaml"))
  177. if err != nil {
  178. return err
  179. }
  180. fmt.Println(string(config))
  181. return nil
  182. }
  183. func listAndSetProject(ctx context.Context, _ *types.GetAuthenticatedUserResponse, client api.Client, cliConf config.CLIConfig, currentProfile string, featureFlags config.FeatureFlags, cmd *cobra.Command, args []string) error {
  184. s := spinner.New(spinner.CharSets[9], 100*time.Millisecond)
  185. _ = s.Color("cyan")
  186. s.Suffix = " Loading list of projects"
  187. s.Start()
  188. resp, err := client.ListUserProjects(ctx)
  189. if err != nil {
  190. return fmt.Errorf("error listing projects to set config: %w", err)
  191. }
  192. s.Stop()
  193. var projID uint64
  194. if len(*resp) > 1 {
  195. // only give the option to select when more than one option exists
  196. projName, err := utils.PromptSelect("Select a project with ID", func() []string {
  197. var names []string
  198. for _, proj := range *resp {
  199. names = append(names, fmt.Sprintf("%s - %d", proj.Name, proj.ID))
  200. }
  201. return names
  202. }())
  203. if err != nil {
  204. return err
  205. }
  206. projID, _ = strconv.ParseUint(strings.Split(projName, " - ")[1], 10, 64)
  207. } else {
  208. projID = uint64((*resp)[0].ID)
  209. }
  210. err = config.SetProject(uint(projID), currentProfile)
  211. if err != nil {
  212. return err
  213. }
  214. return nil
  215. }
  216. func setProjectAndCluster(ctx context.Context, _ *types.GetAuthenticatedUserResponse, client api.Client, cliConf config.CLIConfig, currentProfile string, featureFlags config.FeatureFlags, cmd *cobra.Command, args []string) error {
  217. projID, err := strconv.ParseUint(args[0], 10, 64)
  218. if err != nil {
  219. return fmt.Errorf("error parsing project id: %w", err)
  220. }
  221. err = config.SetProject(uint(projID), currentProfile)
  222. if err != nil {
  223. return fmt.Errorf("error setting project: %w", err)
  224. }
  225. err = listAndSetCluster(ctx, nil, client, cliConf, currentProfile, featureFlags, cmd, args)
  226. if err != nil {
  227. return fmt.Errorf("error listing and setting cluster: %w", err)
  228. }
  229. return nil
  230. }
  231. func listAndSetCluster(ctx context.Context, _ *types.GetAuthenticatedUserResponse, client api.Client, cliConf config.CLIConfig, currentProfile string, featureFlags config.FeatureFlags, cmd *cobra.Command, args []string) error {
  232. s := spinner.New(spinner.CharSets[9], 100*time.Millisecond)
  233. _ = s.Color("cyan")
  234. s.Suffix = " Loading list of clusters"
  235. s.Start()
  236. resp, err := client.ListProjectClusters(ctx, cliConf.Project)
  237. if err != nil {
  238. return err
  239. }
  240. s.Stop()
  241. var clusterID uint64
  242. if len(*resp) > 1 {
  243. clusterName, err := utils.PromptSelect("Select a cluster with ID", func() []string {
  244. var names []string
  245. for _, cluster := range *resp {
  246. names = append(names, fmt.Sprintf("%s - %d", cluster.Name, cluster.ID))
  247. }
  248. return names
  249. }())
  250. if err != nil {
  251. return err
  252. }
  253. clusterID, _ = strconv.ParseUint(strings.Split(clusterName, " - ")[1], 10, 64)
  254. } else {
  255. clusterID = uint64((*resp)[0].ID)
  256. }
  257. err = config.SetCluster(uint(clusterID), currentProfile)
  258. if err != nil {
  259. return fmt.Errorf("unable to set cluster: %w", err)
  260. }
  261. return nil
  262. }
  263. func listAndSetRegistry(ctx context.Context, _ *types.GetAuthenticatedUserResponse, client api.Client, cliConf config.CLIConfig, currentProfile string, featureFlags config.FeatureFlags, cmd *cobra.Command, args []string) error {
  264. s := spinner.New(spinner.CharSets[9], 100*time.Millisecond)
  265. _ = s.Color("cyan")
  266. s.Suffix = " Loading list of registries"
  267. s.Start()
  268. resp, err := client.ListRegistries(ctx, cliConf.Project)
  269. s.Stop()
  270. if err != nil {
  271. return err
  272. }
  273. var regID uint64
  274. if len(*resp) > 1 {
  275. regName, err := utils.PromptSelect("Select a registry with ID", func() []string {
  276. var names []string
  277. for _, cluster := range *resp {
  278. names = append(names, fmt.Sprintf("%s - %d", cluster.Name, cluster.ID))
  279. }
  280. return names
  281. }())
  282. if err != nil {
  283. return err
  284. }
  285. regID, _ = strconv.ParseUint(strings.Split(regName, " - ")[1], 10, 64)
  286. } else {
  287. regID = uint64((*resp)[0].ID)
  288. }
  289. err = config.SetRegistry(uint(regID))
  290. if err != nil {
  291. return fmt.Errorf("error setting registry: %w", err)
  292. }
  293. return nil
  294. }