// convertToContainerDef transforms each service in the compose yml
// to an equivalent container definition
func convertToContainerDef(inputCfg *libcompose.ServiceConfig,
	volumes map[string]string, outputContDef *ecs.ContainerDefinition) error {
	// setting memory
	var mem int64
	if inputCfg.MemLimit != 0 {
		mem = inputCfg.MemLimit / kiB / kiB // convert bytes to MiB
	}
	if mem == 0 {
		mem = defaultMemLimit
	}

	// convert environment variables
	// TODO, read env file
	environment := []*ecs.KeyValuePair{}
	for _, env := range inputCfg.Environment.Slice() {
		parts := strings.SplitN(env, "=", 2)
		name := &parts[0]
		var value *string
		if len(parts) > 1 {
			value = &parts[1]
		}
		environment = append(environment, &ecs.KeyValuePair{
			Name:  name,
			Value: value,
		})
	}

	// convert port mappings
	portMappings, err := convertToPortMappings(*outputContDef.Name, inputCfg.Ports)
	if err != nil {
		return err
	}

	// convert volumes from
	volumesFrom := []*ecs.VolumeFrom{}
	for _, val := range inputCfg.VolumesFrom {
		volumeFrom := &ecs.VolumeFrom{
			SourceContainer: aws.String(val),
		}
		volumesFrom = append(volumesFrom, volumeFrom)
	}

	// convert mount points
	mountPoints, err := convertToMountPoints(inputCfg.Volumes, volumes)
	if err != nil {
		return err
	}
	// populating container definition, offloading the validation to aws-sdk
	outputContDef.Cpu = aws.Int64(inputCfg.CpuShares)
	outputContDef.Memory = aws.Int64(mem)
	outputContDef.EntryPoint = aws.StringSlice(inputCfg.Entrypoint.Slice())
	outputContDef.Command = aws.StringSlice(inputCfg.Command.Slice())
	outputContDef.Environment = environment
	outputContDef.Image = aws.String(inputCfg.Image)
	outputContDef.Links = aws.StringSlice(inputCfg.Links.Slice()) //TODO, read from external links
	outputContDef.MountPoints = mountPoints
	outputContDef.PortMappings = portMappings
	outputContDef.VolumesFrom = volumesFrom
	return nil
}
Example #2
0
func containerDef(family *string, containerPort *int64, hostPort *int64, image *string, cpu *int64, memory *int64, essential bool, links []*string) *ecs.ContainerDefinition {
	portMapping := &ecs.PortMapping{
		ContainerPort: containerPort,
		HostPort:      hostPort,
		Protocol:      aws.String("tcp"),
	}
	mountPoint := &ecs.MountPoint{
		ContainerPath: aws.String("/var/www/" + (*family) + "-vol"),
		SourceVolume:  aws.String(*family + "-vol"),
		ReadOnly:      aws.Bool(false),
	}
	c := ecs.ContainerDefinition{}

	c.Name = aws.String(*family + "-app")
	c.Image = image
	c.Cpu = cpu
	c.Memory = memory
	c.Essential = aws.Bool(essential)
	c.Links = links
	if *hostPort != 0 {
		c.PortMappings = []*ecs.PortMapping{portMapping}
	}
	c.MountPoints = []*ecs.MountPoint{mountPoint}
	return &c
}
Example #3
0
//
// Called by createTask() above. Given a filename, parse the JSON file and create a ContainerDefinition
// struct that can be passed to the SDK to create the task definition.
//
func makeTaskDefinition(taskFile string) (ecs.ContainerDefinition, string) {
	var taskJSON TaskDefn
	// Do it the easy way and read in the whole file. A JSON file's not going to be very large.
	fileBytes, err := ioutil.ReadFile(taskFile)
	CheckError(fmt.Sprintf("Error reading task file %s", taskFile), err)
	err = json.Unmarshal(fileBytes, &taskJSON)
	CheckError(fmt.Sprintf("Error reading task file %s", taskFile), err)
	// TODO: Support more than one if it's ever needed.
	if len(taskJSON.ContainerDefinitions) > 1 {
		fmt.Println("Right now I only support a single ContainerDefinition, sorry. Please edit and try again.")
		os.Exit(1)
	}

	// Now let's construct our Container Definition object, which is a lot of boring copying of fields.
	var defn ecs.ContainerDefinition
	defn.Cpu = &taskJSON.ContainerDefinitions[0].CPU
	var commands = make([]*string, 0)
	for i := 0; i < len(taskJSON.ContainerDefinitions[0].Command); i++ {
		commands = append(commands, &taskJSON.ContainerDefinitions[0].Command[i])
	}
	defn.Command = commands
	var entrypoints = make([]*string, 0)
	for i := 0; i < len(taskJSON.ContainerDefinitions[0].EntryPoint); i++ {
		entrypoints = append(entrypoints, &taskJSON.ContainerDefinitions[0].EntryPoint[i])
	}
	defn.EntryPoint = entrypoints
	var environments = make([]*ecs.KeyValuePair, 0)
	for i := 0; i < len(taskJSON.ContainerDefinitions[0].Environment); i++ {
		var keyval ecs.KeyValuePair
		keyval.Name = taskJSON.ContainerDefinitions[0].Environment[i].Name
		keyval.Value = taskJSON.ContainerDefinitions[0].Environment[i].Value
		environments = append(environments, &keyval)
	}
	defn.Environment = environments
	defn.Essential = &taskJSON.ContainerDefinitions[0].Essential
	defn.Image = &taskJSON.ContainerDefinitions[0].Image
	defn.Memory = &taskJSON.ContainerDefinitions[0].Memory
	defn.Name = &taskJSON.ContainerDefinitions[0].Name
	var ports = make([]*ecs.PortMapping, 0)
	for i := 0; i < len(taskJSON.ContainerDefinitions[0].PortMappings); i++ {
		var portmap ecs.PortMapping
		portmap.ContainerPort = taskJSON.ContainerDefinitions[0].PortMappings[i].ContainerPort
		portmap.HostPort = taskJSON.ContainerDefinitions[0].PortMappings[i].HostPort
		ports = append(ports, &portmap)
	}
	defn.PortMappings = ports
	return defn, taskJSON.Family
}
Example #4
0
func registratorDefinition(hostname *string, advertiseIP *string) *ecs.ContainerDefinition {
	c := ecs.ContainerDefinition{}
	c.Name = aws.String("kinja-consul-registrator")
	c.Hostname = hostname
	c.Image = aws.String("gliderlabs/registrator:latest")
	c.Cpu = aws.Int64(100)
	c.Memory = aws.Int64(64)
	c.Essential = aws.Bool(true)
	c.MountPoints = []*ecs.MountPoint{
		&ecs.MountPoint{
			ContainerPath: aws.String("/tmp/docker.sock"),
			SourceVolume:  aws.String("consul-socket"),
			ReadOnly:      aws.Bool(false),
		},
	}

	c.Command = []*string{
		//aws.String("-ip  $(curl -s http://169.254.169.254/latest/meta-data/local-ipv4)"),
		aws.String("-ip=" + *advertiseIP),
		aws.String("consul://" + *advertiseIP + ":8500"),
	}
	return &c
}
Example #5
0
func consulDefinition(hostname *string, serverIP *string, advertiseIP *string) *ecs.ContainerDefinition {
	c := ecs.ContainerDefinition{}
	c.Name = aws.String("kinja-consul-agent")
	c.Hostname = hostname
	c.Image = aws.String("progrium/consul")
	c.Cpu = aws.Int64(156)
	c.Memory = aws.Int64(256)
	c.Essential = aws.Bool(true)
	c.PortMappings = []*ecs.PortMapping{
		&ecs.PortMapping{
			ContainerPort: aws.Int64(8301),
			HostPort:      aws.Int64(8301),
			Protocol:      aws.String("tcp"),
		},
		&ecs.PortMapping{
			ContainerPort: aws.Int64(8301),
			HostPort:      aws.Int64(8301),
			Protocol:      aws.String("udp"),
		},
		&ecs.PortMapping{
			ContainerPort: aws.Int64(8400),
			HostPort:      aws.Int64(8400),
			Protocol:      aws.String("tcp"),
		},
		&ecs.PortMapping{
			ContainerPort: aws.Int64(8500),
			HostPort:      aws.Int64(8500),
			Protocol:      aws.String("tcp"),
		},
		&ecs.PortMapping{
			ContainerPort: aws.Int64(53),
			HostPort:      aws.Int64(53),
			Protocol:      aws.String("udp"),
		},
	}
	c.MountPoints = []*ecs.MountPoint{
		&ecs.MountPoint{
			ContainerPath: aws.String("/data"),
			SourceVolume:  aws.String("consul-vol"),
			ReadOnly:      aws.Bool(false),
		},
		&ecs.MountPoint{
			ContainerPath: aws.String("/var/run/docker.sock"),
			SourceVolume:  aws.String("consul-socket"),
			ReadOnly:      aws.Bool(false),
		},
		&ecs.MountPoint{
			ContainerPath: aws.String("/etc/consul"),
			SourceVolume:  aws.String("consul-config"),
			ReadOnly:      aws.Bool(false),
		},
	}

	session := sess.InitSession()

	c.Command = []*string{
		aws.String("--join " + *serverIP),
		//aws.String("--advertise  $(curl -s http://169.254.169.254/latest/meta-data/local-ipv4)"),
		aws.String("--advertise " + *advertiseIP),
		aws.String("-dc " + *session.Config.Region),
		aws.String("--config-file /etc/consul/consul.json"),
	}
	return &c
}
// convertToContainerDef transforms each service in the compose yml
// to an equivalent container definition
func convertToContainerDef(inputCfg *libcompose.ServiceConfig,
	volumes map[string]string, outputContDef *ecs.ContainerDefinition) error {
	// setting memory
	var mem int64
	if inputCfg.MemLimit != 0 {
		mem = inputCfg.MemLimit / kiB / kiB // convert bytes to MiB
	}
	if mem == 0 {
		mem = defaultMemLimit
	}

	// convert environment variables
	// TODO, read env file
	environment := []*ecs.KeyValuePair{}
	for _, env := range inputCfg.Environment.Slice() {
		parts := strings.SplitN(env, "=", 2)
		name := &parts[0]
		var value *string
		if len(parts) > 1 {
			value = &parts[1]
		}
		environment = append(environment, &ecs.KeyValuePair{
			Name:  name,
			Value: value,
		})
	}

	// convert port mappings
	portMappings, err := convertToPortMappings(*outputContDef.Name, inputCfg.Ports)
	if err != nil {
		return err
	}

	// convert volumes from
	volumesFrom := []*ecs.VolumeFrom{}
	for _, val := range inputCfg.VolumesFrom {
		volumeFrom := &ecs.VolumeFrom{
			SourceContainer: aws.String(val),
		}
		volumesFrom = append(volumesFrom, volumeFrom)
	}

	// convert mount points
	mountPoints, err := convertToMountPoints(inputCfg.Volumes, volumes)
	if err != nil {
		return err
	}

	// convert extra hosts
	extraHosts, err := convertToExtraHosts(inputCfg.ExtraHosts)
	if err != nil {
		return err
	}

	// convert log configuration
	var logConfig *ecs.LogConfiguration
	if inputCfg.LogDriver != "" {
		logConfig = &ecs.LogConfiguration{
			LogDriver: aws.String(inputCfg.LogDriver),
			Options:   aws.StringMap(inputCfg.LogOpt),
		}
	}

	// convert ulimits
	ulimits, err := convertToULimits(inputCfg.ULimits)
	if err != nil {
		return err
	}

	// populating container definition, offloading the validation to aws-sdk
	outputContDef.Cpu = aws.Int64(inputCfg.CpuShares)
	outputContDef.Command = aws.StringSlice(inputCfg.Command.Slice())
	outputContDef.DnsSearchDomains = aws.StringSlice(inputCfg.DNSSearch.Slice())
	outputContDef.DnsServers = aws.StringSlice(inputCfg.DNS.Slice())
	outputContDef.DockerLabels = aws.StringMap(inputCfg.Labels.MapParts())
	outputContDef.DockerSecurityOptions = aws.StringSlice(inputCfg.SecurityOpt)
	outputContDef.EntryPoint = aws.StringSlice(inputCfg.Entrypoint.Slice())
	outputContDef.Environment = environment
	outputContDef.ExtraHosts = extraHosts
	if inputCfg.Hostname != "" {
		outputContDef.Hostname = aws.String(inputCfg.Hostname)
	}
	outputContDef.Image = aws.String(inputCfg.Image)
	outputContDef.Links = aws.StringSlice(inputCfg.Links.Slice()) //TODO, read from external links
	outputContDef.LogConfiguration = logConfig
	outputContDef.Memory = aws.Int64(mem)
	outputContDef.MountPoints = mountPoints
	outputContDef.Privileged = aws.Bool(inputCfg.Privileged)
	outputContDef.PortMappings = portMappings
	outputContDef.ReadonlyRootFilesystem = aws.Bool(inputCfg.ReadOnly)
	outputContDef.Ulimits = ulimits
	if inputCfg.User != "" {
		outputContDef.User = aws.String(inputCfg.User)
	}
	outputContDef.VolumesFrom = volumesFrom
	if inputCfg.WorkingDir != "" {
		outputContDef.WorkingDirectory = aws.String(inputCfg.WorkingDir)
	}

	return nil
}
Example #7
0
func main() {
	fmt.Printf("Drone AWS ECS Plugin built at %s\n", buildDate)

	workspace := drone.Workspace{}
	repo := drone.Repo{}
	build := drone.Build{}
	vargs := Params{}

	plugin.Param("workspace", &workspace)
	plugin.Param("repo", &repo)
	plugin.Param("build", &build)
	plugin.Param("vargs", &vargs)
	plugin.MustParse()

	if len(vargs.AccessKey) == 0 {
		fmt.Println("Please provide an access key")

		os.Exit(1)
		return
	}

	if len(vargs.SecretKey) == 0 {
		fmt.Println("Please provide a secret key")

		os.Exit(1)
		return
	}

	if len(vargs.Region) == 0 {
		fmt.Println("Please provide a region")

		os.Exit(1)
		return
	}

	if len(vargs.Family) == 0 {
		fmt.Println("Please provide a task definition family name")

		os.Exit(1)
		return
	}

	if len(vargs.Image) == 0 {
		fmt.Println("Please provide an image name")

		os.Exit(1)
		return
	}

	if len(vargs.Tag) == 0 {
		vargs.Tag = "latest"
	}

	if len(vargs.Service) == 0 {
		fmt.Println("Please provide a service name")

		os.Exit(1)
		return
	}

	if vargs.Memory == 0 {
		vargs.Memory = 128
	}

	svc := ecs.New(
		session.New(&aws.Config{
			Region:      aws.String(vargs.Region),
			Credentials: credentials.NewStaticCredentials(vargs.AccessKey, vargs.SecretKey, ""),
		}))

	Image := vargs.Image + ":" + vargs.Tag

	definition := ecs.ContainerDefinition{
		Command: []*string{},

		DnsSearchDomains:      []*string{},
		DnsServers:            []*string{},
		DockerLabels:          map[string]*string{},
		DockerSecurityOptions: []*string{},
		EntryPoint:            []*string{},
		Environment:           []*ecs.KeyValuePair{},
		Essential:             aws.Bool(true),
		ExtraHosts:            []*ecs.HostEntry{},

		Image:        aws.String(Image),
		Links:        []*string{},
		Memory:       aws.Int64(vargs.Memory),
		MountPoints:  []*ecs.MountPoint{},
		Name:         aws.String(vargs.Family + "-container"),
		PortMappings: []*ecs.PortMapping{},

		Ulimits: []*ecs.Ulimit{},
		//User: aws.String("String"),
		VolumesFrom: []*ecs.VolumeFrom{},
		//WorkingDirectory: aws.String("String"),
	}

	// Port mappings
	for _, portMapping := range vargs.PortMappings.Slice() {
		cleanedPortMapping := strings.Trim(portMapping, " ")
		parts := strings.SplitN(cleanedPortMapping, " ", 2)
		hostPort, hostPortErr := strconv.ParseInt(parts[0], 10, 64)
		if hostPortErr != nil {
			fmt.Println(hostPortErr.Error())
			os.Exit(1)
			return
		}
		containerPort, containerPortError := strconv.ParseInt(parts[1], 10, 64)
		if containerPortError != nil {
			fmt.Println(containerPortError.Error())
			os.Exit(1)
			return
		}

		pair := ecs.PortMapping{
			ContainerPort: aws.Int64(containerPort),
			HostPort:      aws.Int64(hostPort),
			Protocol:      aws.String("TransportProtocol"),
		}

		definition.PortMappings = append(definition.PortMappings, &pair)
	}

	// Environment variables
	for _, envVar := range vargs.Environment.Slice() {
		parts := strings.SplitN(envVar, "=", 2)
		pair := ecs.KeyValuePair{
			Name:  aws.String(strings.Trim(parts[0], " ")),
			Value: aws.String(strings.Trim(parts[1], " ")),
		}
		definition.Environment = append(definition.Environment, &pair)
	}
	params := &ecs.RegisterTaskDefinitionInput{
		ContainerDefinitions: []*ecs.ContainerDefinition{
			&definition,
		},
		Family:  aws.String(vargs.Family),
		Volumes: []*ecs.Volume{},
	}
	resp, err := svc.RegisterTaskDefinition(params)

	if err != nil {
		fmt.Println(err.Error())

		os.Exit(1)
		return
	}

	val := *(resp.TaskDefinition.TaskDefinitionArn)
	sparams := &ecs.UpdateServiceInput{
		Service:        aws.String(vargs.Service),
		TaskDefinition: aws.String(val),
	}
	sresp, serr := svc.UpdateService(sparams)

	if serr != nil {
		fmt.Println(serr.Error())
		return
	}

	fmt.Println(sresp)

	fmt.Println(resp)
}
// convertToContainerDef transforms each service in the compose yml
// to an equivalent container definition
func convertToContainerDef(context *project.Context, inputCfg *config.ServiceConfig,
	volumes map[string]string, outputContDef *ecs.ContainerDefinition) error {
	// setting memory
	var mem int64
	if inputCfg.MemLimit != 0 {
		mem = int64(inputCfg.MemLimit) / kiB / kiB // convert bytes to MiB
	}
	if mem == 0 {
		mem = defaultMemLimit
	}

	// convert environment variables
	environment := convertToKeyValuePairs(context, inputCfg.Environment, *outputContDef.Name)

	// convert port mappings
	portMappings, err := convertToPortMappings(*outputContDef.Name, inputCfg.Ports)
	if err != nil {
		return err
	}

	// convert volumes from
	volumesFrom, err := convertToVolumesFrom(inputCfg.VolumesFrom)
	if err != nil {
		return err
	}

	// convert mount points
	mountPoints, err := convertToMountPoints(inputCfg.Volumes, volumes)
	if err != nil {
		return err
	}

	// convert extra hosts
	extraHosts, err := convertToExtraHosts(inputCfg.ExtraHosts)
	if err != nil {
		return err
	}

	// convert log configuration
	var logConfig *ecs.LogConfiguration
	if inputCfg.Logging.Driver != "" {
		logConfig = &ecs.LogConfiguration{
			LogDriver: aws.String(inputCfg.Logging.Driver),
			Options:   aws.StringMap(inputCfg.Logging.Options),
		}
	}

	// convert ulimits
	ulimits, err := convertToULimits(inputCfg.Ulimits)
	if err != nil {
		return err
	}

	// populating container definition, offloading the validation to aws-sdk
	outputContDef.Cpu = aws.Int64(int64(inputCfg.CPUShares))
	outputContDef.Command = aws.StringSlice(inputCfg.Command)
	outputContDef.DnsSearchDomains = aws.StringSlice(inputCfg.DNSSearch)
	outputContDef.DnsServers = aws.StringSlice(inputCfg.DNS)
	outputContDef.DockerLabels = aws.StringMap(inputCfg.Labels)
	outputContDef.DockerSecurityOptions = aws.StringSlice(inputCfg.SecurityOpt)
	outputContDef.EntryPoint = aws.StringSlice(inputCfg.Entrypoint)
	outputContDef.Environment = environment
	outputContDef.ExtraHosts = extraHosts
	if inputCfg.Hostname != "" {
		outputContDef.Hostname = aws.String(inputCfg.Hostname)
	}
	outputContDef.Image = aws.String(inputCfg.Image)
	outputContDef.Links = aws.StringSlice(inputCfg.Links) //TODO, read from external links
	outputContDef.LogConfiguration = logConfig
	outputContDef.Memory = aws.Int64(mem)
	outputContDef.MountPoints = mountPoints
	outputContDef.Privileged = aws.Bool(inputCfg.Privileged)
	outputContDef.PortMappings = portMappings
	outputContDef.ReadonlyRootFilesystem = aws.Bool(inputCfg.ReadOnly)
	outputContDef.Ulimits = ulimits
	if inputCfg.User != "" {
		outputContDef.User = aws.String(inputCfg.User)
	}
	outputContDef.VolumesFrom = volumesFrom
	if inputCfg.WorkingDir != "" {
		outputContDef.WorkingDirectory = aws.String(inputCfg.WorkingDir)
	}

	return nil
}