utils.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. package preview
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "strconv"
  7. "github.com/porter-dev/porter/api/types"
  8. "github.com/porter-dev/porter/cli/cmd/config"
  9. "github.com/porter-dev/porter/internal/integrations/preview"
  10. )
  11. func GetSource(projectID uint, resourceName string, input map[string]interface{}) (*preview.Source, error) {
  12. output := &preview.Source{}
  13. // first read from env vars
  14. output.Name = os.Getenv("PORTER_SOURCE_NAME")
  15. output.Repo = os.Getenv("PORTER_SOURCE_REPO")
  16. output.Version = os.Getenv("PORTER_SOURCE_VERSION")
  17. // next, check for values in the YAML file
  18. if output.Name == "" {
  19. if name, ok := input["name"]; ok {
  20. nameVal, ok := name.(string)
  21. if !ok {
  22. return nil, fmt.Errorf("error parsing source for resource '%s': invalid name provided", resourceName)
  23. }
  24. output.Name = nameVal
  25. }
  26. }
  27. if output.Name == "" {
  28. return nil, fmt.Errorf("error parsing source for resource '%s': source name required", resourceName)
  29. }
  30. if output.Repo == "" {
  31. if repo, ok := input["repo"]; ok {
  32. repoVal, ok := repo.(string)
  33. if !ok {
  34. return nil, fmt.Errorf("error parsing source for resource '%s': invalid repo provided", resourceName)
  35. }
  36. output.Repo = repoVal
  37. }
  38. }
  39. if output.Version == "" {
  40. if version, ok := input["version"]; ok {
  41. versionVal, ok := version.(string)
  42. if !ok {
  43. return nil, fmt.Errorf("error parsing source for resource '%s': invalid version provided", resourceName)
  44. }
  45. output.Version = versionVal
  46. }
  47. }
  48. // lastly, just put in the defaults
  49. if output.Version == "" {
  50. output.Version = "latest"
  51. }
  52. apiClient := config.GetAPIClient()
  53. serverMetadata, err := apiClient.GetPorterInstanceMetadata(context.Background())
  54. if err != nil {
  55. return nil, fmt.Errorf("error fetching Porter instance metadata: %w", err)
  56. }
  57. if output.Repo == "" {
  58. if serverMetadata.DefaultAppHelmRepoURL != "" {
  59. output.Repo = serverMetadata.DefaultAppHelmRepoURL
  60. } else {
  61. output.Repo = "https://charts.getporter.dev"
  62. }
  63. values, err := existsInRepo(projectID, output.Name, output.Version, output.Repo)
  64. if err == nil {
  65. output.SourceValues = values
  66. output.IsApplication = true
  67. return output, nil
  68. }
  69. if serverMetadata.DefaultAddonHelmRepoURL != "" {
  70. output.Repo = serverMetadata.DefaultAddonHelmRepoURL
  71. } else {
  72. output.Repo = "https://chart-addons.getporter.dev"
  73. }
  74. values, err = existsInRepo(projectID, output.Name, output.Version, output.Repo)
  75. if err == nil {
  76. output.SourceValues = values
  77. return output, nil
  78. }
  79. return nil, fmt.Errorf("error parsing source for resource '%s': source chart does not exist in the default "+
  80. "Helm repositories", resourceName)
  81. } else {
  82. // we look in the passed-in repo
  83. values, err := existsInRepo(projectID, output.Name, output.Version, output.Repo)
  84. if err == nil {
  85. output.SourceValues = values
  86. output.IsApplication = output.Repo == serverMetadata.DefaultAppHelmRepoURL || output.Repo == "https://charts.getporter.dev"
  87. return output, nil
  88. }
  89. }
  90. return nil, fmt.Errorf("error parsing source for resource '%s': source '%s' does not exist in repo '%s'",
  91. resourceName, output.Name, output.Repo)
  92. }
  93. func GetTarget(resourceName string, input map[string]interface{}) (*preview.Target, error) {
  94. output := &preview.Target{}
  95. // first read from env vars
  96. if projectEnv := os.Getenv("PORTER_PROJECT"); projectEnv != "" {
  97. project, err := strconv.Atoi(projectEnv)
  98. if err != nil {
  99. return nil, fmt.Errorf("error parsing target for resource '%s': %w", resourceName, err)
  100. }
  101. output.Project = uint(project)
  102. }
  103. if clusterEnv := os.Getenv("PORTER_CLUSTER"); clusterEnv != "" {
  104. cluster, err := strconv.Atoi(clusterEnv)
  105. if err != nil {
  106. return nil, fmt.Errorf("error parsing target for resource '%s': %w", resourceName, err)
  107. }
  108. output.Cluster = uint(cluster)
  109. }
  110. output.Namespace = os.Getenv("PORTER_NAMESPACE")
  111. // next, check for values in the YAML file
  112. if output.Project == 0 {
  113. if project, ok := input["project"]; ok {
  114. projectVal, ok := project.(uint)
  115. if !ok {
  116. return nil, fmt.Errorf("error parsing target for resource '%s': project value must be an integer", resourceName)
  117. }
  118. output.Project = projectVal
  119. }
  120. }
  121. if output.Cluster == 0 {
  122. if cluster, ok := input["cluster"]; ok {
  123. clusterVal, ok := cluster.(uint)
  124. if !ok {
  125. return nil, fmt.Errorf("error parsing target for resource '%s': cluster value must be an integer",
  126. resourceName)
  127. }
  128. output.Cluster = clusterVal
  129. }
  130. }
  131. if output.Namespace == "" {
  132. if namespace, ok := input["namespace"]; ok {
  133. namespaceVal, ok := namespace.(string)
  134. if !ok {
  135. return nil, fmt.Errorf("error parsing target for resource '%s': invalid namespace provided", resourceName)
  136. }
  137. output.Namespace = namespaceVal
  138. }
  139. }
  140. if appName, ok := input["app_name"]; ok {
  141. appNameVal, ok := appName.(string)
  142. if !ok {
  143. return nil, fmt.Errorf("error parsing target for resource '%s': invalid app_name provided", resourceName)
  144. }
  145. output.AppName = appNameVal
  146. }
  147. // lastly, just put in the defaults
  148. if output.Project == 0 {
  149. output.Project = config.GetCLIConfig().Project
  150. }
  151. if output.Cluster == 0 {
  152. output.Cluster = config.GetCLIConfig().Cluster
  153. }
  154. if output.Namespace == "" {
  155. output.Namespace = "default"
  156. }
  157. return output, nil
  158. }
  159. func existsInRepo(projectID uint, name, version, url string) (map[string]interface{}, error) {
  160. chart, err := config.GetAPIClient().GetTemplate(
  161. context.Background(),
  162. projectID,
  163. name, version,
  164. &types.GetTemplateRequest{
  165. TemplateGetBaseRequest: types.TemplateGetBaseRequest{
  166. RepoURL: url,
  167. },
  168. },
  169. )
  170. if err != nil {
  171. return nil, err
  172. }
  173. return chart.Values, nil
  174. }