From 884af69da14c132a378a6fb3cc10f9501fdbf03b Mon Sep 17 00:00:00 2001 From: Ali Rizvi-Santiago Date: Mon, 27 Feb 2017 15:34:53 -0600 Subject: [PATCH] go fmt on builder/vmware/* --- builder/vmware/common/driver.go | 158 ++- builder/vmware/common/driver_mock.go | 2 +- builder/vmware/common/driver_parser.go | 1122 +++++++++-------- builder/vmware/common/driver_player_unix.go | 2 +- builder/vmware/common/driver_workstation10.go | 1 - builder/vmware/iso/builder.go | 29 +- builder/vmware/iso/step_create_vmx.go | 360 +++--- builder/vmware/iso/step_create_vmx_test.go | 234 ++-- 8 files changed, 1075 insertions(+), 833 deletions(-) diff --git a/builder/vmware/common/driver.go b/builder/vmware/common/driver.go index 0f0bc1fe8..745b48d69 100644 --- a/builder/vmware/common/driver.go +++ b/builder/vmware/common/driver.go @@ -1,19 +1,19 @@ package common import ( - "errors" "bytes" + "errors" "fmt" + "io/ioutil" "log" + "net" "os" "os/exec" - "io/ioutil" "regexp" "runtime" "strconv" "strings" "time" - "net" "github.com/hashicorp/packer/helper/multistep" ) @@ -214,23 +214,27 @@ func compareVersions(versionFound string, versionWanted string, product string) /// helper functions that read configuration information from a file // read the network<->device configuration out of the specified path -func ReadNetmapConfig(path string) (NetworkMap,error) { - fd,err := os.Open(path) - if err != nil { return nil, err } +func ReadNetmapConfig(path string) (NetworkMap, error) { + fd, err := os.Open(path) + if err != nil { + return nil, err + } defer fd.Close() return ReadNetworkMap(fd) } // read the dhcp configuration out of the specified path -func ReadDhcpConfig(path string) (DhcpConfiguration,error) { - fd,err := os.Open(path) - if err != nil { return nil, err } +func ReadDhcpConfig(path string) (DhcpConfiguration, error) { + fd, err := os.Open(path) + if err != nil { + return nil, err + } defer fd.Close() return ReadDhcpConfiguration(fd) } // read the VMX configuration from the specified path -func readVMXConfig(path string) (map[string]string,error) { +func readVMXConfig(path string) (map[string]string, error) { f, err := os.Open(path) if err != nil { return map[string]string{}, err @@ -245,7 +249,7 @@ func readVMXConfig(path string) (map[string]string,error) { } // read the connection type out of a vmx configuration -func readCustomDeviceName(vmxData map[string]string) (string,error) { +func readCustomDeviceName(vmxData map[string]string) (string, error) { connectionType, ok := vmxData["ethernet0.connectiontype"] if !ok || connectionType != "custom" { @@ -266,18 +270,20 @@ type VmwareDriver struct { /// A driver must overload these in order to point to the correct /// files so that the address detection (ip and ethernet) machinery /// works. - DhcpLeasesPath func(string) string - DhcpConfPath func(string) string + DhcpLeasesPath func(string) string + DhcpConfPath func(string) string VmnetnatConfPath func(string) string - NetmapConfPath func() string + NetmapConfPath func() string } -func (d *VmwareDriver) GuestAddress(state multistep.StateBag) (string,error) { +func (d *VmwareDriver) GuestAddress(state multistep.StateBag) (string, error) { vmxPath := state.Get("vmx_path").(string) log.Println("Lookup up IP information...") vmxData, err := readVMXConfig(vmxPath) - if err != nil { return "", err } + if err != nil { + return "", err + } var ok bool macAddress := "" @@ -287,40 +293,50 @@ func (d *VmwareDriver) GuestAddress(state multistep.StateBag) (string,error) { } } - res,err := net.ParseMAC(macAddress) - if err != nil { return "", err } + res, err := net.ParseMAC(macAddress) + if err != nil { + return "", err + } - return res.String(),nil + return res.String(), nil } -func (d *VmwareDriver) GuestIP(state multistep.StateBag) (string,error) { +func (d *VmwareDriver) GuestIP(state multistep.StateBag) (string, error) { // read netmap config pathNetmap := d.NetmapConfPath() if _, err := os.Stat(pathNetmap); err != nil { return "", fmt.Errorf("Could not find netmap conf file: %s", pathNetmap) } - netmap,err := ReadNetmapConfig(pathNetmap) - if err != nil { return "",err } + netmap, err := ReadNetmapConfig(pathNetmap) + if err != nil { + return "", err + } // convert the stashed network to a device network := state.Get("vmnetwork").(string) - device,err := netmap.NameIntoDevice(network) + device, err := netmap.NameIntoDevice(network) // we were unable to find the device, maybe it's a custom one... // so, check to see if it's in the .vmx configuration if err != nil || network == "custom" { vmxPath := state.Get("vmx_path").(string) vmxData, err := readVMXConfig(vmxPath) - if err != nil { return "", err } + if err != nil { + return "", err + } device, err = readCustomDeviceName(vmxData) - if err != nil { return "", err } + if err != nil { + return "", err + } } // figure out our MAC address for looking up the guest address - MACAddress,err := d.GuestAddress(state) - if err != nil { return "", err } + MACAddress, err := d.GuestAddress(state) + if err != nil { + return "", err + } // figure out the correct dhcp leases dhcpLeasesPath := d.DhcpLeasesPath(device) @@ -382,29 +398,35 @@ func (d *VmwareDriver) GuestIP(state multistep.StateBag) (string,error) { return curIp, nil } -func (d *VmwareDriver) HostAddress(state multistep.StateBag) (string,error) { +func (d *VmwareDriver) HostAddress(state multistep.StateBag) (string, error) { // parse network<->device mapping pathNetmap := d.NetmapConfPath() if _, err := os.Stat(pathNetmap); err != nil { return "", fmt.Errorf("Could not find netmap conf file: %s", pathNetmap) } - netmap,err := ReadNetmapConfig(pathNetmap) - if err != nil { return "",err } + netmap, err := ReadNetmapConfig(pathNetmap) + if err != nil { + return "", err + } // convert network to name network := state.Get("vmnetwork").(string) - device,err := netmap.NameIntoDevice(network) + device, err := netmap.NameIntoDevice(network) // we were unable to find the device, maybe it's a custom one... // so, check to see if it's in the .vmx configuration if err != nil || network == "custom" { vmxPath := state.Get("vmx_path").(string) vmxData, err := readVMXConfig(vmxPath) - if err != nil { return "", err } + if err != nil { + return "", err + } device, err = readCustomDeviceName(vmxData) - if err != nil { return "", err } + if err != nil { + return "", err + } } // parse dhcpd configuration @@ -413,54 +435,68 @@ func (d *VmwareDriver) HostAddress(state multistep.StateBag) (string,error) { return "", fmt.Errorf("Could not find vmnetdhcp conf file: %s", pathDhcpConfig) } - config,err := ReadDhcpConfig(pathDhcpConfig) - if err != nil { return "",err } + config, err := ReadDhcpConfig(pathDhcpConfig) + if err != nil { + return "", err + } // find the entry configured in the dhcpd - interfaceConfig,err := config.HostByName(device) - if err != nil { return "", err } + interfaceConfig, err := config.HostByName(device) + if err != nil { + return "", err + } // finally grab the hardware address - address,err := interfaceConfig.Hardware() - if err == nil { return address.String(), nil } + address, err := interfaceConfig.Hardware() + if err == nil { + return address.String(), nil + } // we didn't find it, so search through our interfaces for the device name - interfaceList,err := net.Interfaces() - if err == nil { return "", err } + interfaceList, err := net.Interfaces() + if err == nil { + return "", err + } names := make([]string, 0) - for _,intf := range interfaceList { - if strings.HasSuffix( strings.ToLower(intf.Name), device ) { - return intf.HardwareAddr.String(),nil + for _, intf := range interfaceList { + if strings.HasSuffix(strings.ToLower(intf.Name), device) { + return intf.HardwareAddr.String(), nil } names = append(names, intf.Name) } - return "",fmt.Errorf("Unable to find device %s : %v", device, names) + return "", fmt.Errorf("Unable to find device %s : %v", device, names) } -func (d *VmwareDriver) HostIP(state multistep.StateBag) (string,error) { +func (d *VmwareDriver) HostIP(state multistep.StateBag) (string, error) { // parse network<->device mapping pathNetmap := d.NetmapConfPath() if _, err := os.Stat(pathNetmap); err != nil { return "", fmt.Errorf("Could not find netmap conf file: %s", pathNetmap) } - netmap,err := ReadNetmapConfig(pathNetmap) - if err != nil { return "",err } + netmap, err := ReadNetmapConfig(pathNetmap) + if err != nil { + return "", err + } // convert network to name network := state.Get("vmnetwork").(string) - device,err := netmap.NameIntoDevice(network) + device, err := netmap.NameIntoDevice(network) // we were unable to find the device, maybe it's a custom one... // so, check to see if it's in the .vmx configuration if err != nil || network == "custom" { vmxPath := state.Get("vmx_path").(string) vmxData, err := readVMXConfig(vmxPath) - if err != nil { return "", err } + if err != nil { + return "", err + } device, err = readCustomDeviceName(vmxData) - if err != nil { return "", err } + if err != nil { + return "", err + } } // parse dhcpd configuration @@ -468,15 +504,21 @@ func (d *VmwareDriver) HostIP(state multistep.StateBag) (string,error) { if _, err := os.Stat(pathDhcpConfig); err != nil { return "", fmt.Errorf("Could not find vmnetdhcp conf file: %s", pathDhcpConfig) } - config,err := ReadDhcpConfig(pathDhcpConfig) - if err != nil { return "",err } + config, err := ReadDhcpConfig(pathDhcpConfig) + if err != nil { + return "", err + } // find the entry configured in the dhcpd - interfaceConfig,err := config.HostByName(device) - if err != nil { return "", err } + interfaceConfig, err := config.HostByName(device) + if err != nil { + return "", err + } - address,err := interfaceConfig.IP4() - if err != nil { return "", err } + address, err := interfaceConfig.IP4() + if err != nil { + return "", err + } - return address.String(),nil + return address.String(), nil } diff --git a/builder/vmware/common/driver_mock.go b/builder/vmware/common/driver_mock.go index da28cd474..562eab382 100644 --- a/builder/vmware/common/driver_mock.go +++ b/builder/vmware/common/driver_mock.go @@ -83,7 +83,7 @@ type DriverMock struct { VmnetnatConfPathCalled bool VmnetnatConfPathResult string - + NetmapConfPathCalled bool NetmapConfPathResult string diff --git a/builder/vmware/common/driver_parser.go b/builder/vmware/common/driver_parser.go index 7071e424d..dbf15b5b5 100644 --- a/builder/vmware/common/driver_parser.go +++ b/builder/vmware/common/driver_parser.go @@ -1,12 +1,13 @@ package common + import ( "fmt" - "os" "io" - "strings" - "strconv" "net" + "os" "sort" + "strconv" + "strings" ) type sentinelSignaller chan struct{} @@ -20,16 +21,20 @@ func uncomment(eof sentinelSignaller, in <-chan byte) chan byte { var endofline bool for stillReading := true; stillReading; { select { - case <-eof: - stillReading = false - case ch := <-in: - switch ch { - case '#': - endofline = true - case '\n': - if endofline { endofline = false } + case <-eof: + stillReading = false + case ch := <-in: + switch ch { + case '#': + endofline = true + case '\n': + if endofline { + endofline = false } - if !endofline { out <- ch } + } + if !endofline { + out <- ch + } } } }(in, out) @@ -46,62 +51,71 @@ func tokenizeDhcpConfig(eof sentinelSignaller, in chan byte) chan string { go func(out chan string) { for stillReading := true; stillReading; { select { - case <-eof: - stillReading = false + case <-eof: + stillReading = false - case ch = <-in: - if quote { - if ch == '"' { - out <- state + string(ch) - state,quote = "",false - continue - } - state += string(ch) + case ch = <-in: + if quote { + if ch == '"' { + out <- state + string(ch) + state, quote = "", false continue } + state += string(ch) + continue + } - switch ch { - case '"': - quote = true - state += string(ch) - continue + switch ch { + case '"': + quote = true + state += string(ch) + continue - case '\r': - fallthrough - case '\n': - fallthrough - case '\t': - fallthrough - case ' ': - if len(state) == 0 { continue } - out <- state - state = "" - - case '{': fallthrough - case '}': fallthrough - case ';': - if len(state) > 0 { out <- state } - out <- string(ch) - state = "" - - default: - state += string(ch) + case '\r': + fallthrough + case '\n': + fallthrough + case '\t': + fallthrough + case ' ': + if len(state) == 0 { + continue } + out <- state + state = "" + + case '{': + fallthrough + case '}': + fallthrough + case ';': + if len(state) > 0 { + out <- state + } + out <- string(ch) + state = "" + + default: + state += string(ch) + } } } - if len(state) > 0 { out <- state } + if len(state) > 0 { + out <- state + } }(out) return out } /** mid-level parsing */ type tkParameter struct { - name string + name string operand []string } + func (e *tkParameter) String() string { var values []string - for _,val := range e.operand { + for _, val := range e.operand { values = append(values, val) } return fmt.Sprintf("%s [%s]", e.name, strings.Join(values, ",")) @@ -109,21 +123,22 @@ func (e *tkParameter) String() string { type tkGroup struct { parent *tkGroup - id tkParameter + id tkParameter groups []*tkGroup params []tkParameter } + func (e *tkGroup) String() string { var id []string id = append(id, e.id.name) - for _,val := range e.id.operand { + for _, val := range e.id.operand { id = append(id, val) } var config []string - for _,val := range e.params { + for _, val := range e.params { config = append(config, val.String()) } return fmt.Sprintf("%s {\n%s\n}", strings.Join(id, " "), strings.Join(config, "\n")) @@ -139,11 +154,14 @@ func parseTokenParameter(in chan string) tkParameter { continue } switch token { - case "{": fallthrough - case "}": fallthrough - case ";": goto leave - default: - result.operand = append(result.operand, token) + case "{": + fallthrough + case "}": + fallthrough + case ";": + goto leave + default: + result.operand = append(result.operand, token) } } leave: @@ -151,50 +169,52 @@ leave: } // convert a channel of pseudo-tokens into an tkGroup tree */ -func parseDhcpConfig(eof sentinelSignaller, in chan string) (tkGroup,error) { +func parseDhcpConfig(eof sentinelSignaller, in chan string) (tkGroup, error) { var tokens []string var result tkGroup toParameter := func(tokens []string) tkParameter { out := make(chan string) - go func(out chan string){ - for _,v := range tokens { out <- v } + go func(out chan string) { + for _, v := range tokens { + out <- v + } out <- ";" }(out) return parseTokenParameter(out) } - for stillReading,currentgroup := true,&result; stillReading; { + for stillReading, currentgroup := true, &result; stillReading; { select { - case <-eof: - stillReading = false + case <-eof: + stillReading = false - case tk := <-in: - switch tk { - case "{": - grp := &tkGroup{parent:currentgroup} - grp.id = toParameter(tokens) - currentgroup.groups = append(currentgroup.groups, grp) - currentgroup = grp - case "}": - if currentgroup.parent == nil { - return tkGroup{}, fmt.Errorf("Unable to close the global declaration") - } - if len(tokens) > 0 { - return tkGroup{}, fmt.Errorf("List of tokens was left unterminated : %v", tokens) - } - currentgroup = currentgroup.parent - case ";": - arg := toParameter(tokens) - currentgroup.params = append(currentgroup.params, arg) - default: - tokens = append(tokens, tk) - continue + case tk := <-in: + switch tk { + case "{": + grp := &tkGroup{parent: currentgroup} + grp.id = toParameter(tokens) + currentgroup.groups = append(currentgroup.groups, grp) + currentgroup = grp + case "}": + if currentgroup.parent == nil { + return tkGroup{}, fmt.Errorf("Unable to close the global declaration") } - tokens = []string{} + if len(tokens) > 0 { + return tkGroup{}, fmt.Errorf("List of tokens was left unterminated : %v", tokens) + } + currentgroup = currentgroup.parent + case ";": + arg := toParameter(tokens) + currentgroup.params = append(currentgroup.params, arg) + default: + tokens = append(tokens, tk) + continue + } + tokens = []string{} } } - return result,nil + return result, nil } func tokenizeNetworkMapConfig(eof sentinelSignaller, in chan byte) chan string { @@ -207,70 +227,85 @@ func tokenizeNetworkMapConfig(eof sentinelSignaller, in chan byte) chan string { go func(out chan string) { for stillReading := true; stillReading; { select { - case <-eof: - stillReading = false + case <-eof: + stillReading = false - case ch = <-in: - if quote { - if ch == '"' { - out <- state + string(ch) - state,quote = "",false - continue - } - state += string(ch) + case ch = <-in: + if quote { + if ch == '"' { + out <- state + string(ch) + state, quote = "", false continue } + state += string(ch) + continue + } - switch ch { - case '"': - quote = true - state += string(ch) - continue + switch ch { + case '"': + quote = true + state += string(ch) + continue - case '\r': - fallthrough - case '\t': - fallthrough - case ' ': - if len(state) == 0 { continue } - out <- state - state = "" - - case '\n': - if lastnewline { continue } - if len(state) > 0 { out <- state } - out <- string(ch) - state = "" - lastnewline = true - continue - - case '.': fallthrough - case '=': - if len(state) > 0 { out <- state } - out <- string(ch) - state = "" - - default: - state += string(ch) + case '\r': + fallthrough + case '\t': + fallthrough + case ' ': + if len(state) == 0 { + continue } - lastnewline = false + out <- state + state = "" + + case '\n': + if lastnewline { + continue + } + if len(state) > 0 { + out <- state + } + out <- string(ch) + state = "" + lastnewline = true + continue + + case '.': + fallthrough + case '=': + if len(state) > 0 { + out <- state + } + out <- string(ch) + state = "" + + default: + state += string(ch) + } + lastnewline = false } } - if len(state) > 0 { out <- state } + if len(state) > 0 { + out <- state + } }(out) return out } -func parseNetworkMapConfig(eof sentinelSignaller, in chan string) (NetworkMap,error) { +func parseNetworkMapConfig(eof sentinelSignaller, in chan string) (NetworkMap, error) { var unsorted map[string]map[string]string var state []string addResult := func(network string, attribute string, value string) error { - _,ok := unsorted[network] - if !ok { unsorted[network] = make(map[string]string) } + _, ok := unsorted[network] + if !ok { + unsorted[network] = make(map[string]string) + } - val,err := strconv.Unquote(value) - if err != nil { return err } + val, err := strconv.Unquote(value) + if err != nil { + return err + } current := unsorted[network] current[attribute] = val @@ -280,135 +315,174 @@ func parseNetworkMapConfig(eof sentinelSignaller, in chan string) (NetworkMap,er stillReading := true for unsorted = make(map[string]map[string]string); stillReading; { select { - case <-eof: - if len(state) == 3 { - err := addResult(state[0], state[1], state[2]) - if err != nil { return nil,err } + case <-eof: + if len(state) == 3 { + err := addResult(state[0], state[1], state[2]) + if err != nil { + return nil, err } - stillReading = false - case tk := <-in: - switch tk { - case ".": - if len(state) != 1 { return nil,fmt.Errorf("Missing network index") } - case "=": - if len(state) != 2 { return nil,fmt.Errorf("Assignment to empty attribute") } - case "\n": - if len(state) == 0 { continue } - if len(state) != 3 { return nil,fmt.Errorf("Invalid attribute assignment : %v", state) } - err := addResult(state[0], state[1], state[2]) - if err != nil { return nil,err } - state = make([]string, 0) - default: - state = append(state, tk) + } + stillReading = false + case tk := <-in: + switch tk { + case ".": + if len(state) != 1 { + return nil, fmt.Errorf("Missing network index") } + case "=": + if len(state) != 2 { + return nil, fmt.Errorf("Assignment to empty attribute") + } + case "\n": + if len(state) == 0 { + continue + } + if len(state) != 3 { + return nil, fmt.Errorf("Invalid attribute assignment : %v", state) + } + err := addResult(state[0], state[1], state[2]) + if err != nil { + return nil, err + } + state = make([]string, 0) + default: + state = append(state, tk) + } } } result := make([]map[string]string, 0) var keys []string - for k := range unsorted { keys = append(keys, k) } + for k := range unsorted { + keys = append(keys, k) + } sort.Strings(keys) - for _,k := range keys { + for _, k := range keys { result = append(result, unsorted[k]) } - return result,nil + return result, nil } /** higher-level parsing */ /// parameters -type pParameter interface { repr() string } +type pParameter interface { + repr() string +} type pParameterInclude struct { filename string } -func (e pParameterInclude) repr() string { return fmt.Sprintf("include-file:filename=%s",e.filename) } + +func (e pParameterInclude) repr() string { return fmt.Sprintf("include-file:filename=%s", e.filename) } type pParameterOption struct { - name string + name string value string } -func (e pParameterOption) repr() string { return fmt.Sprintf("option:%s=%s",e.name,e.value) } + +func (e pParameterOption) repr() string { return fmt.Sprintf("option:%s=%s", e.name, e.value) } // allow some-kind-of-something type pParameterGrant struct { - verb string // allow,deny,ignore + verb string // allow,deny,ignore attribute string } -func (e pParameterGrant) repr() string { return fmt.Sprintf("grant:%s,%s",e.verb,e.attribute) } + +func (e pParameterGrant) repr() string { return fmt.Sprintf("grant:%s,%s", e.verb, e.attribute) } type pParameterAddress4 []string + func (e pParameterAddress4) repr() string { - return fmt.Sprintf("fixed-address4:%s",strings.Join(e,",")) + return fmt.Sprintf("fixed-address4:%s", strings.Join(e, ",")) } type pParameterAddress6 []string + func (e pParameterAddress6) repr() string { - return fmt.Sprintf("fixed-address6:%s",strings.Join(e,",")) + return fmt.Sprintf("fixed-address6:%s", strings.Join(e, ",")) } // hardware address 00:00:00:00:00:00 type pParameterHardware struct { - class string + class string address []byte } + func (e pParameterHardware) repr() string { res := make([]string, 0) - for _,v := range e.address { - res = append(res, fmt.Sprintf("%02x",v)) + for _, v := range e.address { + res = append(res, fmt.Sprintf("%02x", v)) } - return fmt.Sprintf("hardware-address:%s[%s]",e.class,strings.Join(res,":")) + return fmt.Sprintf("hardware-address:%s[%s]", e.class, strings.Join(res, ":")) } type pParameterBoolean struct { parameter string - truancy bool + truancy bool } -func (e pParameterBoolean) repr() string { return fmt.Sprintf("boolean:%s=%v",e.parameter,e.truancy) } + +func (e pParameterBoolean) repr() string { return fmt.Sprintf("boolean:%s=%v", e.parameter, e.truancy) } type pParameterClientMatch struct { name string data string } -func (e pParameterClientMatch) repr() string { return fmt.Sprintf("match-client:%s=%s",e.name,e.data) } + +func (e pParameterClientMatch) repr() string { return fmt.Sprintf("match-client:%s=%s", e.name, e.data) } // range 127.0.0.1 127.0.0.255 type pParameterRange4 struct { min net.IP max net.IP } -func (e pParameterRange4) repr() string { return fmt.Sprintf("range4:%s-%s",e.min.String(),e.max.String()) } + +func (e pParameterRange4) repr() string { + return fmt.Sprintf("range4:%s-%s", e.min.String(), e.max.String()) +} type pParameterRange6 struct { min net.IP max net.IP } -func (e pParameterRange6) repr() string { return fmt.Sprintf("range6:%s-%s",e.min.String(),e.max.String()) } + +func (e pParameterRange6) repr() string { + return fmt.Sprintf("range6:%s-%s", e.min.String(), e.max.String()) +} type pParameterPrefix6 struct { - min net.IP - max net.IP + min net.IP + max net.IP bits int } -func (e pParameterPrefix6) repr() string { return fmt.Sprintf("prefix6:/%d:%s-%s",e.bits,e.min.String(),e.max.String()) } + +func (e pParameterPrefix6) repr() string { + return fmt.Sprintf("prefix6:/%d:%s-%s", e.bits, e.min.String(), e.max.String()) +} // some-kind-of-parameter 1024 type pParameterOther struct { parameter string - value string + value string } -func (e pParameterOther) repr() string { return fmt.Sprintf("parameter:%s=%s",e.parameter,e.value) } + +func (e pParameterOther) repr() string { return fmt.Sprintf("parameter:%s=%s", e.parameter, e.value) } type pParameterExpression struct { - parameter string + parameter string expression string } -func (e pParameterExpression) repr() string { return fmt.Sprintf("parameter-expression:%s=\"%s\"",e.parameter,e.expression) } -type pDeclarationIdentifier interface { repr() string } +func (e pParameterExpression) repr() string { + return fmt.Sprintf("parameter-expression:%s=\"%s\"", e.parameter, e.expression) +} + +type pDeclarationIdentifier interface { + repr() string +} type pDeclaration struct { - id pDeclarationIdentifier - parent *pDeclaration - parameters []pParameter + id pDeclarationIdentifier + parent *pDeclaration + parameters []pParameter declarations []pDeclaration } @@ -420,277 +494,305 @@ func (e *pDeclaration) repr() string { res := e.short() var parameters []string - for _,v := range e.parameters { + for _, v := range e.parameters { parameters = append(parameters, v.repr()) } var groups []string - for _,v := range e.declarations { - groups = append(groups, fmt.Sprintf("-> %s",v.short())) + for _, v := range e.declarations { + groups = append(groups, fmt.Sprintf("-> %s", v.short())) } if e.parent != nil { - res = fmt.Sprintf("%s parent:%s",res,e.parent.short()) + res = fmt.Sprintf("%s parent:%s", res, e.parent.short()) } - return fmt.Sprintf("%s\n%s\n%s\n", res, strings.Join(parameters,"\n"), strings.Join(groups,"\n")) + return fmt.Sprintf("%s\n%s\n%s\n", res, strings.Join(parameters, "\n"), strings.Join(groups, "\n")) } -type pDeclarationGlobal struct {} +type pDeclarationGlobal struct{} + func (e pDeclarationGlobal) repr() string { return fmt.Sprintf("{global}") } -type pDeclarationShared struct { name string } +type pDeclarationShared struct{ name string } + func (e pDeclarationShared) repr() string { return fmt.Sprintf("{shared-network %s}", e.name) } -type pDeclarationSubnet4 struct { net.IPNet } +type pDeclarationSubnet4 struct{ net.IPNet } + func (e pDeclarationSubnet4) repr() string { return fmt.Sprintf("{subnet4 %s}", e.String()) } -type pDeclarationSubnet6 struct { net.IPNet } +type pDeclarationSubnet6 struct{ net.IPNet } + func (e pDeclarationSubnet6) repr() string { return fmt.Sprintf("{subnet6 %s}", e.String()) } -type pDeclarationHost struct { name string } +type pDeclarationHost struct{ name string } + func (e pDeclarationHost) repr() string { return fmt.Sprintf("{host name:%s}", e.name) } -type pDeclarationPool struct {} +type pDeclarationPool struct{} + func (e pDeclarationPool) repr() string { return fmt.Sprintf("{pool}") } -type pDeclarationGroup struct {} +type pDeclarationGroup struct{} + func (e pDeclarationGroup) repr() string { return fmt.Sprintf("{group}") } -type pDeclarationClass struct { name string } +type pDeclarationClass struct{ name string } + func (e pDeclarationClass) repr() string { return fmt.Sprintf("{class}") } /** parsers */ -func parseParameter(val tkParameter) (pParameter,error) { +func parseParameter(val tkParameter) (pParameter, error) { switch val.name { - case "include": - if len(val.operand) != 2 { - return nil,fmt.Errorf("Invalid number of parameters for pParameterInclude : %v",val.operand) - } - name := val.operand[0] - return pParameterInclude{filename: name},nil + case "include": + if len(val.operand) != 2 { + return nil, fmt.Errorf("Invalid number of parameters for pParameterInclude : %v", val.operand) + } + name := val.operand[0] + return pParameterInclude{filename: name}, nil - case "option": - if len(val.operand) != 2 { - return nil,fmt.Errorf("Invalid number of parameters for pParameterOption : %v",val.operand) - } - name, value := val.operand[0], val.operand[1] - return pParameterOption{name: name, value: value},nil + case "option": + if len(val.operand) != 2 { + return nil, fmt.Errorf("Invalid number of parameters for pParameterOption : %v", val.operand) + } + name, value := val.operand[0], val.operand[1] + return pParameterOption{name: name, value: value}, nil - case "allow": fallthrough - case "deny": fallthrough - case "ignore": - if len(val.operand) < 1 { - return nil,fmt.Errorf("Invalid number of parameters for pParameterGrant : %v",val.operand) - } - attribute := strings.Join(val.operand," ") - return pParameterGrant{verb: strings.ToLower(val.name), attribute: attribute},nil + case "allow": + fallthrough + case "deny": + fallthrough + case "ignore": + if len(val.operand) < 1 { + return nil, fmt.Errorf("Invalid number of parameters for pParameterGrant : %v", val.operand) + } + attribute := strings.Join(val.operand, " ") + return pParameterGrant{verb: strings.ToLower(val.name), attribute: attribute}, nil - case "range": - if len(val.operand) < 1 { - return nil,fmt.Errorf("Invalid number of parameters for pParameterRange4 : %v",val.operand) - } - idxAddress := map[bool]int{true:1,false:0}[strings.ToLower(val.operand[0]) == "bootp"] - if len(val.operand) > 2 + idxAddress { - return nil,fmt.Errorf("Invalid number of parameters for pParameterRange : %v",val.operand) - } - if idxAddress + 1 > len(val.operand) { - res := net.ParseIP(val.operand[idxAddress]) - return pParameterRange4{min: res, max: res},nil - } - addr1 := net.ParseIP(val.operand[idxAddress]) - addr2 := net.ParseIP(val.operand[idxAddress+1]) - return pParameterRange4{min: addr1, max: addr2},nil + case "range": + if len(val.operand) < 1 { + return nil, fmt.Errorf("Invalid number of parameters for pParameterRange4 : %v", val.operand) + } + idxAddress := map[bool]int{true: 1, false: 0}[strings.ToLower(val.operand[0]) == "bootp"] + if len(val.operand) > 2+idxAddress { + return nil, fmt.Errorf("Invalid number of parameters for pParameterRange : %v", val.operand) + } + if idxAddress+1 > len(val.operand) { + res := net.ParseIP(val.operand[idxAddress]) + return pParameterRange4{min: res, max: res}, nil + } + addr1 := net.ParseIP(val.operand[idxAddress]) + addr2 := net.ParseIP(val.operand[idxAddress+1]) + return pParameterRange4{min: addr1, max: addr2}, nil - case "range6": - if len(val.operand) == 1 { - address := val.operand[0] - if (strings.Contains(address, "/")) { - cidr := strings.SplitN(address, "/", 2) - if len(cidr) != 2 { return nil,fmt.Errorf("Unknown ipv6 format : %v", address) } - address := net.ParseIP(cidr[0]) - bits,err := strconv.Atoi(cidr[1]) - if err != nil { return nil,err } - mask := net.CIDRMask(bits, net.IPv6len*8) - - // figure out the network address - network := address.Mask(mask) - - // make a broadcast address - broadcast := network - networkSize,totalSize := mask.Size() - hostSize := totalSize-networkSize - for i := networkSize / 8; i < totalSize / 8; i++ { - broadcast[i] = byte(0xff) - } - octetIndex := network[networkSize / 8] - bitsLeft := (uint32)(hostSize%8) - broadcast[octetIndex] = network[octetIndex] | ((1< 1 { + if val.operand[0] == "=" { + return pParameterExpression{parameter: val.name, expression: strings.Join(val.operand[1:], "")}, nil } - if val.operand[0] != "option" { - return nil,fmt.Errorf("Invalid match parameter : %v",val.operand[0]) - } - optionName := val.operand[1] - optionData := val.operand[2] - return pParameterClientMatch{name: optionName, data: optionData},nil - - default: - length := len(val.operand) - if length < 1 { - return pParameterBoolean{parameter: val.name, truancy: true},nil - } else if length > 1 { - if val.operand[0] == "=" { - return pParameterExpression{parameter: val.name, expression: strings.Join(val.operand[1:],"")},nil - } - } - if length != 1 { - return nil,fmt.Errorf("Invalid number of parameters for pParameterOther : %v",val.operand) - } - if strings.ToLower(val.name) == "not" { - return pParameterBoolean{parameter: val.operand[0], truancy: false},nil - } - return pParameterOther{parameter: val.name, value: val.operand[0]}, nil + } + if length != 1 { + return nil, fmt.Errorf("Invalid number of parameters for pParameterOther : %v", val.operand) + } + if strings.ToLower(val.name) == "not" { + return pParameterBoolean{parameter: val.operand[0], truancy: false}, nil + } + return pParameterOther{parameter: val.name, value: val.operand[0]}, nil } } -func parseTokenGroup(val tkGroup) (*pDeclaration,error) { +func parseTokenGroup(val tkGroup) (*pDeclaration, error) { params := val.id.operand switch val.id.name { - case "group": - return &pDeclaration{id:pDeclarationGroup{}},nil + case "group": + return &pDeclaration{id: pDeclarationGroup{}}, nil - case "pool": - return &pDeclaration{id:pDeclarationPool{}},nil + case "pool": + return &pDeclaration{id: pDeclarationPool{}}, nil - case "host": - if len(params) == 1 { - return &pDeclaration{id:pDeclarationHost{name: params[0]}},nil - } + case "host": + if len(params) == 1 { + return &pDeclaration{id: pDeclarationHost{name: params[0]}}, nil + } - case "subnet": - if len(params) == 3 && strings.ToLower(params[1]) == "netmask" { - addr := make([]byte, 4) - for i,v := range strings.SplitN(params[2], ".", 4) { - res,err := strconv.ParseInt(v, 10, 0) - if err != nil { return nil,err } - addr[i] = byte(res) + case "subnet": + if len(params) == 3 && strings.ToLower(params[1]) == "netmask" { + addr := make([]byte, 4) + for i, v := range strings.SplitN(params[2], ".", 4) { + res, err := strconv.ParseInt(v, 10, 0) + if err != nil { + return nil, err } - oc1,oc2,oc3,oc4 := addr[0],addr[1],addr[2],addr[3] - if subnet,mask := net.ParseIP(params[0]),net.IPv4Mask(oc1,oc2,oc3,oc4); subnet != nil && mask != nil { - return &pDeclaration{id:pDeclarationSubnet4{net.IPNet{IP:subnet,Mask:mask}}},nil + addr[i] = byte(res) + } + oc1, oc2, oc3, oc4 := addr[0], addr[1], addr[2], addr[3] + if subnet, mask := net.ParseIP(params[0]), net.IPv4Mask(oc1, oc2, oc3, oc4); subnet != nil && mask != nil { + return &pDeclaration{id: pDeclarationSubnet4{net.IPNet{IP: subnet, Mask: mask}}}, nil + } + } + case "subnet6": + if len(params) == 1 { + ip6 := strings.SplitN(params[0], "/", 2) + if len(ip6) == 2 && strings.Contains(ip6[0], ":") { + address := net.ParseIP(ip6[0]) + prefix, err := strconv.Atoi(ip6[1]) + if err != nil { + return nil, err } + return &pDeclaration{id: pDeclarationSubnet6{net.IPNet{IP: address, Mask: net.CIDRMask(prefix, net.IPv6len*8)}}}, nil } - case "subnet6": - if len(params) == 1 { - ip6 := strings.SplitN(params[0], "/", 2) - if len(ip6) == 2 && strings.Contains(ip6[0], ":") { - address := net.ParseIP(ip6[0]) - prefix,err := strconv.Atoi(ip6[1]) - if err != nil { return nil, err } - return &pDeclaration{id:pDeclarationSubnet6{net.IPNet{IP:address,Mask:net.CIDRMask(prefix, net.IPv6len*8)}}},nil - } - } - case "shared-network": - if len(params) == 1 { - return &pDeclaration{id:pDeclarationShared{name: params[0]}},nil - } - case "": - return &pDeclaration{id:pDeclarationGlobal{}},nil + } + case "shared-network": + if len(params) == 1 { + return &pDeclaration{id: pDeclarationShared{name: params[0]}}, nil + } + case "": + return &pDeclaration{id: pDeclarationGlobal{}}, nil } - return nil,fmt.Errorf("Invalid pDeclaration : %v : %v", val.id.name, params) + return nil, fmt.Errorf("Invalid pDeclaration : %v : %v", val.id.name, params) } -func flattenDhcpConfig(root tkGroup) (*pDeclaration,error) { +func flattenDhcpConfig(root tkGroup) (*pDeclaration, error) { var result *pDeclaration - result,err := parseTokenGroup(root) - if err != nil { return nil,err } + result, err := parseTokenGroup(root) + if err != nil { + return nil, err + } - for _,p := range root.params { - param,err := parseParameter(p) - if err != nil { return nil,err } + for _, p := range root.params { + param, err := parseParameter(p) + if err != nil { + return nil, err + } result.parameters = append(result.parameters, param) } - for _,p := range root.groups { - group,err := flattenDhcpConfig(*p) - if err != nil { return nil,err } + for _, p := range root.groups { + group, err := flattenDhcpConfig(*p) + if err != nil { + return nil, err + } group.parent = result result.declarations = append(result.declarations, *group) } - return result,nil + return result, nil } /** reduce the tree into the things that we care about */ type grant uint + const ( - ALLOW grant = iota + ALLOW grant = iota IGNORE grant = iota - DENY grant = iota + DENY grant = iota ) + type configDeclaration struct { - id []pDeclarationIdentifier + id []pDeclarationIdentifier composites []pDeclaration address []pParameter - options map[string]string - grants map[string]grant - attributes map[string]bool - parameters map[string]string + options map[string]string + grants map[string]grant + attributes map[string]bool + parameters map[string]string expressions map[string]string hostid []pParameterClientMatch @@ -715,28 +817,28 @@ func createDeclaration(node pDeclaration) configDeclaration { result.hostid = make([]pParameterClientMatch, 0) // walk from globals to pDeclaration collecting all parameters - for i := len(hierarchy)-1; i >= 0; i-- { - result.composites = append(result.composites, hierarchy[(len(hierarchy)-1) - i]) - result.id = append(result.id, hierarchy[(len(hierarchy)-1) - i].id) + for i := len(hierarchy) - 1; i >= 0; i-- { + result.composites = append(result.composites, hierarchy[(len(hierarchy)-1)-i]) + result.id = append(result.id, hierarchy[(len(hierarchy)-1)-i].id) // update configDeclaration parameters - for _,p := range hierarchy[i].parameters { + for _, p := range hierarchy[i].parameters { switch p.(type) { - case pParameterOption: - result.options[p.(pParameterOption).name] = p.(pParameterOption).value - case pParameterGrant: - Grant := map[string]grant{"ignore":IGNORE, "allow":ALLOW, "deny":DENY} - result.grants[p.(pParameterGrant).attribute] = Grant[p.(pParameterGrant).verb] - case pParameterBoolean: - result.attributes[p.(pParameterBoolean).parameter] = p.(pParameterBoolean).truancy - case pParameterClientMatch: - result.hostid = append(result.hostid, p.(pParameterClientMatch)) - case pParameterExpression: - result.expressions[p.(pParameterExpression).parameter] = p.(pParameterExpression).expression - case pParameterOther: - result.parameters[p.(pParameterOther).parameter] = p.(pParameterOther).value - default: - result.address = append(result.address, p) + case pParameterOption: + result.options[p.(pParameterOption).name] = p.(pParameterOption).value + case pParameterGrant: + Grant := map[string]grant{"ignore": IGNORE, "allow": ALLOW, "deny": DENY} + result.grants[p.(pParameterGrant).attribute] = Grant[p.(pParameterGrant).verb] + case pParameterBoolean: + result.attributes[p.(pParameterBoolean).parameter] = p.(pParameterBoolean).truancy + case pParameterClientMatch: + result.hostid = append(result.hostid, p.(pParameterClientMatch)) + case pParameterExpression: + result.expressions[p.(pParameterExpression).parameter] = p.(pParameterExpression).expression + case pParameterOther: + result.parameters[p.(pParameterOther).parameter] = p.(pParameterOther).value + default: + result.address = append(result.address, p) } } } @@ -749,112 +851,141 @@ func (e *configDeclaration) repr() string { var res []string res = make([]string, 0) - for _,v := range e.id { res = append(res, v.repr()) } + for _, v := range e.id { + res = append(res, v.repr()) + } result = append(result, strings.Join(res, ",")) if len(e.address) > 0 { res = make([]string, 0) - for _,v := range e.address { res = append(res, v.repr()) } + for _, v := range e.address { + res = append(res, v.repr()) + } result = append(result, fmt.Sprintf("address : %v", strings.Join(res, ","))) } - if len(e.options) > 0 { result = append(result, fmt.Sprintf("options : %v", e.options)) } - if len(e.grants) > 0 { result = append(result, fmt.Sprintf("grants : %v", e.grants)) } - if len(e.attributes) > 0 { result = append(result, fmt.Sprintf("attributes : %v", e.attributes)) } - if len(e.parameters) > 0 { result = append(result, fmt.Sprintf("parameters : %v", e.parameters)) } - if len(e.expressions) > 0 { result = append(result, fmt.Sprintf("parameter-expressions : %v", e.expressions)) } + if len(e.options) > 0 { + result = append(result, fmt.Sprintf("options : %v", e.options)) + } + if len(e.grants) > 0 { + result = append(result, fmt.Sprintf("grants : %v", e.grants)) + } + if len(e.attributes) > 0 { + result = append(result, fmt.Sprintf("attributes : %v", e.attributes)) + } + if len(e.parameters) > 0 { + result = append(result, fmt.Sprintf("parameters : %v", e.parameters)) + } + if len(e.expressions) > 0 { + result = append(result, fmt.Sprintf("parameter-expressions : %v", e.expressions)) + } if len(e.hostid) > 0 { res = make([]string, 0) - for _,v := range e.hostid { res = append(res, v.repr()) } + for _, v := range e.hostid { + res = append(res, v.repr()) + } result = append(result, fmt.Sprintf("hostid : %v", strings.Join(res, " "))) } return strings.Join(result, "\n") + "\n" } -func (e *configDeclaration) IP4() (net.IP,error) { +func (e *configDeclaration) IP4() (net.IP, error) { var result []string - for _,entry := range e.address { + for _, entry := range e.address { switch entry.(type) { - case pParameterAddress4: - for _,s := range entry.(pParameterAddress4) { - result = append(result, s) - } + case pParameterAddress4: + for _, s := range entry.(pParameterAddress4) { + result = append(result, s) + } } } if len(result) > 1 { - return nil,fmt.Errorf("More than one address4 returned : %v", result) + return nil, fmt.Errorf("More than one address4 returned : %v", result) } else if len(result) == 0 { - return nil,fmt.Errorf("No IP4 addresses found") + return nil, fmt.Errorf("No IP4 addresses found") } - if res := net.ParseIP(result[0]); res != nil { return res,nil } - res,err := net.ResolveIPAddr("ip4", result[0]) - if err != nil { return nil,err } - return res.IP,nil + if res := net.ParseIP(result[0]); res != nil { + return res, nil + } + res, err := net.ResolveIPAddr("ip4", result[0]) + if err != nil { + return nil, err + } + return res.IP, nil } -func (e *configDeclaration) IP6() (net.IP,error) { +func (e *configDeclaration) IP6() (net.IP, error) { var result []string - for _,entry := range e.address { + for _, entry := range e.address { switch entry.(type) { - case pParameterAddress6: - for _,s := range entry.(pParameterAddress6) { - result = append(result, s) - } + case pParameterAddress6: + for _, s := range entry.(pParameterAddress6) { + result = append(result, s) + } } } if len(result) > 1 { - return nil,fmt.Errorf("More than one address6 returned : %v", result) + return nil, fmt.Errorf("More than one address6 returned : %v", result) } else if len(result) == 0 { - return nil,fmt.Errorf("No IP6 addresses found") + return nil, fmt.Errorf("No IP6 addresses found") } - if res := net.ParseIP(result[0]); res != nil { return res,nil } - res,err := net.ResolveIPAddr("ip6", result[0]) - if err != nil { return nil,err } - return res.IP,nil + if res := net.ParseIP(result[0]); res != nil { + return res, nil + } + res, err := net.ResolveIPAddr("ip6", result[0]) + if err != nil { + return nil, err + } + return res.IP, nil } -func (e *configDeclaration) Hardware() (net.HardwareAddr,error) { +func (e *configDeclaration) Hardware() (net.HardwareAddr, error) { var result []pParameterHardware - for _,addr := range e.address { + for _, addr := range e.address { switch addr.(type) { - case pParameterHardware: - result = append(result, addr.(pParameterHardware)) + case pParameterHardware: + result = append(result, addr.(pParameterHardware)) } } if len(result) > 0 { - return nil,fmt.Errorf("More than one hardware address returned : %v", result) + return nil, fmt.Errorf("More than one hardware address returned : %v", result) } res := make(net.HardwareAddr, 0) - for _,by := range result[0].address { + for _, by := range result[0].address { res = append(res, by) } - return res,nil + return res, nil } /*** Dhcp Configuration */ type DhcpConfiguration []configDeclaration -func ReadDhcpConfiguration(fd *os.File) (DhcpConfiguration,error) { - fromfile,eof := consumeFile(fd) + +func ReadDhcpConfiguration(fd *os.File) (DhcpConfiguration, error) { + fromfile, eof := consumeFile(fd) uncommented := uncomment(eof, fromfile) tokenized := tokenizeDhcpConfig(eof, uncommented) - parsetree,err := parseDhcpConfig(eof, tokenized) - if err != nil { return nil,err } + parsetree, err := parseDhcpConfig(eof, tokenized) + if err != nil { + return nil, err + } - global,err := flattenDhcpConfig(parsetree) - if err != nil { return nil,err } + global, err := flattenDhcpConfig(parsetree) + if err != nil { + return nil, err + } - var walkDeclarations func(root pDeclaration, out chan*configDeclaration); - walkDeclarations = func(root pDeclaration, out chan*configDeclaration) { + var walkDeclarations func(root pDeclaration, out chan *configDeclaration) + walkDeclarations = func(root pDeclaration, out chan *configDeclaration) { res := createDeclaration(root) out <- &res - for _,p := range root.declarations { + for _, p := range root.declarations { walkDeclarations(p, out) } } - each := make(chan*configDeclaration) - go func(out chan*configDeclaration) { + each := make(chan *configDeclaration) + go func(out chan *configDeclaration) { walkDeclarations(*global, out) out <- nil }(each) @@ -863,7 +994,7 @@ func ReadDhcpConfiguration(fd *os.File) (DhcpConfiguration,error) { for decl := <-each; decl != nil; decl = <-each { result = append(result, *decl) } - return result,nil + return result, nil } func (e *DhcpConfiguration) Global() configDeclaration { @@ -874,83 +1005,86 @@ func (e *DhcpConfiguration) Global() configDeclaration { return result } -func (e *DhcpConfiguration) SubnetByAddress(address net.IP) (configDeclaration,error) { +func (e *DhcpConfiguration) SubnetByAddress(address net.IP) (configDeclaration, error) { var result []configDeclaration - for _,entry := range *e { + for _, entry := range *e { switch entry.id[0].(type) { - case pDeclarationSubnet4: - id := entry.id[0].(pDeclarationSubnet4) - if id.Contains(address) { - result = append(result, entry) - } - case pDeclarationSubnet6: - id := entry.id[0].(pDeclarationSubnet6) - if id.Contains(address) { - result = append(result, entry) - } + case pDeclarationSubnet4: + id := entry.id[0].(pDeclarationSubnet4) + if id.Contains(address) { + result = append(result, entry) + } + case pDeclarationSubnet6: + id := entry.id[0].(pDeclarationSubnet6) + if id.Contains(address) { + result = append(result, entry) + } } } if len(result) == 0 { - return configDeclaration{},fmt.Errorf("No network declarations containing %s found", address.String()) + return configDeclaration{}, fmt.Errorf("No network declarations containing %s found", address.String()) } if len(result) > 1 { - return configDeclaration{},fmt.Errorf("More than 1 network declaration found : %v", result) + return configDeclaration{}, fmt.Errorf("More than 1 network declaration found : %v", result) } - return result[0],nil + return result[0], nil } -func (e *DhcpConfiguration) HostByName(host string) (configDeclaration,error) { +func (e *DhcpConfiguration) HostByName(host string) (configDeclaration, error) { var result []configDeclaration - for _,entry := range *e { + for _, entry := range *e { switch entry.id[0].(type) { - case pDeclarationHost: - id := entry.id[0].(pDeclarationHost) - if strings.ToLower(id.name) == strings.ToLower(host) { - result = append(result, entry) - } + case pDeclarationHost: + id := entry.id[0].(pDeclarationHost) + if strings.ToLower(id.name) == strings.ToLower(host) { + result = append(result, entry) + } } } if len(result) == 0 { - return configDeclaration{},fmt.Errorf("No host declarations containing %s found", host) + return configDeclaration{}, fmt.Errorf("No host declarations containing %s found", host) } if len(result) > 1 { - return configDeclaration{},fmt.Errorf("More than 1 host declaration found : %v", result) + return configDeclaration{}, fmt.Errorf("More than 1 host declaration found : %v", result) } - return result[0],nil + return result[0], nil } /*** Network Map */ type NetworkMap []map[string]string -func ReadNetworkMap(fd *os.File) (NetworkMap,error) { - fromfile,eof := consumeFile(fd) - uncommented := uncomment(eof,fromfile) +func ReadNetworkMap(fd *os.File) (NetworkMap, error) { + + fromfile, eof := consumeFile(fd) + uncommented := uncomment(eof, fromfile) tokenized := tokenizeNetworkMapConfig(eof, uncommented) - result,err := parseNetworkMapConfig(eof, tokenized) - if err != nil { return nil,err } - return result,nil + result, err := parseNetworkMapConfig(eof, tokenized) + if err != nil { + return nil, err + } + return result, nil } -func (e *NetworkMap) NameIntoDevice(name string) (string,error) { - for _,val := range *e { +func (e *NetworkMap) NameIntoDevice(name string) (string, error) { + for _, val := range *e { if strings.ToLower(val["name"]) == strings.ToLower(name) { - return val["device"],nil + return val["device"], nil } } - return "",fmt.Errorf("Network name not found : %v", name) + return "", fmt.Errorf("Network name not found : %v", name) } -func (e *NetworkMap) DeviceIntoName(device string) (string,error) { - for _,val := range *e { +func (e *NetworkMap) DeviceIntoName(device string) (string, error) { + for _, val := range *e { if strings.ToLower(val["device"]) == strings.ToLower(device) { - return val["name"],nil + return val["name"], nil } } - return "",fmt.Errorf("Device name not found : %v", device) + return "", fmt.Errorf("Device name not found : %v", device) } func (e *NetworkMap) repr() string { var result []string - for idx,val := range *e { + for idx, val := range *e { result = append(result, fmt.Sprintf("network%d.name = \"%s\"", idx, val["name"])) result = append(result, fmt.Sprintf("network%d.device = \"%s\"", idx, val["device"])) } @@ -958,17 +1092,19 @@ func (e *NetworkMap) repr() string { } /** main */ -func consumeFile(fd *os.File) (chan byte,sentinelSignaller) { +func consumeFile(fd *os.File) (chan byte, sentinelSignaller) { fromfile := make(chan byte) eof := make(sentinelSignaller) go func() { b := make([]byte, 1) for { - _,err := fd.Read(b) - if err == io.EOF { break } + _, err := fd.Read(b) + if err == io.EOF { + break + } fromfile <- b[0] } close(eof) }() - return fromfile,eof + return fromfile, eof } diff --git a/builder/vmware/common/driver_player_unix.go b/builder/vmware/common/driver_player_unix.go index 01b877d92..068720a6c 100644 --- a/builder/vmware/common/driver_player_unix.go +++ b/builder/vmware/common/driver_player_unix.go @@ -8,9 +8,9 @@ import ( "fmt" "log" "os/exec" + "path/filepath" "regexp" "runtime" - "path/filepath" ) func playerFindVdiskManager() (string, error) { diff --git a/builder/vmware/common/driver_workstation10.go b/builder/vmware/common/driver_workstation10.go index 716717e39..7e6ac8b8f 100644 --- a/builder/vmware/common/driver_workstation10.go +++ b/builder/vmware/common/driver_workstation10.go @@ -33,4 +33,3 @@ func (d *Workstation10Driver) Verify() error { return workstationVerifyVersion(VMWARE_WS_VERSION) } - diff --git a/builder/vmware/iso/builder.go b/builder/vmware/iso/builder.go index 2cce8fd3c..2dcc082ac 100644 --- a/builder/vmware/iso/builder.go +++ b/builder/vmware/iso/builder.go @@ -39,38 +39,35 @@ type Config struct { vmwcommon.VMXConfig `mapstructure:",squash"` // disk drives - AdditionalDiskSize []uint `mapstructure:"disk_additional_size"` - DiskName string `mapstructure:"vmdk_name"` - DiskSize uint `mapstructure:"disk_size"` - DiskTypeId string `mapstructure:"disk_type_id"` - Format string `mapstructure:"format"` + AdditionalDiskSize []uint `mapstructure:"disk_additional_size"` + DiskName string `mapstructure:"vmdk_name"` + DiskSize uint `mapstructure:"disk_size"` + DiskTypeId string `mapstructure:"disk_type_id"` + Format string `mapstructure:"format"` // platform information - GuestOSType string `mapstructure:"guest_os_type"` - Version string `mapstructure:"version"` - VMName string `mapstructure:"vm_name"` + GuestOSType string `mapstructure:"guest_os_type"` + Version string `mapstructure:"version"` + VMName string `mapstructure:"vm_name"` // Network type - Network string `mapstructure:"network"` + Network string `mapstructure:"network"` // device presence - Sound bool `mapstructure:"sound"` - USB bool `mapstructure:"usb"` + Sound bool `mapstructure:"sound"` + USB bool `mapstructure:"usb"` // communication ports - Serial string `mapstructure:"serial"` - Parallel string `mapstructure:"parallel"` + Serial string `mapstructure:"serial"` + Parallel string `mapstructure:"parallel"` // booting a guest - BootCommand []string `mapstructure:"boot_command"` KeepRegistered bool `mapstructure:"keep_registered"` OVFToolOptions []string `mapstructure:"ovftool_options"` SkipCompaction bool `mapstructure:"skip_compaction"` SkipExport bool `mapstructure:"skip_export"` - VMName string `mapstructure:"vm_name"` VMXDiskTemplatePath string `mapstructure:"vmx_disk_template_path"` VMXTemplatePath string `mapstructure:"vmx_template_path"` - Version string `mapstructure:"version"` // remote vsphere RemoteType string `mapstructure:"remote_type"` diff --git a/builder/vmware/iso/step_create_vmx.go b/builder/vmware/iso/step_create_vmx.go index d37f00969..0261123a6 100644 --- a/builder/vmware/iso/step_create_vmx.go +++ b/builder/vmware/iso/step_create_vmx.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "os" "path/filepath" + "runtime" "strings" vmwcommon "github.com/hashicorp/packer/builder/vmware/common" @@ -21,24 +22,24 @@ type vmxTemplateData struct { ISOPath string Version string - Network_Type string - Network_Device string + Network_Type string + Network_Device string Sound_Present string - Usb_Present string + Usb_Present string - Serial_Present string - Serial_Type string + Serial_Present string + Serial_Type string Serial_Endpoint string - Serial_Host string - Serial_Yield string + Serial_Host string + Serial_Yield string Serial_Filename string - Serial_Auto string + Serial_Auto string - Parallel_Present string + Parallel_Present string Parallel_Bidirectional string - Parallel_Filename string - Parallel_Auto string + Parallel_Filename string + Parallel_Auto string } type additionalDiskTemplateData struct { @@ -63,34 +64,34 @@ type stepCreateVMX struct { type serialConfigPipe struct { filename string endpoint string - host string - yield string + host string + yield string } type serialConfigFile struct { filename string - yield string + yield string } type serialConfigDevice struct { devicename string - yield string + yield string } type serialConfigAuto struct { devicename string - yield string + yield string } type serialUnion struct { serialType interface{} - pipe *serialConfigPipe - file *serialConfigFile - device *serialConfigDevice - auto *serialConfigAuto + pipe *serialConfigPipe + file *serialConfigFile + device *serialConfigDevice + auto *serialConfigAuto } -func unformat_serial(config string) (*serialUnion,error) { +func unformat_serial(config string) (*serialUnion, error) { var defaultSerialPort string if runtime.GOOS == "windows" { defaultSerialPort = "COM1" @@ -100,7 +101,7 @@ func unformat_serial(config string) (*serialUnion,error) { input := strings.SplitN(config, ":", 2) if len(input) < 1 { - return nil,fmt.Errorf("Unexpected format for serial port: %s", config) + return nil, fmt.Errorf("Unexpected format for serial port: %s", config) } var formatType, formatOptions string @@ -112,116 +113,116 @@ func unformat_serial(config string) (*serialUnion,error) { } switch strings.ToUpper(formatType) { - case "PIPE": - comp := strings.Split(formatOptions, ",") - if len(comp) < 3 || len(comp) > 4 { - return nil,fmt.Errorf("Unexpected format for serial port : pipe : %s", config) - } - if res := strings.ToLower(comp[1]); res != "client" && res != "server" { - return nil,fmt.Errorf("Unexpected format for serial port : pipe : endpoint : %s : %s", res, config) - } - if res := strings.ToLower(comp[2]); res != "app" && res != "vm" { - return nil,fmt.Errorf("Unexpected format for serial port : pipe : host : %s : %s", res, config) - } - res := &serialConfigPipe{ - filename : comp[0], - endpoint : comp[1], - host : map[string]string{"app":"TRUE","vm":"FALSE"}[strings.ToLower(comp[2])], - yield : "FALSE", - } - if len(comp) == 4 { - res.yield = strings.ToUpper(comp[3]) - } - if res.yield != "TRUE" && res.yield != "FALSE" { - return nil,fmt.Errorf("Unexpected format for serial port : pipe : yield : %s : %s", res.yield, config) - } - return &serialUnion{serialType:res, pipe:res},nil + case "PIPE": + comp := strings.Split(formatOptions, ",") + if len(comp) < 3 || len(comp) > 4 { + return nil, fmt.Errorf("Unexpected format for serial port : pipe : %s", config) + } + if res := strings.ToLower(comp[1]); res != "client" && res != "server" { + return nil, fmt.Errorf("Unexpected format for serial port : pipe : endpoint : %s : %s", res, config) + } + if res := strings.ToLower(comp[2]); res != "app" && res != "vm" { + return nil, fmt.Errorf("Unexpected format for serial port : pipe : host : %s : %s", res, config) + } + res := &serialConfigPipe{ + filename: comp[0], + endpoint: comp[1], + host: map[string]string{"app": "TRUE", "vm": "FALSE"}[strings.ToLower(comp[2])], + yield: "FALSE", + } + if len(comp) == 4 { + res.yield = strings.ToUpper(comp[3]) + } + if res.yield != "TRUE" && res.yield != "FALSE" { + return nil, fmt.Errorf("Unexpected format for serial port : pipe : yield : %s : %s", res.yield, config) + } + return &serialUnion{serialType: res, pipe: res}, nil - case "FILE": - comp := strings.Split(formatOptions, ",") - if len(comp) > 2 { - return nil,fmt.Errorf("Unexpected format for serial port : file : %s", config) - } + case "FILE": + comp := strings.Split(formatOptions, ",") + if len(comp) > 2 { + return nil, fmt.Errorf("Unexpected format for serial port : file : %s", config) + } - res := &serialConfigFile{ yield : "FALSE" } + res := &serialConfigFile{yield: "FALSE"} - res.filename = filepath.FromSlash(comp[0]) + res.filename = filepath.FromSlash(comp[0]) - res.yield = map[bool]string{true:strings.ToUpper(comp[0]), false:"FALSE"}[len(comp) > 1] - if res.yield != "TRUE" && res.yield != "FALSE" { - return nil,fmt.Errorf("Unexpected format for serial port : file : yield : %s : %s", res.yield, config) - } + res.yield = map[bool]string{true: strings.ToUpper(comp[0]), false: "FALSE"}[len(comp) > 1] + if res.yield != "TRUE" && res.yield != "FALSE" { + return nil, fmt.Errorf("Unexpected format for serial port : file : yield : %s : %s", res.yield, config) + } - return &serialUnion{serialType:res, file:res},nil + return &serialUnion{serialType: res, file: res}, nil - case "DEVICE": - comp := strings.Split(formatOptions, ",") - if len(comp) > 2 { - return nil,fmt.Errorf("Unexpected format for serial port : device : %s", config) - } + case "DEVICE": + comp := strings.Split(formatOptions, ",") + if len(comp) > 2 { + return nil, fmt.Errorf("Unexpected format for serial port : device : %s", config) + } - res := new(serialConfigDevice) + res := new(serialConfigDevice) - if len(comp) == 2 { - res.devicename = map[bool]string{true:filepath.FromSlash(comp[0]), false:defaultSerialPort}[len(comp[0]) > 0] - res.yield = strings.ToUpper(comp[1]) - } else if len(comp) == 1 { - res.devicename = map[bool]string{true:filepath.FromSlash(comp[0]), false:defaultSerialPort}[len(comp[0]) > 0] - res.yield = "FALSE" - } else if len(comp) == 0 { - res.devicename = defaultSerialPort - res.yield = "FALSE" - } - - if res.yield != "TRUE" && res.yield != "FALSE" { - return nil,fmt.Errorf("Unexpected format for serial port : device : yield : %s : %s", res.yield, config) - } - - return &serialUnion{serialType:res, device:res},nil - - case "AUTO": - res := new(serialConfigAuto) + if len(comp) == 2 { + res.devicename = map[bool]string{true: filepath.FromSlash(comp[0]), false: defaultSerialPort}[len(comp[0]) > 0] + res.yield = strings.ToUpper(comp[1]) + } else if len(comp) == 1 { + res.devicename = map[bool]string{true: filepath.FromSlash(comp[0]), false: defaultSerialPort}[len(comp[0]) > 0] + res.yield = "FALSE" + } else if len(comp) == 0 { res.devicename = defaultSerialPort + res.yield = "FALSE" + } - if len(formatOptions) > 0 { - res.yield = strings.ToUpper(formatOptions) - } else { - res.yield = "FALSE" - } + if res.yield != "TRUE" && res.yield != "FALSE" { + return nil, fmt.Errorf("Unexpected format for serial port : device : yield : %s : %s", res.yield, config) + } - if res.yield != "TRUE" && res.yield != "FALSE" { - return nil,fmt.Errorf("Unexpected format for serial port : auto : yield : %s : %s", res.yield, config) - } + return &serialUnion{serialType: res, device: res}, nil - return &serialUnion{serialType:res, auto:res},nil + case "AUTO": + res := new(serialConfigAuto) + res.devicename = defaultSerialPort - default: - return nil,fmt.Errorf("Unknown serial type : %s : %s", strings.ToUpper(formatType), config) + if len(formatOptions) > 0 { + res.yield = strings.ToUpper(formatOptions) + } else { + res.yield = "FALSE" + } + + if res.yield != "TRUE" && res.yield != "FALSE" { + return nil, fmt.Errorf("Unexpected format for serial port : auto : yield : %s : %s", res.yield, config) + } + + return &serialUnion{serialType: res, auto: res}, nil + + default: + return nil, fmt.Errorf("Unknown serial type : %s : %s", strings.ToUpper(formatType), config) } } /* parallel port */ type parallelUnion struct { parallelType interface{} - file *parallelPortFile - device *parallelPortDevice - auto *parallelPortAuto + file *parallelPortFile + device *parallelPortDevice + auto *parallelPortAuto } type parallelPortFile struct { filename string } type parallelPortDevice struct { bidirectional string - devicename string + devicename string } type parallelPortAuto struct { bidirectional string } -func unformat_parallel(config string) (*parallelUnion,error) { +func unformat_parallel(config string) (*parallelUnion, error) { input := strings.SplitN(config, ":", 2) if len(input) < 1 { - return nil,fmt.Errorf("Unexpected format for parallel port: %s", config) + return nil, fmt.Errorf("Unexpected format for parallel port: %s", config) } var formatType, formatOptions string @@ -233,39 +234,44 @@ func unformat_parallel(config string) (*parallelUnion,error) { } switch strings.ToUpper(formatType) { - case "FILE": - res := ¶llelPortFile{ filename: filepath.FromSlash(formatOptions) } - return ¶llelUnion{ parallelType:res, file: res},nil - case "DEVICE": - comp := strings.Split(formatOptions, ",") - if len(comp) < 1 || len(comp) > 2 { - return nil,fmt.Errorf("Unexpected format for parallel port: %s", config) + case "FILE": + res := ¶llelPortFile{filename: filepath.FromSlash(formatOptions)} + return ¶llelUnion{parallelType: res, file: res}, nil + case "DEVICE": + comp := strings.Split(formatOptions, ",") + if len(comp) < 1 || len(comp) > 2 { + return nil, fmt.Errorf("Unexpected format for parallel port: %s", config) + } + res := new(parallelPortDevice) + res.bidirectional = "FALSE" + res.devicename = filepath.FromSlash(comp[0]) + if len(comp) > 1 { + switch strings.ToUpper(comp[1]) { + case "BI": + res.bidirectional = "TRUE" + case "UNI": + res.bidirectional = "FALSE" + default: + return nil, fmt.Errorf("Unknown parallel port direction : %s : %s", strings.ToUpper(comp[0]), config) } - res := new(parallelPortDevice) - res.bidirectional = "FALSE" - res.devicename = strings.ToUpper(comp[0]) - if len(comp) > 1 { - switch strings.ToUpper(comp[1]) { - case "BI": res.bidirectional = "TRUE" - case "UNI": res.bidirectional = "FALSE" - default: - return nil,fmt.Errorf("Unknown parallel port direction : %s : %s", strings.ToUpper(comp[0]), config) - } - } - return ¶llelUnion{ parallelType:res, device:res },nil + } + return ¶llelUnion{parallelType: res, device: res}, nil - case "AUTO": - res := new(parallelPortAuto) - switch strings.ToUpper(formatOptions) { - case "": fallthrough - case "UNI": res.bidirectional = "FALSE" - case "BI": res.bidirectional = "TRUE" - default: - return nil,fmt.Errorf("Unknown parallel port direction : %s : %s", strings.ToUpper(formatOptions), config) - } - return ¶llelUnion{ parallelType:res, auto:res },nil + case "AUTO": + res := new(parallelPortAuto) + switch strings.ToUpper(formatOptions) { + case "": + fallthrough + case "UNI": + res.bidirectional = "FALSE" + case "BI": + res.bidirectional = "TRUE" + default: + return nil, fmt.Errorf("Unknown parallel port direction : %s : %s", strings.ToUpper(formatOptions), config) + } + return ¶llelUnion{parallelType: res, auto: res}, nil } - return nil,fmt.Errorf("Unexpected format for parallel port: %s", config) + return nil, fmt.Errorf("Unexpected format for parallel port: %s", config) } /* regular steps */ @@ -348,11 +354,11 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist Version: config.Version, ISOPath: isoPath, - Sound_Present: map[bool]string{true:"TRUE",false:"FALSE"}[bool(config.Sound)], - Usb_Present: map[bool]string{true:"TRUE",false:"FALSE"}[bool(config.USB)], + Sound_Present: map[bool]string{true: "TRUE", false: "FALSE"}[bool(config.Sound)], + Usb_Present: map[bool]string{true: "TRUE", false: "FALSE"}[bool(config.USB)], - Serial_Present: "FALSE", - Parallel_Present: "FALSE", + Serial_Present: "FALSE", + Parallel_Present: "FALSE", } /// Check the network type that the user specified @@ -367,7 +373,7 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist ui.Error(err.Error()) return multistep.ActionHalt } - netmap,res := vmwcommon.ReadNetmapConfig(pathNetmap) + netmap, res := vmwcommon.ReadNetmapConfig(pathNetmap) if res != nil { err := fmt.Errorf("Unable to read netmap conf file: %s: %v", pathNetmap, res) state.Put("error", err) @@ -376,13 +382,13 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist } // try and convert the specified network to a device - device,err := netmap.NameIntoDevice(network) + device, err := netmap.NameIntoDevice(network) // success. so we know that it's an actual network type inside netmap.conf if err == nil { templateData.Network_Type = network templateData.Network_Device = device - // we were unable to find the type, so assume it's a custom network device. + // we were unable to find the type, so assume it's a custom network device. } else { templateData.Network_Type = "custom" templateData.Network_Device = network @@ -392,7 +398,7 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist /// check if serial port has been configured if config.Serial != "" { - serial,err := unformat_serial(config.Serial) + serial, err := unformat_serial(config.Serial) if err != nil { err := fmt.Errorf("Error procesing VMX template: %s", err) state.Put("error", err) @@ -408,35 +414,35 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist templateData.Serial_Auto = "FALSE" switch serial.serialType.(type) { - case *serialConfigPipe: - templateData.Serial_Type = "pipe" - templateData.Serial_Endpoint = serial.pipe.endpoint - templateData.Serial_Host = serial.pipe.host - templateData.Serial_Yield = serial.pipe.yield - templateData.Serial_Filename = filepath.FromSlash(serial.pipe.filename) - case *serialConfigFile: - templateData.Serial_Type = "file" - templateData.Serial_Filename = filepath.FromSlash(serial.file.filename) - case *serialConfigDevice: - templateData.Serial_Type = "device" - templateData.Serial_Filename = filepath.FromSlash(serial.device.devicename) - case *serialConfigAuto: - templateData.Serial_Type = "device" - templateData.Serial_Filename = filepath.FromSlash(serial.auto.devicename) - templateData.Serial_Yield = serial.auto.yield - templateData.Serial_Auto = "TRUE" + case *serialConfigPipe: + templateData.Serial_Type = "pipe" + templateData.Serial_Endpoint = serial.pipe.endpoint + templateData.Serial_Host = serial.pipe.host + templateData.Serial_Yield = serial.pipe.yield + templateData.Serial_Filename = filepath.FromSlash(serial.pipe.filename) + case *serialConfigFile: + templateData.Serial_Type = "file" + templateData.Serial_Filename = filepath.FromSlash(serial.file.filename) + case *serialConfigDevice: + templateData.Serial_Type = "device" + templateData.Serial_Filename = filepath.FromSlash(serial.device.devicename) + case *serialConfigAuto: + templateData.Serial_Type = "device" + templateData.Serial_Filename = filepath.FromSlash(serial.auto.devicename) + templateData.Serial_Yield = serial.auto.yield + templateData.Serial_Auto = "TRUE" - default: - err := fmt.Errorf("Error procesing VMX template: %v", serial) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt + default: + err := fmt.Errorf("Error procesing VMX template: %v", serial) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt } } /// check if parallel port has been configured if config.Parallel != "" { - parallel,err := unformat_parallel(config.Parallel) + parallel, err := unformat_parallel(config.Parallel) if err != nil { err := fmt.Errorf("Error procesing VMX template: %s", err) state.Put("error", err) @@ -446,22 +452,22 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist templateData.Parallel_Auto = "FALSE" switch parallel.parallelType.(type) { - case *parallelPortFile: - templateData.Parallel_Present = "TRUE" - templateData.Parallel_Filename = filepath.FromSlash(parallel.file.filename) - case *parallelPortDevice: - templateData.Parallel_Present = "TRUE" - templateData.Parallel_Bidirectional = parallel.device.bidirectional - templateData.Parallel_Filename = filepath.FromSlash(parallel.device.devicename) - case *parallelPortAuto: - templateData.Parallel_Present = "TRUE" - templateData.Parallel_Auto = "TRUE" - templateData.Parallel_Bidirectional = parallel.auto.bidirectional - default: - err := fmt.Errorf("Error procesing VMX template: %v", parallel) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt + case *parallelPortFile: + templateData.Parallel_Present = "TRUE" + templateData.Parallel_Filename = filepath.FromSlash(parallel.file.filename) + case *parallelPortDevice: + templateData.Parallel_Present = "TRUE" + templateData.Parallel_Bidirectional = parallel.device.bidirectional + templateData.Parallel_Filename = filepath.FromSlash(parallel.device.devicename) + case *parallelPortAuto: + templateData.Parallel_Present = "TRUE" + templateData.Parallel_Auto = "TRUE" + templateData.Parallel_Bidirectional = parallel.auto.bidirectional + default: + err := fmt.Errorf("Error procesing VMX template: %v", parallel) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt } } diff --git a/builder/vmware/iso/step_create_vmx_test.go b/builder/vmware/iso/step_create_vmx_test.go index e540eee8a..7f5c1d91c 100644 --- a/builder/vmware/iso/step_create_vmx_test.go +++ b/builder/vmware/iso/step_create_vmx_test.go @@ -1,37 +1,37 @@ package iso import ( + "bytes" "fmt" - "os" - "path/filepath" - "strings" + "io/ioutil" "math" "math/rand" - "strconv" - "io/ioutil" - "bytes" + "os" + "path/filepath" "runtime" + "strconv" + "strings" - "testing" "github.com/mitchellh/packer/packer" - "github.com/mitchellh/packer/template" "github.com/mitchellh/packer/provisioner/shell" + "github.com/mitchellh/packer/template" + "testing" ) var vmxTestBuilderConfig = map[string]string{ - "type": `"vmware-iso"`, - "iso_url": `"https://archive.org/download/ut-ttylinux-i686-12.6/ut-ttylinux-i686-12.6.iso"`, + "type": `"vmware-iso"`, + "iso_url": `"https://archive.org/download/ut-ttylinux-i686-12.6/ut-ttylinux-i686-12.6.iso"`, "iso_checksum_type": `"md5"`, - "iso_checksum": `"43c1feeae55a44c6ef694b8eb18408a6"`, - "ssh_username": `"root"`, - "ssh_password": `"password"`, - "ssh_wait_timeout": `"45s"`, - "boot_command": `["","rootpassword","udhcpc"]`, - "shutdown_command": `"/sbin/shutdown -h; exit 0"`, + "iso_checksum": `"43c1feeae55a44c6ef694b8eb18408a6"`, + "ssh_username": `"root"`, + "ssh_password": `"password"`, + "ssh_wait_timeout": `"45s"`, + "boot_command": `["","rootpassword","udhcpc"]`, + "shutdown_command": `"/sbin/shutdown -h; exit 0"`, } var vmxTestProvisionerConfig = map[string]string{ - "type": `"shell"`, + "type": `"shell"`, "inline": `["echo hola mundo"]`, } @@ -40,24 +40,26 @@ const vmxTestTemplate string = `{"builders":[{%s}],"provisioners":[{%s}]}` func tmpnam(prefix string) string { var path string var err error - + const length = 16 - + dir := os.TempDir() max := int(math.Pow(2, float64(length))) - n,err := rand.Intn(max),nil - for path = filepath.Join(dir, prefix + strconv.Itoa(n)); err == nil; _,err = os.Stat(path) { + n, err := rand.Intn(max), nil + for path = filepath.Join(dir, prefix+strconv.Itoa(n)); err == nil; _, err = os.Stat(path) { n = rand.Intn(max) - path = filepath.Join(dir, prefix + strconv.Itoa(n)) + path = filepath.Join(dir, prefix+strconv.Itoa(n)) } return path } -func createFloppyOutput(prefix string) (string,string,error) { +func createFloppyOutput(prefix string) (string, string, error) { output := tmpnam(prefix) - f,err := os.Create(output) - if err != nil { return "","",fmt.Errorf("Unable to create empty %s: %s", output, err) } + f, err := os.Create(output) + if err != nil { + return "", "", fmt.Errorf("Unable to create empty %s: %s", output, err) + } f.Close() vmxData := []string{ @@ -69,18 +71,24 @@ func createFloppyOutput(prefix string) (string,string,error) { } outputFile := strings.Replace(output, "\\", "\\\\", -1) - vmxString := fmt.Sprintf("{" + strings.Join(vmxData, ",") + "}", outputFile) - return output,vmxString,nil + vmxString := fmt.Sprintf("{"+strings.Join(vmxData, ",")+"}", outputFile) + return output, vmxString, nil } -func readFloppyOutput(path string) (string,error) { - f,err := os.Open(path) - if err != nil { return "",fmt.Errorf("Unable to open file %s", path) } +func readFloppyOutput(path string) (string, error) { + f, err := os.Open(path) + if err != nil { + return "", fmt.Errorf("Unable to open file %s", path) + } defer f.Close() - data,err := ioutil.ReadAll(f) - if err != nil { return "",fmt.Errorf("Unable to read file: %s", err) } - if len(data) == 0 { return "", nil } - return string(data[:bytes.IndexByte(data,0)]),nil + data, err := ioutil.ReadAll(f) + if err != nil { + return "", fmt.Errorf("Unable to read file: %s", err) + } + if len(data) == 0 { + return "", nil + } + return string(data[:bytes.IndexByte(data, 0)]), nil } func setupVMwareBuild(t *testing.T, builderConfig map[string]string, provisionerConfig map[string]string) error { @@ -88,72 +96,84 @@ func setupVMwareBuild(t *testing.T, builderConfig map[string]string, provisioner // create builder config and update with user-supplied options cfgBuilder := map[string]string{} - for k,v := range vmxTestBuilderConfig { cfgBuilder[k] = v } - for k,v := range builderConfig { cfgBuilder[k] = v } + for k, v := range vmxTestBuilderConfig { + cfgBuilder[k] = v + } + for k, v := range builderConfig { + cfgBuilder[k] = v + } // convert our builder config into a single sprintfable string builderLines := []string{} - for k,v := range cfgBuilder { + for k, v := range cfgBuilder { builderLines = append(builderLines, fmt.Sprintf(`"%s":%s`, k, v)) } // create provisioner config and update with user-supplied options cfgProvisioner := map[string]string{} - for k,v := range vmxTestProvisionerConfig { cfgProvisioner[k] = v } - for k,v := range provisionerConfig { cfgProvisioner[k] = v } + for k, v := range vmxTestProvisionerConfig { + cfgProvisioner[k] = v + } + for k, v := range provisionerConfig { + cfgProvisioner[k] = v + } // convert our provisioner config into a single sprintfable string provisionerLines := []string{} - for k,v := range cfgProvisioner { + for k, v := range cfgProvisioner { provisionerLines = append(provisionerLines, fmt.Sprintf(`"%s":%s`, k, v)) } // and now parse them into a template - configString := fmt.Sprintf(vmxTestTemplate, strings.Join(builderLines,`,`), strings.Join(provisionerLines,`,`)) + configString := fmt.Sprintf(vmxTestTemplate, strings.Join(builderLines, `,`), strings.Join(provisionerLines, `,`)) - tpl,err := template.Parse(strings.NewReader(configString)) + tpl, err := template.Parse(strings.NewReader(configString)) if err != nil { t.Fatalf("Unable to parse test config: %s", err) } // create our config to test the vmware-iso builder components := packer.ComponentFinder{ - Builder: func(n string) (packer.Builder,error) { - return &Builder{},nil + Builder: func(n string) (packer.Builder, error) { + return &Builder{}, nil }, - Hook: func(n string) (packer.Hook,error) { - return &packer.DispatchHook{},nil + Hook: func(n string) (packer.Hook, error) { + return &packer.DispatchHook{}, nil }, - PostProcessor: func(n string) (packer.PostProcessor,error) { - return &packer.MockPostProcessor{},nil + PostProcessor: func(n string) (packer.PostProcessor, error) { + return &packer.MockPostProcessor{}, nil }, - Provisioner: func(n string) (packer.Provisioner,error) { - return &shell.Provisioner{},nil + Provisioner: func(n string) (packer.Provisioner, error) { + return &shell.Provisioner{}, nil }, } config := packer.CoreConfig{ - Template: tpl, + Template: tpl, Components: components, } // create a core using our template - core,err := packer.NewCore(&config) - if err != nil { t.Fatalf("Unable to create core: %s", err) } + core, err := packer.NewCore(&config) + if err != nil { + t.Fatalf("Unable to create core: %s", err) + } // now we can prepare our build - b,err := core.Build("vmware-iso") - if err != nil { t.Fatalf("Unable to create build: %s", err) } + b, err := core.Build("vmware-iso") + if err != nil { + t.Fatalf("Unable to create build: %s", err) + } - warn,err := b.Prepare() + warn, err := b.Prepare() if len(warn) > 0 { - for _,w := range warn { + for _, w := range warn { t.Logf("Configuration warning: %s", w) } } // and then finally build it cache := &packer.FileCache{CacheDir: os.TempDir()} - artifacts,err := b.Run(ui, cache) + artifacts, err := b.Run(ui, cache) if err != nil { t.Fatalf("Failed to build artifact: %s", err) } @@ -166,7 +186,7 @@ func setupVMwareBuild(t *testing.T, builderConfig map[string]string, provisioner // otherwise some number of errors happened t.Logf("Unexpected number of artifacts returned: %d", len(artifacts)) errors := make([]error, 0) - for _,artifact := range artifacts { + for _, artifact := range artifacts { if err := artifact.Destroy(); err != nil { errors = append(errors, err) } @@ -186,9 +206,11 @@ func TestStepCreateVmx_SerialFile(t *testing.T) { } error := setupVMwareBuild(t, serialConfig, map[string]string{}) - if error != nil { t.Errorf("Unable to read file: %s", error) } + if error != nil { + t.Errorf("Unable to read file: %s", error) + } - f,err := os.Stat(tmpfile) + f, err := os.Stat(tmpfile) if err != nil { t.Errorf("VMware builder did not create a file for serial port: %s", err) } @@ -216,19 +238,29 @@ func TestStepCreateVmx_SerialPort(t *testing.T) { } // where to write output - output,vmxData,err := createFloppyOutput("SerialPortOutput.") - if err != nil { t.Fatalf("Error creating output: %s", err) } - defer func() { if _,err := os.Stat(output); err == nil { os.Remove(output) } }() + output, vmxData, err := createFloppyOutput("SerialPortOutput.") + if err != nil { + t.Fatalf("Error creating output: %s", err) + } + defer func() { + if _, err := os.Stat(output); err == nil { + os.Remove(output) + } + }() config["vmx_data"] = vmxData t.Logf("Preparing to write output to %s", output) // whee err = setupVMwareBuild(t, config, provision) - if err != nil { t.Errorf("%s", err) } + if err != nil { + t.Errorf("%s", err) + } // check the output - data,err := readFloppyOutput(output) - if err != nil { t.Errorf("%s", err) } + data, err := readFloppyOutput(output) + if err != nil { + t.Errorf("%s", err) + } if data != "serial8250: ttyS1 at\n" { t.Errorf("Serial port not detected : %v", data) @@ -251,19 +283,29 @@ func TestStepCreateVmx_ParallelPort(t *testing.T) { } // where to write output - output,vmxData,err := createFloppyOutput("ParallelPortOutput.") - if err != nil { t.Fatalf("Error creating output: %s", err) } - defer func() { if _,err := os.Stat(output); err == nil { os.Remove(output) } }() + output, vmxData, err := createFloppyOutput("ParallelPortOutput.") + if err != nil { + t.Fatalf("Error creating output: %s", err) + } + defer func() { + if _, err := os.Stat(output); err == nil { + os.Remove(output) + } + }() config["vmx_data"] = vmxData t.Logf("Preparing to write output to %s", output) // whee error := setupVMwareBuild(t, config, provision) - if error != nil { t.Errorf("%s", error) } + if error != nil { + t.Errorf("%s", error) + } // check the output - data,err := readFloppyOutput(output) - if err != nil { t.Errorf("%s", err) } + data, err := readFloppyOutput(output) + if err != nil { + t.Errorf("%s", err) + } if data != "parport \n" { t.Errorf("Parallel port not detected : %v", data) @@ -279,19 +321,29 @@ func TestStepCreateVmx_Usb(t *testing.T) { } // where to write output - output,vmxData,err := createFloppyOutput("UsbOutput.") - if err != nil { t.Fatalf("Error creating output: %s", err) } - defer func() { if _,err := os.Stat(output); err == nil { os.Remove(output) } }() + output, vmxData, err := createFloppyOutput("UsbOutput.") + if err != nil { + t.Fatalf("Error creating output: %s", err) + } + defer func() { + if _, err := os.Stat(output); err == nil { + os.Remove(output) + } + }() config["vmx_data"] = vmxData t.Logf("Preparing to write output to %s", output) // whee error := setupVMwareBuild(t, config, provision) - if error != nil { t.Errorf("%s", error) } + if error != nil { + t.Errorf("%s", error) + } // check the output - data,err := readFloppyOutput(output) - if err != nil { t.Errorf("%s", err) } + data, err := readFloppyOutput(output) + if err != nil { + t.Errorf("%s", err) + } if data != "USB hub found\n" { t.Errorf("USB support not detected : %v", data) @@ -302,24 +354,34 @@ func TestStepCreateVmx_Sound(t *testing.T) { config := map[string]string{ "sound": `"TRUE"`, } - provision := map[string]string { + provision := map[string]string{ "inline": `"cat /proc/modules | egrep -o '^soundcore' > /dev/fd0"`, } // where to write output - output,vmxData,err := createFloppyOutput("SoundOutput.") - if err != nil { t.Fatalf("Error creating output: %s", err) } - defer func() { if _,err := os.Stat(output); err == nil { os.Remove(output) } }() + output, vmxData, err := createFloppyOutput("SoundOutput.") + if err != nil { + t.Fatalf("Error creating output: %s", err) + } + defer func() { + if _, err := os.Stat(output); err == nil { + os.Remove(output) + } + }() config["vmx_data"] = vmxData t.Logf("Preparing to write output to %s", output) // whee error := setupVMwareBuild(t, config, provision) - if error != nil { t.Errorf("Unable to read file: %s", error) } + if error != nil { + t.Errorf("Unable to read file: %s", error) + } // check the output - data,err := readFloppyOutput(output) - if err != nil { t.Errorf("%s", err) } + data, err := readFloppyOutput(output) + if err != nil { + t.Errorf("%s", err) + } if data != "soundcore\n" { t.Errorf("Soundcard not detected : %v", data)