github.com/mitchellh/packer@v1.3.2/builder/vmware/common/vmx.go (about)

     1  package common
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	"log"
     9  	"os"
    10  	"regexp"
    11  	"sort"
    12  	"strings"
    13  )
    14  
    15  // ParseVMX parses the keys and values from a VMX file and returns
    16  // them as a Go map.
    17  func ParseVMX(contents string) map[string]string {
    18  	results := make(map[string]string)
    19  
    20  	lineRe := regexp.MustCompile(`^(.+?)\s*=\s*"?(.*?)"?\s*$`)
    21  
    22  	for _, line := range strings.Split(contents, "\n") {
    23  		matches := lineRe.FindStringSubmatch(line)
    24  		if matches == nil {
    25  			continue
    26  		}
    27  
    28  		key := strings.ToLower(matches[1])
    29  		results[key] = matches[2]
    30  	}
    31  
    32  	return results
    33  }
    34  
    35  // EncodeVMX takes a map and turns it into valid VMX contents.
    36  func EncodeVMX(contents map[string]string) string {
    37  	var buf bytes.Buffer
    38  
    39  	i := 0
    40  	keys := make([]string, len(contents))
    41  	for k := range contents {
    42  		keys[i] = k
    43  		i++
    44  	}
    45  
    46  	// a list of VMX key fragments that the value must not be quoted
    47  	// fragments are used to cover multiples (i.e. multiple disks)
    48  	// keys are still lowercase at this point, use lower fragments
    49  	noQuotes := []string{
    50  		".virtualssd",
    51  	}
    52  
    53  	// a list of VMX key fragments that are case sensitive
    54  	// fragments are used to cover multiples (i.e. multiple disks)
    55  	caseSensitive := []string{
    56  		".virtualSSD",
    57  	}
    58  
    59  	sort.Strings(keys)
    60  	for _, k := range keys {
    61  		pat := "%s = \"%s\"\n"
    62  		// items with no quotes
    63  		for _, q := range noQuotes {
    64  			if strings.Contains(k, q) {
    65  				pat = "%s = %s\n"
    66  				break
    67  			}
    68  		}
    69  		key := k
    70  		// case sensitive key fragments
    71  		for _, c := range caseSensitive {
    72  			key = strings.Replace(key, strings.ToLower(c), c, 1)
    73  		}
    74  		buf.WriteString(fmt.Sprintf(pat, key, contents[k]))
    75  	}
    76  
    77  	return buf.String()
    78  }
    79  
    80  // WriteVMX takes a path to a VMX file and contents in the form of a
    81  // map and writes it out.
    82  func WriteVMX(path string, data map[string]string) (err error) {
    83  	log.Printf("Writing VMX to: %s", path)
    84  	f, err := os.Create(path)
    85  	if err != nil {
    86  		return
    87  	}
    88  	defer f.Close()
    89  
    90  	var buf bytes.Buffer
    91  	buf.WriteString(EncodeVMX(data))
    92  	if _, err = io.Copy(f, &buf); err != nil {
    93  		return
    94  	}
    95  
    96  	return
    97  }
    98  
    99  // ReadVMX takes a path to a VMX file and reads it into a k/v mapping.
   100  func ReadVMX(path string) (map[string]string, error) {
   101  	data, err := ioutil.ReadFile(path)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  
   106  	return ParseVMX(string(data)), nil
   107  }