]>
Commit | Line | Data |
---|---|---|
107c1cdb ND |
1 | package funcs |
2 | ||
3 | import ( | |
4 | "bytes" | |
5 | "compress/gzip" | |
6 | "encoding/base64" | |
7 | "fmt" | |
8 | "log" | |
9 | "net/url" | |
10 | "unicode/utf8" | |
11 | ||
12 | "github.com/zclconf/go-cty/cty" | |
13 | "github.com/zclconf/go-cty/cty/function" | |
14 | ) | |
15 | ||
16 | // Base64DecodeFunc constructs a function that decodes a string containing a base64 sequence. | |
17 | var Base64DecodeFunc = function.New(&function.Spec{ | |
18 | Params: []function.Parameter{ | |
19 | { | |
20 | Name: "str", | |
21 | Type: cty.String, | |
22 | }, | |
23 | }, | |
24 | Type: function.StaticReturnType(cty.String), | |
25 | Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { | |
26 | s := args[0].AsString() | |
27 | sDec, err := base64.StdEncoding.DecodeString(s) | |
28 | if err != nil { | |
29 | return cty.UnknownVal(cty.String), fmt.Errorf("failed to decode base64 data '%s'", s) | |
30 | } | |
31 | if !utf8.Valid([]byte(sDec)) { | |
32 | log.Printf("[DEBUG] the result of decoding the the provided string is not valid UTF-8: %s", sDec) | |
33 | return cty.UnknownVal(cty.String), fmt.Errorf("the result of decoding the the provided string is not valid UTF-8") | |
34 | } | |
35 | return cty.StringVal(string(sDec)), nil | |
36 | }, | |
37 | }) | |
38 | ||
39 | // Base64EncodeFunc constructs a function that encodes a string to a base64 sequence. | |
40 | var Base64EncodeFunc = function.New(&function.Spec{ | |
41 | Params: []function.Parameter{ | |
42 | { | |
43 | Name: "str", | |
44 | Type: cty.String, | |
45 | }, | |
46 | }, | |
47 | Type: function.StaticReturnType(cty.String), | |
48 | Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { | |
49 | return cty.StringVal(base64.StdEncoding.EncodeToString([]byte(args[0].AsString()))), nil | |
50 | }, | |
51 | }) | |
52 | ||
53 | // Base64GzipFunc constructs a function that compresses a string with gzip and then encodes the result in | |
54 | // Base64 encoding. | |
55 | var Base64GzipFunc = function.New(&function.Spec{ | |
56 | Params: []function.Parameter{ | |
57 | { | |
58 | Name: "str", | |
59 | Type: cty.String, | |
60 | }, | |
61 | }, | |
62 | Type: function.StaticReturnType(cty.String), | |
63 | Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { | |
64 | s := args[0].AsString() | |
65 | ||
66 | var b bytes.Buffer | |
67 | gz := gzip.NewWriter(&b) | |
68 | if _, err := gz.Write([]byte(s)); err != nil { | |
69 | return cty.UnknownVal(cty.String), fmt.Errorf("failed to write gzip raw data: '%s'", s) | |
70 | } | |
71 | if err := gz.Flush(); err != nil { | |
72 | return cty.UnknownVal(cty.String), fmt.Errorf("failed to flush gzip writer: '%s'", s) | |
73 | } | |
74 | if err := gz.Close(); err != nil { | |
75 | return cty.UnknownVal(cty.String), fmt.Errorf("failed to close gzip writer: '%s'", s) | |
76 | } | |
77 | return cty.StringVal(base64.StdEncoding.EncodeToString(b.Bytes())), nil | |
78 | }, | |
79 | }) | |
80 | ||
81 | // URLEncodeFunc constructs a function that applies URL encoding to a given string. | |
82 | var URLEncodeFunc = function.New(&function.Spec{ | |
83 | Params: []function.Parameter{ | |
84 | { | |
85 | Name: "str", | |
86 | Type: cty.String, | |
87 | }, | |
88 | }, | |
89 | Type: function.StaticReturnType(cty.String), | |
90 | Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { | |
91 | return cty.StringVal(url.QueryEscape(args[0].AsString())), nil | |
92 | }, | |
93 | }) | |
94 | ||
95 | // Base64Decode decodes a string containing a base64 sequence. | |
96 | // | |
97 | // Terraform uses the "standard" Base64 alphabet as defined in RFC 4648 section 4. | |
98 | // | |
99 | // Strings in the Terraform language are sequences of unicode characters rather | |
100 | // than bytes, so this function will also interpret the resulting bytes as | |
101 | // UTF-8. If the bytes after Base64 decoding are _not_ valid UTF-8, this function | |
102 | // produces an error. | |
103 | func Base64Decode(str cty.Value) (cty.Value, error) { | |
104 | return Base64DecodeFunc.Call([]cty.Value{str}) | |
105 | } | |
106 | ||
107 | // Base64Encode applies Base64 encoding to a string. | |
108 | // | |
109 | // Terraform uses the "standard" Base64 alphabet as defined in RFC 4648 section 4. | |
110 | // | |
111 | // Strings in the Terraform language are sequences of unicode characters rather | |
112 | // than bytes, so this function will first encode the characters from the string | |
113 | // as UTF-8, and then apply Base64 encoding to the result. | |
114 | func Base64Encode(str cty.Value) (cty.Value, error) { | |
115 | return Base64EncodeFunc.Call([]cty.Value{str}) | |
116 | } | |
117 | ||
118 | // Base64Gzip compresses a string with gzip and then encodes the result in | |
119 | // Base64 encoding. | |
120 | // | |
121 | // Terraform uses the "standard" Base64 alphabet as defined in RFC 4648 section 4. | |
122 | // | |
123 | // Strings in the Terraform language are sequences of unicode characters rather | |
124 | // than bytes, so this function will first encode the characters from the string | |
125 | // as UTF-8, then apply gzip compression, and then finally apply Base64 encoding. | |
126 | func Base64Gzip(str cty.Value) (cty.Value, error) { | |
127 | return Base64GzipFunc.Call([]cty.Value{str}) | |
128 | } | |
129 | ||
130 | // URLEncode applies URL encoding to a given string. | |
131 | // | |
132 | // This function identifies characters in the given string that would have a | |
133 | // special meaning when included as a query string argument in a URL and | |
134 | // escapes them using RFC 3986 "percent encoding". | |
135 | // | |
136 | // If the given string contains non-ASCII characters, these are first encoded as | |
137 | // UTF-8 and then percent encoding is applied separately to each UTF-8 byte. | |
138 | func URLEncode(str cty.Value) (cty.Value, error) { | |
139 | return URLEncodeFunc.Call([]cty.Value{str}) | |
140 | } |