Hello, world!
25 |Made with ❤️ with Pulumi
26 | 27 | 28 | "; 29 | 30 | // write our index.html into the site bucket 31 | var @object = new Pulumi.Aws.S3.BucketObject( 32 | "index", 33 | new Pulumi.Aws.S3.BucketObjectArgs 34 | { 35 | Bucket = siteBucket.BucketName, // reference to the s3 bucket object 36 | Content = indexContent, 37 | Key = "index.html", // set the key of the object 38 | ContentType = "text/html; charset=utf-8", // set the MIME type of the file 39 | }); 40 | 41 | var bucketPolicyDocument = siteBucket.Arn.Apply(bucketArn => 42 | { 43 | return Output.Create(Pulumi.Aws.Iam.GetPolicyDocument.InvokeAsync( 44 | new Pulumi.Aws.Iam.GetPolicyDocumentArgs 45 | { 46 | Statements = new ListHello, world!
Made with ❤️ with Pulumi
26 | 27 | ` 28 | // upload our index.html 29 | if _, err := s3.NewBucketObject(ctx, "index", &s3.BucketObjectArgs{ 30 | Bucket: siteBucket.ID(), // reference to the s3.Bucket object 31 | Content: pulumi.String(indexContent), 32 | Key: pulumi.String("index.html"), // set the key of the object 33 | ContentType: pulumi.String("text/html; charset=utf-8"), // set the MIME type of the file 34 | }); err != nil { 35 | return err 36 | } 37 | 38 | // Allow public ACLs for the bucket 39 | accessBlock, err := s3.NewBucketPublicAccessBlock(ctx, "public-access-block", &s3.BucketPublicAccessBlockArgs{ 40 | Bucket: siteBucket.ID(), 41 | BlockPublicAcls: pulumi.Bool(false), 42 | }) 43 | if err != nil { 44 | return err 45 | } 46 | 47 | // Set the access policy for the bucket so all objects are readable. 48 | if _, err := s3.NewBucketPolicy(ctx, "bucketPolicy", &s3.BucketPolicyArgs{ 49 | Bucket: siteBucket.ID(), // refer to the bucket created earlier 50 | Policy: pulumi.Any(map[string]interface{}{ 51 | "Version": "2012-10-17", 52 | "Statement": []map[string]interface{}{ 53 | { 54 | "Effect": "Allow", 55 | "Principal": "*", 56 | "Action": []interface{}{ 57 | "s3:GetObject", 58 | }, 59 | "Resource": []interface{}{ 60 | pulumi.Sprintf("arn:aws:s3:::%s/*", siteBucket.ID()), // policy refers to bucket name explicitly 61 | }, 62 | }, 63 | }, 64 | }), 65 | }, pulumi.DependsOn([]pulumi.Resource{accessBlock})); err != nil { 66 | return err 67 | } 68 | 69 | // export the website URL 70 | ctx.Export("websiteUrl", siteBucket.WebsiteEndpoint) 71 | return nil 72 | } 73 | -------------------------------------------------------------------------------- /go/inline_local_hybrid/infra/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/go/inline_local_hybrid/infra 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/pulumi/pulumi-aws/sdk/v4 v4.0.0 7 | github.com/pulumi/pulumi/sdk/v3 v3.0.0 8 | ) 9 | -------------------------------------------------------------------------------- /go/inline_passphrase_secrets_provider/README.md: -------------------------------------------------------------------------------- 1 | # Inline Program 2 | 3 | This program demonstrates how to use Automation API with an `inline` Pulumi program and custom secrets provider. This example builds on the basic example in `inline_program` 4 | but uses a custom secrets provider, which requires saving the secrets provider configuration and re-using it on subsequent runs. 5 | 6 | To run this example you'll need a few pre-reqs: 7 | 1. A Pulumi CLI installation ([v3.0.0](https://www.pulumi.com/docs/get-started/install/versions/) or later) 8 | 2. The AWS CLI, with appropriate credentials. 9 | 10 | Running this program is just like any other Go program. No invocation through the Pulumi CLI required: 11 | 12 | ```shell 13 | $ mkdir ~/.pulumi-local 14 | $ go run main.go 15 | Created/Selected stack "dev" 16 | Installing the AWS plugin 17 | Successfully installed AWS plugin 18 | Successfully set config 19 | Starting refresh 20 | Refresh succeeded! 21 | Starting update 22 | Updating (dev) 23 | 24 | View Live: https://app.pulumi.com/EvanBoyle/inlineS3Project/dev/updates/22 25 | 26 | 27 | + pulumi:pulumi:Stack inlineS3Project-dev creating 28 | + aws:s3:Bucket s3-website-bucket creating 29 | + aws:s3:Bucket s3-website-bucket created 30 | + aws:s3:BucketObject index creating 31 | + aws:s3:BucketPolicy bucketPolicy creating 32 | + aws:s3:BucketObject index created 33 | + aws:s3:BucketPolicy bucketPolicy created 34 | + pulumi:pulumi:Stack inlineS3Project-dev created 35 | 36 | Outputs: 37 | secretValue: "[secret]" 38 | websiteUrl : "s3-website-bucket-bf7e357.s3-website-us-west-2.amazonaws.com" 39 | 40 | Resources: 41 | + 4 created 42 | 43 | Duration: 10s 44 | 45 | Update succeeded! 46 | URL: s3-website-bucket-bf7e357.s3-website-us-west-2.amazonaws.com 47 | ``` 48 | 49 | To destroy the stack when you're done, invoke the program with an additional `destroy` argument: 50 | 51 | ```shell 52 | $ go run main.go destroy 53 | Created/Selected stack "dev" 54 | Installing the AWS plugin 55 | Successfully installed AWS plugin 56 | Successfully set config 57 | Starting refresh 58 | Refresh succeeded! 59 | Starting stack destroy 60 | Destroying (dev) 61 | 62 | View Live: https://app.pulumi.com/EvanBoyle/inlineS3Project/dev/updates/24 63 | 64 | 65 | - aws:s3:BucketPolicy bucketPolicy deleting 66 | - aws:s3:BucketObject index deleting 67 | - aws:s3:BucketObject index deleted 68 | - aws:s3:BucketPolicy bucketPolicy deleted 69 | - aws:s3:Bucket s3-website-bucket deleting 70 | - aws:s3:Bucket s3-website-bucket deleted 71 | - pulumi:pulumi:Stack inlineS3Project-dev deleting 72 | - pulumi:pulumi:Stack inlineS3Project-dev deleted 73 | 74 | Outputs: 75 | - secretValue: "[secret]" 76 | - websiteUrl: "s3-website-bucket-bf7e357.s3-website-us-west-2.amazonaws.com" 77 | 78 | Resources: 79 | - 4 deleted 80 | 81 | Duration: 3s 82 | 83 | The resources in the stack have been deleted, but the history and configuration associated with the stack are still maintained. 84 | If you want to remove the stack completely, run 'pulumi stack rm dev'. 85 | Stack successfully destroyed 86 | ``` 87 | -------------------------------------------------------------------------------- /go/inline_passphrase_secrets_provider/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/go/inline_secrets_provider 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/pulumi/pulumi-aws/sdk/v4 v4.23.0 7 | github.com/pulumi/pulumi/sdk/v3 v3.14.0 8 | ) 9 | -------------------------------------------------------------------------------- /go/inline_program/README.md: -------------------------------------------------------------------------------- 1 | # Inline Program 2 | 3 | This program demonstrates how use Automation API with an `inline` Pulumi program. Unlike traditional Pulumi programs, inline functions don't require a separate package on disk, with a `main.go` and `Pulumi.yaml`. Inline programs are just functions, can be authored in the same `main.go` or be imported from anther package. This example deploys an AWS S3 website, with all the context and deployment automation defined in a single file. 4 | 5 | To run this example you'll need a few pre-reqs: 6 | 1. A Pulumi CLI installation ([v3.0.0](https://www.pulumi.com/docs/get-started/install/versions/) or later) 7 | 2. The AWS CLI, with appropriate credentials. 8 | 9 | Running this program is just like any other Go program. No invocation through the Pulumi CLI required: 10 | 11 | ```shell 12 | $ go run main.go 13 | Created/Selected stack "dev" 14 | Installing the AWS plugin 15 | Successfully installed AWS plugin 16 | Successfully set config 17 | Starting refresh 18 | Refresh succeeded! 19 | Starting update 20 | Updating (dev) 21 | 22 | View Live: https://app.pulumi.com/EvanBoyle/inlineS3Project/dev/updates/22 23 | 24 | 25 | + pulumi:pulumi:Stack inlineS3Project-dev creating 26 | + aws:s3:Bucket s3-website-bucket creating 27 | + aws:s3:Bucket s3-website-bucket created 28 | + aws:s3:BucketObject index creating 29 | + aws:s3:BucketPolicy bucketPolicy creating 30 | + aws:s3:BucketObject index created 31 | + aws:s3:BucketPolicy bucketPolicy created 32 | + pulumi:pulumi:Stack inlineS3Project-dev created 33 | 34 | Outputs: 35 | websiteUrl: "s3-website-bucket-bf7e357.s3-website-us-west-2.amazonaws.com" 36 | 37 | Resources: 38 | + 4 created 39 | 40 | Duration: 10s 41 | 42 | Update succeeded! 43 | URL: s3-website-bucket-bf7e357.s3-website-us-west-2.amazonaws.com 44 | ``` 45 | 46 | To destroy the stack when you're done, invoke the program with an additional `destroy` argument: 47 | 48 | ```shell 49 | $ go run main.go destroy 50 | Created/Selected stack "dev" 51 | Installing the AWS plugin 52 | Successfully installed AWS plugin 53 | Successfully set config 54 | Starting refresh 55 | Refresh succeeded! 56 | Starting stack destroy 57 | Destroying (dev) 58 | 59 | View Live: https://app.pulumi.com/EvanBoyle/inlineS3Project/dev/updates/24 60 | 61 | 62 | - aws:s3:BucketPolicy bucketPolicy deleting 63 | - aws:s3:BucketObject index deleting 64 | - aws:s3:BucketObject index deleted 65 | - aws:s3:BucketPolicy bucketPolicy deleted 66 | - aws:s3:Bucket s3-website-bucket deleting 67 | - aws:s3:Bucket s3-website-bucket deleted 68 | - pulumi:pulumi:Stack inlineS3Project-dev deleting 69 | - pulumi:pulumi:Stack inlineS3Project-dev deleted 70 | 71 | Outputs: 72 | - websiteUrl: "s3-website-bucket-bf7e357.s3-website-us-west-2.amazonaws.com" 73 | 74 | Resources: 75 | - 4 deleted 76 | 77 | Duration: 3s 78 | 79 | The resources in the stack have been deleted, but the history and configuration associated with the stack are still maintained. 80 | If you want to remove the stack completely, run 'pulumi stack rm dev'. 81 | Stack successfully destroyed 82 | ``` 83 | -------------------------------------------------------------------------------- /go/inline_program/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/go/inline_program 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/pulumi/pulumi-aws/sdk/v4 v4.0.0 7 | github.com/pulumi/pulumi/sdk/v3 v3.0.0 8 | ) 9 | -------------------------------------------------------------------------------- /go/inline_secrets_provider/README.md: -------------------------------------------------------------------------------- 1 | # Inline Program 2 | 3 | This program demonstrates how to use Automation API with an `inline` Pulumi program and custom secrets provider. This example builds on the basic example in `inline_program` 4 | but uses a custom secrets provider, which requires saving the secrets provider configuration and re-using it on subsequent runs. 5 | 6 | To run this example you'll need a few pre-reqs: 7 | 1. A Pulumi CLI installation ([v3.14.0](https://www.pulumi.com/docs/get-started/install/versions/) or later) 8 | 2. The AWS CLI, with appropriate credentials. 9 | 10 | Running this program is just like any other Go program. No invocation through the Pulumi CLI required: 11 | 12 | ```shell 13 | $ mkdir ~/.pulumi-local 14 | $ go run main.go 15 | Created/Selected stack "dev" 16 | Installing the AWS plugin 17 | Successfully installed AWS plugin 18 | Successfully set config 19 | Starting refresh 20 | Refresh succeeded! 21 | Starting update 22 | Updating (dev) 23 | 24 | View Live: https://app.pulumi.com/EvanBoyle/inlineS3Project/dev/updates/22 25 | 26 | 27 | + pulumi:pulumi:Stack inlineS3Project-dev creating 28 | + aws:s3:Bucket s3-website-bucket creating 29 | + aws:s3:Bucket s3-website-bucket created 30 | + aws:s3:BucketObject index creating 31 | + aws:s3:BucketPolicy bucketPolicy creating 32 | + aws:s3:BucketObject index created 33 | + aws:s3:BucketPolicy bucketPolicy created 34 | + pulumi:pulumi:Stack inlineS3Project-dev created 35 | 36 | Outputs: 37 | secretValue: "[secret]" 38 | websiteUrl : "s3-website-bucket-bf7e357.s3-website-us-west-2.amazonaws.com" 39 | 40 | Resources: 41 | + 4 created 42 | 43 | Duration: 10s 44 | 45 | Update succeeded! 46 | URL: s3-website-bucket-bf7e357.s3-website-us-west-2.amazonaws.com 47 | ``` 48 | 49 | To destroy the stack when you're done, invoke the program with an additional `destroy` argument: 50 | 51 | ```shell 52 | $ go run main.go destroy 53 | Created/Selected stack "dev" 54 | Installing the AWS plugin 55 | Successfully installed AWS plugin 56 | Successfully set config 57 | Starting refresh 58 | Refresh succeeded! 59 | Starting stack destroy 60 | Destroying (dev) 61 | 62 | View Live: https://app.pulumi.com/EvanBoyle/inlineS3Project/dev/updates/24 63 | 64 | 65 | - aws:s3:BucketPolicy bucketPolicy deleting 66 | - aws:s3:BucketObject index deleting 67 | - aws:s3:BucketObject index deleted 68 | - aws:s3:BucketPolicy bucketPolicy deleted 69 | - aws:s3:Bucket s3-website-bucket deleting 70 | - aws:s3:Bucket s3-website-bucket deleted 71 | - pulumi:pulumi:Stack inlineS3Project-dev deleting 72 | - pulumi:pulumi:Stack inlineS3Project-dev deleted 73 | 74 | Outputs: 75 | - secretValue: "[secret]" 76 | - websiteUrl: "s3-website-bucket-bf7e357.s3-website-us-west-2.amazonaws.com" 77 | 78 | Resources: 79 | - 4 deleted 80 | 81 | Duration: 3s 82 | 83 | The resources in the stack have been deleted, but the history and configuration associated with the stack are still maintained. 84 | If you want to remove the stack completely, run 'pulumi stack rm dev'. 85 | Stack successfully destroyed 86 | ``` 87 | -------------------------------------------------------------------------------- /go/inline_secrets_provider/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/go/inline_secrets_provider 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/pulumi/pulumi-aws/sdk/v4 v4.23.0 7 | github.com/pulumi/pulumi/sdk/v3 v3.14.0 8 | ) 9 | -------------------------------------------------------------------------------- /go/local_program/app/Dockerfile: -------------------------------------------------------------------------------- 1 | # Start from a Debian image with the latest version of Go installed 2 | # and a workspace (GOPATH) configured at /go. 3 | FROM golang 4 | 5 | # Copy the local package files to the container's workspace. 6 | ADD . /go/src/foo 7 | 8 | # Build the outyet command inside the container. 9 | # (You may fetch or manage dependencies here, 10 | # either manually or with a tool like "godep".) 11 | WORKDIR /go/src/foo 12 | RUN go build -o /go/bin/main 13 | 14 | # Run the outyet command by default when the container starts. 15 | ENTRYPOINT /go/bin/main 16 | 17 | # Document that the service listens on port 80. 18 | EXPOSE 80 -------------------------------------------------------------------------------- /go/local_program/app/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/go/local_program/app 2 | 3 | go 1.14 4 | 5 | require github.com/gorilla/mux v1.8.0 6 | -------------------------------------------------------------------------------- /go/local_program/app/go.sum: -------------------------------------------------------------------------------- 1 | github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= 2 | github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= 3 | -------------------------------------------------------------------------------- /go/local_program/app/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "math/rand" 7 | "net/http" 8 | "time" 9 | 10 | "github.com/gorilla/mux" 11 | ) 12 | 13 | func main() { 14 | r := mux.NewRouter() 15 | handler := func(w http.ResponseWriter, r *http.Request) { 16 | rand.Seed(time.Now().UnixNano()) 17 | fmt.Fprintf(w, "%d", rand.Intn(100)) 18 | } 19 | r.HandleFunc("/", handler) 20 | s := &http.Server{ 21 | Addr: ":80", 22 | Handler: r, 23 | } 24 | log.Fatal(s.ListenAndServe()) 25 | } 26 | -------------------------------------------------------------------------------- /go/local_program/automation/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/go/local_program/automation 2 | 3 | go 1.14 4 | 5 | require github.com/pulumi/pulumi/sdk/v3 v3.0.0 6 | -------------------------------------------------------------------------------- /go/local_program/automation/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "path/filepath" 8 | 9 | "github.com/pulumi/pulumi/sdk/v3/go/auto" 10 | "github.com/pulumi/pulumi/sdk/v3/go/auto/optdestroy" 11 | "github.com/pulumi/pulumi/sdk/v3/go/auto/optup" 12 | ) 13 | 14 | func main() { 15 | // to destroy our program, we can run `go run main.go destroy` 16 | destroy := false 17 | argsWithoutProg := os.Args[1:] 18 | if len(argsWithoutProg) > 0 { 19 | if argsWithoutProg[0] == "destroy" { 20 | destroy = true 21 | } 22 | } 23 | ctx := context.Background() 24 | 25 | // we use a simple stack name here, but recommend using auto.FullyQualifiedStackName for maximum specificity. 26 | stackName := "dev" 27 | // stackName := auto.FullyQualifiedStackName("myOrgOrUser", projectName, stackName) 28 | 29 | // in this example our automation driver is being added to an exising local Pulumi project. 30 | // we'll create/select a stack from the working directory that contains our "fargate" CLI program. 31 | // this program creates an ecs cluster, an erc registry, builds and uploads the docker image in 32 | // ../app, creates a fargate task, and exposes it behind a load balancer. 33 | workDir := filepath.Join("..", "fargate") 34 | 35 | // create or select a stack from a local workspace with CLI program, using the ../fargate workDir. 36 | // the Pulumi program, and any project or stack settings will be used by our stack. 37 | s, err := auto.UpsertStackLocalSource(ctx, stackName, workDir) 38 | if err != nil { 39 | fmt.Printf("Failed to create or select stack: %v\n", err) 40 | os.Exit(1) 41 | } 42 | 43 | fmt.Printf("Created/Selected stack %q\n", stackName) 44 | 45 | // set stack configuration specifying the AWS region to deploy 46 | s.SetConfig(ctx, "aws:region", auto.ConfigValue{Value: "us-west-2"}) 47 | 48 | fmt.Println("Successfully set config") 49 | fmt.Println("Starting refresh") 50 | 51 | _, err = s.Refresh(ctx) 52 | if err != nil { 53 | fmt.Printf("Failed to refresh stack: %v\n", err) 54 | os.Exit(1) 55 | } 56 | 57 | fmt.Println("Refresh succeeded!") 58 | 59 | if destroy { 60 | fmt.Println("Starting stack destroy") 61 | // wire up our destroy to stream progress to stdout 62 | stdoutStreamer := optdestroy.ProgressStreams(os.Stdout) 63 | // destroy our stack and exit early 64 | _, err := s.Destroy(ctx, stdoutStreamer) 65 | if err != nil { 66 | fmt.Printf("Failed to destroy stack: %v", err) 67 | } 68 | fmt.Println("Stack successfully destroyed") 69 | os.Exit(0) 70 | } 71 | 72 | fmt.Println("Starting update") 73 | 74 | // wire up our update to stream progress to stdout 75 | stdoutStreamer := optup.ProgressStreams(os.Stdout) 76 | 77 | // run the update to deploy our fargate web service 78 | res, err := s.Up(ctx, stdoutStreamer) 79 | if err != nil { 80 | fmt.Printf("Failed to update stack: %v\n\n", err) 81 | os.Exit(1) 82 | } 83 | 84 | fmt.Println("Update succeeded!") 85 | 86 | // get the URL from the stack outputs 87 | url, ok := res.Outputs["url"].Value.(string) 88 | if !ok { 89 | fmt.Println("Failed to unmarshall output URL") 90 | os.Exit(1) 91 | } 92 | 93 | fmt.Printf("URL: %s\n", url) 94 | } 95 | -------------------------------------------------------------------------------- /go/local_program/fargate/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: fargate 2 | runtime: go 3 | description: An end-to-end AWS ECS Fargate infrastructure as code project. 4 | -------------------------------------------------------------------------------- /go/local_program/fargate/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/go/local_program/fargate 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/pulumi/pulumi-aws/sdk/v4 v4.0.0 7 | github.com/pulumi/pulumi-docker/sdk/v3 v3.0.0 8 | github.com/pulumi/pulumi/sdk/v3 v3.0.0 9 | ) 10 | -------------------------------------------------------------------------------- /go/multi_stack_orchestration/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/go/multi_stack_orchestration 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/pulumi/pulumi-aws/sdk/v4 v4.0.0 7 | github.com/pulumi/pulumi/sdk/v3 v3.0.0 8 | ) 9 | -------------------------------------------------------------------------------- /go/pulumi_over_http/README.md: -------------------------------------------------------------------------------- 1 | # Pulumi Over HTTP - Static Websites as a RESTful API 2 | 3 | This application demonstrates how to run Automation API in an HTTP server to expose infrastructure as RESTful resources. In our case, we've defined and exposed a static website `site` that exposes all of the `CRUD` operations plus list. Users can hit our REST endpoint and create custom static websites by specifying the `content` field in the `POST` body. All of our infrastructure is defined in `inline` programs that are constructed and altered on the fly based on input parsed from user-specified `POST` bodies. Be sure to read through the handlers to see how Automation API detect structured error cases such as update conflicts (409), and missing stacks (404). 4 | 5 | To run this example you'll need a few pre-reqs: 6 | 1. A Pulumi CLI installation ([v3.0.0](https://www.pulumi.com/docs/get-started/install/versions/) or later) 7 | 2. The AWS CLI, with appropriate credentials. 8 | 9 | In one terminal window, run the HTTP server that uses Automation API. It will also stream update logs: 10 | 11 | ```bash 12 | $ go run main.go 13 | starting server on :1337 14 | 15 | Updating (hello) 16 | 17 | View Live: https://app.pulumi.com/EvanBoyle/pulumi_over_http/hello/updates/1 18 | 19 | 20 | + pulumi:pulumi:Stack pulumi_over_http-hello creating 21 | + aws:s3:Bucket s3-website-bucket creating 22 | + aws:s3:Bucket s3-website-bucket created 23 | + aws:s3:BucketObject index creating 24 | + aws:s3:BucketPolicy bucketPolicy creating 25 | + aws:s3:BucketObject index created 26 | + aws:s3:BucketPolicy bucketPolicy created 27 | + pulumi:pulumi:Stack pulumi_over_http-hello created 28 | 29 | Outputs: 30 | websiteUrl: "s3-website-bucket-549d9d3.s3-website-us-west-2.amazonaws.com" 31 | 32 | Resources: 33 | + 4 created 34 | 35 | Duration: 6s 36 | ``` 37 | 38 | Open another terminal window to execute some `curl` commands and create some sites: 39 | 40 | ```bash 41 | # create "hello" site 42 | $ curl --header "Content-Type: application/json" --request POST --data '{"id":"hello","content":"hello world\n"}' http://localhost:1337/sites 43 | {"id":"hello","url":"s3-website-bucket-549d9d3.s3-website-us-west-2.amazonaws.com"} 44 | # curl our "hello" site 45 | $ curl s3-website-bucket-549d9d3.s3-website-us-west-2.amazonaws.com 46 | hello world 47 | # update our "hello" site content 48 | $ curl --header "Content-Type: application/json" --request PUT --data '{"id":"hello","content":"hello updated world!\n"}' http://localhost:1337/sites/hello 49 | {"id":"hello","url":"s3-website-bucket-549d9d3.s3-website-us-west-2.amazonaws.com"} 50 | # curl our update hello site 51 | $ curl s3-website-bucket-549d9d3.s3-website-us-west-2.amazonaws.com 52 | hello updated world! 53 | # add a "bye" site 54 | $ curl --header "Content-Type: application/json" --request POST --data '{"id":"bye","content":"good bye world\n"}' http://localhost:1337/sites 55 | {"id":"bye","url":"s3-website-bucket-2eaf3da.s3-website-us-west-2.amazonaws.com"} 56 | # curl our "bye" site 57 | $ curl s3-website-bucket-2eaf3da.s3-website-us-west-2.amazonaws.com 58 | good bye world 59 | # list our sites 60 | $ curl http://localhost:1337/sites 61 | {"ids":["bye","hello"]} 62 | # get the URL of a specific site 63 | $ curl http://localhost:1337/sites/hello 64 | {"id":"hello","url":"s3-website-bucket-549d9d3.s3-website-us-west-2.amazonaws.com"} 65 | # delete our "bye" site 66 | $ curl --header "Content-Type: application/json" --request DELETE http://localhost:1337/sites/bye 67 | # list sites again and see it's gone 68 | $ curl http://localhost:1337/sites 69 | {"ids":["hello"]} 70 | ``` 71 | -------------------------------------------------------------------------------- /go/pulumi_over_http/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/go/pulumi_over_http 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/gorilla/mux v1.8.0 // indirect 7 | github.com/pulumi/pulumi-aws/sdk/v4 v4.0.0 8 | github.com/pulumi/pulumi/sdk/v3 v3.0.0 9 | ) 10 | -------------------------------------------------------------------------------- /go/remote_deployment/README.md: -------------------------------------------------------------------------------- 1 | # Remote Deployment 2 | 3 | This program demonstrates how to use Automation API to run Pulumi programs remotely with Pulumi Deployments on Pulumi service hardware (api.pulumi.com). This example deploys the [aws-ts-s3-folder project from the Pulumi examples repo](https://github.com/pulumi/examples/tree/master/aws-ts-s3-folder). 4 | 5 | To run this example you'll need a few pre-reqs: 6 | 7 | 1. A Pulumi CLI installation ([v3.45.0](https://www.pulumi.com/docs/get-started/install/versions/) or later), logged in to the Pulumi service via `pulumi login`. 8 | 2. AWS environment variables for AWS credentials (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN`). [Learn more](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html?icmpid=docs_sso_user_portal). 9 | 10 | Running this program is just like any other Go program. No invocation through the Pulumi CLI required: 11 | 12 | ```shell 13 | $ go run main.goHello, world!
\n" + 46 | "Made with ❤️ with Pulumi
\n" + 47 | " \n" + 48 | ""; 49 | 50 | var indexHtml = new BucketObject("index.html", BucketObjectArgs.builder() 51 | .bucket(siteBucket.id()) 52 | .content(indexContent) 53 | .contentType("text/html") 54 | .acl("public-read") 55 | .build(), 56 | CustomResourceOptions.builder() 57 | .dependsOn( 58 | publicAccessBlock, 59 | ownershipControls, 60 | website) 61 | .build()); 62 | 63 | // Export the name of the bucket 64 | ctx.export("website_url", 65 | website.websiteEndpoint().applyValue(websiteEndpoint -> String.format("http://%s", websiteEndpoint))); 66 | }); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /nodejs/crossLanguage-tsnode/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | yarn.lock -------------------------------------------------------------------------------- /nodejs/crossLanguage-tsnode/app/Dockerfile: -------------------------------------------------------------------------------- 1 | # Start from a Debian image with the latest version of Go installed 2 | # and a workspace (GOPATH) configured at /go. 3 | FROM golang 4 | 5 | # Copy the local package files to the container's workspace. 6 | ADD . /go/src/foo 7 | 8 | # Build the outyet command inside the container. 9 | # (You may fetch or manage dependencies here, 10 | # either manually or with a tool like "godep".) 11 | WORKDIR /go/src/foo 12 | RUN go build -o /go/bin/main 13 | 14 | # Run the outyet command by default when the container starts. 15 | ENTRYPOINT /go/bin/main 16 | 17 | # Document that the service listens on port 80. 18 | EXPOSE 80 -------------------------------------------------------------------------------- /nodejs/crossLanguage-tsnode/app/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/nodejs/crossLanguage-tsnode/app 2 | 3 | go 1.14 4 | 5 | require github.com/gorilla/mux v1.8.0 6 | -------------------------------------------------------------------------------- /nodejs/crossLanguage-tsnode/app/go.sum: -------------------------------------------------------------------------------- 1 | github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= 2 | github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= 3 | -------------------------------------------------------------------------------- /nodejs/crossLanguage-tsnode/app/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "math/rand" 7 | "net/http" 8 | "time" 9 | 10 | "github.com/gorilla/mux" 11 | ) 12 | 13 | func main() { 14 | r := mux.NewRouter() 15 | handler := func(w http.ResponseWriter, r *http.Request) { 16 | rand.Seed(time.Now().UnixNano()) 17 | fmt.Fprintf(w, "%d", rand.Intn(100)) 18 | } 19 | r.HandleFunc("/", handler) 20 | s := &http.Server{ 21 | Addr: ":80", 22 | Handler: r, 23 | } 24 | log.Fatal(s.ListenAndServe()) 25 | } 26 | -------------------------------------------------------------------------------- /nodejs/crossLanguage-tsnode/automation/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Automation API - Debug - index.ts", 6 | "type": "node", 7 | "request": "launch", 8 | "cwd": "${workspaceRoot}", 9 | "runtimeArgs": ["-r", "ts-node/register"], 10 | "args": ["${workspaceRoot}/index.ts"] 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /nodejs/crossLanguage-tsnode/automation/index.ts: -------------------------------------------------------------------------------- 1 | import { LocalProgramArgs, LocalWorkspace } from "@pulumi/pulumi/automation"; 2 | import * as upath from "upath"; 3 | 4 | const process = require('process'); 5 | 6 | const args = process.argv.slice(2); 7 | let destroy = false; 8 | if (args.length > 0 && args[0]) { 9 | destroy = args[0] === "destroy"; 10 | } 11 | 12 | const run = async () => { 13 | 14 | 15 | // Create our stack using a local program 16 | // in the ../fargate directory 17 | const args: LocalProgramArgs = { 18 | stackName: "dev", 19 | workDir: upath.joinSafe(__dirname, "..", "fargate"), 20 | }; 21 | 22 | // create (or select if one already exists) a stack that uses our local program 23 | const stack = await LocalWorkspace.createOrSelectStack(args); 24 | 25 | console.info("successfully initialized stack"); 26 | console.info("setting up config"); 27 | await stack.setConfig("aws:region", { value: "us-west-2" }); 28 | console.info("config set"); 29 | console.info("refreshing stack..."); 30 | await stack.refresh({ onOutput: console.info }); 31 | console.info("refresh complete"); 32 | 33 | if (destroy) { 34 | console.info("destroying stack..."); 35 | await stack.destroy({onOutput: console.info}); 36 | console.info("stack destroy complete"); 37 | process.exit(0); 38 | } 39 | 40 | console.info("updating stack..."); 41 | const upRes = await stack.up({ onOutput: console.info }); 42 | console.log(`update summary: \n${JSON.stringify(upRes.summary.resourceChanges, null, 4)}`); 43 | console.log(`website url: ${upRes.outputs.url.value}`); 44 | }; 45 | 46 | run().catch(err => console.log(err)); 47 | -------------------------------------------------------------------------------- /nodejs/crossLanguage-tsnode/automation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.ts", 3 | "repository": "github.com/pulumi/automation-api-examples", 4 | "author": "EvanBoyle", 5 | "license": "MIT", 6 | "dependencies": { 7 | "@pulumi/aws": "^4.0.0", 8 | "@pulumi/pulumi": "^3.0.0", 9 | "@types/node": "^14.11.7", 10 | "ts-node": "^9.0.0", 11 | "upath": "^2.0.0" 12 | }, 13 | "scripts": { 14 | "start": "./node_modules/ts-node/dist/bin.js index.ts" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /nodejs/crossLanguage-tsnode/fargate/Pulumi.dev.yaml: -------------------------------------------------------------------------------- 1 | config: 2 | aws:region: us-west-2 3 | -------------------------------------------------------------------------------- /nodejs/crossLanguage-tsnode/fargate/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: fargate 2 | runtime: go 3 | description: An end-to-end AWS ECS Fargate infrastructure as code project. 4 | -------------------------------------------------------------------------------- /nodejs/crossLanguage-tsnode/fargate/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/nodejs/crossLanguage-tsnode/fargate 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/pulumi/pulumi-aws/sdk/v4 v4.0.0 7 | github.com/pulumi/pulumi-docker/sdk/v3 v3.0.0 8 | github.com/pulumi/pulumi/sdk/v3 v3.0.0 9 | ) 10 | -------------------------------------------------------------------------------- /nodejs/databaseMigration-ts/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bin 3 | package-lock.json 4 | yarn.lock -------------------------------------------------------------------------------- /nodejs/databaseMigration-ts/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Automation API - debug - index.ts", 11 | "program": "${workspaceFolder}/index.ts", 12 | "preLaunchTask": "tsc: build - tsconfig.json", 13 | "outFiles": ["${workspaceFolder}/bin/index.js"] 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /nodejs/databaseMigration-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "./bin/index.js", 3 | "repository": "github.com/pulumi/automation-api-examples", 4 | "author": "EvanBoyle", 5 | "license": "MIT", 6 | "dependencies": { 7 | "@pulumi/aws": "^4.0.0", 8 | "@pulumi/awsx": "^0.20.0", 9 | "@pulumi/pulumi": "^3.0.0", 10 | "@types/mysql": "^2.15.15", 11 | "@types/node": "^14.11.7", 12 | "mysql": "^2.18.1", 13 | "typescript": "^3.1.3" 14 | }, 15 | "scripts": { 16 | "build": "tsc", 17 | "start": "tsc && node ./bin/index.js" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /nodejs/databaseMigration-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es2016", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "declaration": true, 8 | "sourceMap": true, 9 | }, 10 | } -------------------------------------------------------------------------------- /nodejs/inlineProgram-js/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bin 3 | package-lock.json 4 | yarn.lock -------------------------------------------------------------------------------- /nodejs/inlineProgram-js/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Automation API - debug - index.ts", 11 | "program": "${workspaceFolder}/index.js", 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /nodejs/inlineProgram-js/index.js: -------------------------------------------------------------------------------- 1 | const auto = require("@pulumi/pulumi/automation"); 2 | const aws = require("@pulumi/aws"); 3 | const process = require('process'); 4 | 5 | const args = process.argv.slice(2); 6 | let destroy = false; 7 | if (args.length > 0 && args[0]) { 8 | destroy = args[0] === "destroy"; 9 | } 10 | 11 | const run = async () => { 12 | // This is our pulumi program in "inline function" form 13 | const pulumiProgram = async () => { 14 | // Create a bucket and expose a website index document 15 | const siteBucket = new aws.s3.Bucket("s3-website-bucket", { 16 | website: { 17 | indexDocument: "index.html", 18 | }, 19 | }); 20 | const indexContent = ` 21 |Hello, world!
Made with ❤️ with Pulumi
24 | 25 | ` 26 | // write our index.html into the site bucket 27 | let object = new aws.s3.BucketObject("index", { 28 | bucket: siteBucket, 29 | content: indexContent, 30 | contentType: "text/html; charset=utf-8", 31 | key: "index.html" 32 | }); 33 | 34 | // Create an S3 Bucket Policy to allow public read of all objects in bucket 35 | function publicReadPolicyForBucket(bucketName) { 36 | return { 37 | Version: "2012-10-17", 38 | Statement: [{ 39 | Effect: "Allow", 40 | Principal: "*", 41 | Action: [ 42 | "s3:GetObject" 43 | ], 44 | Resource: [ 45 | `arn:aws:s3:::${bucketName}/*` // policy refers to bucket name explicitly 46 | ] 47 | }] 48 | }; 49 | } 50 | 51 | // Set the access policy for the bucket so all objects are readable 52 | let bucketPolicy = new aws.s3.BucketPolicy("bucketPolicy", { 53 | bucket: siteBucket.bucket, // refer to the bucket created earlier 54 | policy: siteBucket.bucket.apply(publicReadPolicyForBucket) // use output property `siteBucket.bucket` 55 | }); 56 | 57 | return { 58 | websiteUrl: siteBucket.websiteEndpoint, 59 | }; 60 | }; 61 | 62 | // Create our stack 63 | const args = { 64 | stackName: "dev", 65 | projectName: "inlineNode", 66 | program: pulumiProgram 67 | }; 68 | 69 | // create (or select if one already exists) a stack that uses our inline program 70 | const stack = await auto.LocalWorkspace.createOrSelectStack(args); 71 | 72 | console.info("successfully initialized stack"); 73 | console.info("installing plugins..."); 74 | await stack.workspace.installPlugin("aws", "v4.0.0"); 75 | console.info("plugins installed"); 76 | console.info("setting up config"); 77 | await stack.setConfig("aws:region", { value: "us-west-2" }); 78 | console.info("config set"); 79 | console.info("refreshing stack..."); 80 | await stack.refresh({ onOutput: console.info }); 81 | console.info("refresh complete"); 82 | 83 | if (destroy) { 84 | console.info("destroying stack..."); 85 | await stack.destroy({ onOutput: console.info }); 86 | console.info("stack destroy complete"); 87 | process.exit(0); 88 | } 89 | 90 | console.info("updating stack..."); 91 | const upRes = await stack.up({ onOutput: console.info }); 92 | console.info(`update summary: \n${JSON.stringify(upRes.summary.resourceChanges, null, 4)}`); 93 | console.info(`website url: ${upRes.outputs.websiteUrl.value}`); 94 | }; 95 | 96 | run().catch(err => console.log(err)); 97 | -------------------------------------------------------------------------------- /nodejs/inlineProgram-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.js", 3 | "type": "commonjs", 4 | "repository": "github.com/pulumi/automation-api-examples", 5 | "author": "EvanBoyle", 6 | "license": "MIT", 7 | "dependencies": { 8 | "@pulumi/aws": "^4.0.0", 9 | "@pulumi/pulumi": "^3.0.0" 10 | }, 11 | "scripts": { 12 | "start": "node index.js" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /nodejs/inlineProgram-ts/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bin 3 | package-lock.json 4 | yarn.lock -------------------------------------------------------------------------------- /nodejs/inlineProgram-ts/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Automation API - debug - index.ts", 11 | "program": "${workspaceFolder}/index.ts", 12 | "preLaunchTask": "tsc: build - tsconfig.json", 13 | "outFiles": ["${workspaceFolder}/bin/index.js"] 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /nodejs/inlineProgram-ts/index.ts: -------------------------------------------------------------------------------- 1 | import { InlineProgramArgs, LocalWorkspace } from "@pulumi/pulumi/automation"; 2 | import { s3 } from "@pulumi/aws"; 3 | import { PolicyDocument } from "@pulumi/aws/iam"; 4 | 5 | const process = require('process'); 6 | 7 | const args = process.argv.slice(2); 8 | let destroy = false; 9 | if (args.length > 0 && args[0]) { 10 | destroy = args[0] === "destroy"; 11 | } 12 | 13 | const run = async () => { 14 | // This is our pulumi program in "inline function" form 15 | const pulumiProgram = async () => { 16 | // Create a bucket and expose a website index document 17 | const siteBucket = new s3.Bucket("s3-website-bucket", { 18 | website: { 19 | indexDocument: "index.html", 20 | }, 21 | }); 22 | const indexContent = ` 23 |Hello, world!
Made with ❤️ with Pulumi
26 | 27 | ` 28 | 29 | // write our index.html into the site bucket 30 | let object = new s3.BucketObject("index", { 31 | bucket: siteBucket, 32 | content: indexContent, 33 | contentType: "text/html; charset=utf-8", 34 | key: "index.html" 35 | }); 36 | 37 | // Create an S3 Bucket Policy to allow public read of all objects in bucket 38 | function publicReadPolicyForBucket(bucketName): PolicyDocument { 39 | return { 40 | Version: "2012-10-17", 41 | Statement: [{ 42 | Effect: "Allow", 43 | Principal: "*", 44 | Action: [ 45 | "s3:GetObject" 46 | ], 47 | Resource: [ 48 | `arn:aws:s3:::${bucketName}/*` // policy refers to bucket name explicitly 49 | ] 50 | }] 51 | }; 52 | } 53 | 54 | // Set the access policy for the bucket so all objects are readable 55 | let bucketPolicy = new s3.BucketPolicy("bucketPolicy", { 56 | bucket: siteBucket.bucket, // refer to the bucket created earlier 57 | policy: siteBucket.bucket.apply(publicReadPolicyForBucket) // use output property `siteBucket.bucket` 58 | }); 59 | 60 | return { 61 | websiteUrl: siteBucket.websiteEndpoint, 62 | }; 63 | }; 64 | 65 | // Create our stack 66 | const args: InlineProgramArgs = { 67 | stackName: "dev", 68 | projectName: "inlineNode", 69 | program: pulumiProgram 70 | }; 71 | 72 | // create (or select if one already exists) a stack that uses our inline program 73 | const stack = await LocalWorkspace.createOrSelectStack(args); 74 | 75 | console.info("successfully initialized stack"); 76 | console.info("installing plugins..."); 77 | await stack.workspace.installPlugin("aws", "v4.0.0"); 78 | console.info("plugins installed"); 79 | console.info("setting up config"); 80 | await stack.setConfig("aws:region", { value: "us-west-2" }); 81 | console.info("config set"); 82 | console.info("refreshing stack..."); 83 | await stack.refresh({ onOutput: console.info }); 84 | console.info("refresh complete"); 85 | 86 | if (destroy) { 87 | console.info("destroying stack..."); 88 | await stack.destroy({ onOutput: console.info }); 89 | console.info("stack destroy complete"); 90 | process.exit(0); 91 | } 92 | 93 | console.info("updating stack..."); 94 | const upRes = await stack.up({ onOutput: console.info }); 95 | console.log(`update summary: \n${JSON.stringify(upRes.summary.resourceChanges, null, 4)}`); 96 | console.log(`website url: ${upRes.outputs.websiteUrl.value}`); 97 | }; 98 | 99 | run().catch(err => console.log(err)); -------------------------------------------------------------------------------- /nodejs/inlineProgram-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "./bin/index.js", 3 | "repository": "github.com/pulumi/automation-api-examples", 4 | "author": "EvanBoyle", 5 | "license": "MIT", 6 | "dependencies": { 7 | "@pulumi/aws": "^4.0.0", 8 | "@pulumi/pulumi": "^3.0.0", 9 | "@types/node": "^14.11.7" 10 | }, 11 | "scripts": { 12 | "build": "tsc", 13 | "start": "tsc && node ./bin/index.js" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /nodejs/inlineProgram-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es2016", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "declaration": true, 8 | "sourceMap": true, 9 | }, 10 | } -------------------------------------------------------------------------------- /nodejs/inlineProgram-tsnode/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | yarn.lock -------------------------------------------------------------------------------- /nodejs/inlineProgram-tsnode/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Automation API - Debug - index.ts", 6 | "type": "node", 7 | "request": "launch", 8 | "cwd": "${workspaceRoot}", 9 | "runtimeArgs": ["-r", "ts-node/register"], 10 | "args": ["${workspaceRoot}/index.ts"] 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /nodejs/inlineProgram-tsnode/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.ts", 3 | "repository": "github.com/pulumi/automation-api-examples", 4 | "author": "EvanBoyle", 5 | "license": "MIT", 6 | "dependencies": { 7 | "@pulumi/aws": "^4.0.0", 8 | "@pulumi/pulumi": "^3.0.0", 9 | "@types/node": "^14.11.7", 10 | "ts-node": "^9.0.0" 11 | }, 12 | "scripts": { 13 | "start": "./node_modules/ts-node/dist/bin.js index.ts" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /nodejs/inlineSecretsProvider-ts/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bin 3 | package-lock.json 4 | yarn.lock -------------------------------------------------------------------------------- /nodejs/inlineSecretsProvider-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "./bin/index.js", 3 | "repository": "github.com/pulumi/automation-api-examples", 4 | "author": "EvanBoyle", 5 | "license": "MIT", 6 | "dependencies": { 7 | "@pulumi/aws": "^4.0.0", 8 | "@pulumi/pulumi": "^3.0.0", 9 | "@types/node": "^14.11.7" 10 | }, 11 | "scripts": { 12 | "build": "tsc", 13 | "start": "tsc && node ./bin/index.js" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /nodejs/inlineSecretsProvider-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es2016", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "declaration": true, 8 | "sourceMap": true, 9 | }, 10 | } -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode-mochatests/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | yarn.lock -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode-mochatests/README.md: -------------------------------------------------------------------------------- 1 | # Deploy a S3 website using Automation API 2 | 3 | ## Requirements 4 | 5 | 1. Pulumi CLI installed ([v3.0.0](https://www.pulumi.com/docs/get-started/install/versions/) or later) 6 | 1. AWS CLI with appropriate credentials set up 7 | 8 | ## To run tests 9 | 10 | 1. `npm install` 11 | 1. `npm test` 12 | 13 | ## To run Pulumi code 14 | 15 | 1. `cd infrastructure` 16 | 1. `npm install` 17 | 1. `pulumi up` 18 | 19 | ## To destroy stack 20 | 21 | The tests will destroy the infrastructure once all the tests are complete but you can run `cd infrastructure && pulumi destroy` as well 22 | 23 | ## Delete the stack 24 | 25 | Automation API currently doesn't allow for stack deletion so you'll have to run `cd infrastructure && pulumi stack rm dev` 26 | -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode-mochatests/automation.ts: -------------------------------------------------------------------------------- 1 | import { 2 | LocalProgramArgs, 3 | LocalWorkspace, 4 | OutputMap 5 | } from "@pulumi/pulumi/automation"; 6 | import * as upath from "upath"; 7 | 8 | const args: LocalProgramArgs = { 9 | stackName: "dev", 10 | workDir: upath.joinSafe(__dirname, ".", "infrastructure"), 11 | }; 12 | 13 | export async function deploy(): PromiseHello, world!
Made with ❤️ with Pulumi
15 | 16 | `; 17 | 18 | // Upload the HTML content to the bucket 19 | new aws.s3.BucketObject("index-html", { 20 | bucket: bucket, 21 | content: indexContent, 22 | contentType: "text/html; charset=utf-8", 23 | key: "index.html" 24 | }); 25 | 26 | // Create an S3 Bucket Policy to allow public read of all objects in bucket 27 | function publicReadPolicyForBucket(bucketName: string): aws.iam.PolicyDocument { 28 | return { 29 | Version: "2012-10-17", 30 | Statement: [ 31 | { 32 | Effect: "Allow", 33 | Principal: "*", 34 | Action: ["s3:GetObject"], 35 | Resource: [ 36 | `arn:aws:s3:::${bucketName}/*`, // policy refers to bucket name explicitly 37 | ], 38 | }, 39 | ], 40 | }; 41 | } 42 | 43 | // Set the access policy for the bucket so all objects are readable 44 | let bucketPolicy = new aws.s3.BucketPolicy("bucketPolicy", { 45 | bucket: bucket.bucket, // refer to the bucket created earlier 46 | policy: bucket.bucket.apply(publicReadPolicyForBucket), // use output property `siteBucket.bucket`, 47 | }); 48 | 49 | export const url = pulumi.interpolate`${bucket.websiteEndpoint}/index.html`; -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode-mochatests/infrastructure/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "automationS3website", 3 | "devDependencies": { 4 | "@types/node": "^10.0.0" 5 | }, 6 | "dependencies": { 7 | "@pulumi/aws": "^4.0.0", 8 | "@pulumi/awsx": "^0.30.0", 9 | "@pulumi/pulumi": "^3.0.0" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode-mochatests/infrastructure/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "outDir": "bin", 5 | "target": "es2016", 6 | "module": "commonjs", 7 | "moduleResolution": "node", 8 | "sourceMap": true, 9 | "experimentalDecorators": true, 10 | "pretty": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "noImplicitReturns": true, 13 | "forceConsistentCasingInFileNames": true 14 | }, 15 | "files": [ 16 | "index.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode-mochatests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "", 3 | "main": "index.ts", 4 | "scripts": { 5 | "start": "./node_modules/ts-node/dist/bin.js index.ts", 6 | "test": "./node_modules/mocha/bin/mocha --timeout=120000 -r ts-node/register ./test.ts" 7 | }, 8 | "author": "", 9 | "license": "ISC", 10 | "dependencies": { 11 | "@pulumi/aws": "^4.0.0", 12 | "@pulumi/awsx": "^0.22.0", 13 | "@pulumi/pulumi": "^3.0.0" 14 | }, 15 | "devDependencies": { 16 | "@types/chai": "^4.2.14", 17 | "@types/mocha": "^8.2.0", 18 | "chai": "^4.2.0", 19 | "cheerio": "^1.0.0-rc.5", 20 | "mocha": "^8.2.1", 21 | "superagent": "^6.1.0", 22 | "ts-node": "^7.0.1" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode-mochatests/test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | import * as automation from "./automation"; 3 | import * as superagent from "superagent"; 4 | import * as cheerio from "cheerio"; 5 | 6 | before(async () => { 7 | await automation.deploy(); 8 | }); 9 | 10 | after(async () => { 11 | await automation.destroy(); 12 | }); 13 | 14 | describe("Test infrastructure deployment", () => { 15 | it("should return correct html", async () => { 16 | await automation 17 | .getOutputs() 18 | .then((result) => result.url.value) 19 | .then((url) => { 20 | expect(url).to.be.a("string"); 21 | return superagent.get(url); 22 | }) 23 | .then((response) => response.text) 24 | .then((html) => { 25 | const $ = cheerio.load(html); 26 | expect($("title").text()).to.equal("Hello S3"); 27 | }); 28 | }); 29 | 30 | it("should not return a 404", async () => { 31 | await automation 32 | .getOutputs() 33 | .then((result) => result.url.value) 34 | .then((url) => { 35 | expect(url).to.be.a("string"); 36 | return superagent.get(url); 37 | }) 38 | .then((response) => response.statusCode) 39 | .then((statusCode) => { 40 | expect(statusCode).to.equal(200); 41 | }); 42 | }) 43 | }); -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | yarn.lock -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode/automation/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Automation API - Debug - index.ts", 6 | "type": "node", 7 | "request": "launch", 8 | "cwd": "${workspaceRoot}", 9 | "runtimeArgs": ["-r", "ts-node/register"], 10 | "args": ["${workspaceRoot}/index.ts"] 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode/automation/index.ts: -------------------------------------------------------------------------------- 1 | import { LocalProgramArgs, LocalWorkspace } from "@pulumi/pulumi/automation"; 2 | import * as upath from "upath"; 3 | 4 | const process = require('process'); 5 | 6 | const args = process.argv.slice(2); 7 | let destroy = false; 8 | if (args.length > 0 && args[0]) { 9 | destroy = args[0] === "destroy"; 10 | } 11 | 12 | const run = async () => { 13 | 14 | 15 | // Create our stack using a local program 16 | // in the ../website directory 17 | const args: LocalProgramArgs = { 18 | stackName: "dev", 19 | workDir: upath.joinSafe(__dirname, "..", "website"), 20 | }; 21 | 22 | // create (or select if one already exists) a stack that uses our local program 23 | const stack = await LocalWorkspace.createOrSelectStack(args); 24 | 25 | console.info("successfully initialized stack"); 26 | console.info("setting up config"); 27 | await stack.setConfig("aws:region", { value: "us-west-2" }); 28 | console.info("config set"); 29 | console.info("refreshing stack..."); 30 | await stack.refresh({ onOutput: console.info }); 31 | console.info("refresh complete"); 32 | 33 | if (destroy) { 34 | console.info("destroying stack..."); 35 | await stack.destroy({onOutput: console.info}); 36 | console.info("stack destroy complete"); 37 | process.exit(0); 38 | } 39 | 40 | console.info("updating stack..."); 41 | const upRes = await stack.up({ onOutput: console.info }); 42 | console.log(`update summary: \n${JSON.stringify(upRes.summary.resourceChanges, null, 4)}`); 43 | console.log(`website url: ${upRes.outputs.websiteUrl.value}`); 44 | }; 45 | 46 | run(); 47 | 48 | -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode/automation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "automation", 3 | "version": "1.0.0", 4 | "main": "index.ts", 5 | "repository": "github.com/pulumi/automation-api-examples", 6 | "author": "EvanBoyle", 7 | "license": "MIT", 8 | "dependencies": { 9 | "@pulumi/aws": "^4.0.0", 10 | "@pulumi/pulumi": "^3.0.0", 11 | "@types/node": "^14.11.7", 12 | "ts-node": "^9.0.0", 13 | "upath": "^2.0.0" 14 | }, 15 | "scripts": { 16 | "start": "./node_modules/ts-node/dist/bin.js index.ts" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode/website/.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /node_modules/ 3 | -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode/website/Pulumi.dev.yaml: -------------------------------------------------------------------------------- 1 | config: 2 | aws:region: us-west-2 3 | -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode/website/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: website 2 | runtime: nodejs 3 | description: A Pulumi AWS TS program that deploys a static website. 4 | -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode/website/index.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from "@pulumi/pulumi"; 2 | import * as aws from "@pulumi/aws"; 3 | import { PolicyDocument } from "@pulumi/aws/iam"; 4 | 5 | 6 | // Create a bucket and expose a website index document 7 | const siteBucket = new aws.s3.Bucket("s3-website-bucket", { 8 | website: { 9 | indexDocument: "index.html", 10 | }, 11 | }); 12 | 13 | // Configure ownership controls for the new S3 bucket 14 | const ownershipControls = new aws.s3.BucketOwnershipControls("ownership-controls", { 15 | bucket: siteBucket.bucket, 16 | rule: { 17 | objectOwnership: "ObjectWriter", 18 | }, 19 | }); 20 | 21 | // Configure public ACL block on the new S3 bucket 22 | const publicAccessBlock = new aws.s3.BucketPublicAccessBlock("public-access-block", { 23 | bucket: siteBucket.bucket, 24 | blockPublicAcls: false, 25 | }); 26 | 27 | const indexContent = ` 28 |Hello, world!
Made with ❤️ with Pulumi
31 | 32 | ` 33 | 34 | // write our index.html into the site bucket 35 | let object = new aws.s3.BucketObject("index", { 36 | acl: "public-read", 37 | bucket: siteBucket, 38 | content: indexContent, 39 | contentType: "text/html; charset=utf-8", 40 | key: "index.html" 41 | }, { 42 | dependsOn: [ownershipControls, publicAccessBlock] 43 | }); 44 | 45 | export const websiteUrl = siteBucket.websiteEndpoint; 46 | -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode/website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "website", 3 | "devDependencies": { 4 | "@types/node": "^10.0.0" 5 | }, 6 | "dependencies": { 7 | "@pulumi/pulumi": "^3.0.0", 8 | "@pulumi/aws": "^6.0.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode/website/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "outDir": "bin", 5 | "target": "es2016", 6 | "module": "commonjs", 7 | "moduleResolution": "node", 8 | "sourceMap": true, 9 | "experimentalDecorators": true, 10 | "pretty": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "noImplicitReturns": true, 13 | "forceConsistentCasingInFileNames": true 14 | }, 15 | "files": [ 16 | "index.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /nodejs/pulumiOverHttp-ts/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bin 3 | package-lock.json 4 | yarn.lock -------------------------------------------------------------------------------- /nodejs/pulumiOverHttp-ts/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Automation API - debug - index.ts", 11 | "program": "${workspaceFolder}/index.ts", 12 | "preLaunchTask": "tsc: build - tsconfig.json", 13 | "outFiles": ["${workspaceFolder}/bin/index.js"] 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /nodejs/pulumiOverHttp-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "./bin/index.js", 3 | "repository": "github.com/pulumi/automation-api-examples", 4 | "author": "EvanBoyle", 5 | "license": "MIT", 6 | "dependencies": { 7 | "@pulumi/aws": "^4.0.0", 8 | "@pulumi/pulumi": "^3.0.0", 9 | "@types/express": "^4.17.8", 10 | "@types/node": "^14.11.7", 11 | "express": "^4.17.1" 12 | }, 13 | "scripts": { 14 | "build": "tsc", 15 | "start": "tsc && node ./bin/index.js" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /nodejs/pulumiOverHttp-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "bin", 4 | "target": "es2016", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "declaration": true, 8 | "sourceMap": true, 9 | }, 10 | } -------------------------------------------------------------------------------- /nodejs/remoteDeployment-tsnode/.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /node_modules/ 3 | -------------------------------------------------------------------------------- /nodejs/remoteDeployment-tsnode/README.md: -------------------------------------------------------------------------------- 1 | # Remote Deployment 2 | 3 | This program demonstrates how to use Automation API to run Pulumi programs remotely with Pulumi Deployments on Pulumi service hardware (api.pulumi.com). This example deploys the [aws-ts-s3-folder project from the Pulumi examples repo](https://github.com/pulumi/examples/tree/master/aws-ts-s3-folder). 4 | 5 | To run this example you'll need a few pre-reqs: 6 | 7 | 1. A Pulumi CLI installation ([v3.45.0](https://www.pulumi.com/docs/get-started/install/versions/) or later), logged in to the Pulumi service via `pulumi login`. 8 | 2. AWS environment variables for AWS credentials (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN`). [Learn more](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html?icmpid=docs_sso_user_portal). 9 | 10 | To run our program, first install dependencies using `npm install` and then run: 11 | 12 | ```shell 13 | $ npm run startHello, world!
17 |Made with ❤️ with Pulumi
18 | 19 | 20 | """ 21 | 22 | # Write our index.html into the site bucket 23 | s3.BucketObject("index", 24 | bucket=site_bucket.id, # reference to the s3.Bucket object 25 | content=index_content, 26 | key="index.html", # set the key of the object 27 | content_type="text/html; charset=utf-8") # set the MIME type of the file 28 | 29 | # Allow public ACLs for the bucket 30 | public_access_block = s3.BucketPublicAccessBlock("exampleBucketPublicAccessBlock", 31 | bucket=site_bucket.id, 32 | block_public_acls=False, 33 | ) 34 | 35 | # Set the access policy for the bucket so all objects are readable 36 | s3.BucketPolicy("bucket-policy", bucket=site_bucket.id, policy=site_bucket.id.apply(lambda id: json.dumps({ 37 | "Version": "2012-10-17", 38 | "Statement": { 39 | "Effect": "Allow", 40 | "Principal": "*", 41 | "Action": ["s3:GetObject"], 42 | # Policy refers to bucket explicitly 43 | "Resource": [f"arn:aws:s3:::{id}/*"] 44 | }, 45 | })), opts=pulumi.ResourceOptions(depends_on=[public_access_block])) 46 | 47 | # Export the website URL 48 | pulumi.export("website_url", site_bucket.website_endpoint) 49 | 50 | 51 | # To destroy our program, we can run python main.py destroy 52 | destroy = False 53 | args = sys.argv[1:] 54 | if len(args) > 0: 55 | if args[0] == "destroy": 56 | destroy = True 57 | 58 | project_name = "inline_s3_project" 59 | # We use a simple stack name here, but recommend using auto.fully_qualified_stack_name for maximum specificity. 60 | stack_name = "dev" 61 | # stack_name = auto.fully_qualified_stack_name("myOrgOrUser", project_name, stack_name) 62 | 63 | # create or select a stack matching the specified name and project. 64 | # this will set up a workspace with everything necessary to run our inline program (pulumi_program) 65 | stack = auto.create_or_select_stack(stack_name=stack_name, 66 | project_name=project_name, 67 | program=pulumi_program) 68 | 69 | print("successfully initialized stack") 70 | 71 | # for inline programs, we must manage plugins ourselves 72 | print("installing plugins...") 73 | stack.workspace.install_plugin("aws", "v4.0.0") 74 | print("plugins installed") 75 | 76 | # set stack configuration specifying the AWS region to deploy 77 | print("setting up config") 78 | stack.set_config("aws:region", auto.ConfigValue(value="us-west-2")) 79 | print("config set") 80 | 81 | print("refreshing stack...") 82 | stack.refresh(on_output=print) 83 | print("refresh complete") 84 | 85 | if destroy: 86 | print("destroying stack...") 87 | stack.destroy(on_output=print) 88 | print("stack destroy complete") 89 | sys.exit() 90 | 91 | print("updating stack...") 92 | up_res = stack.up(on_output=print) 93 | print(f"update summary: \n{json.dumps(up_res.summary.resource_changes, indent=4)}") 94 | print(f"website url: {up_res.outputs['website_url'].value}") 95 | -------------------------------------------------------------------------------- /python/inline_program/requirements.txt: -------------------------------------------------------------------------------- 1 | pulumi>=3.0.0,<4.0.0 2 | pulumi-aws>=4.0.0,<5.0.0 3 | -------------------------------------------------------------------------------- /python/inline_secrets_provider/.gitignore: -------------------------------------------------------------------------------- 1 | venv 2 | -------------------------------------------------------------------------------- /python/inline_secrets_provider/README.md: -------------------------------------------------------------------------------- 1 | # Inline Program 2 | 3 | This program demonstrates how to use Automation API with an `inline` Pulumi program and custom secrets provider. This example builds on the basic example in `inline_program` 4 | but uses a local backend and custom secrets provider, which requires setting the configuration and re-using it on subsequent runs. 5 | 6 | To run this example you'll need a few pre-reqs: 7 | 1. A Pulumi CLI installation ([v3.0.0](https://www.pulumi.com/docs/get-started/install/versions/) or later) 8 | 2. The AWS CLI, with appropriate credentials. 9 | 3. An AWS KMS key, which you will replace for `secrets_provider = "awskms://aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee?region=us-west-2"` in `main.py` 10 | 4. Either have `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` set in your environment such that it can use the above key or set as additional `env_vars` 11 | to the local workspace options. 12 | 13 | First, set up your virtual environment: 14 | 1. ```shell 15 | $ python3 -m venv venv 16 | ``` 17 | 2. ```shell 18 | $ venv/bin/python3 -m pip install --upgrade pip 19 | ``` 20 | 3. ```shell 21 | $ venv/bin/pip install -r requirements.txt 22 | ``` 23 | 24 | Running this program is just like any other Python program. No invocation through the Pulumi CLI required: 25 | 26 | ```shell 27 | $ mkdir ~/.pulumi-local 28 | $ venv/bin/python main.py 29 | Created/Selected stack "dev" 30 | Installing the AWS plugin 31 | Successfully installed AWS plugin 32 | Successfully set config 33 | Starting refresh 34 | Refresh succeeded! 35 | Starting update 36 | Updating (dev) 37 | 38 | View Live: https://app.pulumi.com/EvanBoyle/inlineS3Project/dev/updates/22 39 | 40 | 41 | + pulumi:pulumi:Stack inlineS3Project-dev creating 42 | + aws:s3:Bucket s3-website-bucket creating 43 | + aws:s3:Bucket s3-website-bucket created 44 | + aws:s3:BucketObject index creating 45 | + aws:s3:BucketPolicy bucketPolicy creating 46 | + aws:s3:BucketObject index created 47 | + aws:s3:BucketPolicy bucketPolicy created 48 | + pulumi:pulumi:Stack inlineS3Project-dev created 49 | 50 | Outputs: 51 | secret : "[secret]" 52 | websiteUrl: "s3-website-bucket-bf7e357.s3-website-us-west-2.amazonaws.com" 53 | 54 | Resources: 55 | + 4 created 56 | 57 | Duration: 10s 58 | 59 | Update succeeded! 60 | URL: s3-website-bucket-bf7e357.s3-website-us-west-2.amazonaws.com 61 | ``` 62 | 63 | To destroy the stack when you're done, invoke the program with an additional `destroy` argument: 64 | 65 | ```shell 66 | $ venv/bin/python main.py destroy 67 | Created/Selected stack "dev" 68 | Installing the AWS plugin 69 | Successfully installed AWS plugin 70 | Successfully set config 71 | Starting refresh 72 | Refresh succeeded! 73 | Starting stack destroy 74 | Destroying (dev) 75 | 76 | View Live: https://app.pulumi.com/EvanBoyle/inlineS3Project/dev/updates/24 77 | 78 | 79 | - aws:s3:BucketPolicy bucketPolicy deleting 80 | - aws:s3:BucketObject index deleting 81 | - aws:s3:BucketObject index deleted 82 | - aws:s3:BucketPolicy bucketPolicy deleted 83 | - aws:s3:Bucket s3-website-bucket deleting 84 | - aws:s3:Bucket s3-website-bucket deleted 85 | - pulumi:pulumi:Stack inlineS3Project-dev deleting 86 | - pulumi:pulumi:Stack inlineS3Project-dev deleted 87 | 88 | Outputs: 89 | - secret : "[secret]" 90 | - websiteUrl: "s3-website-bucket-bf7e357.s3-website-us-west-2.amazonaws.com" 91 | 92 | Resources: 93 | - 4 deleted 94 | 95 | Duration: 3s 96 | 97 | The resources in the stack have been deleted, but the history and configuration associated with the stack are still maintained. 98 | If you want to remove the stack completely, run 'pulumi stack rm dev'. 99 | Stack successfully destroyed 100 | ``` 101 | -------------------------------------------------------------------------------- /python/inline_secrets_provider/requirements.txt: -------------------------------------------------------------------------------- 1 | pulumi>=3.0.0,<4.0.0 2 | pulumi-aws>=4.0.0,<5.0.0 3 | -------------------------------------------------------------------------------- /python/local_program/.gitignore: -------------------------------------------------------------------------------- 1 | */venv 2 | */__pycache__ 3 | -------------------------------------------------------------------------------- /python/local_program/automation/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import json 3 | import os 4 | import subprocess 5 | from pulumi import automation as auto 6 | 7 | # To destroy our program, we can run python main.py destroy 8 | destroy = False 9 | args = sys.argv[1:] 10 | if len(args) > 0: 11 | if args[0] == "destroy": 12 | destroy = True 13 | 14 | stack_name = "dev" 15 | 16 | work_dir = os.path.join(os.path.dirname(__file__), "..", "aws-py-voting-app") 17 | 18 | print("preparing virtual environment...") 19 | subprocess.run(["python3", "-m", "venv", "venv"], check=True, cwd=work_dir, capture_output=True) 20 | subprocess.run([os.path.join("venv", "bin", "python3"), "-m", "pip", "install", "--upgrade", "pip"], 21 | check=True, cwd=work_dir, capture_output=True) 22 | subprocess.run([os.path.join("venv", "bin", "pip"), "install", "-r", "requirements.txt"], 23 | check=True, cwd=work_dir, capture_output=True) 24 | print("virtual environment is ready!") 25 | 26 | # Create our stack using a local program in the ../aws-py-voting-app directory 27 | stack = auto.create_or_select_stack(stack_name="dev", work_dir=work_dir) 28 | print("successfully initialized stack") 29 | 30 | print("setting up config") 31 | stack.set_config("aws:region", auto.ConfigValue(value="us-west-2")) 32 | stack.set_config("voting-app:redis-password", auto.ConfigValue(value="my_password", secret=True)) 33 | print("config set") 34 | 35 | print("refreshing stack") 36 | stack.refresh(on_output=print) 37 | print("refresh complete") 38 | 39 | if destroy: 40 | print("destroying stack...") 41 | stack.destroy(on_output=print) 42 | print("stack destroy complete") 43 | sys.exit() 44 | 45 | print("updating stack...") 46 | up_res = stack.up(on_output=print) 47 | print(f"update summary: \n{json.dumps(up_res.summary.resource_changes, indent=4)}") 48 | print(f"app url: {up_res.outputs['app-url'].value}") 49 | -------------------------------------------------------------------------------- /python/local_program/automation/requirements.txt: -------------------------------------------------------------------------------- 1 | pulumi>=3.0.0,<4.0.0 2 | -------------------------------------------------------------------------------- /python/local_program/aws-py-voting-app/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: voting-app 2 | runtime: 3 | name: python 4 | options: 5 | virtualenv: venv 6 | description: Voting app that uses containers 7 | template: 8 | config: 9 | aws:region: 10 | description: The AWS region to deploy into 11 | default: us-west-2 12 | -------------------------------------------------------------------------------- /python/local_program/aws-py-voting-app/frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tiangolo/uwsgi-nginx-flask:python3.6 2 | RUN pip install redis 3 | COPY /app /app 4 | -------------------------------------------------------------------------------- /python/local_program/aws-py-voting-app/frontend/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /python/local_program/aws-py-voting-app/frontend/app/config_file.cfg: -------------------------------------------------------------------------------- 1 | # UI Configurations 2 | TITLE = 'Pulumi Voting App' 3 | VOTE1VALUE = 'Tabs' 4 | VOTE2VALUE = 'Spaces' 5 | SHOWHOST = 'false' 6 | -------------------------------------------------------------------------------- /python/local_program/aws-py-voting-app/frontend/app/main.py: -------------------------------------------------------------------------------- 1 | # Copied from https://github.com/Azure-Samples/azure-voting-app-redis 2 | 3 | from flask import Flask, request, render_template 4 | import os 5 | import random 6 | import redis 7 | import socket 8 | import sys 9 | 10 | app = Flask(__name__) 11 | 12 | # Load configurations 13 | app.config.from_pyfile('config_file.cfg') 14 | button1 = app.config['VOTE1VALUE'] 15 | button2 = app.config['VOTE2VALUE'] 16 | title = app.config['TITLE'] 17 | 18 | # Redis configurations 19 | redis_server = os.environ['REDIS'] 20 | redis_port = os.environ['REDIS_PORT'] 21 | redis_password = os.environ['REDIS_PWD'] 22 | 23 | # Redis Connection 24 | try: 25 | r = redis.StrictRedis(host=redis_server, port=redis_port, password=redis_password) 26 | r.ping() 27 | except redis.ConnectionError: 28 | exit('Failed to connect to Redis, terminating.') 29 | 30 | # Init Redis 31 | if not r.get(button1): r.set(button1,0) 32 | if not r.get(button2): r.set(button2,0) 33 | 34 | @app.route('/', methods=['GET', 'POST']) 35 | def index(): 36 | 37 | if request.method == 'GET': 38 | 39 | # Get current values 40 | vote1 = r.get(button1).decode('utf-8') 41 | vote2 = r.get(button2).decode('utf-8') 42 | 43 | # Return index with values 44 | return render_template("index.html", value1=int(vote1), value2=int(vote2), button1=button1, button2=button2, title=title) 45 | 46 | elif request.method == 'POST': 47 | 48 | if request.form['vote'] == 'reset': 49 | 50 | # Empty table and return results 51 | r.set(button1,0) 52 | r.set(button2,0) 53 | vote1 = r.get(button1).decode('utf-8') 54 | vote2 = r.get(button2).decode('utf-8') 55 | return render_template("index.html", value1=int(vote1), value2=int(vote2), button1=button1, button2=button2, title=title) 56 | 57 | else: 58 | 59 | # Insert vote result into DB 60 | vote = request.form['vote'] 61 | r.incr(vote,1) 62 | 63 | # Get current values 64 | vote1 = r.get(button1).decode('utf-8') 65 | vote2 = r.get(button2).decode('utf-8') 66 | 67 | # Return results 68 | return render_template("index.html", value1=int(vote1), value2=int(vote2), button1=button1, button2=button2, title=title) 69 | 70 | if __name__ == "__main__": 71 | app.run() 72 | -------------------------------------------------------------------------------- /python/local_program/aws-py-voting-app/frontend/app/static/default.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color:#F8F8F8; 3 | } 4 | 5 | div#container { 6 | margin-top:5%; 7 | } 8 | 9 | div#space { 10 | display:block; 11 | margin: 0 auto; 12 | width: 500px; 13 | height: 10px; 14 | 15 | } 16 | 17 | div#logo { 18 | display:block; 19 | margin: 0 auto; 20 | width: 500px; 21 | text-align: center; 22 | font-size:30px; 23 | font-family: 'PT Sans', sans-serif; 24 | /*border-bottom: 1px solid black;*/ 25 | } 26 | 27 | div#form { 28 | padding: 20px; 29 | padding-right: 20px; 30 | padding-top: 20px; 31 | display:block; 32 | margin: 0 auto; 33 | width: 500px; 34 | text-align: center; 35 | font-size:30px; 36 | font-family: 'PT Sans', sans-serif; 37 | border-bottom: 1px solid black; 38 | border-top: 1px solid black; 39 | } 40 | 41 | div#results { 42 | display:block; 43 | margin: 0 auto; 44 | width: 500px; 45 | text-align: center; 46 | font-size:30px; 47 | font-family: 'PT Sans', sans-serif; 48 | } 49 | 50 | .button { 51 | background-color: #4CAF50; /* Green */ 52 | border: none; 53 | color: white; 54 | padding: 16px 32px; 55 | text-align: center; 56 | text-decoration: none; 57 | display: inline-block; 58 | font-size: 16px; 59 | margin: 4px 2px; 60 | -webkit-transition-duration: 0.4s; /* Safari */ 61 | transition-duration: 0.4s; 62 | cursor: pointer; 63 | width: 250px; 64 | } 65 | 66 | .button1 { 67 | background-color: white; 68 | color: black; 69 | border: 2px solid #008CBA; 70 | } 71 | 72 | .button1:hover { 73 | background-color: #008CBA; 74 | color: white; 75 | } 76 | .button2 { 77 | background-color: white; 78 | color: black; 79 | border: 2px solid #555555; 80 | } 81 | 82 | .button2:hover { 83 | background-color: #555555; 84 | color: white; 85 | } 86 | 87 | .button3 { 88 | background-color: white; 89 | color: black; 90 | border: 2px solid #f44336; 91 | } 92 | 93 | .button3:hover { 94 | background-color: #f44336; 95 | color: white; 96 | } 97 | -------------------------------------------------------------------------------- /python/local_program/aws-py-voting-app/frontend/app/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |Hello, world!
Made with ❤️ with Pulumi
18 | """ 19 | 20 | uploaded_content = s3.BucketObject('index_html', 21 | bucket=bucket, 22 | content=content, 23 | content_type="text/html; charset=utf-8", 24 | key="index.html" 25 | ) 26 | 27 | policy_document = iam.get_policy_document_output(statements=[iam.GetPolicyDocumentStatementArgs( 28 | principals=[iam.GetPolicyDocumentStatementPrincipalArgs( 29 | type="*", 30 | identifiers=["*"] 31 | )], 32 | actions=["s3:GetObject"], 33 | resources=[bucket.arn.apply(lambda bucket_arn: f"{bucket_arn}/*")] 34 | )]) 35 | 36 | # Allow public ACLs for the bucket 37 | public_access_block = s3.BucketPublicAccessBlock("exampleBucketPublicAccessBlock", 38 | bucket=bucket.id, 39 | block_public_acls=False, 40 | ) 41 | 42 | bucket_policy = s3.BucketPolicy("bucket_policy", 43 | bucket=bucket.id, 44 | policy=policy_document.json, 45 | opts=pulumi.ResourceOptions(depends_on=[public_access_block]) 46 | ) 47 | 48 | # # Export the name of the bucket 49 | pulumi.export('url', pulumi.Output.concat("http://", bucket.website_endpoint, "/index.html")) 50 | -------------------------------------------------------------------------------- /python/testing_local_program/infrastructure/requirements.txt: -------------------------------------------------------------------------------- 1 | pulumi>=3.0.0,<4.0.0 2 | pulumi-aws>=5.0.0,<6.0.0 3 | -------------------------------------------------------------------------------- /python/testing_local_program/requirements.txt: -------------------------------------------------------------------------------- 1 | pulumi>=3.0.0,<4.0.0 2 | requests -------------------------------------------------------------------------------- /python/testing_local_program/test_infrastructure.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | from pulumi import automation as auto 3 | import os 4 | import requests 5 | import unittest 6 | 7 | stack_name = "dev" 8 | aws_region = "eu-west-1" 9 | 10 | work_dir = os.path.join(os.path.dirname(__file__), "infrastructure") 11 | 12 | def deploy_infrastructure(): 13 | print("preparing virtual environment...") 14 | subprocess.run(["python3", "-m", "venv", "venv"], check=True, cwd=work_dir, capture_output=True) 15 | subprocess.run([os.path.join("venv", "bin", "python3"), "-m", "pip", "install", "--upgrade", "pip"], 16 | check=True, cwd=work_dir, capture_output=True) 17 | subprocess.run([os.path.join("venv", "bin", "pip"), "install", "-r", "requirements.txt"], 18 | check=True, cwd=work_dir, capture_output=True) 19 | print("virtual environment is ready!") 20 | 21 | stack = auto.create_or_select_stack(stack_name=stack_name, work_dir=work_dir) 22 | print("successfully initialized stack") 23 | 24 | print("setting up config") 25 | stack.set_config("aws:region", auto.ConfigValue(value=aws_region)) 26 | print("config set") 27 | 28 | print("refreshing stack") 29 | stack.refresh(on_output=print) 30 | print("refresh complete") 31 | 32 | print("deploying infrastructure") 33 | up_result = stack.up(on_output=print) 34 | print("infrastructure deployed") 35 | 36 | return up_result.outputs["url"].value 37 | 38 | def destroy_infrastructure(): 39 | stack = auto.create_or_select_stack(stack_name=stack_name, work_dir=work_dir) 40 | print("destroying infrastructure") 41 | stack.destroy(on_output=print) 42 | print("infrastructure destroyed") 43 | 44 | print("deleting stack") 45 | stack.workspace.remove_stack(stack_name=stack_name) 46 | print("stack deleted") 47 | 48 | class TestInfrastructure(unittest.TestCase): 49 | def setUp(self): 50 | self.url = deploy_infrastructure() 51 | 52 | def tearDown(self): 53 | destroy_infrastructure() 54 | 55 | def test_for_200_status_code(self): 56 | http_request = requests.get(self.url) 57 | self.assertEqual(200, http_request.status_code) 58 | --------------------------------------------------------------------------------