Skip to content

Commit fee577b

Browse files
committed
Interpolate and then validate services
1 parent 444a221 commit fee577b

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
}
@@ -640,7 +657,7 @@ func (r *TaskRunner) updatedTokenHandler() {
640657
if err := r.setTaskEnv(); err != nil {
641658
r.setState(
642659
structs.TaskStateDead,
643-
structs.NewTaskEvent(structs.TaskDriverFailure).SetDriverError(err))
660+
structs.NewTaskEvent(structs.TaskSetupFailure).SetSetupError(err))
644661
return
645662
}
646663

@@ -679,7 +696,7 @@ func (r *TaskRunner) prestart(resultCh chan bool) {
679696
if err := r.setTaskEnv(); err != nil {
680697
r.setState(
681698
structs.TaskStateDead,
682-
structs.NewTaskEvent(structs.TaskDriverFailure).SetDriverError(err))
699+
structs.NewTaskEvent(structs.TaskSetupFailure).SetSetupError(err))
683700
resultCh <- false
684701
return
685702
}

nomad/structs/structs.go

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

1857-
// Ensure the service name is valid per RFC-952 §1
1858-
// (https://tools.ietf.org/html/rfc952), RFC-1123 §2.1
1857+
// Ensure the service name is valid per the below RFCs but make an exception
1858+
// for our interpolation syntax
1859+
// RFC-952 §1 (https://tools.ietf.org/html/rfc952), RFC-1123 §2.1
18591860
// (https://tools.ietf.org/html/rfc1123), and RFC-2782
18601861
// (https://tools.ietf.org/html/rfc2782).
1861-
re := regexp.MustCompile(`^(?i:[a-z0-9]|[a-z0-9][a-z0-9\-]{0,61}[a-z0-9])$`)
1862+
re := regexp.MustCompile(`^(?i:[a-z0-9]|[a-z0-9\$][a-zA-Z0-9\-\$\{\}\_\.]*[a-z0-9\}])$`)
18621863
if !re.MatchString(s.Name) {
1863-
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))
1864+
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))
18641865
}
18651866

18661867
for _, c := range s.Checks {
@@ -1876,6 +1877,20 @@ func (s *Service) Validate() error {
18761877
return mErr.ErrorOrNil()
18771878
}
18781879

1880+
// ValidateName checks if the services Name is valid and should be called after
1881+
// the name has been interpolated
1882+
func (s *Service) ValidateName(name string) error {
1883+
// Ensure the service name is valid per RFC-952 §1
1884+
// (https://tools.ietf.org/html/rfc952), RFC-1123 §2.1
1885+
// (https://tools.ietf.org/html/rfc1123), and RFC-2782
1886+
// (https://tools.ietf.org/html/rfc2782).
1887+
re := regexp.MustCompile(`^(?i:[a-z0-9]|[a-z0-9][a-z0-9\-]{0,61}[a-z0-9])$`)
1888+
if !re.MatchString(name) {
1889+
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)
1890+
}
1891+
return nil
1892+
}
1893+
18791894
// Hash calculates the hash of the check based on it's content and the service
18801895
// which owns it
18811896
func (s *Service) Hash() string {

nomad/structs/structs_test.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -864,7 +864,7 @@ func TestInvalidServiceCheck(t *testing.T) {
864864
Name: "service.name",
865865
PortLabel: "bar",
866866
}
867-
if err := s.Validate(); err == nil {
867+
if err := s.ValidateName(s.Name); err == nil {
868868
t.Fatalf("Service should be invalid (contains a dot): %v", err)
869869
}
870870

@@ -876,11 +876,19 @@ func TestInvalidServiceCheck(t *testing.T) {
876876
t.Fatalf("Service should be invalid (begins with a hyphen): %v", err)
877877
}
878878

879+
s = Service{
880+
Name: "my-service-${NOMAD_META_FOO}",
881+
PortLabel: "bar",
882+
}
883+
if err := s.Validate(); err != nil {
884+
t.Fatalf("Service should be valid: %v", err)
885+
}
886+
879887
s = Service{
880888
Name: "abcdef0123456789-abcdef0123456789-abcdef0123456789-abcdef0123456",
881889
PortLabel: "bar",
882890
}
883-
if err := s.Validate(); err == nil {
891+
if err := s.ValidateName(s.Name); err == nil {
884892
t.Fatalf("Service should be invalid (too long): %v", err)
885893
}
886894

0 commit comments

Comments
 (0)