Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a command line argument to set the logConfiguration #731

Merged
merged 7 commits into from
Jan 22, 2016
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
build
.env*
*.swp
4 changes: 4 additions & 0 deletions cmd/empire/factories.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ func newECSScheduler(c *cli.Context) (scheduler.Scheduler, error) {
InternalSubnetIDs: c.StringSlice(FlagEC2SubnetsPrivate),
ExternalSubnetIDs: c.StringSlice(FlagEC2SubnetsPublic),
ZoneID: c.String(FlagRoute53InternalZoneID),
LogDriver: c.String(FlagECSLogDriver),
LogOpts: c.StringSlice(FlagECSLogOpts),
}

s, err := ecs.NewLoadBalancedScheduler(config)
Expand All @@ -109,6 +111,8 @@ func newECSScheduler(c *cli.Context) (scheduler.Scheduler, error) {
log.Println(fmt.Sprintf(" InternalSubnetIDs: %v", config.InternalSubnetIDs))
log.Println(fmt.Sprintf(" ExternalSubnetIDs: %v", config.ExternalSubnetIDs))
log.Println(fmt.Sprintf(" ZoneID: %v", config.ZoneID))
log.Println(fmt.Sprintf(" LogDriver: %v", config.LogDriver))
log.Println(fmt.Sprintf(" LogOpts: %v", config.LogOpts))

return &scheduler.AttachedRunner{
Scheduler: s,
Expand Down
14 changes: 14 additions & 0 deletions cmd/empire/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ const (
FlagAWSDebug = "aws.debug"
FlagECSCluster = "ecs.cluster"
FlagECSServiceRole = "ecs.service.role"
FlagECSLogDriver = "ecs.logdriver"
FlagECSLogOpts = "ecs.logopt"

FlagELBSGPrivate = "elb.sg.private"
FlagELBSGPublic = "elb.sg.public"
Expand Down Expand Up @@ -183,6 +185,18 @@ var EmpireFlags = []cli.Flag{
Usage: "The IAM Role to use for managing ECS",
EnvVar: "EMPIRE_ECS_SERVICE_ROLE",
},
cli.StringFlag{
Name: FlagECSLogDriver,
Value: "json-file",
Usage: "Log driver to use when running containers. Maps to the --log-driver docker cli arg",
EnvVar: "EMPIRE_ECS_LOG_DRIVER",
},
cli.StringSliceFlag{
Name: FlagECSLogOpts,
Value: &cli.StringSlice{},
Usage: "Log driver to options. Maps to the --log-opt docker cli arg",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give an example of the format you'd pass here? I'd assume tag=foo,thing=bar?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logopt takes multiple arguments, which is exactly how it works with docker run:

empire server --ecs.logdriver syslog --ecs.logopt tag=brianz --ecs.logopt syslog-facility=daemon

...results in:

        "LogConfig": {
            "Type": "syslog",
            "Config": {
                "syslog-facility": "daemon",
                "tag": "brianz"
            }
        },

EnvVar: "EMPIRE_ECS_LOG_OPT",
},
cli.StringFlag{
Name: FlagELBSGPrivate,
Value: "",
Expand Down
19 changes: 19 additions & 0 deletions pkg/ecsutil/ecs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package ecsutil

import (
"fmt"
"strings"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/remind101/pkg/trace"
Expand Down Expand Up @@ -237,3 +239,20 @@ func (c *limitedClient) DescribeTasks(ctx context.Context, input *ecs.DescribeTa
Tasks: tasks,
}, nil
}

func NewLogConfiguration(logDriver string, logOpts []string) *ecs.LogConfiguration {

logOptions := make(map[string]*string)

for _, opt := range logOpts {
logOpt := strings.SplitN(opt, "=", 2)
if len(logOpt) == 2 {
logOptions[logOpt[0]] = &logOpt[1]
}
}

return &ecs.LogConfiguration{
LogDriver: aws.String(logDriver),
Options: logOptions,
}
}
52 changes: 32 additions & 20 deletions scheduler/ecs/ecs.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,27 @@ type Config struct {

// AWS configuration.
AWS client.ConfigProvider

// Log driver to use when starting ECS tasks. Maps to the --log-driver docker cli arg
LogDriver string

// Log options to use when starting ECS tasks. Maps to the --log-opt docker cli arg
LogOpts []string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably do the foo=bar parsing earlier (in cmd/empire) and take a map[string]string here instead.

Actually, maybe even just make this LogConfiguration *ecs.LogConfiguration and build the LogConfiguration in cmd/empire.

}

// NewScheduler returns a new Scehduler implementation that:
//
// * Creates services with ECS.
func NewScheduler(config Config) (*Scheduler, error) {
c := ecsutil.NewClient(config.AWS)
l := ecsutil.NewLogConfiguration(config.LogDriver, config.LogOpts)

// Create the ECS Scheduler
var pm ProcessManager = &ecsProcessManager{
cluster: config.Cluster,
serviceRole: config.ServiceRole,
ecs: c,
cluster: config.Cluster,
serviceRole: config.ServiceRole,
ecs: c,
logConfiguration: l,
}

return &Scheduler{
Expand All @@ -111,12 +119,14 @@ func NewLoadBalancedScheduler(config Config) (*Scheduler, error) {
}

c := ecsutil.NewClient(config.AWS)
l := ecsutil.NewLogConfiguration(config.LogDriver, config.LogOpts)

// Create the ECS Scheduler
var pm ProcessManager = &ecsProcessManager{
cluster: config.Cluster,
serviceRole: config.ServiceRole,
ecs: c,
cluster: config.Cluster,
serviceRole: config.ServiceRole,
ecs: c,
logConfiguration: l,
}

// Create the ELB Manager
Expand Down Expand Up @@ -305,9 +315,10 @@ var _ ProcessManager = &ecsProcessManager{}
// ecsProcessManager is an implementation of the ProcessManager interface that
// creates ECS services for Processes.
type ecsProcessManager struct {
cluster string
serviceRole string
ecs *ecsutil.Client
cluster string
serviceRole string
ecs *ecsutil.Client
logConfiguration *ecs.LogConfiguration
}

// CreateProcess creates an ECS service for the process.
Expand Down Expand Up @@ -341,7 +352,7 @@ func (m *ecsProcessManager) Run(ctx context.Context, app *scheduler.App, process

// createTaskDefinition creates a Task Definition in ECS for the service.
func (m *ecsProcessManager) createTaskDefinition(ctx context.Context, app *scheduler.App, process *scheduler.Process) (*ecs.TaskDefinition, error) {
taskDef, err := taskDefinitionInput(process)
taskDef, err := taskDefinitionInput(process, m.logConfiguration)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -479,7 +490,7 @@ func (m *ecsProcessManager) Scale(ctx context.Context, app string, process strin

// taskDefinitionInput returns an ecs.RegisterTaskDefinitionInput suitable for
// creating a task definition from a Process.
func taskDefinitionInput(p *scheduler.Process) (*ecs.RegisterTaskDefinitionInput, error) {
func taskDefinitionInput(p *scheduler.Process, logConfiguration *ecs.LogConfiguration) (*ecs.RegisterTaskDefinitionInput, error) {
args, err := shellwords.Parse(p.Command)
if err != nil {
return nil, err
Expand Down Expand Up @@ -517,15 +528,16 @@ func taskDefinitionInput(p *scheduler.Process) (*ecs.RegisterTaskDefinitionInput
Family: aws.String(p.Type),
ContainerDefinitions: []*ecs.ContainerDefinition{
&ecs.ContainerDefinition{
Name: aws.String(p.Type),
Cpu: aws.Int64(int64(p.CPUShares)),
Command: command,
Image: aws.String(p.Image.String()),
Essential: aws.Bool(true),
Memory: aws.Int64(int64(p.MemoryLimit / MB)),
Environment: environment,
PortMappings: ports,
DockerLabels: labels,
Name: aws.String(p.Type),
Cpu: aws.Int64(int64(p.CPUShares)),
Command: command,
Image: aws.String(p.Image.String()),
Essential: aws.Bool(true),
Memory: aws.Int64(int64(p.MemoryLimit / MB)),
Environment: environment,
LogConfiguration: logConfiguration,
PortMappings: ports,
DockerLabels: labels,
},
},
}, nil
Expand Down