stack.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. package gorm
  2. import (
  3. "github.com/porter-dev/porter/internal/models"
  4. "github.com/porter-dev/porter/internal/repository"
  5. "gorm.io/gorm"
  6. )
  7. // StackRepository uses gorm.DB for querying the database
  8. type StackRepository struct {
  9. db *gorm.DB
  10. }
  11. // NewStackRepository returns a StackRepository which uses
  12. // gorm.DB for querying the database
  13. func NewStackRepository(db *gorm.DB) repository.StackRepository {
  14. return &StackRepository{db}
  15. }
  16. // CreateStack creates a new stack
  17. func (repo *StackRepository) CreateStack(stack *models.Stack) (*models.Stack, error) {
  18. if err := repo.db.Create(stack).Error; err != nil {
  19. return nil, err
  20. }
  21. return stack, nil
  22. }
  23. // ReadStack gets a stack specified by its string id
  24. func (repo *StackRepository) ListStacks(projectID, clusterID uint, namespace string) ([]*models.Stack, error) {
  25. stacks := make([]*models.Stack, 0)
  26. query := repo.db.Where("stacks.project_id = ? AND stacks.cluster_id = ?", projectID, clusterID)
  27. if namespace != "" {
  28. query = query.Where("stacks.namespace = ?", namespace)
  29. }
  30. // get stack IDs
  31. if err := query.Find(&stacks).Error; err != nil {
  32. return nil, err
  33. }
  34. stackIDs := make([]uint, 0)
  35. for _, initStack := range stacks {
  36. stackIDs = append(stackIDs, initStack.ID)
  37. }
  38. // query for each stack's revision
  39. revisions := make([]*models.StackRevision, 0)
  40. if err := repo.db.Preload("SourceConfigs").Preload("Resources").Preload("EnvGroups").Where("stack_revisions.stack_id IN (?)", stackIDs).Where(`
  41. stack_revisions.id IN (
  42. SELECT s2.id FROM (SELECT MAX(stack_revisions.id) id FROM stack_revisions WHERE stack_revisions.stack_id IN (?) GROUP BY stack_revisions.stack_id) s2
  43. )
  44. `, stackIDs).
  45. Find(&revisions).Error; err != nil {
  46. return nil, err
  47. }
  48. // insert revisions into a map
  49. stackIDToRevisionMap := make(map[uint]models.StackRevision)
  50. for _, revision := range revisions {
  51. stackIDToRevisionMap[revision.StackID] = *revision
  52. }
  53. // look up each revision for each stack
  54. for _, stack := range stacks {
  55. if _, exists := stackIDToRevisionMap[stack.ID]; exists {
  56. stack.Revisions = append(stack.Revisions, stackIDToRevisionMap[stack.ID])
  57. }
  58. }
  59. return stacks, nil
  60. }
  61. func (repo *StackRepository) ReadStackByID(projectID, stackID uint) (*models.Stack, error) {
  62. stack := &models.Stack{}
  63. if err := repo.db.
  64. Preload("Revisions", func(db *gorm.DB) *gorm.DB {
  65. return db.Order("stack_revisions.revision_number DESC").Limit(100)
  66. }).
  67. Preload("Revisions.Resources").
  68. Preload("Revisions.SourceConfigs").
  69. Preload("Revisions.EnvGroups").
  70. Where("stacks.project_id = ? AND stacks.id = ?", projectID, stackID).First(&stack).Error; err != nil {
  71. return nil, err
  72. }
  73. return stack, nil
  74. }
  75. // ReadStack gets a stack specified by its string id
  76. func (repo *StackRepository) ReadStackByStringID(projectID uint, stackID string) (*models.Stack, error) {
  77. stack := &models.Stack{}
  78. if err := repo.db.
  79. Preload("Revisions", func(db *gorm.DB) *gorm.DB {
  80. return db.Order("stack_revisions.revision_number DESC").Limit(100)
  81. }).
  82. Preload("Revisions.Resources").
  83. Preload("Revisions.SourceConfigs").
  84. Preload("Revisions.EnvGroups").
  85. Where("stacks.project_id = ? AND stacks.uid = ?", projectID, stackID).First(&stack).Error; err != nil {
  86. return nil, err
  87. }
  88. return stack, nil
  89. }
  90. // DeleteStack creates a new stack
  91. func (repo *StackRepository) DeleteStack(stack *models.Stack) (*models.Stack, error) {
  92. if err := repo.db.Delete(stack).Error; err != nil {
  93. return nil, err
  94. }
  95. return stack, nil
  96. }
  97. func (repo *StackRepository) UpdateStack(stack *models.Stack) (*models.Stack, error) {
  98. if err := repo.db.Save(stack).Error; err != nil {
  99. return nil, err
  100. }
  101. return stack, nil
  102. }
  103. func (repo *StackRepository) UpdateStackRevision(revision *models.StackRevision) (*models.StackRevision, error) {
  104. if err := repo.db.Save(revision).Error; err != nil {
  105. return nil, err
  106. }
  107. return revision, nil
  108. }
  109. func (repo *StackRepository) ReadStackRevision(stackRevisionID uint) (*models.StackRevision, error) {
  110. revision := &models.StackRevision{}
  111. if err := repo.db.Preload("Resources").Preload("SourceConfigs").Preload("EnvGroups").Where("id = ?", stackRevisionID).First(&revision).Error; err != nil {
  112. return nil, err
  113. }
  114. return revision, nil
  115. }
  116. func (repo *StackRepository) ReadStackRevisionByNumber(stackID uint, revisionNumber uint) (*models.StackRevision, error) {
  117. revision := &models.StackRevision{}
  118. if err := repo.db.Preload("Resources").Preload("SourceConfigs").Preload("EnvGroups").Where("stack_id = ? AND revision_number = ?", stackID, revisionNumber).First(&revision).Error; err != nil {
  119. return nil, err
  120. }
  121. return revision, nil
  122. }
  123. func (repo *StackRepository) AppendNewRevision(revision *models.StackRevision) (*models.StackRevision, error) {
  124. stack := &models.Stack{}
  125. if err := repo.db.Where("id = ?", revision.StackID).First(&stack).Error; err != nil {
  126. return nil, err
  127. }
  128. assoc := repo.db.Model(&stack).Association("Revisions")
  129. if assoc.Error != nil {
  130. return nil, assoc.Error
  131. }
  132. if err := assoc.Append(revision); err != nil {
  133. return nil, err
  134. }
  135. return revision, nil
  136. }
  137. func (repo *StackRepository) ReadStackResource(resourceID uint) (*models.StackResource, error) {
  138. resource := &models.StackResource{}
  139. if err := repo.db.Where("id = ?", resourceID).First(&resource).Error; err != nil {
  140. return nil, err
  141. }
  142. return resource, nil
  143. }
  144. func (repo *StackRepository) UpdateStackResource(resource *models.StackResource) (*models.StackResource, error) {
  145. if err := repo.db.Save(resource).Error; err != nil {
  146. return nil, err
  147. }
  148. return resource, nil
  149. }
  150. func (repo *StackRepository) ReadStackEnvGroupFirstMatch(projectID, clusterID uint, namespace, name string) (*models.StackEnvGroup, error) {
  151. envGroup := &models.StackEnvGroup{}
  152. if err := repo.db.Where("project_id = ? AND cluster_id = ? AND namespace = ? AND name = ?", projectID, clusterID, namespace, name).Order("id desc").First(&envGroup).Error; err != nil {
  153. return nil, err
  154. }
  155. return envGroup, nil
  156. }