infra.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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 GCP integration that was used to create the infra
  39. GCPIntegrationID uint
  40. // The DO integration that was used to create the infra:
  41. // this points to an OAuthIntegrationID
  42. DOIntegrationID uint
  43. // The database id for the infra, if this infra provisioned a database
  44. DatabaseID uint
  45. Database Database
  46. // ------------------------------------------------------------------
  47. // All fields below this line are encrypted before storage
  48. // ------------------------------------------------------------------
  49. // The last-applied input variables to the provisioner
  50. LastApplied []byte
  51. }
  52. type Operation struct {
  53. gorm.Model
  54. UID string `gorm:"unique"`
  55. InfraID uint
  56. Type string
  57. Status string
  58. Errored bool
  59. Error string
  60. TemplateVersion string
  61. // ------------------------------------------------------------------
  62. // All fields below this line are encrypted before storage
  63. // ------------------------------------------------------------------
  64. // The last-applied input variables to the provisioner
  65. LastApplied []byte
  66. }
  67. func (o *Operation) ToOperationMetaType() *types.OperationMeta {
  68. return &types.OperationMeta{
  69. LastUpdated: o.UpdatedAt,
  70. UID: o.UID,
  71. InfraID: o.InfraID,
  72. Type: o.Type,
  73. Status: o.Status,
  74. Errored: o.Errored,
  75. Error: o.Error,
  76. }
  77. }
  78. func (o *Operation) ToOperationType() (*types.Operation, error) {
  79. // unmarshal last applied
  80. lastApplied := make(map[string]interface{})
  81. err := json.Unmarshal(o.LastApplied, &lastApplied)
  82. if err != nil {
  83. return nil, err
  84. }
  85. return &types.Operation{
  86. OperationMeta: o.ToOperationMetaType(),
  87. LastApplied: lastApplied,
  88. }, nil
  89. }
  90. func GetOperationID() (string, error) {
  91. return encryption.GenerateRandomBytes(10)
  92. }
  93. // ToInfraType generates an external Infra to be shared over REST
  94. func (i *Infra) ToInfraType() *types.Infra {
  95. return &types.Infra{
  96. ID: i.ID,
  97. CreatedAt: i.CreatedAt,
  98. UpdatedAt: i.UpdatedAt,
  99. ProjectID: i.ProjectID,
  100. APIVersion: i.APIVersion,
  101. SourceLink: i.SourceLink,
  102. SourceVersion: i.SourceVersion,
  103. Kind: i.Kind,
  104. Status: i.Status,
  105. AWSIntegrationID: i.AWSIntegrationID,
  106. DOIntegrationID: i.DOIntegrationID,
  107. GCPIntegrationID: i.GCPIntegrationID,
  108. }
  109. }
  110. // GetID returns the unique id for this infra
  111. func (i *Infra) GetUniqueName() string {
  112. return fmt.Sprintf("%s-%d-%d-%s", i.Kind, i.ProjectID, i.ID, i.Suffix)
  113. }
  114. // ParseUniqueName returns the (kind, projectID, infraID, suffix)
  115. func ParseUniqueName(workspaceID string) (string, uint, uint, string, error) {
  116. strArr := strings.Split(workspaceID, "-")
  117. if len(strArr) != 4 {
  118. return "", 0, 0, "", fmt.Errorf("workspace id improperly formatted")
  119. }
  120. projID, err := strconv.ParseUint(strArr[1], 10, 64)
  121. if err != nil {
  122. return "", 0, 0, "", err
  123. }
  124. infraID, err := strconv.ParseUint(strArr[2], 10, 64)
  125. if err != nil {
  126. return "", 0, 0, "", err
  127. }
  128. return strArr[0], uint(projID), uint(infraID), strArr[3], nil
  129. }
  130. type UniqueNameWithOperation struct {
  131. Kind string
  132. ProjectID uint
  133. InfraID uint
  134. Suffix string
  135. OperationUID string
  136. }
  137. func ParseWorkspaceID(workspaceID string) (*UniqueNameWithOperation, error) {
  138. strArr := strings.Split(workspaceID, "-")
  139. if len(strArr) != 5 {
  140. return nil, fmt.Errorf("workspace id improperly formatted: %s", workspaceID)
  141. }
  142. projID, err := strconv.ParseUint(strArr[1], 10, 64)
  143. if err != nil {
  144. return nil, err
  145. }
  146. infraID, err := strconv.ParseUint(strArr[2], 10, 64)
  147. if err != nil {
  148. return nil, err
  149. }
  150. if len(strArr[4]) != hex.EncodedLen(10) {
  151. return nil, fmt.Errorf("operation uid does not have hex length 10")
  152. }
  153. return &UniqueNameWithOperation{
  154. Kind: strArr[0],
  155. ProjectID: uint(projID),
  156. InfraID: uint(infraID),
  157. Suffix: strArr[3],
  158. OperationUID: strArr[4],
  159. }, nil
  160. }
  161. func GetWorkspaceID(infra *Infra, operation *Operation) string {
  162. return fmt.Sprintf("%s-%d-%d-%s-%s", infra.Kind, infra.ProjectID, infra.ID, infra.Suffix, operation.UID)
  163. }