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

Implemented interpolation of Job, Task group and Task Names in Service Name #509

Merged
merged 8 commits into from
Nov 27, 2015
Merged
Show file tree
Hide file tree
Changes from all 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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ IMPROVEMENTS:
* driver/docker: Added TLS client options to the config file [GH-480]
* core/api: Can list all known regions in the cluster [GH-495]
* client/discovery: Added more consul client api configuration options [GH-503]
* jobspec: More flexibility in naming Services [GH-509]

BUG FIXES:

Expand Down
2 changes: 1 addition & 1 deletion client/driver/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import (

"github.com/hashicorp/nomad/client/allocdir"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/client/driver/args"
cstructs "github.com/hashicorp/nomad/client/driver/structs"
"github.com/hashicorp/nomad/client/fingerprint"
"github.com/hashicorp/nomad/helper/args"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/mitchellh/mapstructure"
)
Expand Down
2 changes: 1 addition & 1 deletion client/driver/executor/exec_basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import (
"strings"

"github.com/hashicorp/nomad/client/allocdir"
"github.com/hashicorp/nomad/client/driver/args"
"github.com/hashicorp/nomad/client/driver/environment"
"github.com/hashicorp/nomad/client/driver/spawn"
"github.com/hashicorp/nomad/helper/args"
"github.com/hashicorp/nomad/nomad/structs"

cstructs "github.com/hashicorp/nomad/client/driver/structs"
Expand Down
2 changes: 1 addition & 1 deletion client/driver/executor/exec_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import (

"github.com/hashicorp/go-multierror"
"github.com/hashicorp/nomad/client/allocdir"
"github.com/hashicorp/nomad/client/driver/args"
"github.com/hashicorp/nomad/client/driver/environment"
"github.com/hashicorp/nomad/client/driver/spawn"
"github.com/hashicorp/nomad/helper/args"
"github.com/hashicorp/nomad/nomad/structs"

"github.com/opencontainers/runc/libcontainer/cgroups"
Expand Down
2 changes: 1 addition & 1 deletion client/driver/rkt.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import (

"github.com/hashicorp/nomad/client/allocdir"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/client/driver/args"
cstructs "github.com/hashicorp/nomad/client/driver/structs"
"github.com/hashicorp/nomad/client/fingerprint"
"github.com/hashicorp/nomad/helper/args"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/mitchellh/mapstructure"
)
Expand Down
2 changes: 1 addition & 1 deletion command/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ job "example" {
}

service {
# name = redis
name = "${TASKGROUP}-redis"
tags = ["global", "cache"]
port = "db"
check {
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 0 additions & 2 deletions jobspec/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -502,8 +502,6 @@ func parseServices(jobName string, taskGroupName string, task *structs.Task, ser
if service.Name == "" {
defaultServiceName = true
service.Name = fmt.Sprintf("%s-%s-%s", jobName, taskGroupName, task.Name)
} else {
service.Name = fmt.Sprintf("%s-%s-%s-%s", jobName, taskGroupName, task.Name, service.Name)
}

// Fileter checks
Expand Down
4 changes: 4 additions & 0 deletions nomad/job_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ func (j *Job) Register(args *structs.JobRegisterRequest, reply *structs.JobRegis
if err := args.Job.Validate(); err != nil {
return err
}

// Expand the service names
args.Job.ExpandAllServiceNames()
Copy link
Contributor

Choose a reason for hiding this comment

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

I would put a comment on this


if args.Job.Type == structs.JobTypeCore {
return fmt.Errorf("job type cannot be core")
}
Expand Down
10 changes: 9 additions & 1 deletion nomad/job_endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -347,7 +351,11 @@ func TestJobEndpoint_GetJob(t *testing.T) {
t.Fatalf("Bad index: %d %d", resp2.Index, resp.Index)
}

if !reflect.DeepEqual(job, resp2.Job) {
// Make a copy of the origin job and change the service name so that we can
// do a deep equal with the response from the GET JOB Api
j := job
j.TaskGroups[0].Tasks[0].Services[0].Name = "web-frontend"
if !reflect.DeepEqual(j, resp2.Job) {
t.Fatalf("bad: %#v %#v", job, resp2.Job)
}

Expand Down
6 changes: 6 additions & 0 deletions nomad/mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
37 changes: 37 additions & 0 deletions nomad/structs/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1025,6 +1042,18 @@ type ServiceCheck struct {
Timeout time.Duration // Timeout of the response from the check before consul fails the check
}

// ExpandName interpolates values of Job, Task Group and Task in the Service
// Name
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 {
Expand Down Expand Up @@ -1109,6 +1138,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)
}
Expand Down
79 changes: 79 additions & 0 deletions nomad/structs/structs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

}
6 changes: 4 additions & 2 deletions website/source/docs/jobspec/servicediscovery.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,10 @@ group "database" {
name of a service is $(job-name)-$(task-group)-$(task-name). Users can
explicitly name the service by specifying this option. If multiple services
are defined for a Task then only one task can have the default name, all the
services have to be explicitly named. Nomad will add the prefix ```$(job-name
)-${task-group}-${task-name}``` prefix to each user defined name.
services have to be explicitly named. Users can add the following to the
service names: ```${JOB}```, ```${TASKGROUP}```, ```${TASK}```, ```${BASE}```.
Nomad will replace them with the appropriate value of the Job, Task Group and
Task names while registering the Job. ```${BASE}``` expands to ${JOB}-${TASKGROUP}-${TASK}

* `tags`: A list of tags associated with this Service.

Expand Down