Compare commits
8 commits
master
...
t-vova/cod
Author | SHA1 | Date | |
---|---|---|---|
4bc8ee0316 | |||
809cf11d79 | |||
aa8aff0572 | |||
6d48d3355e | |||
1c1e7e9d7d | |||
584f109588 | |||
fba8aa6575 | |||
cae67f1f83 |
|
@ -238,12 +238,13 @@ func (g *generator) genRange(w io.Writer, call *model.FunctionCallExpression, en
|
|||
}
|
||||
|
||||
var functionNamespaces = map[string][]string{
|
||||
"readDir": {"System.IO", "System.Linq"},
|
||||
"readFile": {"System.IO"},
|
||||
"filebase64": {"System", "System.IO"},
|
||||
"toJSON": {"System.Text.Json", "System.Collections.Generic"},
|
||||
"toBase64": {"System"},
|
||||
"sha1": {"System.Security.Cryptography", "System.Text"},
|
||||
"readDir": {"System.IO", "System.Linq"},
|
||||
"readFile": {"System.IO"},
|
||||
"filebase64": {"System", "System.IO"},
|
||||
"filebase64sha256": {"System", "System.IO", "System.Security.Cryptography", "System.Text"},
|
||||
"toJSON": {"System.Text.Json", "System.Collections.Generic"},
|
||||
"toBase64": {"System"},
|
||||
"sha1": {"System.Security.Cryptography", "System.Text"},
|
||||
}
|
||||
|
||||
func (g *generator) genFunctionUsings(x *model.FunctionCallExpression) []string {
|
||||
|
@ -313,6 +314,9 @@ func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionC
|
|||
case "filebase64":
|
||||
// Assuming the existence of the following helper method located earlier in the preamble
|
||||
g.Fgenf(w, "ReadFileBase64(%v)", expr.Args[0])
|
||||
case "filebase64sha256":
|
||||
// Assuming the existence of the following helper method located earlier in the preamble
|
||||
g.Fgenf(w, "ComputeFileBase64Sha256(%v)", expr.Args[0])
|
||||
case pcl.Invoke:
|
||||
_, name := g.functionName(expr.Args[0])
|
||||
|
||||
|
|
|
@ -126,7 +126,13 @@ func getHelperMethodIfNeeded(functionName string) (string, bool) {
|
|||
switch functionName {
|
||||
case "filebase64":
|
||||
return `private static string ReadFileBase64(string path) {
|
||||
return Convert.ToBase64String(System.Text.UTF8.GetBytes(File.ReadAllText(path)))
|
||||
return Convert.ToBase64String(Encoding.UTF8.GetBytes(File.ReadAllText(path)))
|
||||
}`, true
|
||||
case "filebase64sha256":
|
||||
return `private static string ComputeFileBase64Sha256(string path) {
|
||||
var fileData = Encoding.UTF8.GetBytes(File.ReadAllText(path));
|
||||
var hashData = SHA256.Create().ComputeHash(fileData);
|
||||
return Convert.ToBase64String(hashData);
|
||||
}`, true
|
||||
case "sha1":
|
||||
return `private static string ComputeSHA1(string input) {
|
||||
|
|
|
@ -182,13 +182,15 @@ func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionC
|
|||
// }
|
||||
// g.Fgenf(w, " => new { Key = k, Value = v })")
|
||||
case "fileArchive":
|
||||
g.genNYI(w, "call %v", expr.Name)
|
||||
// g.Fgenf(w, "new FileArchive(%.v)", expr.Args[0])
|
||||
g.Fgenf(w, "pulumi.NewFileArchive(%.v)", expr.Args[0])
|
||||
case "fileAsset":
|
||||
g.Fgenf(w, "pulumi.NewFileAsset(%.v)", expr.Args[0])
|
||||
case "filebase64":
|
||||
// Assuming the existence of the following helper method
|
||||
g.Fgenf(w, "filebase64OrPanic(%v)", expr.Args[0])
|
||||
case "filebase64sha256":
|
||||
// Assuming the existence of the following helper method
|
||||
g.Fgenf(w, "filebase64sha256OrPanic(%v)", expr.Args[0])
|
||||
case pcl.Invoke:
|
||||
pkg, module, fn, diags := g.functionName(expr.Args[0])
|
||||
contract.Assert(len(diags) == 0)
|
||||
|
@ -1004,14 +1006,15 @@ func (g *generator) functionName(tokenArg model.Expression) (string, string, str
|
|||
}
|
||||
|
||||
var functionPackages = map[string][]string{
|
||||
"join": {"strings"},
|
||||
"mimeType": {"mime", "path"},
|
||||
"readDir": {"io/ioutil"},
|
||||
"readFile": {"io/ioutil"},
|
||||
"filebase64": {"io/ioutil", "encoding/base64"},
|
||||
"toBase64": {"encoding/base64"},
|
||||
"toJSON": {"encoding/json"},
|
||||
"sha1": {"fmt", "crypto/sha1"},
|
||||
"join": {"strings"},
|
||||
"mimeType": {"mime", "path"},
|
||||
"readDir": {"io/ioutil"},
|
||||
"readFile": {"io/ioutil"},
|
||||
"filebase64": {"io/ioutil", "encoding/base64"},
|
||||
"toBase64": {"encoding/base64"},
|
||||
"toJSON": {"encoding/json"},
|
||||
"sha1": {"fmt", "crypto/sha1"},
|
||||
"filebase64sha256": {"fmt", "io/ioutil", "crypto/sha256"},
|
||||
}
|
||||
|
||||
func (g *generator) genFunctionPackages(x *model.FunctionCallExpression) []string {
|
||||
|
|
|
@ -77,6 +77,15 @@ func getHelperMethodIfNeeded(functionName string) (string, bool) {
|
|||
panic(err.Error())
|
||||
}
|
||||
}`, true
|
||||
case "filebase64sha256":
|
||||
return `func filebase64sha256OrPanic(path string) pulumi.StringPtrInput {
|
||||
if fileData, err := ioutil.ReadFile(path); err == nil {
|
||||
hashedData := sha256.Sum256([]byte(fileData))
|
||||
return pulumi.String(base64.StdEncoding.EncodeToString(hashedData[:]))
|
||||
} else {
|
||||
panic(err.Error())
|
||||
}
|
||||
}`, true
|
||||
case "sha1":
|
||||
return `func sha1Hash(input string) string {
|
||||
hash := sha1.Sum([]byte(input))
|
||||
|
|
|
@ -53,6 +53,9 @@ func GenerateProgram(program *pcl.Program) (map[string][]byte, hcl.Diagnostics,
|
|||
}
|
||||
g.Formatter = format.NewFormatter(g)
|
||||
|
||||
// Creating a list to store and later print helper methods if they turn out to be needed
|
||||
preambleHelperMethods := codegen.NewStringSet()
|
||||
|
||||
for _, p := range program.Packages() {
|
||||
if err := p.ImportLanguages(map[string]schema.Language{"nodejs": Importer}); err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -60,7 +63,7 @@ func GenerateProgram(program *pcl.Program) (map[string][]byte, hcl.Diagnostics,
|
|||
}
|
||||
|
||||
var index bytes.Buffer
|
||||
g.genPreamble(&index, program)
|
||||
g.genPreamble(&index, program, preambleHelperMethods)
|
||||
for _, n := range nodes {
|
||||
if r, ok := n.(*pcl.Resource); ok && requiresAsyncMain(r) {
|
||||
g.asyncMain = true
|
||||
|
@ -150,7 +153,7 @@ func (g *generator) genComment(w io.Writer, comment syntax.Comment) {
|
|||
}
|
||||
}
|
||||
|
||||
func (g *generator) genPreamble(w io.Writer, program *pcl.Program) {
|
||||
func (g *generator) genPreamble(w io.Writer, program *pcl.Program, preambleHelperMethods codegen.StringSet) {
|
||||
// Print the @pulumi/pulumi import at the top.
|
||||
g.Fprintln(w, `import * as pulumi from "@pulumi/pulumi";`)
|
||||
|
||||
|
@ -164,8 +167,13 @@ func (g *generator) genPreamble(w io.Writer, program *pcl.Program) {
|
|||
}
|
||||
diags := n.VisitExpressions(nil, func(n model.Expression) (model.Expression, hcl.Diagnostics) {
|
||||
if call, ok := n.(*model.FunctionCallExpression); ok {
|
||||
if i := g.getFunctionImports(call); i != "" {
|
||||
importSet.Add(i)
|
||||
if i := g.getFunctionImports(call); len(i) > 0 && i[0] != "" {
|
||||
for _, importPackage := range i {
|
||||
importSet.Add(importPackage)
|
||||
}
|
||||
}
|
||||
if helperMethodBody, ok := getHelperMethodIfNeeded(call.Name); ok {
|
||||
preambleHelperMethods.Add(helperMethodBody)
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
|
@ -192,6 +200,11 @@ func (g *generator) genPreamble(w io.Writer, program *pcl.Program) {
|
|||
g.Fprintln(w, i)
|
||||
}
|
||||
g.Fprint(w, "\n")
|
||||
|
||||
// If we collected any helper methods that should be added, write them just before the main func
|
||||
for _, preambleHelperMethodBody := range preambleHelperMethods.SortedValues() {
|
||||
g.Fprintf(w, "%s\n\n", preambleHelperMethodBody)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *generator) genNode(w io.Writer, n pcl.Node) {
|
||||
|
|
|
@ -266,24 +266,25 @@ func (g *generator) genRange(w io.Writer, call *model.FunctionCallExpression, en
|
|||
genSuffix()
|
||||
}
|
||||
|
||||
var functionImports = map[string]string{
|
||||
intrinsicInterpolate: "@pulumi/pulumi",
|
||||
"fileArchive": "@pulumi/pulumi",
|
||||
"fileAsset": "@pulumi/pulumi",
|
||||
"filebase64": "fs",
|
||||
"readFile": "fs",
|
||||
"readDir": "fs",
|
||||
"sha1": "crypto",
|
||||
var functionImports = map[string][]string{
|
||||
intrinsicInterpolate: {"@pulumi/pulumi"},
|
||||
"fileArchive": {"@pulumi/pulumi"},
|
||||
"fileAsset": {"@pulumi/pulumi"},
|
||||
"filebase64": {"fs"},
|
||||
"filebase64sha256": {"fs", "crypto"},
|
||||
"readFile": {"fs"},
|
||||
"readDir": {"fs"},
|
||||
"sha1": {"crypto"},
|
||||
}
|
||||
|
||||
func (g *generator) getFunctionImports(x *model.FunctionCallExpression) string {
|
||||
func (g *generator) getFunctionImports(x *model.FunctionCallExpression) []string {
|
||||
if x.Name != pcl.Invoke {
|
||||
return functionImports[x.Name]
|
||||
}
|
||||
|
||||
pkg, _, _, diags := functionName(x.Args[0])
|
||||
contract.Assert(len(diags) == 0)
|
||||
return "@pulumi/" + pkg
|
||||
return []string{"@pulumi/" + pkg}
|
||||
}
|
||||
|
||||
func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionCallExpression) {
|
||||
|
@ -322,6 +323,9 @@ func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionC
|
|||
g.Fgenf(w, "new pulumi.asset.FileAsset(%.v)", expr.Args[0])
|
||||
case "filebase64":
|
||||
g.Fgenf(w, "Buffer.from(fs.readFileSync(%v), 'binary').toString('base64')", expr.Args[0])
|
||||
case "filebase64sha256":
|
||||
// Assuming the existence of the following helper method
|
||||
g.Fgenf(w, "computeFilebase64sha256(%v)", expr.Args[0])
|
||||
case pcl.Invoke:
|
||||
pkg, module, fn, diags := functionName(expr.Args[0])
|
||||
contract.Assert(len(diags) == 0)
|
||||
|
|
17
pkg/codegen/nodejs/gen_program_utils.go
Normal file
17
pkg/codegen/nodejs/gen_program_utils.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package nodejs
|
||||
|
||||
// Provides code for a method which will be placed in the program preamble if deemed
|
||||
// necessary. Because many tasks in Go such as reading a file require extensive error
|
||||
// handling, it is much prettier to encapsulate that error handling boilerplate as its
|
||||
// own function in the preamble.
|
||||
func getHelperMethodIfNeeded(functionName string) (string, bool) {
|
||||
switch functionName {
|
||||
case "filebase64sha256":
|
||||
return `func computeFilebase64sha256(path string) string {
|
||||
const fileData = Buffer.from(fs.readFileSync(path), 'binary')
|
||||
return crypto.createHash('sha256').update(fileData).digest('hex')
|
||||
}`, true
|
||||
default:
|
||||
return "", false
|
||||
}
|
||||
}
|
|
@ -216,6 +216,13 @@ var pulumiBuiltins = map[string]*model.Function{
|
|||
}},
|
||||
ReturnType: model.StringType,
|
||||
}),
|
||||
"filebase64sha256": model.NewFunction(model.StaticFunctionSignature{
|
||||
Parameters: []model.Parameter{{
|
||||
Name: "path",
|
||||
Type: model.StringType,
|
||||
}},
|
||||
ReturnType: model.StringType,
|
||||
}),
|
||||
"secret": model.NewFunction(model.GenericFunctionSignature(
|
||||
func(args []model.Expression) (model.StaticFunctionSignature, hcl.Diagnostics) {
|
||||
valueType := model.Type(model.DynamicType)
|
||||
|
|
|
@ -50,8 +50,11 @@ func GenerateProgram(program *pcl.Program) (map[string][]byte, hcl.Diagnostics,
|
|||
// Linearize the nodes into an order appropriate for procedural code generation.
|
||||
nodes := pcl.Linearize(program)
|
||||
|
||||
// Creating a list to store and later print helper methods if they turn out to be needed
|
||||
preambleHelperMethods := codegen.NewStringSet()
|
||||
|
||||
var main bytes.Buffer
|
||||
g.genPreamble(&main, program)
|
||||
g.genPreamble(&main, program, preambleHelperMethods)
|
||||
for _, n := range nodes {
|
||||
g.genNode(&main, n)
|
||||
}
|
||||
|
@ -112,7 +115,7 @@ func (g *generator) genComment(w io.Writer, comment syntax.Comment) {
|
|||
}
|
||||
}
|
||||
|
||||
func (g *generator) genPreamble(w io.Writer, program *pcl.Program) {
|
||||
func (g *generator) genPreamble(w io.Writer, program *pcl.Program, preambleHelperMethods codegen.StringSet) {
|
||||
// Print the pulumi import at the top.
|
||||
g.Fprintln(w, "import pulumi")
|
||||
|
||||
|
@ -125,8 +128,13 @@ func (g *generator) genPreamble(w io.Writer, program *pcl.Program) {
|
|||
}
|
||||
diags := n.VisitExpressions(nil, func(n model.Expression) (model.Expression, hcl.Diagnostics) {
|
||||
if call, ok := n.(*model.FunctionCallExpression); ok {
|
||||
if i := g.getFunctionImports(call); i != "" {
|
||||
importSet.Add(i)
|
||||
if i := g.getFunctionImports(call); len(i) > 0 && i[0] != "" {
|
||||
for _, importPackage := range i {
|
||||
importSet.Add(importPackage)
|
||||
}
|
||||
}
|
||||
if helperMethodBody, ok := getHelperMethodIfNeeded(call.Name); ok {
|
||||
preambleHelperMethods.Add(helperMethodBody)
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
|
@ -152,6 +160,11 @@ func (g *generator) genPreamble(w io.Writer, program *pcl.Program) {
|
|||
g.Fprintln(w, i)
|
||||
}
|
||||
g.Fprint(w, "\n")
|
||||
|
||||
// If we collected any helper methods that should be added, write them just before the main func
|
||||
for _, preambleHelperMethodBody := range preambleHelperMethods.SortedValues() {
|
||||
g.Fprintf(w, "%s\n\n", preambleHelperMethodBody)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *generator) genNode(w io.Writer, n pcl.Node) {
|
||||
|
|
|
@ -181,24 +181,25 @@ func functionName(tokenArg model.Expression) (string, string, string, hcl.Diagno
|
|||
return makeValidIdentifier(pkg), strings.Replace(module, "/", ".", -1), title(member), diagnostics
|
||||
}
|
||||
|
||||
var functionImports = map[string]string{
|
||||
"fileArchive": "pulumi",
|
||||
"fileAsset": "pulumi",
|
||||
"filebase64": "base64",
|
||||
"readDir": "os",
|
||||
"toBase64": "base64",
|
||||
"toJSON": "json",
|
||||
"sha1": "hashlib",
|
||||
var functionImports = map[string][]string{
|
||||
"fileArchive": {"pulumi"},
|
||||
"fileAsset": {"pulumi"},
|
||||
"filebase64": {"base64"},
|
||||
"filebase64sha256": {"base64", "hashlib"},
|
||||
"readDir": {"os"},
|
||||
"toBase64": {"base64"},
|
||||
"toJSON": {"json"},
|
||||
"sha1": {"hashlib"},
|
||||
}
|
||||
|
||||
func (g *generator) getFunctionImports(x *model.FunctionCallExpression) string {
|
||||
func (g *generator) getFunctionImports(x *model.FunctionCallExpression) []string {
|
||||
if x.Name != pcl.Invoke {
|
||||
return functionImports[x.Name]
|
||||
}
|
||||
|
||||
pkg, _, _, diags := functionName(x.Args[0])
|
||||
contract.Assert(len(diags) == 0)
|
||||
return "pulumi_" + pkg
|
||||
return []string{"pulumi_" + pkg}
|
||||
}
|
||||
|
||||
func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionCallExpression) {
|
||||
|
@ -222,6 +223,9 @@ func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionC
|
|||
g.Fgenf(w, "pulumi.FileAsset(%.v)", expr.Args[0])
|
||||
case "filebase64":
|
||||
g.Fgenf(w, "(lambda path: base64.b64encode(open(path).read().encode()).decode())(%.v)", expr.Args[0])
|
||||
case "filebase64sha256":
|
||||
// Assuming the existence of the following helper method
|
||||
g.Fgenf(w, "computeFilebase64sha256(%v)", expr.Args[0])
|
||||
case pcl.Invoke:
|
||||
pkg, module, fn, diags := functionName(expr.Args[0])
|
||||
contract.Assert(len(diags) == 0)
|
||||
|
|
17
pkg/codegen/python/gen_program_utils.go
Normal file
17
pkg/codegen/python/gen_program_utils.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package python
|
||||
|
||||
// Provides code for a method which will be placed in the program preamble if deemed
|
||||
// necessary. Because many tasks in Go such as reading a file require extensive error
|
||||
// handling, it is much prettier to encapsulate that error handling boilerplate as its
|
||||
// own function in the preamble.
|
||||
func getHelperMethodIfNeeded(functionName string) (string, bool) {
|
||||
switch functionName {
|
||||
case "filebase64sha256":
|
||||
return `def computeFilebase64sha256(path):
|
||||
fileData = open(path).read().encode()
|
||||
hashedData = hashlib.sha256(fileData.encode()).digest()
|
||||
return base64.b64encode(hashedData).decode()`, true
|
||||
default:
|
||||
return "", false
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue