2
0

cluster.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. package models
  2. import (
  3. "encoding/json"
  4. "github.com/porter-dev/porter/api/types"
  5. "github.com/porter-dev/porter/internal/models/integrations"
  6. "gorm.io/gorm"
  7. )
  8. // ClusterAuth is an auth mechanism that a cluster candidate can resolve
  9. type ClusterAuth string
  10. // The support cluster candidate auth mechanisms
  11. const (
  12. X509 ClusterAuth = "x509"
  13. Basic ClusterAuth = "basic"
  14. Bearer ClusterAuth = "bearerToken"
  15. OIDC ClusterAuth = "oidc"
  16. GCP ClusterAuth = "gcp-sa"
  17. AWS ClusterAuth = "aws-sa"
  18. DO ClusterAuth = "do-oauth"
  19. Azure ClusterAuth = "azure-sp"
  20. Local ClusterAuth = "local"
  21. InCluster ClusterAuth = "in-cluster"
  22. )
  23. // Cluster is an integration that can connect to a Kubernetes cluster via
  24. // a specific auth mechanism
  25. type Cluster struct {
  26. gorm.Model
  27. // The auth mechanism that this cluster will use
  28. AuthMechanism ClusterAuth `json:"auth_mechanism"`
  29. // The project that this integration belongs to
  30. ProjectID uint `json:"project_id"`
  31. // Whether or not the Porter agent integration is enabled on the cluster
  32. AgentIntegrationEnabled bool
  33. // Name of the cluster
  34. Name string `json:"name"`
  35. // VanityName allows for a display-only name without changing how the cluster looks
  36. VanityName string `json:"vanity_name"`
  37. // Server endpoint for the cluster
  38. Server string `json:"server"`
  39. // Additional fields optionally used by the kube client
  40. ClusterLocationOfOrigin string `json:"location_of_origin,omitempty"`
  41. TLSServerName string `json:"tls-server-name,omitempty"`
  42. InsecureSkipTLSVerify bool `json:"insecure-skip-tls-verify,omitempty"`
  43. ProxyURL string `json:"proxy-url,omitempty"`
  44. UserLocationOfOrigin string
  45. UserImpersonate string `json:"act-as,omitempty"`
  46. UserImpersonateGroups string `json:"act-as-groups,omitempty"`
  47. InfraID uint `json:"infra_id"`
  48. NotificationsDisabled bool `json:"notifications_disabled"`
  49. PreviewEnvsEnabled bool
  50. AWSClusterID string
  51. // Status defines the current status of the cluster. Accepted values: [READY, UPDATING]
  52. Status types.ClusterStatus `json:"status"`
  53. // ProvisionedBy is used for identifing the provisioner used for the cluster. Accepted values: [CAPI, ]
  54. ProvisionedBy string `json:"provisioned_by"`
  55. // CloudProvider is the cloud provider that hosts the Kubernetes Cluster. Accepted values: [AWS, GCP, AZURE]
  56. CloudProvider string `json:"cloud_provider"`
  57. // CloudProviderCredentialIdentifier is a reference to find the credentials required for access the cluster's API.
  58. // This was likely the credential that was used to create the cluster.
  59. // For AWS EKS clusters, this will be an ARN for the final target role in the assume role chain.
  60. CloudProviderCredentialIdentifier string `json:"cloud_provider_credential_identifier"`
  61. // ------------------------------------------------------------------
  62. // All fields below this line are encrypted before storage
  63. // ------------------------------------------------------------------
  64. // The various auth mechanisms available to the integration
  65. KubeIntegrationID uint
  66. OIDCIntegrationID uint
  67. GCPIntegrationID uint
  68. AWSIntegrationID uint
  69. DOIntegrationID uint
  70. AzureIntegrationID uint
  71. // A token cache that can be used by an auth mechanism, if desired
  72. TokenCache integrations.ClusterTokenCache `json:"token_cache" gorm:"-" sql:"-"`
  73. TokenCacheID uint `gorm:"token_cache_id"`
  74. // CertificateAuthorityData for the cluster, encrypted at rest
  75. CertificateAuthorityData []byte `json:"certificate-authority-data,omitempty"`
  76. // MonitorHelmReleases to trim down the number of revisions per release
  77. MonitorHelmReleases bool
  78. }
  79. // ToClusterType generates an external types.Cluster to be shared over REST
  80. func (c *Cluster) ToClusterType() *types.Cluster {
  81. serv := types.Kube
  82. if c.AWSIntegrationID != 0 {
  83. serv = types.EKS
  84. } else if c.GCPIntegrationID != 0 {
  85. serv = types.GKE
  86. } else if c.DOIntegrationID != 0 {
  87. serv = types.DOKS
  88. } else if c.AzureIntegrationID != 0 {
  89. serv = types.AKS
  90. }
  91. return &types.Cluster{
  92. ID: c.ID,
  93. ProjectID: c.ProjectID,
  94. Name: c.Name,
  95. VanityName: c.VanityName,
  96. Server: c.Server,
  97. Service: serv,
  98. AgentIntegrationEnabled: c.AgentIntegrationEnabled,
  99. InfraID: c.InfraID,
  100. AWSIntegrationID: c.AWSIntegrationID,
  101. AWSClusterID: c.AWSClusterID,
  102. PreviewEnvsEnabled: c.PreviewEnvsEnabled,
  103. Status: c.Status,
  104. ProvisionedBy: c.ProvisionedBy,
  105. CloudProvider: c.CloudProvider,
  106. CloudProviderCredentialIdentifier: c.CloudProviderCredentialIdentifier,
  107. }
  108. }
  109. // ClusterCandidate is a cluster integration that requires additional action
  110. // from the user to set up.
  111. type ClusterCandidate struct {
  112. gorm.Model
  113. // The auth mechanism that this candidate will parse for
  114. AuthMechanism ClusterAuth `json:"auth_mechanism"`
  115. // The project that this integration belongs to
  116. ProjectID uint `json:"project_id"`
  117. // CreatedClusterID is the ID of the cluster that's eventually
  118. // created
  119. CreatedClusterID uint `json:"created_cluster_id"`
  120. // Resolvers are the list of resolvers: once all resolvers are "resolved," the
  121. // cluster will be created
  122. Resolvers []ClusterResolver `json:"resolvers"`
  123. // Name of the cluster
  124. Name string `json:"name"`
  125. // Server endpoint for the cluster
  126. Server string `json:"server"`
  127. // Name of the context that this was created from, if it exists
  128. ContextName string `json:"context_name"`
  129. // ------------------------------------------------------------------
  130. // All fields below this line are encrypted before storage
  131. // ------------------------------------------------------------------
  132. // The best-guess for the AWSClusterID, which is required by aws auth mechanisms
  133. // See https://github.com/kubernetes-sigs/aws-iam-authenticator#what-is-a-cluster-id
  134. AWSClusterIDGuess []byte `json:"aws_cluster_id_guess"`
  135. // The raw kubeconfig
  136. Kubeconfig []byte `json:"kubeconfig"`
  137. }
  138. func (cc *ClusterCandidate) ToClusterCandidateType() *types.ClusterCandidate {
  139. resolvers := make([]types.ClusterResolver, 0)
  140. for _, resolver := range cc.Resolvers {
  141. resolvers = append(resolvers, *resolver.ToClusterResolverType())
  142. }
  143. return &types.ClusterCandidate{
  144. ID: cc.ID,
  145. ProjectID: cc.ProjectID,
  146. CreatedClusterID: cc.CreatedClusterID,
  147. Name: cc.Name,
  148. Server: cc.Server,
  149. ContextName: cc.ContextName,
  150. Resolvers: resolvers,
  151. AWSClusterIDGuess: string(cc.AWSClusterIDGuess),
  152. }
  153. }
  154. // ClusterResolver is an action that must be resolved to set up
  155. // a Cluster
  156. type ClusterResolver struct {
  157. gorm.Model
  158. // The ClusterCandidate that this is resolving
  159. ClusterCandidateID uint `json:"cluster_candidate_id"`
  160. // One of the ClusterResolverNames
  161. Name types.ClusterResolverName `json:"name"`
  162. // Resolved is true if this has been resolved, false otherwise
  163. Resolved bool `json:"resolved"`
  164. // Data is additional data for resolving the action, for example a file name,
  165. // context name, etc
  166. Data []byte `json:"data,omitempty"`
  167. }
  168. func (cr *ClusterResolver) ToClusterResolverType() *types.ClusterResolver {
  169. info := types.ClusterResolverInfos[cr.Name]
  170. data := make(types.ClusterResolverData)
  171. json.Unmarshal(cr.Data, &data)
  172. return &types.ClusterResolver{
  173. ID: cr.ID,
  174. ClusterCandidateID: cr.ClusterCandidateID,
  175. Name: cr.Name,
  176. Resolved: cr.Resolved,
  177. Docs: info.Docs,
  178. Fields: info.Fields,
  179. Data: data,
  180. }
  181. }