github.com/defang-io/defang/src@v0.0.0-20240505002154-bdf411911834/pkg/cmd/run.go (about)

     1  package cmd
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"os/signal"
     8  	"syscall"
     9  	"time"
    10  
    11  	"github.com/defang-io/defang/src/pkg/clouds/aws/ecs/cfn"
    12  	"github.com/defang-io/defang/src/pkg/types"
    13  )
    14  
    15  type RunContainerArgs struct {
    16  	Region   Region
    17  	Image    string
    18  	Memory   uint64
    19  	Args     []string
    20  	Env      map[string]string
    21  	Platform string
    22  	VpcID    string
    23  	SubnetID string
    24  }
    25  
    26  var cleanup = make(chan func())
    27  
    28  func init() {
    29  	go func() {
    30  		c := make(chan os.Signal, 1)
    31  		signal.Notify(c, os.Interrupt, syscall.SIGTERM)
    32  		var clanupFns []func()
    33  
    34  		for {
    35  			select {
    36  			case f := <-cleanup:
    37  				clanupFns = append(clanupFns, f)
    38  			case s := <-c:
    39  				fmt.Printf("Caught signal %v, cleaning up...\n", s)
    40  				for _, f := range clanupFns {
    41  					f()
    42  				}
    43  				os.Exit(0)
    44  			}
    45  		}
    46  	}()
    47  }
    48  
    49  func Run(ctx context.Context, args RunContainerArgs) error {
    50  	driver, err := createDriver(args.Region, cfn.OptionVPCAndSubnetID(ctx, args.VpcID, args.SubnetID))
    51  	if err != nil { // VPC affects the cloudformation template
    52  		return err
    53  	}
    54  
    55  	containers := []types.Container{
    56  		{
    57  			Image:    args.Image,
    58  			Memory:   args.Memory,
    59  			Platform: args.Platform,
    60  		},
    61  	}
    62  	if err := driver.SetUp(ctx, containers); err != nil {
    63  		return err
    64  	}
    65  
    66  	id, err := driver.Run(ctx, args.Env, args.Args...)
    67  	if err != nil {
    68  		return err
    69  	}
    70  
    71  	cleanup <- func() {
    72  		fmt.Printf("Stopping task %s...\n", *id)
    73  		driver.Stop(ctx, id)
    74  	}
    75  	fmt.Println("Task ID:", *id)
    76  
    77  	// Try 10 times to get the public IP address
    78  	for i := 0; i < 10; i++ {
    79  		info, err := driver.GetInfo(ctx, id)
    80  		if err != nil {
    81  			time.Sleep(time.Second)
    82  			continue
    83  		}
    84  		if info != nil {
    85  			fmt.Println("IP:", info.IP)
    86  		}
    87  		break
    88  	}
    89  
    90  	// FIXME: stop task on context cancelation/ctrl-c?
    91  	return driver.Tail(ctx, id)
    92  }