github.com/awslabs/fargatecli@v0.3.2-0.20210502061925-aa1c09cd404e/cmd/task_run.go (about) 1 package cmd 2 3 import ( 4 CWL "github.com/awslabs/fargatecli/cloudwatchlogs" 5 "github.com/awslabs/fargatecli/console" 6 "github.com/awslabs/fargatecli/docker" 7 EC2 "github.com/awslabs/fargatecli/ec2" 8 ECR "github.com/awslabs/fargatecli/ecr" 9 ECS "github.com/awslabs/fargatecli/ecs" 10 "github.com/awslabs/fargatecli/git" 11 IAM "github.com/awslabs/fargatecli/iam" 12 "github.com/spf13/cobra" 13 ) 14 15 const typeTask string = "task" 16 17 type TaskRunOperation struct { 18 Cpu string 19 EnvVars []ECS.EnvVar 20 Image string 21 Memory string 22 Num int64 23 SecurityGroupIds []string 24 SubnetIds []string 25 TaskName string 26 TaskRole string 27 TaskCommand []string 28 } 29 30 func (o *TaskRunOperation) Validate() { 31 err := validateCpuAndMemory(o.Cpu, o.Memory) 32 33 if err != nil { 34 console.ErrorExit(err, "Invalid settings: %s CPU units / %s MiB", o.Cpu, o.Memory) 35 } 36 37 if o.Num < 1 { 38 console.ErrorExit(err, "Invalid number of tasks: %d, num must be > 1", o.Num) 39 } 40 } 41 42 func (o *TaskRunOperation) SetEnvVars(inputEnvVars []string) { 43 o.EnvVars = extractEnvVars(inputEnvVars) 44 } 45 46 var ( 47 flagTaskRunNum int64 48 flagTaskRunCpu string 49 flagTaskRunEnvVars []string 50 flagTaskRunImage string 51 flagTaskRunMemory string 52 flagTaskRunSecurityGroupIds []string 53 flagTaskRunSubnetIds []string 54 flagTaskRunTaskRole string 55 flagTaskRunTaskCommand []string 56 ) 57 58 var taskRunCmd = &cobra.Command{ 59 Use: "run <task name>", 60 Short: "Run new tasks", 61 Long: `Run new tasks 62 63 You must specify a task group name in order to interact with the task(s) in 64 subsequent commands to view logs, stop and inspect tasks. Task group names do 65 not have to be unique -- multiple configurations of task instances can be 66 started with the same task group. 67 68 Multiple instances of a task can be run by specifying a number in the --num 69 flag. If no number is specified, a single task instance will be run. 70 71 CPU and memory settings can be optionally specified as CPU units and mebibytes 72 respectively using the --cpu and --memory flags. Every 1024 CPU units is 73 equivilent to a single vCPU. AWS Fargate only supports certain combinations of 74 CPU and memory configurations: 75 76 | CPU (CPU Units) | Memory (MiB) | 77 | --------------- | ------------------------------------- | 78 | 256 | 512, 1024, or 2048 | 79 | 512 | 1024 through 4096 in 1GiB increments | 80 | 1024 | 2048 through 8192 in 1GiB increments | 81 | 2048 | 4096 through 16384 in 1GiB increments | 82 | 4096 | 8192 through 30720 in 1GiB increments | 83 84 If not specified, fargate will launch minimally sized tasks at 0.25 vCPU (256 85 CPU units) and 0.5GB (512 MiB) of memory. 86 87 The Docker container image to use in the task can be optionally specified via 88 the --image flag. If not specified, fargate will build a new Docker container 89 image from the current working directory and push it to Amazon ECR in a 90 repository named for the task group. If the current working directory is a git 91 repository, the container image will be tagged with the short ref of the HEAD 92 commit. If not, a timestamp in the format of YYYYMMDDHHMMSS will be used. 93 94 Environment variables can be specified via the --env flag. Specify --env with a 95 key=value parameter multiple times to add multiple variables. 96 97 Security groups can optionally be specified for the task by passing the 98 --security-group-id flag with a security group ID. To add multiple security 99 groups, pass --security-group-id with a security group ID multiple times. If 100 --security-group-id is omitted, a permissive security group will be applied to 101 the task. 102 103 By default, the task will be created in the default VPC and attached to the 104 default VPC subnets for each availability zone. You can override this by 105 specifying explicit subnets by passing the --subnet-id flag with a subnet ID. 106 107 A task role can be optionally specified via the --task-role flag by providing 108 eith a full IAM role ARN or the name of an IAM role. The tasks will be able to 109 assume this role. 110 111 The default command of the docker image can be overridden using the 112 --task-command flag, where the value is a string of comma seperated values 113 representing the command. These values will be placed into an array as per 114 the requirements of the docker CMD syntax`, 115 116 Args: cobra.ExactArgs(1), 117 Run: func(cmd *cobra.Command, args []string) { 118 operation := &TaskRunOperation{ 119 Cpu: flagTaskRunCpu, 120 Image: flagTaskRunImage, 121 Memory: flagTaskRunMemory, 122 Num: flagTaskRunNum, 123 SecurityGroupIds: flagTaskRunSecurityGroupIds, 124 SubnetIds: flagTaskRunSubnetIds, 125 TaskName: args[0], 126 TaskRole: flagTaskRunTaskRole, 127 TaskCommand: flagTaskRunTaskCommand, 128 } 129 130 operation.SetEnvVars(flagTaskRunEnvVars) 131 operation.Validate() 132 133 runTask(operation) 134 }, 135 } 136 137 func init() { 138 taskRunCmd.Flags().Int64VarP(&flagTaskRunNum, "num", "n", 1, "Number of task instances to run") 139 taskRunCmd.Flags().StringSliceVarP(&flagTaskRunEnvVars, "env", "e", []string{}, "Environment variables to set [e.g. KEY=value] (can be specified multiple times)") 140 taskRunCmd.Flags().StringVarP(&flagTaskRunCpu, "cpu", "c", "256", "Amount of cpu units to allocate for each task") 141 taskRunCmd.Flags().StringVarP(&flagTaskRunImage, "image", "i", "", "Docker image to run; if omitted Fargate will build an image from the Dockerfile in the current directory") 142 taskRunCmd.Flags().StringVarP(&flagTaskRunMemory, "memory", "m", "512", "Amount of MiB to allocate for each task") 143 taskRunCmd.Flags().StringSliceVar(&flagTaskRunSecurityGroupIds, "security-group-id", []string{}, "ID of a security group to apply to the task (can be specified multiple times)") 144 taskRunCmd.Flags().StringSliceVar(&flagTaskRunSubnetIds, "subnet-id", []string{}, "ID of a subnet in which to place the task (can be specified multiple times)") 145 taskRunCmd.Flags().StringVarP(&flagTaskRunTaskRole, "task-role", "", "", "Name or ARN of an IAM role that the tasks can assume") 146 taskRunCmd.Flags().StringSliceVar(&flagTaskRunTaskCommand, "task-command", []string{}, "Command to run inside container instead of the one specified in the docker image") 147 taskCmd.AddCommand(taskRunCmd) 148 } 149 150 func runTask(operation *TaskRunOperation) { 151 cwl := CWL.New(sess) 152 ec2 := EC2.New(sess) 153 ecr := ECR.New(sess) 154 ecs := ECS.New(sess, clusterName) 155 iam := IAM.New(sess) 156 ecsTaskExecutionRoleArn := iam.CreateEcsTaskExecutionRole() 157 logGroupName := cwl.CreateLogGroup(taskLogGroupFormat, operation.TaskName) 158 159 if len(operation.SecurityGroupIds) == 0 { 160 defaultSecurityGroupID, _ := ec2.GetDefaultSecurityGroupID() 161 operation.SecurityGroupIds = []string{defaultSecurityGroupID} 162 } 163 164 if len(operation.SubnetIds) == 0 { 165 operation.SubnetIds, _ = ec2.GetDefaultSubnetIDs() 166 } 167 168 if operation.Image == "" { 169 var repositoryUri, tag string 170 171 if ecr.IsRepositoryCreated(operation.TaskName) { 172 repositoryUri = ecr.GetRepositoryUri(operation.TaskName) 173 } else { 174 repositoryUri = ecr.CreateRepository(operation.TaskName) 175 } 176 177 if git.IsCwdGitRepo() { 178 tag = git.GetShortSha() 179 } else { 180 tag = docker.GenerateTag() 181 } 182 183 repository := docker.NewRepository(repositoryUri) 184 username, password := ecr.GetUsernameAndPassword() 185 186 repository.Login(username, password) 187 repository.Build(tag) 188 repository.Push(tag) 189 190 operation.Image = repository.UriFor(tag) 191 } 192 193 taskDefinitionArn := ecs.CreateTaskDefinition( 194 &ECS.CreateTaskDefinitionInput{ 195 Cpu: operation.Cpu, 196 EnvVars: operation.EnvVars, 197 ExecutionRoleArn: ecsTaskExecutionRoleArn, 198 Image: operation.Image, 199 LogGroupName: logGroupName, 200 LogRegion: region, 201 Memory: operation.Memory, 202 Name: operation.TaskName, 203 Type: typeTask, 204 TaskRole: operation.TaskRole, 205 TaskCommand: operation.TaskCommand, 206 }, 207 ) 208 209 ecs.RunTask( 210 &ECS.RunTaskInput{ 211 ClusterName: clusterName, 212 Count: operation.Num, 213 TaskName: operation.TaskName, 214 TaskDefinitionArn: taskDefinitionArn, 215 SubnetIds: operation.SubnetIds, 216 SecurityGroupIds: operation.SecurityGroupIds, 217 }, 218 ) 219 220 console.Info("Running task %s", operation.TaskName) 221 }