forked from dmacvicar/terraform-provider-libvirt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils_xslt.go
111 lines (96 loc) · 2.97 KB
/
utils_xslt.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package libvirt
import (
"io/ioutil"
"log"
"os"
"os/exec"
"strings"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
const (
identitySpaceStripXSLT = `
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
`
)
// This is the function we use to detect if the XSLT attribute itself changed
// As we don't want to recreate resources when the XSLT is changed with whitespace,
// we specify the diff supress function as the result of applying the identity
// transform to the xslt, stripping whitespace
// See https://www.terraform.io/docs/extend/schemas/schema-behaviors.html#diffsuppressfunc
func xsltDiffSupressFunc(k, old, new string, d *schema.ResourceData) bool {
oldStrip, err := transformXML(old, identitySpaceStripXSLT)
if err != nil {
// fail, just use normal equality
log.Printf("[ERROR] Couldn't normalize XSLT stylesheet")
return old == new
}
newStrip, err := transformXML(new, identitySpaceStripXSLT)
if err != nil {
// fail, just use normal equality
log.Printf("[ERROR] Couldn't normalize XSLT stylesheet")
return old == new
}
return oldStrip == newStrip
}
// this function applies a XSLT transform to the xml data
func transformXML(xmlS string, xsltS string) (string, error) {
// empty xslt is a no-op
if strings.TrimSpace(xsltS) == "" {
return xmlS, nil
}
xsltFile, err := ioutil.TempFile("", "terraform-provider-libvirt-xslt")
if err != nil {
log.Fatal(err)
}
defer os.Remove(xsltFile.Name()) // clean up
// we trim the xslt as it may contain space before the xml declaration
// because of HCL heredoc
if _, err := xsltFile.Write([]byte(strings.TrimSpace(xsltS))); err != nil {
log.Fatal(err)
}
if err := xsltFile.Close(); err != nil {
log.Fatal(err)
}
xmlFile, err := ioutil.TempFile("", "terraform-provider-libvirt-xml")
if err != nil {
log.Fatal(err)
}
defer os.Remove(xmlFile.Name()) // clean up
if _, err := xmlFile.Write([]byte(xmlS)); err != nil {
log.Fatal(err)
}
if err := xmlFile.Close(); err != nil {
log.Fatal(err)
}
cmd := exec.Command("xsltproc",
"--nomkdir",
"--nonet",
"--nowrite",
xsltFile.Name(),
xmlFile.Name())
transformedXML, err := cmd.Output()
if err != nil {
log.Printf("[ERROR] Failed to run xsltproc (is it installed?)")
return xmlS, err
}
log.Printf("[DEBUG] Transformed XML with user specified XSLT:\n%s", transformedXML)
//return strings.Trim(string(transformedXML), " \r\n"), nil
return string(transformedXML), err
}
// this function applies a XSLT transform to the xml data
// and is to be reused in all resource types
// your resource need to have a xml.xslt element in the schema
func transformResourceXML(xml string, d *schema.ResourceData) (string, error) {
xslt, ok := d.GetOk("xml.0.xslt")
if !ok {
return xml, nil
}
return transformXML(xml, xslt.(string))
}