github.phpd.cn/hashicorp/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 }