infra.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. package models
  2. import (
  3. "encoding/hex"
  4. "encoding/json"
  5. "fmt"
  6. "strconv"
  7. "strings"
  8. "gorm.io/gorm"
  9. "github.com/porter-dev/porter/api/types"
  10. "github.com/porter-dev/porter/internal/encryption"
  11. )
  12. // Infra represents the metadata for an infrastructure type provisioned on
  13. // Porter
  14. type Infra struct {
  15. gorm.Model
  16. // The type of infra that was provisioned
  17. Kind types.InfraKind
  18. // The infrastructure API version
  19. APIVersion string
  20. // The source link (only set on apiVersion >= v2)
  21. SourceLink string
  22. // The source version (only set on apiVersion >= v2)
  23. SourceVersion string
  24. // A random 6-byte suffix to ensure workspace/stream ids are unique
  25. Suffix string
  26. // The project that this infra belongs to
  27. ProjectID uint
  28. // The ID of the user that created this infra
  29. CreatedByUserID uint
  30. // If this infra was created under a cluster scope (for example, for RDS), the parent cluster
  31. // ID
  32. ParentClusterID uint
  33. // Status is the status of the infra
  34. Status types.InfraStatus
  35. Operations []Operation
  36. // The AWS integration that was used to create the infra
  37. AWSIntegrationID uint
  38. // The Azure integration that was used to create the infra
  39. AzureIntegrationID uint
  40. // The GCP integration that was used to create the infra
  41. GCPIntegrationID uint
  42. // The DO integration that was used to create the infra:
  43. // this points to an OAuthIntegrationID
  44. DOIntegrationID uint
  45. // The database id for the infra, if this infra provisioned a database
  46. DatabaseID uint
  47. Database Database
  48. // ------------------------------------------------------------------
  49. // All fields below this line are encrypted before storage
  50. // ------------------------------------------------------------------
  51. // The last-applied input variables to the provisioner
  52. LastApplied []byte
  53. }
  54. type Operation struct {
  55. gorm.Model
  56. UID string `gorm:"unique"`
  57. InfraID uint
  58. Type string
  59. Status string
  60. Errored bool
  61. Error string
  62. TemplateVersion string
  63. // ------------------------------------------------------------------
  64. // All fields below this line are encrypted before storage
  65. // ------------------------------------------------------------------
  66. // The last-applied input variables to the provisioner
  67. LastApplied []byte
  68. }
  69. func (o *Operation) ToOperationMetaType() *types.OperationMeta {
  70. return &types.OperationMeta{
  71. LastUpdated: o.UpdatedAt,
  72. UID: o.UID,
  73. InfraID: o.InfraID,
  74. Type: o.Type,
  75. Status: o.Status,
  76. Errored: o.Errored,
  77. Error: o.Error,
  78. }
  79. }
  80. func (o *Operation) ToOperationType() (*types.Operation, error) {
  81. // unmarshal last applied
  82. lastApplied := make(map[string]interface{})
  83. err := json.Unmarshal(o.LastApplied, &lastApplied)
  84. if err != nil {
  85. return nil, err
  86. }
  87. return &types.Operation{
  88. OperationMeta: o.ToOperationMetaType(),
  89. LastApplied: lastApplied,
  90. }, nil
  91. }
  92. func GetOperationID() (string, error) {
  93. return encryption.GenerateRandomBytes(10)
  94. }
  95. // ToInfraType generates an external Infra to be shared over REST
  96. func (i *Infra) ToInfraType() *types.Infra {
  97. return &types.Infra{
  98. ID: i.ID,
  99. CreatedAt: i.CreatedAt,
  100. UpdatedAt: i.UpdatedAt,
  101. ProjectID: i.ProjectID,
  102. APIVersion: i.APIVersion,
  103. SourceLink: i.SourceLink,
  104. SourceVersion: i.SourceVersion,
  105. Kind: i.Kind,
  106. Status: i.Status,
  107. AWSIntegrationID: i.AWSIntegrationID,
  108. DOIntegrationID: i.DOIntegrationID,
  109. GCPIntegrationID: i.GCPIntegrationID,
  110. }
  111. }
  112. // GetID returns the unique id for this infra
  113. func (i *Infra) GetUniqueName() string {
  114. return fmt.Sprintf("%s-%d-%d-%s", i.Kind, i.ProjectID, i.ID, i.Suffix)
  115. }
  116. // ParseUniqueName returns the (kind, projectID, infraID, suffix)
  117. func ParseUniqueName(workspaceID string) (string, uint, uint, string, error) {
  118. strArr := strings.Split(workspaceID, "-")
  119. if len(strArr) != 4 {
  120. return "", 0, 0, "", fmt.Errorf("workspace id improperly formatted")
  121. }
  122. projID, err := strconv.ParseUint(strArr[1], 10, 64)
  123. if err != nil {
  124. return "", 0, 0, "", err
  125. }
  126. infraID, err := strconv.ParseUint(strArr[2], 10, 64)
  127. if err != nil {
  128. return "", 0, 0, "", err
  129. }
  130. return strArr[0], uint(projID), uint(infraID), strArr[3], nil
  131. }
  132. type UniqueNameWithOperation struct {
  133. Kind string
  134. ProjectID uint
  135. InfraID uint
  136. Suffix string
  137. OperationUID string
  138. }
  139. func ParseWorkspaceID(workspaceID string) (*UniqueNameWithOperation, error) {
  140. strArr := strings.Split(workspaceID, "-")
  141. if len(strArr) != 5 {
  142. return nil, fmt.Errorf("workspace id improperly formatted: %s", workspaceID)
  143. }
  144. projID, err := strconv.ParseUint(strArr[1], 10, 64)
  145. if err != nil {
  146. return nil, err
  147. }
  148. infraID, err := strconv.ParseUint(strArr[2], 10, 64)
  149. if err != nil {
  150. return nil, err
  151. }
  152. if len(strArr[4]) != hex.EncodedLen(10) {
  153. return nil, fmt.Errorf("operation uid does not have hex length 10")
  154. }
  155. return &UniqueNameWithOperation{
  156. Kind: strArr[0],
  157. ProjectID: uint(projID),
  158. InfraID: uint(infraID),
  159. Suffix: strArr[3],
  160. OperationUID: strArr[4],
  161. }, nil
  162. }
  163. func GetWorkspaceID(infra *Infra, operation *Operation) string {
  164. return fmt.Sprintf("%s-%d-%d-%s-%s", infra.Kind, infra.ProjectID, infra.ID, infra.Suffix, operation.UID)
  165. }