// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package nomad import ( "fmt" "github.com/hashicorp/nomad/nomad/structs" ) type jobNamespaceConstraintCheckHook struct { srv *Server } func (jobNamespaceConstraintCheckHook) Name() string { return "namespace-constraint-check" } func (c jobNamespaceConstraintCheckHook) Validate(job *structs.Job) (warnings []error, err error) { // This was validated before and matches the WriteRequest namespace ns, err := c.srv.State().NamespaceByName(nil, job.Namespace) if err != nil { return nil, err } if ns == nil { return nil, fmt.Errorf("job %q is in nonexistent namespace %q", job.ID, job.Namespace) } var disallowedDrivers []string for _, tg := range job.TaskGroups { for _, t := range tg.Tasks { if !taskValidateDriver(t, ns) { disallowedDrivers = append(disallowedDrivers, t.Driver) } } } if len(disallowedDrivers) > 0 { if len(disallowedDrivers) == 1 { return nil, fmt.Errorf( "used task driver %q is not allowed in namespace %q", disallowedDrivers[0], ns.Name, ) } else { return nil, fmt.Errorf( "used task drivers %q are not allowed in namespace %q", disallowedDrivers, ns.Name, ) } } return nil, nil } func taskValidateDriver(task *structs.Task, ns *structs.Namespace) bool { if ns.Capabilities == nil { return true } allow := len(ns.Capabilities.EnabledTaskDrivers) == 0 for _, d := range ns.Capabilities.EnabledTaskDrivers { if task.Driver == d { allow = true break } } for _, d := range ns.Capabilities.DisabledTaskDrivers { if task.Driver == d { allow = false break } } return allow }