utils.go 6.0 KB

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