Making the Job expand all service names during registration

This commit is contained in:
Diptanu Choudhury
2015-11-26 19:26:00 -08:00
parent 70a38fc8cf
commit 7b04700b35
7 changed files with 127 additions and 46 deletions

View File

@@ -1,8 +1,6 @@
package api
import (
"fmt"
"github.com/hashicorp/nomad/helper/args"
"time"
)
@@ -44,16 +42,6 @@ type Service struct {
Checks []ServiceCheck
}
func (s *Service) ExpandName(job string, taskGroup string, task string) {
s.Name = args.ReplaceEnv(s.Name, map[string]string{
"JOB": job,
"TASKGROUP": taskGroup,
"TASK": task,
"BASE": fmt.Sprintf("%s-%s-%s", job, taskGroup, task),
},
)
}
// TaskGroup is the unit of scheduling.
type TaskGroup struct {
Name string

View File

@@ -218,37 +218,3 @@ func TestTask_Constrain(t *testing.T) {
t.Fatalf("expect: %#v, got: %#v", expect, task.Constraints)
}
}
func TestService_Expand_Name(t *testing.T) {
job := "example"
taskGroup := "cache"
task := "redis"
s := Service{
Name: "${TASK}-db",
}
s.ExpandName(job, taskGroup, task)
if s.Name != "redis-db" {
t.Fatalf("Expected name: %v, Actual: %v", "redis-db", s.Name)
}
s.Name = "db"
s.ExpandName(job, taskGroup, task)
if s.Name != "db" {
t.Fatalf("Expected name: %v, Actual: %v", "redis-db", s.Name)
}
s.Name = "${JOB}-${TASKGROUP}-${TASK}-db"
s.ExpandName(job, taskGroup, task)
if s.Name != "example-cache-redis-db" {
t.Fatalf("Expected name: %v, Actual: %v", "expample-cache-redis-db", s.Name)
}
s.Name = "${BASE}-db"
s.ExpandName(job, taskGroup, task)
if s.Name != "example-cache-redis-db" {
t.Fatalf("Expected name: %v, Actual: %v", "expample-cache-redis-db", s.Name)
}
}

View File

@@ -28,6 +28,9 @@ func (j *Job) Register(args *structs.JobRegisterRequest, reply *structs.JobRegis
if err := args.Job.Validate(); err != nil {
return err
}
args.Job.ExpandAllServiceNames()
if args.Job.Type == structs.JobTypeCore {
return fmt.Errorf("job type cannot be core")
}

View File

@@ -47,6 +47,10 @@ func TestJobEndpoint_Register(t *testing.T) {
if out.CreateIndex != resp.JobModifyIndex {
t.Fatalf("index mis-match")
}
serviceName := out.TaskGroups[0].Tasks[0].Services[0].Name
if serviceName != "web-frontend" {
t.Fatalf("Expected Service Name: %s, Actual: %s", serviceName)
}
// Lookup the evaluation
eval, err := state.EvalByID(resp.EvalID)

View File

@@ -90,6 +90,12 @@ func Job() *structs.Job {
Env: map[string]string{
"FOO": "bar",
},
Services: []*structs.Service{
{
Name: "${TASK}-frontend",
PortLabel: "http",
},
},
Resources: &structs.Resources{
CPU: 500,
MemoryMB: 256,

View File

@@ -14,6 +14,7 @@ import (
"github.com/hashicorp/go-msgpack/codec"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-version"
"github.com/hashicorp/nomad/helper/args"
)
var (
@@ -774,6 +775,14 @@ type Job struct {
ModifyIndex uint64
}
// ExpandAllServiceNames traverses all Task Groups and makes them
// interpolate Job, Task group and Task names in all Service names
func (j *Job) ExpandAllServiceNames() {
for _, tg := range j.TaskGroups {
tg.ExpandAllServiceNames(j.Name)
}
}
// Validate is used to sanity check a job input
func (j *Job) Validate() error {
var mErr multierror.Error
@@ -942,6 +951,14 @@ type TaskGroup struct {
Meta map[string]string
}
// ExpandAllServiceNames traverses over all Tasks and makes them to interpolate
// values of Job, Task Group and Task names in all Service Names
func (tg *TaskGroup) ExpandAllServiceNames(job string) {
for _, task := range tg.Tasks {
task.ExpandAllServiceNames(job, tg.Name)
}
}
// Validate is used to sanity check a task group
func (tg *TaskGroup) Validate() error {
var mErr multierror.Error
@@ -1025,6 +1042,16 @@ type ServiceCheck struct {
Timeout time.Duration // Timeout of the response from the check before consul fails the check
}
func (s *Service) ExpandName(job string, taskGroup string, task string) {
s.Name = args.ReplaceEnv(s.Name, map[string]string{
"JOB": job,
"TASKGROUP": taskGroup,
"TASK": task,
"BASE": fmt.Sprintf("%s-%s-%s", job, taskGroup, task),
},
)
}
func (sc *ServiceCheck) Validate() error {
t := strings.ToLower(sc.Type)
if t != ServiceCheckTCP && t != ServiceCheckHTTP {
@@ -1109,6 +1136,14 @@ type Task struct {
Meta map[string]string
}
// ExpandAllServiceNames interpolates values of Job, Task Group
// and Tasks in all the service Names of a Task
func (t *Task) ExpandAllServiceNames(job string, taskGroup string) {
for _, service := range t.Services {
service.ExpandName(job, taskGroup, t.Name)
}
}
func (t *Task) GoString() string {
return fmt.Sprintf("*%#v", *t)
}

View File

@@ -405,3 +405,82 @@ func TestDistinctCheckId(t *testing.T) {
}
}
func TestService_Expand_Name(t *testing.T) {
job := "example"
taskGroup := "cache"
task := "redis"
s := Service{
Name: "${TASK}-db",
}
s.ExpandName(job, taskGroup, task)
if s.Name != "redis-db" {
t.Fatalf("Expected name: %v, Actual: %v", "redis-db", s.Name)
}
s.Name = "db"
s.ExpandName(job, taskGroup, task)
if s.Name != "db" {
t.Fatalf("Expected name: %v, Actual: %v", "redis-db", s.Name)
}
s.Name = "${JOB}-${TASKGROUP}-${TASK}-db"
s.ExpandName(job, taskGroup, task)
if s.Name != "example-cache-redis-db" {
t.Fatalf("Expected name: %v, Actual: %v", "expample-cache-redis-db", s.Name)
}
s.Name = "${BASE}-db"
s.ExpandName(job, taskGroup, task)
if s.Name != "example-cache-redis-db" {
t.Fatalf("Expected name: %v, Actual: %v", "expample-cache-redis-db", s.Name)
}
}
func TestJob_ExpandServiceNames(t *testing.T) {
j := &Job{
Name: "my-job",
TaskGroups: []*TaskGroup{
&TaskGroup{
Name: "web",
Tasks: []*Task{
{
Name: "frontend",
Services: []*Service{
{
Name: "${BASE}-default",
},
{
Name: "jmx",
},
},
},
},
},
&TaskGroup{
Name: "admin",
Tasks: []*Task{
{
Name: "admin-web",
},
},
},
},
}
j.ExpandAllServiceNames()
service1Name := j.TaskGroups[0].Tasks[0].Services[0].Name
if service1Name != "my-job-web-frontend-default" {
t.Fatalf("Expected Service Name: %s, Actual: %s", "my-job-web-frontend-default", service1Name)
}
service2Name := j.TaskGroups[0].Tasks[0].Services[1].Name
if service2Name != "jmx" {
t.Fatalf("Expected Service Name: %s, Actual: %s", "jmx", service2Name)
}
}