github.com/superfly/nomad@v0.10.5-fly/jobspec/parse_network.go (about)

     1  package jobspec
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	multierror "github.com/hashicorp/go-multierror"
     8  	"github.com/hashicorp/hcl"
     9  	"github.com/hashicorp/hcl/hcl/ast"
    10  	"github.com/hashicorp/nomad/api"
    11  	"github.com/hashicorp/nomad/helper"
    12  	"github.com/mitchellh/mapstructure"
    13  )
    14  
    15  // ParseNetwork parses a collection containing exactly one NetworkResource
    16  func ParseNetwork(o *ast.ObjectList) (*api.NetworkResource, error) {
    17  	if len(o.Items) > 1 {
    18  		return nil, fmt.Errorf("only one 'network' resource allowed")
    19  	}
    20  
    21  	// Check for invalid keys
    22  	valid := []string{
    23  		"mode",
    24  		"mbits",
    25  		"port",
    26  	}
    27  	if err := helper.CheckHCLKeys(o.Items[0].Val, valid); err != nil {
    28  		return nil, multierror.Prefix(err, "network ->")
    29  	}
    30  
    31  	var r api.NetworkResource
    32  	var m map[string]interface{}
    33  	if err := hcl.DecodeObject(&m, o.Items[0].Val); err != nil {
    34  		return nil, err
    35  	}
    36  	if err := mapstructure.WeakDecode(m, &r); err != nil {
    37  		return nil, err
    38  	}
    39  
    40  	var networkObj *ast.ObjectList
    41  	if ot, ok := o.Items[0].Val.(*ast.ObjectType); ok {
    42  		networkObj = ot.List
    43  	} else {
    44  		return nil, fmt.Errorf("should be an object")
    45  	}
    46  	if err := parsePorts(networkObj, &r); err != nil {
    47  		return nil, multierror.Prefix(err, "network, ports ->")
    48  	}
    49  
    50  	return &r, nil
    51  }
    52  
    53  func parsePorts(networkObj *ast.ObjectList, nw *api.NetworkResource) error {
    54  	// Check for invalid keys
    55  	valid := []string{
    56  		"mbits",
    57  		"port",
    58  		"mode",
    59  	}
    60  	if err := helper.CheckHCLKeys(networkObj, valid); err != nil {
    61  		return err
    62  	}
    63  
    64  	portsObjList := networkObj.Filter("port")
    65  	knownPortLabels := make(map[string]bool)
    66  	for _, port := range portsObjList.Items {
    67  		if len(port.Keys) == 0 {
    68  			return fmt.Errorf("ports must be named")
    69  		}
    70  		label := port.Keys[0].Token.Value().(string)
    71  		if !reDynamicPorts.MatchString(label) {
    72  			return errPortLabel
    73  		}
    74  		l := strings.ToLower(label)
    75  		if knownPortLabels[l] {
    76  			return fmt.Errorf("found a port label collision: %s", label)
    77  		}
    78  		var p map[string]interface{}
    79  		var res api.Port
    80  		if err := hcl.DecodeObject(&p, port.Val); err != nil {
    81  			return err
    82  		}
    83  		if err := mapstructure.WeakDecode(p, &res); err != nil {
    84  			return err
    85  		}
    86  		res.Label = label
    87  		if res.Value > 0 {
    88  			nw.ReservedPorts = append(nw.ReservedPorts, res)
    89  		} else {
    90  			nw.DynamicPorts = append(nw.DynamicPorts, res)
    91  		}
    92  		knownPortLabels[l] = true
    93  	}
    94  	return nil
    95  }