[Go Program Gen] multiline strings, get/lookup disambiguation, webserver example (#4850)

This commit is contained in:
Evan Boyle 2020-06-18 13:34:22 -07:00 committed by GitHub
parent 08d94466db
commit 8b8170252b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 240 additions and 74 deletions

View file

@ -3,6 +3,9 @@ CHANGELOG
## HEAD (Unreleased)
- Go program gen improvements (multiline strings, get/lookup disambiguation, invoke improvements)
[#4850](https://github.com/pulumi/pulumi/pull/4850)
- Go program gen improvements (splat, all, index, traversal, range)
[#4831](https://github.com/pulumi/pulumi/pull/4831)

View file

@ -13,6 +13,7 @@ import (
"github.com/pulumi/pulumi/pkg/v2/codegen/hcl2"
"github.com/pulumi/pulumi/pkg/v2/codegen/hcl2/model"
"github.com/pulumi/pulumi/pkg/v2/codegen/hcl2/model/format"
"github.com/pulumi/pulumi/pkg/v2/codegen/schema"
"github.com/pulumi/pulumi/sdk/v2/go/common/util/contract"
)
@ -20,6 +21,7 @@ type generator struct {
// The formatter to use when generating code.
*format.Formatter
program *hcl2.Program
contexts map[string]map[string]*pkgContext
diagnostics hcl.Diagnostics
jsonTempSpiller *jsonSpiller
ternaryTempSpiller *tempSpiller
@ -32,8 +34,15 @@ func GenerateProgram(program *hcl2.Program) (map[string][]byte, hcl.Diagnostics,
// Linearize the nodes into an order appropriate for procedural code generation.
nodes := hcl2.Linearize(program)
contexts := make(map[string]map[string]*pkgContext)
for _, pkg := range program.Packages() {
contexts[pkg.Name] = getPackages("tool", pkg)
}
g := &generator{
program: program,
contexts: contexts,
jsonTempSpiller: &jsonSpiller{},
ternaryTempSpiller: &tempSpiller{},
readDirTempSpiller: &readDirSpiller{},
@ -68,6 +77,15 @@ func GenerateProgram(program *hcl2.Program) (map[string][]byte, hcl.Diagnostics,
return files, g.diagnostics, nil
}
func getPackages(tool string, pkg *schema.Package) map[string]*pkgContext {
if err := pkg.ImportLanguages(map[string]schema.Language{"go": Importer}); err != nil {
return nil
}
goInfo, _ := pkg.Language["go"].(GoPackageInfo)
return generatePackageContextMap(tool, pkg, goInfo)
}
func (g *generator) collectScopeRoots(n hcl2.Node) {
diags := n.VisitExpressions(nil, func(n model.Expression) (model.Expression, hcl.Diagnostics) {
if st, ok := n.(*model.ScopeTraversalExpression); ok {
@ -120,15 +138,54 @@ func (g *generator) collectImports(w io.Writer, program *hcl2.Program) (codegen.
panic(errors.Errorf("could not find package information for resource with type token:\n\n%s", r.Token))
}
vPath := fmt.Sprintf("/v%d", version)
if version <= 1 {
vPath = ""
var vPath string
if version > 1 {
vPath = fmt.Sprintf("/v%d", version)
}
pulumiImports.Add(fmt.Sprintf("github.com/pulumi/pulumi-%s/sdk%s/go/%s/%s", pkg, vPath, pkg, mod))
}
diags := n.VisitExpressions(nil, func(n model.Expression) (model.Expression, hcl.Diagnostics) {
if call, ok := n.(*model.FunctionCallExpression); ok {
if call.Name == hcl2.Invoke {
tokenArg := call.Args[0]
token := tokenArg.(*model.TemplateExpression).Parts[0].(*model.LiteralValueExpression).Value.AsString()
tokenRange := tokenArg.SyntaxNode().Range()
pkg, mod, _, diagnostics := hcl2.DecomposeToken(token, tokenRange)
contract.Assert(len(diagnostics) == 0)
version := -1
for _, p := range program.Packages() {
if p.Name == pkg {
version = int(p.Version.Major)
break
}
}
if version == -1 {
panic(errors.Errorf("could not find package information for resource with type token:\n\n%s", token))
}
var vPath string
if version > 1 {
vPath = fmt.Sprintf("/v%d", version)
}
// namespaceless invokes "aws:index:..."
if mod == "" {
pulumiImports.Add(fmt.Sprintf("github.com/pulumi/pulumi-%s/sdk%s/go/%s", pkg, vPath, pkg))
} else {
pulumiImports.Add(fmt.Sprintf("github.com/pulumi/pulumi-%s/sdk%s/go/%s/%s", pkg, vPath, pkg, mod))
}
}
}
return n, nil
})
contract.Assert(len(diags) == 0)
diags = n.VisitExpressions(nil, func(n model.Expression) (model.Expression, hcl.Diagnostics) {
if call, ok := n.(*model.FunctionCallExpression); ok {
for _, fnPkg := range g.genFunctionPackages(call) {
stdImports.Add(fnPkg)
@ -260,7 +317,7 @@ func (g *generator) genTempsMultiReturn(w io.Writer, temps []interface{}, zeroVa
case *ternaryTemp:
// TODO derive from ambient context
isInput := false
g.Fgenf(w, "var %s %s\n", t.Name, argumentTypeName(t.Value.TrueResult, t.Type(), isInput))
g.Fgenf(w, "var %s %s\n", t.Name, g.argumentTypeName(t.Value.TrueResult, t.Type(), isInput))
g.Fgenf(w, "if %.v {\n", t.Value.Condition)
g.Fgenf(w, "%s = %.v\n", t.Name, t.Value.TrueResult)
g.Fgenf(w, "} else {\n")
@ -297,7 +354,7 @@ func (g *generator) genTempsMultiReturn(w io.Writer, temps []interface{}, zeroVa
g.Fgenf(w, "%s[%s] = %s.Name()\n", namesVar, iVar, valVar)
g.Fgenf(w, "}\n")
case *splatTemp:
argTyp := argumentTypeName(t.Value.Each, t.Value.Each.Type(), false)
argTyp := g.argumentTypeName(t.Value.Each, t.Value.Each.Type(), false)
g.Fgenf(w, "var %s []%s\n", t.Name, argTyp)
g.Fgenf(w, "for _, val0 := range %.v {\n", t.Value.Source)
g.Fgenf(w, "%s = append(%s, %.v)\n", t.Name, t.Name, t.Value.Each)
@ -331,3 +388,30 @@ func (g *generator) genLocalVariable(w io.Writer, v *hcl2.LocalVariable) {
}
}
// nolint: lll
// uselookupInvokeForm takes a token for an invoke and determines whether to use the
// .Get or .Lookup form. The Go SDK has collisions in .Get methods that require renaming.
// For instance, gen.go creates a resource getter for AWS VPCs that collides with a function:
// GetVPC resource getter: https://github.com/pulumi/pulumi-aws/blob/7835df354694e2f9f23371602a9febebc6b45be8/sdk/go/aws/ec2/getVpc.go#L15
// LookupVPC function: https://github.com/pulumi/pulumi-aws/blob/7835df354694e2f9f23371602a9febebc6b45be8/sdk/go/aws/ec2/getVpc.go#L15
// Given that the naming here is not consisten, we must reverse the process from gen.go.
func (g *generator) useLookupInvokeForm(token string) bool {
pkg, module, member, _ := hcl2.DecomposeToken(token, *new(hcl.Range))
modSplit := strings.Split(module, "/")
mod := modSplit[0]
if mod == "index" {
mod = ""
}
fn := Title(member)
if len(modSplit) >= 2 {
fn = Title(modSplit[1])
}
fnLookup := "Lookup" + fn[3:]
pkgContext := g.contexts[pkg][mod]
if pkgContext.names.has(fnLookup) {
return true
}
return false
}

View file

@ -66,12 +66,12 @@ func (g *generator) GenAnonymousFunctionExpression(w io.Writer, expr *model.Anon
leadingSep := ""
for _, param := range expr.Signature.Parameters {
isInput := isInputty(param.Type)
g.Fgenf(w, "%s%s %s", leadingSep, param.Name, argumentTypeName(nil, param.Type, isInput))
g.Fgenf(w, "%s%s %s", leadingSep, param.Name, g.argumentTypeName(nil, param.Type, isInput))
leadingSep = ", "
}
isInput := isInputty(expr.Signature.ReturnType)
retType := argumentTypeName(nil, expr.Signature.ReturnType, isInput)
retType := g.argumentTypeName(nil, expr.Signature.ReturnType, isInput)
g.Fgenf(w, ") (%s, error) {\n", retType)
body, temps := g.lowerExpression(expr.Body, expr.Signature.ReturnType, isInput)
@ -144,8 +144,10 @@ func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionC
g.genRelativeTraversalExpression(w, arg, isInput)
case *model.ScopeTraversalExpression:
g.genScopeTraversalExpression(w, arg, isInput)
case *model.ObjectConsExpression:
g.genObjectConsExpression(w, arg, expr.Type(), isInput)
default:
argType := argumentTypeName(arg, arg.Type(), isInput)
argType := g.argumentTypeName(arg, arg.Type(), isInput)
g.Fgenf(w, "%s(%v", argType, arg)
g.Fgenf(w, ")")
}
@ -154,7 +156,8 @@ func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionC
case *model.TupleConsExpression:
g.genTupleConsExpression(w, arg, expr.Type())
case *model.ObjectConsExpression:
g.genObjectConsExpression(w, arg, expr.Type())
isInput := false
g.genObjectConsExpression(w, arg, expr.Type(), isInput)
case *model.LiteralValueExpression:
g.genLiteralValueExpression(w, arg, expr.Type())
default:
@ -188,7 +191,7 @@ func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionC
case "fileAsset":
g.Fgenf(w, "pulumi.NewFileAsset(%.v)", expr.Args[0])
case hcl2.Invoke:
pkg, module, fn, diags := functionName(expr.Args[0])
pkg, module, fn, diags := g.functionName(expr.Args[0])
contract.Assert(len(diags) == 0)
if module == "" {
module = pkg
@ -240,7 +243,7 @@ func (g *generator) GenLiteralValueExpression(w io.Writer, expr *model.LiteralVa
}
func (g *generator) genLiteralValueExpression(w io.Writer, expr *model.LiteralValueExpression, destType model.Type) {
argTypeName := argumentTypeName(expr, destType, false)
argTypeName := g.argumentTypeName(expr, destType, false)
isPulumiType := strings.HasPrefix(argTypeName, "pulumi.")
switch destType := destType.(type) {
@ -298,19 +301,25 @@ func (g *generator) genLiteralValueExpression(w io.Writer, expr *model.LiteralVa
}
func (g *generator) GenObjectConsExpression(w io.Writer, expr *model.ObjectConsExpression) {
g.genObjectConsExpression(w, expr, expr.Type())
isInput := false
g.genObjectConsExpression(w, expr, expr.Type(), isInput)
}
func (g *generator) genObjectConsExpression(w io.Writer, expr *model.ObjectConsExpression, destType model.Type) {
func (g *generator) genObjectConsExpression(
w io.Writer,
expr *model.ObjectConsExpression,
destType model.Type,
isInput bool,
) {
if len(expr.Items) > 0 {
var temps []interface{}
isInput := isInputty(destType)
typeName := argumentTypeName(expr, destType, isInput)
isInput = isInput || isInputty(destType)
typeName := g.argumentTypeName(expr, destType, isInput)
if strings.HasSuffix(typeName, "Args") {
isInput = true
}
// invokes are not inputty
if strings.Contains(typeName, ".Lookup") {
if strings.Contains(typeName, ".Lookup") || strings.Contains(typeName, ".Get") {
isInput = false
}
isMap := strings.HasPrefix(typeName, "map[")
@ -330,7 +339,7 @@ func (g *generator) genObjectConsExpression(w io.Writer, expr *model.ObjectConsE
}
g.genTemps(w, temps)
if isMap {
if isMap || !strings.HasSuffix(typeName, "Args") {
g.Fgenf(w, "%s", typeName)
} else {
g.Fgenf(w, "&%s", typeName)
@ -339,7 +348,7 @@ func (g *generator) genObjectConsExpression(w io.Writer, expr *model.ObjectConsE
for _, item := range expr.Items {
if lit, ok := g.literalKey(item.Key); ok {
if isMap {
if isMap || strings.HasSuffix(typeName, "Map") {
g.Fgenf(w, "\"%s\"", lit)
} else {
g.Fgenf(w, "%s", Title(lit))
@ -366,7 +375,7 @@ func (g *generator) genRelativeTraversalExpression(w io.Writer, expr *model.Rela
isInput = false
}
if isInput {
g.Fgenf(w, "%s(", argumentTypeName(expr, expr.Type(), isInput))
g.Fgenf(w, "%s(", g.argumentTypeName(expr, expr.Type(), isInput))
}
g.GenRelativeTraversalExpression(w, expr)
if isInput {
@ -415,7 +424,7 @@ func (g *generator) genScopeTraversalExpression(w io.Writer, expr *model.ScopeTr
// TODO if it's an array type, we need a lowering step to turn []string -> pulumi.StringArray
if isInput {
g.Fgenf(w, "%s(", argumentTypeName(expr, expr.Type(), isInput))
g.Fgenf(w, "%s(", g.argumentTypeName(expr, expr.Type(), isInput))
}
// TODO: this isn't exhaustively correct as "range" could be a legit var name
@ -488,7 +497,7 @@ func (g *generator) genTupleConsExpression(w io.Writer, expr *model.TupleConsExp
expr.Expressions[i] = item
}
g.genTemps(w, temps)
argType := argumentTypeName(expr, destType, isInput)
argType := g.argumentTypeName(expr, destType, isInput)
g.Fgenf(w, "%s{\n", argType)
switch len(expr.Expressions) {
case 0:
@ -514,7 +523,7 @@ func (g *generator) GenUnaryOpExpression(w io.Writer, expr *model.UnaryOpExpress
}
// argumentTypeName computes the go type for the given expression and model type.
func argumentTypeName(expr model.Expression, destType model.Type, isInput bool) string {
func (g *generator) argumentTypeName(expr model.Expression, destType model.Type, isInput bool) string {
var tokenRange hcl.Range
if expr != nil {
node := expr.SyntaxNode()
@ -526,22 +535,39 @@ func argumentTypeName(expr model.Expression, destType model.Type, isInput bool)
switch schemaType := schemaType.(type) {
case *schema.ArrayType:
token := schemaType.ElementType.(*schema.ObjectType).Token
_, module, member, diags := hcl2.DecomposeToken(token, tokenRange)
pkg, module, member, diags := hcl2.DecomposeToken(token, tokenRange)
// namespaceless invokes
if module == "" || strings.HasPrefix(module, "/") || strings.HasPrefix(module, "index/") {
module = pkg
}
importPrefix := strings.Split(module, "/")[0]
contract.Assert(len(diags) == 0)
fmtString := "[]%s.%s"
if isInput {
member = Title(member)
if strings.HasPrefix(member, "Get") {
if g.useLookupInvokeForm(token) {
member = strings.Replace(member, "Get", "Lookup", 1)
}
return fmt.Sprintf("[]%s.%s", importPrefix, member)
}
fmtString = "%s.%sArray"
}
return fmt.Sprintf(fmtString, importPrefix, member)
case *schema.ObjectType:
token := schemaType.Token
_, module, member, diags := hcl2.DecomposeToken(token, tokenRange)
pkg, module, member, diags := hcl2.DecomposeToken(token, tokenRange)
// namespaceless invokes
if module == "" || strings.HasPrefix(module, "/") || strings.HasPrefix(module, "index/") {
module = pkg
}
importPrefix := strings.Split(module, "/")[0]
contract.Assert(len(diags) == 0)
member = Title(member)
if strings.HasPrefix(member, "Get") {
member = strings.Replace(member, "Get", "Lookup", 1)
if g.useLookupInvokeForm(token) {
member = strings.Replace(member, "Get", "Lookup", 1)
}
return fmt.Sprintf("%s.%s", importPrefix, member)
}
fmtString := "%s.%s"
@ -586,13 +612,13 @@ func argumentTypeName(expr model.Expression, destType model.Type, isInput bool)
}
return "map[string]interface{}"
case *model.MapType:
valType := argumentTypeName(nil, destType.ElementType, isInput)
valType := g.argumentTypeName(nil, destType.ElementType, isInput)
if isInput {
return fmt.Sprintf("pulumi.%sMap", Title(valType))
}
return fmt.Sprintf("map[string]%s", valType)
case *model.ListType:
argTypeName := argumentTypeName(nil, destType.ElementType, isInput)
argTypeName := g.argumentTypeName(nil, destType.ElementType, isInput)
if strings.HasPrefix(argTypeName, "pulumi.") {
return fmt.Sprintf("%sArray", argTypeName)
}
@ -613,7 +639,7 @@ func argumentTypeName(expr model.Expression, destType model.Type, isInput bool)
}
if elmType != nil {
argTypeName := argumentTypeName(nil, elmType, isInput)
argTypeName := g.argumentTypeName(nil, elmType, isInput)
if strings.HasPrefix(argTypeName, "pulumi.") {
return fmt.Sprintf("%sArray", argTypeName)
}
@ -626,16 +652,16 @@ func argumentTypeName(expr model.Expression, destType model.Type, isInput bool)
return "[]interface{}"
case *model.OutputType:
isInput = true
return argumentTypeName(expr, destType.ElementType, isInput)
return g.argumentTypeName(expr, destType.ElementType, isInput)
case *model.UnionType:
for _, ut := range destType.ElementTypes {
if _, isOpaqueType := ut.(*model.OpaqueType); isOpaqueType {
return argumentTypeName(expr, ut, isInput)
return g.argumentTypeName(expr, ut, isInput)
}
}
return "interface{}"
case *model.PromiseType:
return argumentTypeName(expr, destType.ElementType, isInput)
return g.argumentTypeName(expr, destType.ElementType, isInput)
default:
contract.Failf("unexpected destType type %T", destType)
}
@ -737,7 +763,7 @@ func (g *generator) genApply(w io.Writer, expr *model.FunctionCallExpression) {
applyArgs, then := hcl2.ParseApplyCall(expr)
then = stripInputs(then).(*model.AnonymousFunctionExpression)
isInput := false
retType := argumentTypeName(nil, then.Signature.ReturnType, isInput)
retType := g.argumentTypeName(nil, then.Signature.ReturnType, isInput)
// TODO account for outputs in other namespaces like aws
typeAssertion := fmt.Sprintf(".(%sOutput)", retType)
if !strings.HasPrefix(retType, "pulumi.") {
@ -755,23 +781,14 @@ func (g *generator) genApply(w io.Writer, expr *model.FunctionCallExpression) {
}
// TODO need lowering step to rewrite then argument references
// in terms of scope traversal from all result: val[i] etc.
g.Fgenf(w, ").Apply(%.v)%s", then, typeAssertion)
g.Fgenf(w, ").ApplyT(%.v)%s", then, typeAssertion)
}
}
func (g *generator) genStringLiteral(w io.Writer, v string) {
// TODO more robust and go-specific handling of strings
newlines := strings.Contains(v, "\n")
if !newlines {
// This string does not contain newlines so we'll generate a regular string literal. Quotes and backslashes
// will be escaped in conformance with
// https://golang.org/ref/spec#String_literals
g.Fgen(w, "\"")
g.Fgen(w, g.escapeString(v))
g.Fgen(w, "\"")
} else {
g.genNYI(w, "TODO multiline strings")
}
g.Fgen(w, "\"")
g.Fgen(w, g.escapeString(v))
g.Fgen(w, "\"")
}
func (g *generator) escapeString(v string) string {
@ -780,6 +797,11 @@ func (g *generator) escapeString(v string) string {
if c == '"' || c == '\\' {
builder.WriteRune('\\')
}
if c == '\n' {
builder.WriteRune('\\')
builder.WriteRune('n')
continue
}
builder.WriteRune(c)
}
return builder.String()
@ -831,17 +853,16 @@ func (g *generator) literalKey(x model.Expression) (string, bool) {
}
// functionName computes the go package, module, and name for the given function token.
func functionName(tokenArg model.Expression) (string, string, string, hcl.Diagnostics) {
func (g *generator) functionName(tokenArg model.Expression) (string, string, string, hcl.Diagnostics) {
token := tokenArg.(*model.TemplateExpression).Parts[0].(*model.LiteralValueExpression).Value.AsString()
tokenRange := tokenArg.SyntaxNode().Range()
// Compute the resource type from the Pulumi type token.
pkg, module, member, diagnostics := hcl2.DecomposeToken(token, tokenRange)
// GetResource -> LookupResource
// TODO figure out how to deal with get/lookup ambiguity
// https://github.com/pulumi/pulumi/blob/adfa8116fbf61ad328568fe4b53e32c751f30553/pkg/codegen/go/gen.go#L1171
if strings.HasPrefix(member, "get") {
member = strings.Replace(member, "get", "lookup", 1)
if g.useLookupInvokeForm(token) {
member = strings.Replace(member, "get", "lookup", 1)
}
}
return pkg, strings.Replace(module, "/", ".", -1), Title(member), diagnostics
}

View file

@ -83,6 +83,7 @@ func modifyInputs(
for _, item := range expr.Items {
item.Value = modifyInputs(item.Value, modf)
}
x = modf(x)
case *model.TupleConsExpression:
for i, item := range expr.Expressions {
expr.Expressions[i] = modifyInputs(item, modf)

View file

@ -27,13 +27,6 @@ func TestGenProgram(t *testing.T) {
if filepath.Ext(f.Name()) != ".pp" {
continue
}
// TODO: include all test files
if filepath.Base(f.Name()) != "aws-s3-logging.pp" &&
filepath.Base(f.Name()) != "aws-s3-folder.pp" &&
filepath.Base(f.Name()) != "aws-eks.pp" &&
filepath.Base(f.Name()) != "aws-fargate.pp" {
continue
}
t.Run(f.Name(), func(t *testing.T) {
path := filepath.Join(testdataPath, f.Name())

View file

@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"github.com/pulumi/pulumi-aws/sdk/v2/go/aws"
"github.com/pulumi/pulumi-aws/sdk/v2/go/aws/ec2"
"github.com/pulumi/pulumi-aws/sdk/v2/go/aws/eks"
"github.com/pulumi/pulumi-aws/sdk/v2/go/aws/iam"
@ -17,8 +18,8 @@ func main() {
InstanceTenancy: pulumi.String("default"),
EnableDnsHostnames: pulumi.Bool(true),
EnableDnsSupport: pulumi.Bool(true),
Tags: map[string]interface{}{
"Name": "pulumi-eks-vpc",
Tags: pulumi.Map{
"Name": pulumi.String("pulumi-eks-vpc"),
},
})
if err != nil {
@ -26,8 +27,8 @@ func main() {
}
eksIgw, err := ec2.NewInternetGateway(ctx, "eksIgw", &ec2.InternetGatewayArgs{
VpcId: eksVpc.ID(),
Tags: map[string]interface{}{
"Name": "pulumi-vpc-ig",
Tags: pulumi.Map{
"Name": pulumi.String("pulumi-vpc-ig"),
},
})
if err != nil {
@ -41,14 +42,14 @@ func main() {
GatewayId: eksIgw.ID(),
},
},
Tags: map[string]interface{}{
"Name": "pulumi-vpc-rt",
Tags: pulumi.Map{
"Name": pulumi.String("pulumi-vpc-rt"),
},
})
if err != nil {
return err
}
zones, err := aws.LookupAvailabilityZones(ctx, nil, nil)
zones, err := aws.GetAvailabilityZones(ctx, nil, nil)
if err != nil {
return err
}
@ -60,8 +61,8 @@ func main() {
MapPublicIpOnLaunch: pulumi.Bool(true),
CidrBlock: pulumi.String(fmt.Sprintf("%v%v%v", "10.100.", key0, ".0/24")),
AvailabilityZone: pulumi.String(val0),
Tags: map[string]interface{}{
"Name": fmt.Sprintf("%v%v", "pulumi-sn-", val0),
Tags: pulumi.Map{
"Name": pulumi.String(fmt.Sprintf("%v%v", "pulumi-sn-", val0)),
},
})
if err != nil {
@ -88,8 +89,8 @@ func main() {
eksSecurityGroup, err := ec2.NewSecurityGroup(ctx, "eksSecurityGroup", &ec2.SecurityGroupArgs{
VpcId: eksVpc.ID(),
Description: pulumi.String("Allow all HTTP(s) traffic to EKS Cluster"),
Tags: map[string]interface{}{
"Name": "pulumi-cluster-sg",
Tags: pulumi.Map{
"Name": pulumi.String("pulumi-cluster-sg"),
},
Ingress: ec2.SecurityGroupIngressArray{
&ec2.SecurityGroupIngressArgs{
@ -198,8 +199,8 @@ func main() {
}
eksCluster, err := eks.NewCluster(ctx, "eksCluster", &eks.ClusterArgs{
RoleArn: eksRole.Arn,
Tags: map[string]interface{}{
"Name": "pulumi-eks-cluster",
Tags: pulumi.Map{
"Name": pulumi.String("pulumi-eks-cluster"),
},
VpcConfig: &eks.ClusterVpcConfigArgs{
PublicAccessCidrs: pulumi.StringArray{
@ -219,8 +220,8 @@ func main() {
NodeGroupName: pulumi.String("pulumi-eks-nodegroup"),
NodeRoleArn: ec2Role.Arn,
SubnetIds: subnetIds,
Tags: map[string]interface{}{
"Name": "pulumi-cluster-nodeGroup",
Tags: pulumi.Map{
"Name": pulumi.String("pulumi-cluster-nodeGroup"),
},
ScalingConfig: &eks.NodeGroupScalingConfigArgs{
DesiredSize: pulumi.Int(2),
@ -232,7 +233,7 @@ func main() {
return err
}
ctx.Export("clusterName", eksCluster.Name)
ctx.Export("kubeconfig", pulumi.All(eksCluster.Endpoint, eksCluster.CertificateAuthority, eksCluster.Name).Apply(func(endpoint string, certificateAuthority eks.ClusterCertificateAuthority, name string) (pulumi.String, error) {
ctx.Export("kubeconfig", pulumi.All(eksCluster.Endpoint, eksCluster.CertificateAuthority, eksCluster.Name).ApplyT(func(endpoint string, certificateAuthority eks.ClusterCertificateAuthority, name string) (pulumi.String, error) {
var _zero pulumi.String
tmpJSON2, err := json.Marshal(map[string]interface{}{
"apiVersion": "v1",

View file

@ -18,7 +18,7 @@ func main() {
if err != nil {
return err
}
subnets, err := ec2.LookupSubnetIds(ctx, &ec2.LookupSubnetIdsArgs{
subnets, err := ec2.GetSubnetIds(ctx, &ec2.GetSubnetIdsArgs{
VpcId: vpc.Id,
}, nil)
if err != nil {

View file

@ -0,0 +1,63 @@
package main
import (
"fmt"
"github.com/pulumi/pulumi-aws/sdk/v2/go/aws"
"github.com/pulumi/pulumi-aws/sdk/v2/go/aws/ec2"
"github.com/pulumi/pulumi/sdk/v2/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
securityGroup, err := ec2.NewSecurityGroup(ctx, "securityGroup", &ec2.SecurityGroupArgs{
Ingress: ec2.SecurityGroupIngressArray{
&ec2.SecurityGroupIngressArgs{
Protocol: pulumi.String("tcp"),
FromPort: pulumi.Int(0),
ToPort: pulumi.Int(0),
CidrBlocks: pulumi.StringArray{
pulumi.String("0.0.0.0/0"),
},
},
},
})
if err != nil {
return err
}
ami, err := aws.GetAmi(ctx, &aws.GetAmiArgs{
Filters: []aws.GetAmiFilter{
aws.GetAmiFilter{
Name: "name",
Values: []string{
"amzn-ami-hvm-*-x86_64-ebs",
},
},
},
Owners: []string{
"137112412989",
},
MostRecent: true,
}, nil)
if err != nil {
return err
}
server, err := ec2.NewInstance(ctx, "server", &ec2.InstanceArgs{
Tags: pulumi.Map{
"Name": pulumi.String("web-server-www"),
},
InstanceType: pulumi.String("t2.micro"),
SecurityGroups: pulumi.StringArray{
securityGroup.Name,
},
Ami: pulumi.String(ami.Id),
UserData: pulumi.String(fmt.Sprintf("%v%v%v", "#!/bin/bash\n", "echo \"Hello, World!\" > index.html\n", "nohup python -m SimpleHTTPServer 80 &\n")),
})
if err != nil {
return err
}
ctx.Export("publicIp", server.PublicIp)
ctx.Export("publicHostName", server.PublicDns)
return nil
})
}