| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- package models
- import (
- "encoding/hex"
- "encoding/json"
- "fmt"
- "strconv"
- "strings"
- "gorm.io/gorm"
- "github.com/porter-dev/porter/api/types"
- "github.com/porter-dev/porter/internal/encryption"
- )
- // Infra represents the metadata for an infrastructure type provisioned on
- // Porter
- type Infra struct {
- gorm.Model
- // The type of infra that was provisioned
- Kind types.InfraKind
- // The infrastructure API version
- APIVersion string
- // The source link (only set on apiVersion >= v2)
- SourceLink string
- // The source version (only set on apiVersion >= v2)
- SourceVersion string
- // A random 6-byte suffix to ensure workspace/stream ids are unique
- Suffix string
- // The project that this infra belongs to
- ProjectID uint
- // The ID of the user that created this infra
- CreatedByUserID uint
- // If this infra was created under a cluster scope (for example, for RDS), the parent cluster
- // ID
- ParentClusterID uint
- // Status is the status of the infra
- Status types.InfraStatus
- Operations []Operation
- // The AWS integration that was used to create the infra
- AWSIntegrationID uint
- // The Azure integration that was used to create the infra
- AzureIntegrationID uint
- // The GCP integration that was used to create the infra
- GCPIntegrationID uint
- // The DO integration that was used to create the infra:
- // this points to an OAuthIntegrationID
- DOIntegrationID uint
- // The database id for the infra, if this infra provisioned a database
- DatabaseID uint
- Database Database
- // ------------------------------------------------------------------
- // All fields below this line are encrypted before storage
- // ------------------------------------------------------------------
- // The last-applied input variables to the provisioner
- LastApplied []byte
- }
- type Operation struct {
- gorm.Model
- UID string `gorm:"unique"`
- InfraID uint
- Type string
- Status string
- Errored bool
- Error string
- TemplateVersion string
- // ------------------------------------------------------------------
- // All fields below this line are encrypted before storage
- // ------------------------------------------------------------------
- // The last-applied input variables to the provisioner
- LastApplied []byte
- }
- func (o *Operation) ToOperationMetaType() *types.OperationMeta {
- return &types.OperationMeta{
- LastUpdated: o.UpdatedAt,
- UID: o.UID,
- InfraID: o.InfraID,
- Type: o.Type,
- Status: o.Status,
- Errored: o.Errored,
- Error: o.Error,
- }
- }
- func (o *Operation) ToOperationType() (*types.Operation, error) {
- // unmarshal last applied
- lastApplied := make(map[string]interface{})
- err := json.Unmarshal(o.LastApplied, &lastApplied)
- if err != nil {
- return nil, err
- }
- return &types.Operation{
- OperationMeta: o.ToOperationMetaType(),
- LastApplied: lastApplied,
- }, nil
- }
- func GetOperationID() (string, error) {
- return encryption.GenerateRandomBytes(10)
- }
- type getInfraName struct {
- Name string `json:"name"`
- ClusterName string `json:"cluster_name"`
- DBName string `json:"db_name"`
- BucketName string `json:"bucket_name"`
- DOCRName string `json:"docr_name"`
- ECRName string `json:"ecr_name"`
- ACRName string `json:"acr_name"`
- }
- // ToInfraType generates an external Infra to be shared over REST
- func (i *Infra) ToInfraType() *types.Infra {
- // perform best attempt to get infra name
- var name string
- infraName := &getInfraName{}
- if err := json.Unmarshal(i.LastApplied, infraName); err == nil {
- if infraName.DOCRName != "" {
- name = infraName.DOCRName
- }
- if infraName.ECRName != "" {
- name = infraName.ECRName
- }
- if infraName.ACRName != "" {
- name = infraName.ACRName
- }
- if infraName.DBName != "" {
- name = infraName.DBName
- }
- if infraName.BucketName != "" {
- name = infraName.BucketName
- }
- if infraName.ClusterName != "" {
- name = infraName.ClusterName
- }
- if infraName.Name != "" {
- name = infraName.Name
- }
- }
- return &types.Infra{
- ID: i.ID,
- Name: name,
- CreatedAt: i.CreatedAt,
- UpdatedAt: i.UpdatedAt,
- ProjectID: i.ProjectID,
- APIVersion: i.APIVersion,
- SourceLink: i.SourceLink,
- SourceVersion: i.SourceVersion,
- Kind: i.Kind,
- Status: i.Status,
- AWSIntegrationID: i.AWSIntegrationID,
- DOIntegrationID: i.DOIntegrationID,
- GCPIntegrationID: i.GCPIntegrationID,
- }
- }
- // GetID returns the unique id for this infra
- func (i *Infra) GetUniqueName() string {
- return fmt.Sprintf("%s-%d-%d-%s", i.Kind, i.ProjectID, i.ID, i.Suffix)
- }
- // ParseUniqueName returns the (kind, projectID, infraID, suffix)
- func ParseUniqueName(workspaceID string) (string, uint, uint, string, error) {
- strArr := strings.Split(workspaceID, "-")
- if len(strArr) != 4 {
- return "", 0, 0, "", fmt.Errorf("workspace id improperly formatted")
- }
- projID, err := strconv.ParseUint(strArr[1], 10, 64)
- if err != nil {
- return "", 0, 0, "", err
- }
- infraID, err := strconv.ParseUint(strArr[2], 10, 64)
- if err != nil {
- return "", 0, 0, "", err
- }
- return strArr[0], uint(projID), uint(infraID), strArr[3], nil
- }
- type UniqueNameWithOperation struct {
- Kind string
- ProjectID uint
- InfraID uint
- Suffix string
- OperationUID string
- }
- func ParseWorkspaceID(workspaceID string) (*UniqueNameWithOperation, error) {
- strArr := strings.Split(workspaceID, "-")
- if len(strArr) != 5 {
- return nil, fmt.Errorf("workspace id improperly formatted: %s", workspaceID)
- }
- projID, err := strconv.ParseUint(strArr[1], 10, 64)
- if err != nil {
- return nil, err
- }
- infraID, err := strconv.ParseUint(strArr[2], 10, 64)
- if err != nil {
- return nil, err
- }
- if len(strArr[4]) != hex.EncodedLen(10) {
- return nil, fmt.Errorf("operation uid does not have hex length 10")
- }
- return &UniqueNameWithOperation{
- Kind: strArr[0],
- ProjectID: uint(projID),
- InfraID: uint(infraID),
- Suffix: strArr[3],
- OperationUID: strArr[4],
- }, nil
- }
- func GetWorkspaceID(infra *Infra, operation *Operation) string {
- return fmt.Sprintf("%s-%d-%d-%s-%s", infra.Kind, infra.ProjectID, infra.ID, infra.Suffix, operation.UID)
- }
|