mirror of https://github.com/pulumi/pulumi.git
423 lines
12 KiB
Go
423 lines
12 KiB
Go
// 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/pulumi/pulumi/pkg/v3/codegen/hcl2/model"
|
|
)
|
|
|
|
func getEntriesSignature(
|
|
args []model.Expression,
|
|
options bindOptions,
|
|
) (model.StaticFunctionSignature, hcl.Diagnostics) {
|
|
var diagnostics hcl.Diagnostics
|
|
|
|
keyType, valueType := model.Type(model.DynamicType), model.Type(model.DynamicType)
|
|
signature := model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "collection",
|
|
Type: model.DynamicType,
|
|
}},
|
|
}
|
|
|
|
if len(args) == 1 {
|
|
strictCollectionTypechecking := !options.skipRangeTypecheck
|
|
keyT, valueT, diags := model.GetCollectionTypes(
|
|
model.ResolveOutputs(args[0].Type()),
|
|
args[0].SyntaxNode().Range(),
|
|
strictCollectionTypechecking)
|
|
keyType, valueType, diagnostics = keyT, valueT, append(diagnostics, diags...)
|
|
}
|
|
|
|
elementType := model.NewObjectType(map[string]model.Type{
|
|
"key": keyType,
|
|
"value": valueType,
|
|
})
|
|
signature.ReturnType = model.NewListType(elementType)
|
|
return signature, diagnostics
|
|
}
|
|
|
|
func pulumiBuiltins(options bindOptions) map[string]*model.Function {
|
|
return map[string]*model.Function{
|
|
"element": model.NewFunction(model.GenericFunctionSignature(
|
|
func(args []model.Expression) (model.StaticFunctionSignature, hcl.Diagnostics) {
|
|
var diagnostics hcl.Diagnostics
|
|
|
|
listType, returnType := model.Type(model.DynamicType), model.Type(model.DynamicType)
|
|
if len(args) > 0 {
|
|
switch t := model.ResolveOutputs(args[0].Type()).(type) {
|
|
case *model.ListType:
|
|
listType, returnType = args[0].Type(), t.ElementType
|
|
case *model.TupleType:
|
|
_, elementType := model.UnifyTypes(t.ElementTypes...)
|
|
listType, returnType = args[0].Type(), elementType
|
|
default:
|
|
if !options.skipRangeTypecheck {
|
|
// we are in strict mode, so we should error if the type is not a list or tuple
|
|
rng := args[0].SyntaxNode().Range()
|
|
diagnostics = hcl.Diagnostics{&hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "the first argument to 'element' must be a list or tuple",
|
|
Subject: &rng,
|
|
}}
|
|
}
|
|
}
|
|
}
|
|
return model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{
|
|
{
|
|
Name: "list",
|
|
Type: listType,
|
|
},
|
|
{
|
|
Name: "index",
|
|
Type: model.NumberType,
|
|
},
|
|
},
|
|
ReturnType: returnType,
|
|
}, diagnostics
|
|
})),
|
|
"entries": model.NewFunction(model.GenericFunctionSignature(
|
|
func(arguments []model.Expression) (model.StaticFunctionSignature, hcl.Diagnostics) {
|
|
return getEntriesSignature(arguments, options)
|
|
})),
|
|
|
|
"fileArchive": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "path",
|
|
Type: model.StringType,
|
|
}},
|
|
ReturnType: ArchiveType,
|
|
}),
|
|
"remoteArchive": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "uri",
|
|
Type: model.StringType,
|
|
}},
|
|
ReturnType: ArchiveType,
|
|
}),
|
|
"assetArchive": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "assets",
|
|
Type: model.NewMapType(AssetOrArchiveType),
|
|
}},
|
|
ReturnType: ArchiveType,
|
|
}),
|
|
"fileAsset": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "path",
|
|
Type: model.StringType,
|
|
}},
|
|
ReturnType: AssetType,
|
|
}),
|
|
"stringAsset": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "value",
|
|
Type: model.StringType,
|
|
}},
|
|
ReturnType: AssetType,
|
|
}),
|
|
"remoteAsset": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "uri",
|
|
Type: model.StringType,
|
|
}},
|
|
ReturnType: AssetType,
|
|
}),
|
|
"join": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{
|
|
{
|
|
Name: "separator",
|
|
Type: model.StringType,
|
|
},
|
|
{
|
|
Name: "strings",
|
|
Type: model.NewListType(model.StringType),
|
|
},
|
|
},
|
|
ReturnType: model.StringType,
|
|
}),
|
|
"length": model.NewFunction(model.GenericFunctionSignature(
|
|
func(args []model.Expression) (model.StaticFunctionSignature, hcl.Diagnostics) {
|
|
var diagnostics hcl.Diagnostics
|
|
|
|
valueType := model.Type(model.DynamicType)
|
|
if len(args) > 0 {
|
|
valueType = args[0].Type()
|
|
elementType := UnwrapOption(model.ResolveOutputs(valueType))
|
|
switch valueType := elementType.(type) {
|
|
case *model.ListType, *model.MapType, *model.ObjectType, *model.TupleType:
|
|
// OK
|
|
default:
|
|
if model.StringType.ConversionFrom(valueType) == model.NoConversion {
|
|
rng := args[0].SyntaxNode().Range()
|
|
diagnostics = hcl.Diagnostics{&hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "the first argument to 'length' must be a list, map, object, tuple, or string",
|
|
Subject: &rng,
|
|
}}
|
|
}
|
|
}
|
|
}
|
|
return model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "value",
|
|
Type: valueType,
|
|
}},
|
|
ReturnType: model.IntType,
|
|
}, diagnostics
|
|
})),
|
|
"lookup": model.NewFunction(model.GenericFunctionSignature(
|
|
func(args []model.Expression) (model.StaticFunctionSignature, hcl.Diagnostics) {
|
|
var diagnostics hcl.Diagnostics
|
|
|
|
mapType, elementType := model.Type(model.DynamicType), model.Type(model.DynamicType)
|
|
if len(args) > 0 {
|
|
switch t := model.ResolveOutputs(args[0].Type()).(type) {
|
|
case *model.MapType:
|
|
mapType, elementType = args[0].Type(), t.ElementType
|
|
case *model.ObjectType:
|
|
var unifiedType model.Type
|
|
for _, t := range t.Properties {
|
|
_, unifiedType = model.UnifyTypes(unifiedType, t)
|
|
}
|
|
mapType, elementType = args[0].Type(), unifiedType
|
|
default:
|
|
rng := args[0].SyntaxNode().Range()
|
|
diagnostics = hcl.Diagnostics{&hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "the first argument to 'lookup' must be a map",
|
|
Subject: &rng,
|
|
}}
|
|
}
|
|
}
|
|
return model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{
|
|
{
|
|
Name: "map",
|
|
Type: mapType,
|
|
},
|
|
{
|
|
Name: "key",
|
|
Type: model.StringType,
|
|
},
|
|
{
|
|
Name: "default",
|
|
Type: model.NewOptionalType(elementType),
|
|
},
|
|
},
|
|
ReturnType: elementType,
|
|
}, diagnostics
|
|
})),
|
|
"mimeType": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "path",
|
|
Type: model.StringType,
|
|
}},
|
|
ReturnType: model.StringType,
|
|
}),
|
|
"range": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{
|
|
{
|
|
Name: "fromOrTo",
|
|
Type: model.NumberType,
|
|
},
|
|
{
|
|
Name: "to",
|
|
Type: model.NewOptionalType(model.NumberType),
|
|
},
|
|
},
|
|
ReturnType: model.NewListType(model.IntType),
|
|
}),
|
|
"readDir": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "path",
|
|
Type: model.StringType,
|
|
}},
|
|
ReturnType: model.NewListType(model.StringType),
|
|
}),
|
|
"readFile": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "path",
|
|
Type: model.StringType,
|
|
}},
|
|
ReturnType: model.StringType,
|
|
}),
|
|
"filebase64": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "path",
|
|
Type: model.StringType,
|
|
}},
|
|
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)
|
|
if len(args) == 1 {
|
|
valueType = args[0].Type()
|
|
}
|
|
|
|
return model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "value",
|
|
Type: valueType,
|
|
}},
|
|
ReturnType: model.NewOutputType(valueType),
|
|
}, nil
|
|
})),
|
|
"unsecret": model.NewFunction(model.GenericFunctionSignature(
|
|
func(args []model.Expression) (model.StaticFunctionSignature, hcl.Diagnostics) {
|
|
valueType := model.Type(model.DynamicType)
|
|
if len(args) == 1 {
|
|
valueType = args[0].Type()
|
|
}
|
|
|
|
return model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "value",
|
|
Type: valueType,
|
|
}},
|
|
ReturnType: model.NewOutputType(valueType),
|
|
}, nil
|
|
})),
|
|
"sha1": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "input",
|
|
Type: model.StringType,
|
|
}},
|
|
ReturnType: model.StringType,
|
|
}),
|
|
"split": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{
|
|
{
|
|
Name: "separator",
|
|
Type: model.StringType,
|
|
},
|
|
{
|
|
Name: "string",
|
|
Type: model.StringType,
|
|
},
|
|
},
|
|
ReturnType: model.NewListType(model.StringType),
|
|
}),
|
|
"toBase64": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "value",
|
|
Type: model.StringType,
|
|
}},
|
|
ReturnType: model.StringType,
|
|
}),
|
|
"fromBase64": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "value",
|
|
Type: model.StringType,
|
|
}},
|
|
ReturnType: model.StringType,
|
|
}),
|
|
"toJSON": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "value",
|
|
Type: model.DynamicType,
|
|
}},
|
|
ReturnType: model.StringType,
|
|
}),
|
|
// Returns the name of the current stack
|
|
"stack": model.NewFunction(model.StaticFunctionSignature{
|
|
ReturnType: model.StringType,
|
|
}),
|
|
// Returns the name of the current project
|
|
"project": model.NewFunction(model.StaticFunctionSignature{
|
|
ReturnType: model.StringType,
|
|
}),
|
|
// Returns the name of the current organization
|
|
"organization": model.NewFunction(model.StaticFunctionSignature{
|
|
ReturnType: model.StringType,
|
|
}),
|
|
// Returns the directory from which pulumi was run
|
|
"cwd": model.NewFunction(model.StaticFunctionSignature{
|
|
ReturnType: model.StringType,
|
|
}),
|
|
"notImplemented": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "errorMessage",
|
|
Type: model.StringType,
|
|
}},
|
|
ReturnType: model.DynamicType,
|
|
}),
|
|
// Returns either the single item in a list, none if the list is empty or errors.
|
|
"singleOrNone": model.NewFunction(model.GenericFunctionSignature(
|
|
func(args []model.Expression) (model.StaticFunctionSignature, hcl.Diagnostics) {
|
|
var diagnostics hcl.Diagnostics
|
|
|
|
valueType := model.Type(model.DynamicType)
|
|
if len(args) == 1 {
|
|
valueType = args[0].Type()
|
|
} else {
|
|
diagnostics = hcl.Diagnostics{&hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "'singleOrNone' only expects one argument",
|
|
}}
|
|
}
|
|
|
|
elementType := model.Type(model.DynamicType)
|
|
|
|
switch valueType := model.ResolveOutputs(valueType).(type) {
|
|
case *model.ListType:
|
|
elementType = valueType.ElementType
|
|
case *model.TupleType:
|
|
if len(valueType.ElementTypes) > 0 {
|
|
elementType = valueType.ElementTypes[0]
|
|
}
|
|
default:
|
|
if valueType != model.DynamicType {
|
|
rng := args[0].SyntaxNode().Range()
|
|
diagnostics = hcl.Diagnostics{&hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "the first argument to 'singleOrNone' must be a list or tuple",
|
|
Subject: &rng,
|
|
}}
|
|
}
|
|
}
|
|
|
|
return model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "value",
|
|
Type: valueType,
|
|
}},
|
|
ReturnType: model.NewOptionalType(elementType),
|
|
}, diagnostics
|
|
})),
|
|
"getOutput": model.NewFunction(model.StaticFunctionSignature{
|
|
Parameters: []model.Parameter{{
|
|
Name: "stackReference",
|
|
// TODO: should be StackReference resource type but I'm not sure how to define that
|
|
Type: model.DynamicType,
|
|
}, {
|
|
Name: "outputName",
|
|
Type: model.StringType,
|
|
}},
|
|
ReturnType: model.NewOutputType(model.DynamicType),
|
|
}),
|
|
}
|
|
}
|