project.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. package models
  2. import (
  3. "fmt"
  4. "gorm.io/gorm"
  5. "github.com/launchdarkly/go-sdk-common/v3/ldcontext"
  6. "github.com/porter-dev/porter/api/types"
  7. "github.com/porter-dev/porter/internal/features"
  8. ints "github.com/porter-dev/porter/internal/models/integrations"
  9. )
  10. // ProjectFeatureFlags keeps track of all project-related feature flags
  11. var ProjectFeatureFlags = map[string]bool{
  12. "api_tokens_enabled": false,
  13. "azure_enabled": false,
  14. "capi_provisioner_enabled": true,
  15. "enable_reprovision": false,
  16. "full_add_ons": false,
  17. "helm_values_enabled": false,
  18. "managed_infra_enabled": false,
  19. "multi_cluster": false,
  20. "preview_envs_enabled": false,
  21. "rds_databases_enabled": false,
  22. "simplified_view_enabled": true,
  23. "stacks_enabled": false,
  24. "validate_apply_v2": false,
  25. }
  26. type ProjectPlan string
  27. const (
  28. ProjectPlanBasic ProjectPlan = "basic"
  29. ProjectPlanTeam ProjectPlan = "team"
  30. ProjectPlanGrowth ProjectPlan = "growth"
  31. ProjectPlanEnterprise ProjectPlan = "enterprise"
  32. )
  33. // Project type that extends gorm.Model
  34. type Project struct {
  35. gorm.Model `gorm:"embedded"`
  36. Name string `json:"name"`
  37. Roles []Role `json:"roles"`
  38. ProjectUsageID uint
  39. ProjectUsageCacheID uint
  40. // linked repos
  41. GitRepos []GitRepo `json:"git_repos,omitempty"`
  42. // linked registries
  43. Registries []Registry `json:"registries,omitempty"`
  44. // linked clusters
  45. Clusters []Cluster `json:"clusters"`
  46. ClusterCandidates []ClusterCandidate `json:"cluster_candidates"`
  47. // linked databases
  48. Databases []Database `json:"databases"`
  49. // linked helm repos
  50. HelmRepos []HelmRepo `json:"helm_repos"`
  51. // invitations to the project
  52. Invites []Invite `json:"invites"`
  53. // provisioned aws infra
  54. Infras []Infra `json:"infras"`
  55. // auth mechanisms
  56. KubeIntegrations []ints.KubeIntegration `json:"kube_integrations"`
  57. BasicIntegrations []ints.BasicIntegration `json:"basic_integrations"`
  58. OIDCIntegrations []ints.OIDCIntegration `json:"oidc_integrations"`
  59. OAuthIntegrations []ints.OAuthIntegration `json:"oauth_integrations"`
  60. AWSIntegrations []ints.AWSIntegration `json:"aws_integrations"`
  61. GCPIntegrations []ints.GCPIntegration `json:"gcp_integrations"`
  62. AzureIntegrations []ints.AzureIntegration `json:"azure_integrations"`
  63. GitlabIntegrations []ints.GitlabIntegration `json:"gitlab_integrations"`
  64. PreviewEnvsEnabled bool
  65. RDSDatabasesEnabled bool
  66. ManagedInfraEnabled bool
  67. StacksEnabled bool
  68. APITokensEnabled bool
  69. CapiProvisionerEnabled bool
  70. SimplifiedViewEnabled bool
  71. AzureEnabled bool
  72. HelmValuesEnabled bool
  73. MultiCluster bool `gorm:"default:false"`
  74. FullAddOns bool `gorm:"default:false"`
  75. ValidateApplyV2 bool `gorm:"default:false"`
  76. EnableReprovision bool `gorm:"default:false"`
  77. }
  78. // GetFeatureFlag calls launchdarkly for the specified flag
  79. // and returns the configured value
  80. func (p *Project) GetFeatureFlag(flagName string, launchDarklyClient *features.Client) bool {
  81. projectID := p.ID
  82. projectName := p.Name
  83. ldContext := getProjectContext(projectID, projectName)
  84. defaultValue := ProjectFeatureFlags[flagName]
  85. value, _ := launchDarklyClient.BoolVariation(flagName, ldContext, defaultValue)
  86. return value
  87. }
  88. // ToProjectType generates an external types.Project to be shared over REST
  89. func (p *Project) ToProjectType(launchDarklyClient *features.Client) types.Project {
  90. roles := make([]*types.Role, 0)
  91. for _, role := range p.Roles {
  92. roles = append(roles, role.ToRoleType())
  93. }
  94. projectID := p.ID
  95. projectName := p.Name
  96. return types.Project{
  97. ID: projectID,
  98. Name: projectName,
  99. Roles: roles,
  100. PreviewEnvsEnabled: p.GetFeatureFlag("preview_envs_enabled", launchDarklyClient),
  101. RDSDatabasesEnabled: p.GetFeatureFlag("rds_databases_enabled", launchDarklyClient),
  102. ManagedInfraEnabled: p.GetFeatureFlag("managed_infra_enabled", launchDarklyClient),
  103. StacksEnabled: p.GetFeatureFlag("stacks_enabled", launchDarklyClient),
  104. APITokensEnabled: p.GetFeatureFlag("api_tokens_enabled", launchDarklyClient),
  105. CapiProvisionerEnabled: p.GetFeatureFlag("capi_provisioner_enabled", launchDarklyClient),
  106. SimplifiedViewEnabled: p.GetFeatureFlag("simplified_view_enabled", launchDarklyClient),
  107. AzureEnabled: p.GetFeatureFlag("azure_enabled", launchDarklyClient),
  108. HelmValuesEnabled: p.GetFeatureFlag("helm_values_enabled", launchDarklyClient),
  109. MultiCluster: p.GetFeatureFlag("multi_cluster", launchDarklyClient),
  110. EnableReprovision: p.GetFeatureFlag("enable_reprovision", launchDarklyClient),
  111. ValidateApplyV2: p.GetFeatureFlag("validate_apply_v2", launchDarklyClient),
  112. FullAddOns: p.GetFeatureFlag("full_add_ons", launchDarklyClient),
  113. }
  114. }
  115. // ToProjectListType returns a "minified" version of a Project
  116. // suitable for api responses to GET /projects
  117. // TODO: update this in the future to use default values for all
  118. // the feature flags instead of trying to retrieve them from the database
  119. func (p *Project) ToProjectListType() *types.ProjectList {
  120. var roles []types.Role
  121. for _, role := range p.Roles {
  122. roles = append(roles, *role.ToRoleType())
  123. }
  124. return &types.ProjectList{
  125. ID: p.ID,
  126. Name: p.Name,
  127. // note: all of these fields should be considered deprecated
  128. // in an api response
  129. Roles: roles,
  130. PreviewEnvsEnabled: p.PreviewEnvsEnabled,
  131. RDSDatabasesEnabled: p.RDSDatabasesEnabled,
  132. ManagedInfraEnabled: p.ManagedInfraEnabled,
  133. StacksEnabled: p.StacksEnabled,
  134. APITokensEnabled: p.APITokensEnabled,
  135. CapiProvisionerEnabled: p.CapiProvisionerEnabled,
  136. SimplifiedViewEnabled: p.SimplifiedViewEnabled,
  137. AzureEnabled: p.AzureEnabled,
  138. HelmValuesEnabled: p.HelmValuesEnabled,
  139. MultiCluster: p.MultiCluster,
  140. EnableReprovision: p.EnableReprovision,
  141. ValidateApplyV2: p.ValidateApplyV2,
  142. FullAddOns: p.FullAddOns,
  143. }
  144. }
  145. func getProjectContext(projectID uint, projectName string) ldcontext.Context {
  146. projectIdentifier := fmt.Sprintf("project-%d", projectID)
  147. launchDarklyName := fmt.Sprintf("%s: %s", projectIdentifier, projectName)
  148. return ldcontext.NewBuilder(projectIdentifier).
  149. Kind("project").
  150. Name(launchDarklyName).
  151. SetInt("project_id", int(projectID)).
  152. Build()
  153. }