2
0

environment.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package porter_app
  2. import (
  3. "context"
  4. "fmt"
  5. porterv1 "github.com/porter-dev/api-contracts/generated/go/porter/v1"
  6. "github.com/porter-dev/porter/internal/deployment_target"
  7. "github.com/porter-dev/porter/internal/kubernetes"
  8. "github.com/porter-dev/porter/internal/kubernetes/environment_groups"
  9. "github.com/porter-dev/porter/internal/repository"
  10. "github.com/porter-dev/porter/internal/telemetry"
  11. )
  12. type envVariarableOptions struct {
  13. includeSecrets bool
  14. envGroups []string
  15. excludeDefaultAppEnvGroups bool
  16. }
  17. // EnvVariableOption is a function that modifies AppEnvironmentFromProto
  18. type EnvVariableOption func(*envVariarableOptions)
  19. // WithSecrets includes secrets in the environment groups
  20. func WithSecrets() EnvVariableOption {
  21. return func(opts *envVariarableOptions) {
  22. opts.includeSecrets = true
  23. }
  24. }
  25. // WithEnvGroupFilter filters the environment groups to only include the ones in this list of names
  26. func WithEnvGroupFilter(envGroups []string) EnvVariableOption {
  27. return func(opts *envVariarableOptions) {
  28. opts.envGroups = envGroups
  29. }
  30. }
  31. // WithoutDefaultAppEnvGroups filters out the default app environment groups from the returned list
  32. func WithoutDefaultAppEnvGroups() EnvVariableOption {
  33. return func(opts *envVariarableOptions) {
  34. opts.excludeDefaultAppEnvGroups = true
  35. }
  36. }
  37. // AppEnvironmentFromProtoInput is the input struct for AppEnvironmentFromProto
  38. type AppEnvironmentFromProtoInput struct {
  39. ProjectID uint
  40. ClusterID int
  41. DeploymentTarget deployment_target.DeploymentTarget
  42. App *porterv1.PorterApp
  43. K8SAgent *kubernetes.Agent
  44. }
  45. // AppEnvironmentFromProto returns all envfironment groups referenced in an app proto with their variables
  46. func AppEnvironmentFromProto(ctx context.Context, inp AppEnvironmentFromProtoInput, varOpts ...EnvVariableOption) ([]environment_groups.EnvironmentGroup, error) {
  47. ctx, span := telemetry.NewSpan(ctx, "porter-app-env-from-proto")
  48. defer span.End()
  49. envGroups := []environment_groups.EnvironmentGroup{}
  50. if inp.ProjectID == 0 {
  51. return nil, telemetry.Error(ctx, span, nil, "must provide a project id")
  52. }
  53. if inp.ClusterID == 0 {
  54. return nil, telemetry.Error(ctx, span, nil, "must provide a cluster id")
  55. }
  56. if inp.App == nil {
  57. return nil, telemetry.Error(ctx, span, nil, "must provide an app")
  58. }
  59. if inp.K8SAgent == nil {
  60. return nil, telemetry.Error(ctx, span, nil, "must provide a kubernetes agent")
  61. }
  62. var opts envVariarableOptions
  63. for _, opt := range varOpts {
  64. opt(&opts)
  65. }
  66. filteredEnvGroups := inp.App.EnvGroups
  67. if len(opts.envGroups) > 0 {
  68. filteredEnvGroups = []*porterv1.EnvGroup{}
  69. for _, envGroup := range inp.App.EnvGroups {
  70. for _, envGroupName := range opts.envGroups {
  71. if envGroup.GetName() == envGroupName {
  72. filteredEnvGroups = append(filteredEnvGroups, envGroup)
  73. }
  74. }
  75. }
  76. }
  77. for _, envGroupRef := range filteredEnvGroups {
  78. envGroup, err := environment_groups.EnvironmentGroupInTargetNamespace(ctx, inp.K8SAgent, environment_groups.EnvironmentGroupInTargetNamespaceInput{
  79. Name: envGroupRef.GetName(),
  80. Version: int(envGroupRef.GetVersion()),
  81. Namespace: inp.DeploymentTarget.Namespace,
  82. ExcludeDefaultAppEnvironmentGroup: opts.excludeDefaultAppEnvGroups,
  83. })
  84. if err != nil {
  85. return nil, telemetry.Error(ctx, span, err, "error getting environment group in target namespace")
  86. }
  87. if !opts.includeSecrets {
  88. envGroup.SecretVariables = nil
  89. }
  90. // if envGroup.Name is empty, it means the environment group was a default app environment group and was filtered out
  91. if envGroup.Name != "" {
  92. envGroups = append(envGroups, envGroup)
  93. }
  94. }
  95. return envGroups, nil
  96. }
  97. // AppEnvGroupName returns the name of the environment group for the app
  98. func AppEnvGroupName(ctx context.Context, appName string, deploymentTargetId string, clusterID uint, porterAppRepository repository.PorterAppRepository) (string, error) {
  99. ctx, span := telemetry.NewSpan(ctx, "app-env-group-name")
  100. defer span.End()
  101. if appName == "" {
  102. return "", telemetry.Error(ctx, span, nil, "app name is empty")
  103. }
  104. telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "app-name", Value: appName})
  105. if deploymentTargetId == "" {
  106. return "", telemetry.Error(ctx, span, nil, "deployment target id is empty")
  107. }
  108. telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "deployment-target-id", Value: deploymentTargetId})
  109. if clusterID == 0 {
  110. return "", telemetry.Error(ctx, span, nil, "cluster id is empty")
  111. }
  112. telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "cluster-id", Value: clusterID})
  113. porterApp, err := porterAppRepository.ReadPorterAppByName(clusterID, appName)
  114. if err != nil {
  115. return "", telemetry.Error(ctx, span, err, "error reading porter app by name")
  116. }
  117. telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "porter-app-id", Value: porterApp.ID})
  118. if len(deploymentTargetId) < 6 {
  119. return "", telemetry.Error(ctx, span, nil, "deployment target id is too short")
  120. }
  121. return fmt.Sprintf("%d-%s", porterApp.ID, deploymentTargetId[:6]), nil
  122. }
  123. // AppTemplateEnvGroupName returns the name of the environment group for an app template
  124. func AppTemplateEnvGroupName(ctx context.Context, appName string, clusterID uint, porterAppRepository repository.PorterAppRepository) (string, error) {
  125. ctx, span := telemetry.NewSpan(ctx, "app-template-env-group-name")
  126. defer span.End()
  127. if appName == "" {
  128. return "", telemetry.Error(ctx, span, nil, "app name is empty")
  129. }
  130. telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "app-name", Value: appName})
  131. if clusterID == 0 {
  132. return "", telemetry.Error(ctx, span, nil, "cluster id is empty")
  133. }
  134. telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "cluster-id", Value: clusterID})
  135. porterApp, err := porterAppRepository.ReadPorterAppByName(clusterID, appName)
  136. if err != nil {
  137. return "", telemetry.Error(ctx, span, err, "error reading porter app by name")
  138. }
  139. telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "porter-app-id", Value: porterApp.ID})
  140. return fmt.Sprintf("%d-template-preview", porterApp.ID), nil
  141. }