Skip to content

Commit

Permalink
Ensure the label exists on checks and small enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
dadgar committed Apr 19, 2016
1 parent 07cf344 commit fc8a689
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 6 deletions.
60 changes: 55 additions & 5 deletions nomad/structs/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1446,6 +1446,16 @@ func (sc *ServiceCheck) Validate() error {
return nil
}

// RequiresPort returns whether the service check requires the task has a port.
func (sc *ServiceCheck) RequiresPort() bool {
switch sc.Type {
case ServiceCheckHTTP, ServiceCheckTCP:
return true
default:
return false
}
}

func (sc *ServiceCheck) Hash(serviceID string) string {
h := sha1.New()
io.WriteString(h, serviceID)
Expand Down Expand Up @@ -1527,7 +1537,7 @@ func (s *Service) Validate() error {
}

for _, c := range s.Checks {
if s.PortLabel == "" && (c.Type == ServiceCheckTCP || c.Type == ServiceCheckHTTP) {
if s.PortLabel == "" && c.RequiresPort() {
mErr.Errors = append(mErr.Errors, fmt.Errorf("check %q is not valid since service %q doesn't have port", c.Name, s.Name))
continue
}
Expand Down Expand Up @@ -1726,10 +1736,9 @@ func (t *Task) Validate() error {
}
}

for _, service := range t.Services {
if err := service.Validate(); err != nil {
mErr.Errors = append(mErr.Errors, err)
}
// Validate Services
if err := validateServices(t); err != nil {
mErr.Errors = append(mErr.Errors, err)
}

if t.LogConfig != nil && t.Resources != nil {
Expand Down Expand Up @@ -1758,6 +1767,47 @@ func (t *Task) Validate() error {
return mErr.ErrorOrNil()
}

// validateServices takes a task and validates the services within it are valid
// and reference ports that exist.
func validateServices(t *Task) error {
var mErr multierror.Error

// Ensure that services don't ask for non-existent ports.
servicePorts := make(map[string][]string)
for i, service := range t.Services {
if err := service.Validate(); err != nil {
outer := fmt.Errorf("service %d validation failed: %s", i, err)
mErr.Errors = append(mErr.Errors, outer)
}

if service.PortLabel != "" {
servicePorts[service.PortLabel] = append(servicePorts[service.PortLabel], service.Name)
}
}

// Get the set of port labels.
portLabels := make(map[string]struct{})
if t.Resources != nil {
for _, network := range t.Resources.Networks {
ports := network.MapLabelToValues(nil)
for portLabel, _ := range ports {
portLabels[portLabel] = struct{}{}
}
}
}

// Ensure all ports referenced in services exist.
for servicePort, services := range servicePorts {
_, ok := portLabels[servicePort]
if !ok {
joined := strings.Join(services, ", ")
err := fmt.Errorf("port label %q referenced by services %v does not exist", servicePort, joined)
mErr.Errors = append(mErr.Errors, err)
}
}
return mErr.ErrorOrNil()
}

// Set of possible states for a task.
const (
TaskStatePending = "pending" // The task is waiting to be run.
Expand Down
33 changes: 32 additions & 1 deletion nomad/structs/structs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,38 @@ func TestTask_Validate(t *testing.T) {
}
}

func TestTask_Validate_Services(t *testing.T) {
s := &Service{
Name: "service-name",
PortLabel: "bar",
Checks: []*ServiceCheck{
{
Name: "check-name",
Type: ServiceCheckTCP,
},
},
}

task := &Task{
Name: "web",
Driver: "docker",
Resources: &Resources{
CPU: 100,
DiskMB: 200,
MemoryMB: 100,
IOPS: 10,
},
Services: []*Service{s},
}
err := task.Validate()
if err == nil {
t.Fatal("expected an error")
}
if !strings.Contains(err.Error(), "referenced by services service-name does not exist") {
t.Fatalf("err: %s", err)
}
}

func TestTask_Validate_LogConfig(t *testing.T) {
task := &Task{
LogConfig: DefaultLogConfig(),
Expand Down Expand Up @@ -518,7 +550,6 @@ func TestInvalidServiceCheck(t *testing.T) {
PortLabel: "bar",
Checks: []*ServiceCheck{
{

Name: "check-name",
Type: "lol",
},
Expand Down

0 comments on commit fc8a689

Please sign in to comment.