Skip to content

Commit 9c932aa

Browse files
committed
Interpolate and then validate services
1 parent 03c541e commit 9c932aa

File tree

3 files changed

+48
-8
lines changed

3 files changed

+48
-8
lines changed

client/task_runner.go

+19-2
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,15 @@ func (r *TaskRunner) Run() {
367367
r.logger.Printf("[DEBUG] client: starting task context for '%s' (alloc '%s')",
368368
r.task.Name, r.alloc.ID)
369369

370+
// Create the initial environment, this will be recreated if a Vault token
371+
// is needed
372+
if err := r.setTaskEnv(); err != nil {
373+
r.setState(
374+
structs.TaskStateDead,
375+
structs.NewTaskEvent(structs.TaskSetupFailure).SetSetupError(err))
376+
return
377+
}
378+
370379
if err := r.validateTask(); err != nil {
371380
r.setState(
372381
structs.TaskStateDead,
@@ -417,6 +426,14 @@ func (r *TaskRunner) validateTask() error {
417426
}
418427
}
419428

429+
// Validate the Service names
430+
for i, service := range r.task.Services {
431+
name := r.taskEnv.ReplaceEnv(service.Name)
432+
if err := service.ValidateName(name); err != nil {
433+
mErr.Errors = append(mErr.Errors, fmt.Errorf("service (%d) failed validation: %v", i, err))
434+
}
435+
}
436+
420437
if len(mErr.Errors) == 1 {
421438
return mErr.Errors[0]
422439
}
@@ -648,7 +665,7 @@ func (r *TaskRunner) updatedTokenHandler() {
648665
if err := r.setTaskEnv(); err != nil {
649666
r.setState(
650667
structs.TaskStateDead,
651-
structs.NewTaskEvent(structs.TaskDriverFailure).SetDriverError(err).SetFailsTask())
668+
structs.NewTaskEvent(structs.TaskSetupFailure).SetSetupError(err).SetFailsTask())
652669
return
653670
}
654671

@@ -687,7 +704,7 @@ func (r *TaskRunner) prestart(resultCh chan bool) {
687704
if err := r.setTaskEnv(); err != nil {
688705
r.setState(
689706
structs.TaskStateDead,
690-
structs.NewTaskEvent(structs.TaskDriverFailure).SetDriverError(err).SetFailsTask())
707+
structs.NewTaskEvent(structs.TaskSetupFailure).SetSetupError(err).SetFailsTask())
691708
resultCh <- false
692709
return
693710
}

nomad/structs/structs.go

+19-4
Original file line numberDiff line numberDiff line change
@@ -1909,13 +1909,14 @@ func (s *Service) Canonicalize(job string, taskGroup string, task string) {
19091909
func (s *Service) Validate() error {
19101910
var mErr multierror.Error
19111911

1912-
// Ensure the service name is valid per RFC-952 §1
1913-
// (https://tools.ietf.org/html/rfc952), RFC-1123 §2.1
1912+
// Ensure the service name is valid per the below RFCs but make an exception
1913+
// for our interpolation syntax
1914+
// RFC-952 §1 (https://tools.ietf.org/html/rfc952), RFC-1123 §2.1
19141915
// (https://tools.ietf.org/html/rfc1123), and RFC-2782
19151916
// (https://tools.ietf.org/html/rfc2782).
1916-
re := regexp.MustCompile(`^(?i:[a-z0-9]|[a-z0-9][a-z0-9\-]{0,61}[a-z0-9])$`)
1917+
re := regexp.MustCompile(`^(?i:[a-z0-9]|[a-z0-9\$][a-zA-Z0-9\-\$\{\}\_\.]*[a-z0-9\}])$`)
19171918
if !re.MatchString(s.Name) {
1918-
mErr.Errors = append(mErr.Errors, fmt.Errorf("service name must be valid per RFC 1123 and can contain only alphanumeric characters or dashes and must be less than 63 characters long: %q", s.Name))
1919+
mErr.Errors = append(mErr.Errors, fmt.Errorf("service name must be valid per RFC 1123 and can contain only alphanumeric characters or dashes: %q", s.Name))
19191920
}
19201921

19211922
for _, c := range s.Checks {
@@ -1931,6 +1932,20 @@ func (s *Service) Validate() error {
19311932
return mErr.ErrorOrNil()
19321933
}
19331934

1935+
// ValidateName checks if the services Name is valid and should be called after
1936+
// the name has been interpolated
1937+
func (s *Service) ValidateName(name string) error {
1938+
// Ensure the service name is valid per RFC-952 §1
1939+
// (https://tools.ietf.org/html/rfc952), RFC-1123 §2.1
1940+
// (https://tools.ietf.org/html/rfc1123), and RFC-2782
1941+
// (https://tools.ietf.org/html/rfc2782).
1942+
re := regexp.MustCompile(`^(?i:[a-z0-9]|[a-z0-9][a-z0-9\-]{0,61}[a-z0-9])$`)
1943+
if !re.MatchString(name) {
1944+
return fmt.Errorf("service name must be valid per RFC 1123 and can contain only alphanumeric characters or dashes and must be less than 63 characters long: %q", name)
1945+
}
1946+
return nil
1947+
}
1948+
19341949
// Hash calculates the hash of the check based on it's content and the service
19351950
// which owns it
19361951
func (s *Service) Hash() string {

nomad/structs/structs_test.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -951,7 +951,7 @@ func TestInvalidServiceCheck(t *testing.T) {
951951
Name: "service.name",
952952
PortLabel: "bar",
953953
}
954-
if err := s.Validate(); err == nil {
954+
if err := s.ValidateName(s.Name); err == nil {
955955
t.Fatalf("Service should be invalid (contains a dot): %v", err)
956956
}
957957

@@ -963,11 +963,19 @@ func TestInvalidServiceCheck(t *testing.T) {
963963
t.Fatalf("Service should be invalid (begins with a hyphen): %v", err)
964964
}
965965

966+
s = Service{
967+
Name: "my-service-${NOMAD_META_FOO}",
968+
PortLabel: "bar",
969+
}
970+
if err := s.Validate(); err != nil {
971+
t.Fatalf("Service should be valid: %v", err)
972+
}
973+
966974
s = Service{
967975
Name: "abcdef0123456789-abcdef0123456789-abcdef0123456789-abcdef0123456",
968976
PortLabel: "bar",
969977
}
970-
if err := s.Validate(); err == nil {
978+
if err := s.ValidateName(s.Name); err == nil {
971979
t.Fatalf("Service should be invalid (too long): %v", err)
972980
}
973981

0 commit comments

Comments
 (0)