Skip to content

Commit

Permalink
feat: Added support for ovfProperty and info templating
Browse files Browse the repository at this point in the history
  • Loading branch information
edmondshtogu committed Aug 10, 2023
1 parent cb32ab6 commit 6f113ab
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 6 deletions.
100 changes: 100 additions & 0 deletions provider/pkg/esxi/utils.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,112 @@
package esxi

import (
"bytes"
"compress/gzip"
"encoding/base64"
"fmt"
"os"
"reflect"
"regexp"
"strings"
"text/template"
"time"

"github.com/pulumi/pulumi/sdk/v3/go/common/util/logging"
)

func ParseTemplate(text string, data any) (string, error) {
// Check if we need to parse text
re := regexp.MustCompile(`{{.*}}`)
matches := re.FindAllString(text, -1)
if len(matches) == 0 {
return text, nil
}

funcMap := template.FuncMap{
"upper": strings.ToUpper,
"lower": strings.ToLower,
"trim": strings.TrimSpace,
"len": func(s string) int { return len(s) },
"substr": func(s string, start, length int) string { return s[start : start+length] },
"replace": strings.Replace,
"printf": fmt.Sprintf,
"add": func(n, add int) int { return n + add },
"formatAsDate": func(t time.Time, layout string) string { return t.Format(layout) },
"now": time.Now,
"base64encode": func(s string) string { return base64.StdEncoding.EncodeToString([]byte(s)) },
"base64gzip": func(s string) (string, error) {
var buf bytes.Buffer
zw := gzip.NewWriter(&buf)
if _, err := zw.Write([]byte(s)); err != nil {
return "", err
}
if err := zw.Close(); err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(buf.Bytes()), nil
},
"parsedTemplateOutput": func(parsedOutput string) string { return parsedOutput },
}

// Check if parsedTemplate is at the end of the template text
re = regexp.MustCompile(`{{\s*parsedTemplateOutput\s*.*}}`)
matches = re.FindAllString(text, -1)

if len(matches) > 1 {
return text, fmt.Errorf("parsedTemplateOutput should be present only once")
}

if len(matches) > 0 {
// Get text after the last match
lastMatch := matches[len(matches)-1]
lastMatchIndex := strings.LastIndex(text, lastMatch)
remainingText := strings.TrimSpace(text[lastMatchIndex+len(lastMatch):])
if remainingText != "" {
return text, fmt.Errorf("parsedTemplateOutput should be at the bottom of the template")
}
}

parsedTextOutputTpl := ""

if len(matches) == 1 {
parsedTextOutputTpl = re.FindString(text)
text = re.ReplaceAllString(text, "")
}

tmpl, err := template.New("text-functions").Funcs(funcMap).Parse(text)
if err != nil {
return text, err
}

var buf bytes.Buffer
err = tmpl.Execute(&buf, data)
if err != nil {
return text, err
}

output := buf.String()

if parsedTextOutputTpl == "" {
return output, nil
}

tmpl, err = template.New("text-final-functions").Funcs(funcMap).Parse(parsedTextOutputTpl)
if err != nil {
return text, err
}

var parsedBuf bytes.Buffer
err = tmpl.Execute(&parsedBuf, output)
if err != nil {
return text, err
}

output = parsedBuf.String()

return output, nil
}

func CloseFile(file *os.File) {
if e := file.Close(); e != nil {
logging.V(logLevel).Info(e)
Expand Down
7 changes: 5 additions & 2 deletions provider/pkg/esxi/virtualMachine.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func VirtualMachineGet(inputs resource.PropertyMap, esxi *Host) (resource.Proper

vm := esxi.readVirtualMachine(VirtualMachine{
Id: id,
StartupTimeout: 1,
StartupTimeout: vmDefaultStartupTimeout,
})

if len(vm.Name) == 0 {
Expand All @@ -42,7 +42,7 @@ func VirtualMachineRead(id string, _ resource.PropertyMap, esxi *Host) (string,
// read vm
vm := esxi.readVirtualMachine(VirtualMachine{
Id: id,
StartupTimeout: 1,
StartupTimeout: vmDefaultStartupTimeout,
})

if len(vm.Name) == 0 {
Expand All @@ -69,6 +69,9 @@ func VirtualMachineCreate(inputs resource.PropertyMap, esxi *Host) (string, reso
vm.Power = vmTurnedOn
}

// read vm
vm = esxi.readVirtualMachine(vm)

result := vm.toMap()
return vm.Id, resource.NewPropertyMapFromMap(result), nil
}
Expand Down
16 changes: 12 additions & 4 deletions provider/pkg/esxi/virtualMacineUtils.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,11 @@ func (esxi *Host) buildVirtualMachineFromSource(vm VirtualMachine) error {
extraParams = fmt.Sprintf("%s --X:injectOvfEnv --allowExtraConfig --powerOn", extraParams)

for _, prop := range vm.OvfProperties {
extraParams = fmt.Sprintf("%s --prop:%s='%s'", extraParams, prop.Key, prop.Value)
value, err := ParseTemplate(prop.Value, vm)
if err != nil {
return fmt.Errorf("unable to parse templated ovfProperty '%s', err: %w", prop.Key, err)
}
extraParams = fmt.Sprintf("%s --prop:%s='%s'", extraParams, prop.Key, value)
}
}

Expand Down Expand Up @@ -443,9 +447,13 @@ func (esxi *Host) updateVmxContents(isNew bool, vm VirtualMachine) error {

if len(vm.Info) > 0 {
parsedVmx := ParseVMX(vmxContents)
for _, config := range vm.Info {
logging.V(logLevel).Infof("SAVING %s => %s", config.Key, config.Value)
parsedVmx["guestinfo."+config.Key] = config.Value
for _, prop := range vm.Info {
value, err := ParseTemplate(prop.Value, vm)
if err != nil {
return fmt.Errorf("unable to parse templated info property '%s', err: %w", prop.Key, err)
}
logging.V(logLevel).Infof("SAVING %s => %s", prop.Key, value)
parsedVmx["guestinfo."+prop.Key] = value
}
vmxContents = EncodeVMX(parsedVmx)
}
Expand Down

0 comments on commit 6f113ab

Please sign in to comment.