// Copyright 2016-2020, Pulumi Corporation. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package pcl import ( "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hclsyntax" "github.com/pulumi/pulumi/pkg/v3/codegen/hcl2/model" "github.com/zclconf/go-cty/cty" ) const Invoke = "invoke" func getInvokeToken(call *hclsyntax.FunctionCallExpr) (string, hcl.Range, bool) { if call.Name != Invoke || len(call.Args) < 1 { return "", hcl.Range{}, false } template, ok := call.Args[0].(*hclsyntax.TemplateExpr) if !ok || len(template.Parts) != 1 { return "", hcl.Range{}, false } literal, ok := template.Parts[0].(*hclsyntax.LiteralValueExpr) if !ok { return "", hcl.Range{}, false } if literal.Val.Type() != cty.String { return "", hcl.Range{}, false } return literal.Val.AsString(), call.Args[0].Range(), true } func (b *binder) bindInvokeSignature(args []model.Expression) (model.StaticFunctionSignature, hcl.Diagnostics) { signature := model.StaticFunctionSignature{ Parameters: []model.Parameter{ { Name: "token", Type: model.StringType, }, { Name: "args", Type: model.NewOptionalType(model.DynamicType), }, { Name: "provider", Type: model.NewOptionalType(model.StringType), }, }, ReturnType: model.DynamicType, } if len(args) < 1 { return signature, nil } template, ok := args[0].(*model.TemplateExpression) if !ok || len(template.Parts) != 1 { return signature, hcl.Diagnostics{tokenMustBeStringLiteral(args[0])} } lit, ok := template.Parts[0].(*model.LiteralValueExpression) if !ok || model.StringType.ConversionFrom(lit.Type()) == model.NoConversion { return signature, hcl.Diagnostics{tokenMustBeStringLiteral(args[0])} } token, tokenRange := lit.Value.AsString(), args[0].SyntaxNode().Range() pkg, _, _, diagnostics := DecomposeToken(token, tokenRange) if diagnostics.HasErrors() { return signature, diagnostics } pkgSchema, ok := b.options.packageCache.entries[pkg] if !ok { return signature, hcl.Diagnostics{unknownPackage(pkg, tokenRange)} } fn, ok := pkgSchema.functions[token] if !ok { canon := canonicalizeToken(token, pkgSchema.schema) if fn, ok = pkgSchema.functions[canon]; ok { token, lit.Value = canon, cty.StringVal(canon) } } if !ok { return signature, hcl.Diagnostics{unknownFunction(token, tokenRange)} } // Create args and result types for the schema. if fn.Inputs == nil { signature.Parameters[1].Type = model.NewOptionalType(model.NewObjectType(map[string]model.Type{})) } else { signature.Parameters[1].Type = b.schemaTypeToType(fn.Inputs) } if fn.Outputs == nil { signature.ReturnType = model.NewObjectType(map[string]model.Type{}) } else { signature.ReturnType = b.schemaTypeToType(fn.Outputs) } signature.ReturnType = model.NewPromiseType(signature.ReturnType) return signature, nil }