github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/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/mitchellh/mapstructure"
    12  )
    13  
    14  // ParseNetwork parses a collection containing exactly one NetworkResource
    15  func ParseNetwork(o *ast.ObjectList) (*api.NetworkResource, error) {
    16  	if len(o.Items) > 1 {
    17  		return nil, fmt.Errorf("only one 'network' resource allowed")
    18  	}
    19  
    20  	// Check for invalid keys
    21  	valid := []string{
    22  		"mode",
    23  		"mbits",
    24  		"dns",
    25  		"port",
    26  	}
    27  	if err := 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  
    37  	delete(m, "dns")
    38  	if err := mapstructure.WeakDecode(m, &r); err != nil {
    39  		return nil, err
    40  	}
    41  
    42  	var networkObj *ast.ObjectList
    43  	if ot, ok := o.Items[0].Val.(*ast.ObjectType); ok {
    44  		networkObj = ot.List
    45  	} else {
    46  		return nil, fmt.Errorf("should be an object")
    47  	}
    48  	if err := parsePorts(networkObj, &r); err != nil {
    49  		return nil, multierror.Prefix(err, "network, ports ->")
    50  	}
    51  
    52  	// Filter dns
    53  	if dns := networkObj.Filter("dns"); len(dns.Items) > 0 {
    54  		if len(dns.Items) > 1 {
    55  			return nil, multierror.Prefix(fmt.Errorf("cannot have more than 1 dns stanza"), "network ->")
    56  		}
    57  
    58  		d, err := parseDNS(dns.Items[0])
    59  		if err != nil {
    60  			return nil, multierror.Prefix(err, "network ->")
    61  		}
    62  
    63  		r.DNS = d
    64  	}
    65  
    66  	return &r, nil
    67  }
    68  
    69  func parsePorts(networkObj *ast.ObjectList, nw *api.NetworkResource) error {
    70  	portsObjList := networkObj.Filter("port")
    71  	knownPortLabels := make(map[string]bool)
    72  	for _, port := range portsObjList.Items {
    73  		if len(port.Keys) == 0 {
    74  			return fmt.Errorf("ports must be named")
    75  		}
    76  
    77  		// check for invalid keys
    78  		valid := []string{
    79  			"static",
    80  			"to",
    81  			"host_network",
    82  		}
    83  		if err := checkHCLKeys(port.Val, valid); err != nil {
    84  			return err
    85  		}
    86  
    87  		label := port.Keys[0].Token.Value().(string)
    88  		if !reDynamicPorts.MatchString(label) {
    89  			return errPortLabel
    90  		}
    91  		l := strings.ToLower(label)
    92  		if knownPortLabels[l] {
    93  			return fmt.Errorf("found a port label collision: %s", label)
    94  		}
    95  		var p map[string]interface{}
    96  		var res api.Port
    97  		if err := hcl.DecodeObject(&p, port.Val); err != nil {
    98  			return err
    99  		}
   100  		if err := mapstructure.WeakDecode(p, &res); err != nil {
   101  			return err
   102  		}
   103  		res.Label = label
   104  		if res.Value > 0 {
   105  			nw.ReservedPorts = append(nw.ReservedPorts, res)
   106  		} else {
   107  			nw.DynamicPorts = append(nw.DynamicPorts, res)
   108  		}
   109  		knownPortLabels[l] = true
   110  	}
   111  	return nil
   112  }
   113  
   114  func parseDNS(dns *ast.ObjectItem) (*api.DNSConfig, error) {
   115  	valid := []string{
   116  		"servers",
   117  		"searches",
   118  		"options",
   119  	}
   120  
   121  	if err := checkHCLKeys(dns.Val, valid); err != nil {
   122  		return nil, multierror.Prefix(err, "dns ->")
   123  	}
   124  
   125  	var dnsCfg api.DNSConfig
   126  	var m map[string]interface{}
   127  	if err := hcl.DecodeObject(&m, dns.Val); err != nil {
   128  		return nil, err
   129  	}
   130  
   131  	if err := mapstructure.WeakDecode(m, &dnsCfg); err != nil {
   132  		return nil, err
   133  	}
   134  
   135  	return &dnsCfg, nil
   136  }