up.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package backend
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "os/signal"
  7. "syscall"
  8. "github.com/compose-spec/compose-go/cli"
  9. "github.com/compose-spec/compose-go/types"
  10. "github.com/docker/ecs-plugin/pkg/compose"
  11. "github.com/docker/ecs-plugin/pkg/console"
  12. )
  13. func (b *Backend) Up(ctx context.Context, options cli.ProjectOptions) error {
  14. project, err := cli.ProjectFromOptions(&options)
  15. if err != nil {
  16. return err
  17. }
  18. err = b.api.CheckRequirements(ctx)
  19. if err != nil {
  20. return err
  21. }
  22. cluster, err := b.GetCluster(ctx, project)
  23. if err != nil {
  24. return err
  25. }
  26. template, err := b.Convert(project)
  27. if err != nil {
  28. return err
  29. }
  30. vpc, err := b.GetVPC(ctx, project)
  31. if err != nil {
  32. return err
  33. }
  34. subNets, err := b.api.GetSubNets(ctx, vpc)
  35. if err != nil {
  36. return err
  37. }
  38. if len(subNets) < 2 {
  39. return fmt.Errorf("VPC %s should have at least 2 associated subnets in different availability zones", vpc)
  40. }
  41. lb, err := b.GetLoadBalancer(ctx, project)
  42. if err != nil {
  43. return err
  44. }
  45. parameters := map[string]string{
  46. ParameterClusterName: cluster,
  47. ParameterVPCId: vpc,
  48. ParameterSubnet1Id: subNets[0],
  49. ParameterSubnet2Id: subNets[1],
  50. ParameterLoadBalancerARN: lb,
  51. }
  52. update, err := b.api.StackExists(ctx, project.Name)
  53. if err != nil {
  54. return err
  55. }
  56. operation := compose.StackCreate
  57. if update {
  58. operation = compose.StackUpdate
  59. changeset, err := b.api.CreateChangeSet(ctx, project.Name, template, parameters)
  60. if err != nil {
  61. return err
  62. }
  63. err = b.api.UpdateStack(ctx, changeset)
  64. if err != nil {
  65. return err
  66. }
  67. } else {
  68. err = b.api.CreateStack(ctx, project.Name, template, parameters)
  69. if err != nil {
  70. return err
  71. }
  72. }
  73. fmt.Println()
  74. w := console.NewProgressWriter()
  75. for k := range template.Resources {
  76. w.ResourceEvent(k, "PENDING", "")
  77. }
  78. signalChan := make(chan os.Signal, 1)
  79. signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
  80. go func() {
  81. <-signalChan
  82. fmt.Println("user interrupted deployment. Deleting stack...")
  83. b.Down(ctx, options)
  84. }()
  85. return b.WaitStackCompletion(ctx, project.Name, operation, w)
  86. }
  87. func (b Backend) GetVPC(ctx context.Context, project *types.Project) (string, error) {
  88. //check compose file for custom VPC selected
  89. if vpc, ok := project.Extensions[compose.ExtensionVPC]; ok {
  90. vpcID := vpc.(string)
  91. ok, err := b.api.VpcExists(ctx, vpcID)
  92. if err != nil {
  93. return "", err
  94. }
  95. if !ok {
  96. return "", fmt.Errorf("VPC does not exist: %s", vpc)
  97. }
  98. return vpcID, nil
  99. }
  100. defaultVPC, err := b.api.GetDefaultVPC(ctx)
  101. if err != nil {
  102. return "", err
  103. }
  104. return defaultVPC, nil
  105. }
  106. func (b Backend) GetLoadBalancer(ctx context.Context, project *types.Project) (string, error) {
  107. //check compose file for custom VPC selected
  108. if ext, ok := project.Extensions[compose.ExtensionLB]; ok {
  109. lb := ext.(string)
  110. ok, err := b.api.LoadBalancerExists(ctx, lb)
  111. if err != nil {
  112. return "", err
  113. }
  114. if !ok {
  115. return "", fmt.Errorf("load balancer does not exist: %s", lb)
  116. }
  117. return lb, nil
  118. }
  119. return "", nil
  120. }
  121. func (b Backend) GetCluster(ctx context.Context, project *types.Project) (string, error) {
  122. //check compose file for custom VPC selected
  123. if ext, ok := project.Extensions[compose.ExtensionCluster]; ok {
  124. cluster := ext.(string)
  125. ok, err := b.api.ClusterExists(ctx, cluster)
  126. if err != nil {
  127. return "", err
  128. }
  129. if !ok {
  130. return "", fmt.Errorf("cluster does not exist: %s", cluster)
  131. }
  132. return cluster, nil
  133. }
  134. return "", nil
  135. }