2019-08-09 19:18:53 +00:00
|
|
|
package jobspec
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
multierror "github.com/hashicorp/go-multierror"
|
|
|
|
"github.com/hashicorp/hcl"
|
|
|
|
"github.com/hashicorp/hcl/hcl/ast"
|
|
|
|
"github.com/hashicorp/nomad/api"
|
|
|
|
"github.com/hashicorp/nomad/helper"
|
|
|
|
"github.com/mitchellh/mapstructure"
|
|
|
|
)
|
|
|
|
|
2019-10-24 14:41:54 +00:00
|
|
|
// ParseNetwork parses a collection containing exactly one NetworkResource
|
|
|
|
func ParseNetwork(o *ast.ObjectList) (*api.NetworkResource, error) {
|
2019-08-09 19:18:53 +00:00
|
|
|
if len(o.Items) > 1 {
|
|
|
|
return nil, fmt.Errorf("only one 'network' resource allowed")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for invalid keys
|
|
|
|
valid := []string{
|
|
|
|
"mode",
|
|
|
|
"mbits",
|
|
|
|
"port",
|
|
|
|
}
|
|
|
|
if err := helper.CheckHCLKeys(o.Items[0].Val, valid); err != nil {
|
|
|
|
return nil, multierror.Prefix(err, "network ->")
|
|
|
|
}
|
|
|
|
|
|
|
|
var r api.NetworkResource
|
|
|
|
var m map[string]interface{}
|
|
|
|
if err := hcl.DecodeObject(&m, o.Items[0].Val); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := mapstructure.WeakDecode(m, &r); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var networkObj *ast.ObjectList
|
|
|
|
if ot, ok := o.Items[0].Val.(*ast.ObjectType); ok {
|
|
|
|
networkObj = ot.List
|
|
|
|
} else {
|
|
|
|
return nil, fmt.Errorf("should be an object")
|
|
|
|
}
|
|
|
|
if err := parsePorts(networkObj, &r); err != nil {
|
|
|
|
return nil, multierror.Prefix(err, "network, ports ->")
|
|
|
|
}
|
|
|
|
|
|
|
|
return &r, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func parsePorts(networkObj *ast.ObjectList, nw *api.NetworkResource) error {
|
|
|
|
// Check for invalid keys
|
|
|
|
valid := []string{
|
|
|
|
"mbits",
|
|
|
|
"port",
|
|
|
|
"mode",
|
|
|
|
}
|
|
|
|
if err := helper.CheckHCLKeys(networkObj, valid); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
portsObjList := networkObj.Filter("port")
|
|
|
|
knownPortLabels := make(map[string]bool)
|
|
|
|
for _, port := range portsObjList.Items {
|
|
|
|
if len(port.Keys) == 0 {
|
|
|
|
return fmt.Errorf("ports must be named")
|
|
|
|
}
|
|
|
|
label := port.Keys[0].Token.Value().(string)
|
|
|
|
if !reDynamicPorts.MatchString(label) {
|
|
|
|
return errPortLabel
|
|
|
|
}
|
|
|
|
l := strings.ToLower(label)
|
|
|
|
if knownPortLabels[l] {
|
|
|
|
return fmt.Errorf("found a port label collision: %s", label)
|
|
|
|
}
|
|
|
|
var p map[string]interface{}
|
|
|
|
var res api.Port
|
|
|
|
if err := hcl.DecodeObject(&p, port.Val); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := mapstructure.WeakDecode(p, &res); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
res.Label = label
|
|
|
|
if res.Value > 0 {
|
|
|
|
nw.ReservedPorts = append(nw.ReservedPorts, res)
|
|
|
|
} else {
|
|
|
|
nw.DynamicPorts = append(nw.DynamicPorts, res)
|
|
|
|
}
|
|
|
|
knownPortLabels[l] = true
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|