├── .github └── workflows │ ├── ci.yml │ ├── command_dispatch.yml │ └── pr.yml ├── .gitignore ├── README.md ├── dotnet ├── .gitignore ├── CrossLanguage │ ├── README.md │ ├── automation │ │ ├── CrossLanguage.csproj │ │ ├── CrossLanguage.sln │ │ └── Program.cs │ └── fargate │ │ ├── Pulumi.dev.yaml │ │ ├── Pulumi.yaml │ │ ├── app │ │ ├── Dockerfile │ │ ├── go.mod │ │ ├── go.sum │ │ └── main.go │ │ ├── go.mod │ │ ├── go.sum │ │ └── main.go ├── DatabaseMigration │ ├── DatabaseMigration.csproj │ ├── DatabaseMigration.sln │ ├── Program.cs │ └── README.md ├── InlineLocalHybrid │ ├── InlineLocalHybrid.Automation │ │ ├── InlineLocalHybrid.Automation.csproj │ │ └── Program.cs │ ├── InlineLocalHybrid.CLI │ │ ├── InlineLocalHybrid.CLI.csproj │ │ ├── Program.cs │ │ ├── Pulumi.dev.yaml │ │ └── Pulumi.yaml │ ├── InlineLocalHybrid.Infra │ │ ├── AwsStaticWebsiteStack.cs │ │ └── InlineLocalHybrid.Infra.csproj │ ├── InlineLocalHybrid.sln │ └── README.md ├── InlineProgram │ ├── InlineProgram.csproj │ ├── InlineProgram.sln │ ├── Program.cs │ └── README.md ├── InlineSecretsProvider │ ├── InlineProgram.csproj │ ├── InlineProgram.sln │ ├── Program.cs │ └── README.md ├── LocalProgram │ ├── README.md │ ├── automation │ │ ├── LocalProgram.csproj │ │ ├── LocalProgram.sln │ │ └── Program.cs │ └── website │ │ ├── Program.cs │ │ ├── Pulumi.dev.yaml │ │ ├── Pulumi.yaml │ │ ├── Website.csproj │ │ ├── Website.sln │ │ └── WebsiteStack.cs └── RemoteDeployment │ ├── Program.cs │ ├── README.md │ └── RemoteDeployment.csproj ├── go ├── cli_installation │ ├── README.md │ ├── go.mod │ ├── go.sum │ └── main.go ├── database_migration │ ├── README.md │ ├── go.mod │ ├── go.sum │ └── main.go ├── git_repo_program │ ├── README.md │ ├── go.mod │ ├── go.sum │ └── main.go ├── inline_local_hybrid │ ├── README.md │ ├── automation │ │ ├── go.mod │ │ ├── go.sum │ │ └── main.go │ ├── cli │ │ ├── Pulumi.dev.yaml │ │ ├── Pulumi.yaml │ │ ├── go.mod │ │ ├── go.sum │ │ └── main.go │ └── infra │ │ ├── deployment.go │ │ ├── go.mod │ │ └── go.sum ├── inline_passphrase_secrets_provider │ ├── README.md │ ├── go.mod │ ├── go.sum │ └── main.go ├── inline_program │ ├── README.md │ ├── go.mod │ ├── go.sum │ └── main.go ├── inline_secrets_provider │ ├── README.md │ ├── go.mod │ ├── go.sum │ └── main.go ├── local_program │ ├── README.md │ ├── app │ │ ├── Dockerfile │ │ ├── go.mod │ │ ├── go.sum │ │ └── main.go │ ├── automation │ │ ├── go.mod │ │ ├── go.sum │ │ └── main.go │ └── fargate │ │ ├── Pulumi.yaml │ │ ├── go.mod │ │ ├── go.sum │ │ └── main.go ├── multi_stack_orchestration │ ├── README.md │ ├── go.mod │ ├── go.sum │ └── main.go ├── pulumi_over_http │ ├── README.md │ ├── go.mod │ ├── go.sum │ └── main.go ├── remote_deployment │ ├── README.md │ ├── go.mod │ ├── go.sum │ └── main.go ├── temporal_vm_mgr │ ├── README.md │ ├── go.mod │ ├── go.sum │ ├── main.go │ ├── webserver │ │ └── webserver.go │ └── workflow │ │ ├── network.go │ │ ├── tearDown.go │ │ ├── virtualMachine.go │ │ └── workflow.go └── vm_manager_azure │ ├── README.md │ ├── cmd │ └── vmgr │ │ ├── add.go │ │ ├── cron.go │ │ ├── main.go │ │ └── vmgr.go │ ├── go.mod │ ├── go.sum │ └── infra │ ├── deploy │ └── deploy.go │ ├── reap │ └── reap.go │ └── webserver │ └── webserver.go ├── java ├── databaseMigration │ ├── .gitignore │ ├── README.md │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── example │ │ └── App.java ├── inlineProgram │ ├── .gitignore │ ├── README.md │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── pulumi │ │ └── App.java └── localProgram │ ├── .gitignore │ ├── README.md │ ├── automation │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── pulumi │ │ └── App.java │ └── website │ ├── Pulumi.dev.yaml │ ├── Pulumi.yaml │ ├── pom.xml │ └── src │ └── main │ └── java │ └── myproject │ └── App.java ├── nodejs ├── crossLanguage-tsnode │ ├── .gitignore │ ├── README.md │ ├── app │ │ ├── Dockerfile │ │ ├── go.mod │ │ ├── go.sum │ │ └── main.go │ ├── automation │ │ ├── .vscode │ │ │ └── launch.json │ │ ├── index.ts │ │ └── package.json │ └── fargate │ │ ├── Pulumi.dev.yaml │ │ ├── Pulumi.yaml │ │ ├── go.mod │ │ ├── go.sum │ │ └── main.go ├── databaseMigration-ts │ ├── .gitignore │ ├── .vscode │ │ └── launch.json │ ├── README.md │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── inlineProgram-js │ ├── .gitignore │ ├── .vscode │ │ └── launch.json │ ├── README.md │ ├── index.js │ └── package.json ├── inlineProgram-ts │ ├── .gitignore │ ├── .vscode │ │ └── launch.json │ ├── README.md │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── inlineProgram-tsnode │ ├── .gitignore │ ├── .vscode │ │ └── launch.json │ ├── README.md │ ├── index.ts │ └── package.json ├── inlineSecretsProvider-ts │ ├── .gitignore │ ├── README.md │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── localProgram-tsnode-mochatests │ ├── .gitignore │ ├── README.md │ ├── automation.ts │ ├── index.ts │ ├── infrastructure │ │ ├── .gitignore │ │ ├── Pulumi.dev.yaml │ │ ├── Pulumi.yaml │ │ ├── index.ts │ │ ├── package.json │ │ └── tsconfig.json │ ├── package.json │ └── test.ts ├── localProgram-tsnode │ ├── .gitignore │ ├── README.md │ ├── automation │ │ ├── .vscode │ │ │ └── launch.json │ │ ├── index.ts │ │ └── package.json │ └── website │ │ ├── .gitignore │ │ ├── Pulumi.dev.yaml │ │ ├── Pulumi.yaml │ │ ├── index.ts │ │ ├── package.json │ │ └── tsconfig.json ├── pulumiOverHttp-ts │ ├── .gitignore │ ├── .vscode │ │ └── launch.json │ ├── README.md │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── remoteDeployment-tsnode │ ├── .gitignore │ ├── README.md │ ├── index.ts │ ├── package.json │ └── tsconfig.json └── ssh-tunnel │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── database │ ├── .gitignore │ ├── Pulumi.yaml │ ├── index.ts │ ├── package.json │ └── tsconfig.json │ ├── package.json │ ├── pulumi.ts │ ├── tsconfig.json │ └── vpc │ ├── .gitignore │ ├── Pulumi.yaml │ ├── index.ts │ ├── package.json │ └── tsconfig.json └── python ├── cross_language ├── .gitignore ├── README.md ├── app │ ├── Dockerfile │ ├── go.mod │ ├── go.sum │ └── main.go ├── automation │ ├── main.py │ └── requirements.txt └── fargate │ ├── Pulumi.dev.yaml │ ├── Pulumi.yaml │ ├── go.mod │ ├── go.sum │ └── main.go ├── database_migration ├── .gitignore ├── README.md ├── main.py └── requirements.txt ├── inline_program ├── .gitignore ├── README.md ├── main.py └── requirements.txt ├── inline_secrets_provider ├── .gitignore ├── README.md ├── main.py └── requirements.txt ├── local_program ├── .gitignore ├── README.md ├── automation │ ├── main.py │ └── requirements.txt └── aws-py-voting-app │ ├── Pulumi.yaml │ ├── README.md │ ├── __main__.py │ ├── frontend │ ├── Dockerfile │ ├── LICENSE │ └── app │ │ ├── config_file.cfg │ │ ├── main.py │ │ ├── static │ │ └── default.css │ │ └── templates │ │ └── index.html │ └── requirements.txt ├── pulumi_over_htp_fastapi ├── .gitignore ├── README.md ├── main.py └── requirements.txt ├── pulumi_over_http ├── .gitignore ├── README.md ├── app.py └── requirements.txt ├── pulumi_via_jupyter ├── .gitignore ├── README.md ├── auto-api.gif ├── automation_api.ipynb ├── database_migration.ipynb ├── notebook-screenshot.png └── requirements.txt ├── remote_deployment ├── .gitignore ├── README.md ├── main.py └── requirements.txt └── testing_local_program ├── .gitignore ├── README.md ├── infrastructure ├── .gitignore ├── Pulumi.yaml ├── __main__.py └── requirements.txt ├── requirements.txt └── test_infrastructure.py /.github/workflows/command_dispatch.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | command-dispatch-for-testing: 3 | runs-on: ubuntu-latest 4 | steps: 5 | - uses: actions/checkout@v2 6 | - name: Run Build 7 | uses: peter-evans/slash-command-dispatch@v2 8 | with: 9 | commands: run-example-tests 10 | issue-type: pull-request 11 | permission: write 12 | reaction-token: ${{ secrets.GITHUB_TOKEN }} 13 | repository: pulumi/automation-api-examples 14 | token: ${{ secrets.EVENT_PAT }} 15 | name: Command Dispatch for testing 16 | "on": 17 | issue_comment: 18 | types: 19 | - created 20 | - edited -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | comment-on-pr: 3 | if: github.event.pull_request.head.repo.full_name != github.repository 4 | name: comment-on-pr 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v2 8 | - name: Comment PR 9 | uses: thollander/actions-comment-pull-request@1.0.1 10 | with: 11 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 12 | message: |- 13 | PR is now waiting for a maintainer to run the acceptance tests. 14 | **Note for the maintainer:** To run the acceptance tests, please comment */run-example-tests* on the PR 15 | name: New Pull request Open 16 | "on": 17 | pull_request_target: {} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | -------------------------------------------------------------------------------- /dotnet/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Visual Studio temp something 3 | .vs/ 4 | 5 | # dotnet stuff 6 | project.lock.json 7 | 8 | # VS 2015+ 9 | *.vc.vc.opendb 10 | *.vc.db 11 | 12 | # Rider 13 | .idea/ 14 | 15 | # Visual Studio Code 16 | .vscode/ 17 | 18 | # User-specific files 19 | *.suo 20 | *.user 21 | *.sln.docstates 22 | 23 | # Build results 24 | [Dd]ebug/ 25 | [Rr]elease/ 26 | x64/ 27 | [Bb]in/ 28 | [Oo]bj/ -------------------------------------------------------------------------------- /dotnet/CrossLanguage/automation/CrossLanguage.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /dotnet/CrossLanguage/automation/CrossLanguage.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31005.135 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CrossLanguage", "CrossLanguage.csproj", "{DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {45337B5B-63BC-4A76-8AF6-27E1D3CC4280} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /dotnet/CrossLanguage/automation/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Threading.Tasks; 6 | using Pulumi.Automation; 7 | 8 | namespace CrossLanguage 9 | { 10 | class Program 11 | { 12 | static async Task Main(string[] args) 13 | { 14 | // to destroy our program, we can run "dotnet run destroy" 15 | var destroy = args.Any() && args[0] == "destroy"; 16 | 17 | var stackName = "dev"; 18 | 19 | // need to account for the assembly executing from within the bin directory 20 | // when getting path to the local program 21 | var executingDir = new DirectoryInfo(Assembly.GetExecutingAssembly().Location).Parent.FullName; 22 | var workingDir = Path.Combine(executingDir, "..", "..", "..", "..", "fargate"); 23 | 24 | // create our stack using a local program in the ../../../../fargate directory 25 | var stackArgs = new LocalProgramArgs(stackName, workingDir); 26 | var stack = await LocalWorkspace.CreateOrSelectStackAsync(stackArgs); 27 | 28 | Console.WriteLine("successfully initialized stack"); 29 | 30 | // set stack configuration specifying the region to deploy 31 | Console.WriteLine("setting up config..."); 32 | await stack.SetConfigAsync("aws:region", new ConfigValue("us-west-2")); 33 | Console.WriteLine("config set"); 34 | 35 | Console.WriteLine("refreshing stack..."); 36 | await stack.RefreshAsync(new RefreshOptions { OnStandardOutput = Console.WriteLine }); 37 | Console.WriteLine("refresh complete"); 38 | 39 | if (destroy) 40 | { 41 | Console.WriteLine("destroying stack..."); 42 | await stack.DestroyAsync(new DestroyOptions { OnStandardOutput = Console.WriteLine }); 43 | Console.WriteLine("stack destroy complete"); 44 | } 45 | else 46 | { 47 | Console.WriteLine("updating stack..."); 48 | var result = await stack.UpAsync(new UpOptions { OnStandardOutput = Console.WriteLine }); 49 | 50 | if (result.Summary.ResourceChanges != null) 51 | { 52 | Console.WriteLine("update summary:"); 53 | foreach (var change in result.Summary.ResourceChanges) 54 | Console.WriteLine($" {change.Key}: {change.Value}"); 55 | } 56 | 57 | Console.WriteLine($"website url: {result.Outputs["url"].Value}"); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /dotnet/CrossLanguage/fargate/Pulumi.dev.yaml: -------------------------------------------------------------------------------- 1 | config: 2 | aws:region: us-west-2 3 | -------------------------------------------------------------------------------- /dotnet/CrossLanguage/fargate/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: fargate 2 | runtime: go 3 | description: An end-to-end AWS ECS Fargate infrastructure as code project. 4 | -------------------------------------------------------------------------------- /dotnet/CrossLanguage/fargate/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 -------------------------------------------------------------------------------- /dotnet/CrossLanguage/fargate/app/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/python/cross_language/app 2 | 3 | go 1.14 4 | 5 | require github.com/gorilla/mux v1.8.0 6 | -------------------------------------------------------------------------------- /dotnet/CrossLanguage/fargate/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 | -------------------------------------------------------------------------------- /dotnet/CrossLanguage/fargate/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 | -------------------------------------------------------------------------------- /dotnet/CrossLanguage/fargate/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/python/cross_language/fargate 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/pulumi/pulumi-aws/sdk/v5 v5.41.0 7 | github.com/pulumi/pulumi-docker/sdk/v4 v4.2.3 8 | github.com/pulumi/pulumi/sdk/v3 v3.68.0 9 | ) 10 | 11 | require ( 12 | github.com/Microsoft/go-winio v0.5.2 // indirect 13 | github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 // indirect 14 | github.com/acomagu/bufpipe v1.0.3 // indirect 15 | github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect 16 | github.com/agext/levenshtein v1.2.1 // indirect 17 | github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect 18 | github.com/blang/semver v3.5.1+incompatible // indirect 19 | github.com/cheggaaa/pb v1.0.29 // indirect 20 | github.com/cloudflare/circl v1.3.3 // indirect 21 | github.com/djherbis/times v1.5.0 // indirect 22 | github.com/emirpasic/gods v1.18.1 // indirect 23 | github.com/go-git/gcfg v1.5.0 // indirect 24 | github.com/go-git/go-billy/v5 v5.4.0 // indirect 25 | github.com/go-git/go-git/v5 v5.6.0 // indirect 26 | github.com/gofrs/uuid v4.2.0+incompatible // indirect 27 | github.com/gogo/protobuf v1.3.2 // indirect 28 | github.com/golang/glog v1.0.0 // indirect 29 | github.com/golang/protobuf v1.5.2 // indirect 30 | github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect 31 | github.com/hashicorp/errwrap v1.1.0 // indirect 32 | github.com/hashicorp/go-multierror v1.1.1 // indirect 33 | github.com/hashicorp/hcl/v2 v2.16.1 // indirect 34 | github.com/imdario/mergo v0.3.13 // indirect 35 | github.com/inconshreveable/mousetrap v1.0.1 // indirect 36 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect 37 | github.com/kevinburke/ssh_config v1.2.0 // indirect 38 | github.com/mattn/go-runewidth v0.0.13 // indirect 39 | github.com/mitchellh/go-ps v1.0.0 // indirect 40 | github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect 41 | github.com/opentracing/basictracer-go v1.1.0 // indirect 42 | github.com/opentracing/opentracing-go v1.2.0 // indirect 43 | github.com/pjbgf/sha1cd v0.3.0 // indirect 44 | github.com/pkg/errors v0.9.1 // indirect 45 | github.com/pkg/term v1.1.0 // indirect 46 | github.com/rivo/uniseg v0.2.0 // indirect 47 | github.com/rogpeppe/go-internal v1.9.0 // indirect 48 | github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 // indirect 49 | github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 // indirect 50 | github.com/sergi/go-diff v1.2.0 // indirect 51 | github.com/skeema/knownhosts v1.1.0 // indirect 52 | github.com/spf13/cobra v1.6.1 // indirect 53 | github.com/spf13/pflag v1.0.5 // indirect 54 | github.com/texttheater/golang-levenshtein v1.0.1 // indirect 55 | github.com/tweekmonster/luser v0.0.0-20161003172636-3fa38070dbd7 // indirect 56 | github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect 57 | github.com/uber/jaeger-lib v2.4.1+incompatible // indirect 58 | github.com/xanzy/ssh-agent v0.3.3 // indirect 59 | github.com/zclconf/go-cty v1.12.1 // indirect 60 | go.uber.org/atomic v1.9.0 // indirect 61 | golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a // indirect 62 | golang.org/x/net v0.7.0 // indirect 63 | golang.org/x/sys v0.5.0 // indirect 64 | golang.org/x/term v0.5.0 // indirect 65 | golang.org/x/text v0.7.0 // indirect 66 | google.golang.org/genproto v0.0.0-20220802133213-ce4fa296bf78 // indirect 67 | google.golang.org/grpc v1.51.0 // indirect 68 | google.golang.org/protobuf v1.28.1 // indirect 69 | gopkg.in/warnings.v0 v0.1.2 // indirect 70 | gopkg.in/yaml.v3 v3.0.1 // indirect 71 | lukechampine.com/frand v1.4.2 // indirect 72 | sourcegraph.com/sourcegraph/appdash v0.0.0-20211028080628-e2786a622600 // indirect 73 | ) 74 | -------------------------------------------------------------------------------- /dotnet/DatabaseMigration/DatabaseMigration.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /dotnet/DatabaseMigration/DatabaseMigration.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31005.135 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DatabaseMigration", "DatabaseMigration.csproj", "{DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {45337B5B-63BC-4A76-8AF6-27E1D3CC4280} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /dotnet/InlineLocalHybrid/InlineLocalHybrid.Automation/InlineLocalHybrid.Automation.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /dotnet/InlineLocalHybrid/InlineLocalHybrid.Automation/Program.cs: -------------------------------------------------------------------------------- 1 | using InlineLocalHybrid.Infra; 2 | using Pulumi.Automation; 3 | 4 | namespace InlineProgram; 5 | 6 | class Program 7 | { 8 | static async Task Main(string[] args) 9 | { 10 | // pass our pulumi stack to "inline" program 11 | var program = PulumiFn.Create(); 12 | 13 | // to destroy our program, we can run "dotnet run destroy" 14 | var destroy = args.Any() && args[0] == "destroy"; 15 | 16 | var projectName = "inline_s3_project"; 17 | var stackName = "dev"; 18 | 19 | // create or select a stack matching the specified name and project 20 | // this will set up a workspace with everything necessary to run our inline program (program) 21 | var stackArgs = new InlineProgramArgs(projectName, stackName, program); 22 | var stack = await LocalWorkspace.CreateOrSelectStackAsync(stackArgs); 23 | 24 | Console.WriteLine("successfully initialized stack"); 25 | 26 | // for inline programs, we must manage plugins ourselves 27 | Console.WriteLine("installing plugins..."); 28 | await stack.Workspace.InstallPluginAsync("aws", "v4.24.1"); 29 | Console.WriteLine("plugins installed"); 30 | 31 | // set stack configuration specifying the region to deploy 32 | Console.WriteLine("setting up config..."); 33 | await stack.SetConfigAsync("aws:region", new ConfigValue("us-west-2")); 34 | Console.WriteLine("config set"); 35 | 36 | Console.WriteLine("refreshing stack..."); 37 | await stack.RefreshAsync(new RefreshOptions { OnStandardOutput = Console.WriteLine }); 38 | Console.WriteLine("refresh complete"); 39 | 40 | if (destroy) 41 | { 42 | Console.WriteLine("destroying stack..."); 43 | await stack.DestroyAsync(new DestroyOptions { OnStandardOutput = Console.WriteLine }); 44 | Console.WriteLine("stack destroy complete"); 45 | } 46 | else 47 | { 48 | Console.WriteLine("updating stack..."); 49 | var result = await stack.UpAsync(new UpOptions { OnStandardOutput = Console.WriteLine }); 50 | 51 | if (result.Summary.ResourceChanges != null) 52 | { 53 | Console.WriteLine("update summary:"); 54 | foreach (var change in result.Summary.ResourceChanges) 55 | Console.WriteLine($" {change.Key}: {change.Value}"); 56 | } 57 | 58 | Console.WriteLine($"website url: {result.Outputs["website_url"].Value}"); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /dotnet/InlineLocalHybrid/InlineLocalHybrid.CLI/InlineLocalHybrid.CLI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /dotnet/InlineLocalHybrid/InlineLocalHybrid.CLI/Program.cs: -------------------------------------------------------------------------------- 1 | using InlineLocalHybrid.Infra; 2 | using Pulumi; 3 | 4 | await Deployment.RunAsync(); 5 | -------------------------------------------------------------------------------- /dotnet/InlineLocalHybrid/InlineLocalHybrid.CLI/Pulumi.dev.yaml: -------------------------------------------------------------------------------- 1 | config: 2 | aws:region: us-west-2 3 | -------------------------------------------------------------------------------- /dotnet/InlineLocalHybrid/InlineLocalHybrid.CLI/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | 2 | name: hybridS3Project 3 | runtime: go 4 | description: A static website hosted on AWS S3 5 | template: 6 | config: 7 | aws:region: 8 | description: The AWS region to deploy into 9 | default: us-west-2 -------------------------------------------------------------------------------- /dotnet/InlineLocalHybrid/InlineLocalHybrid.Infra/AwsStaticWebsiteStack.cs: -------------------------------------------------------------------------------- 1 | using Pulumi; 2 | 3 | namespace InlineLocalHybrid.Infra; 4 | 5 | public class AwsStaticWebsiteStack : Stack 6 | { 7 | public AwsStaticWebsiteStack() 8 | { 9 | // create a bucket and expose a website index document 10 | var siteBucket = new Pulumi.Aws.S3.Bucket( 11 | "s3-website-bucket", 12 | new Pulumi.Aws.S3.BucketArgs 13 | { 14 | Website = new Pulumi.Aws.S3.Inputs.BucketWebsiteArgs 15 | { 16 | IndexDocument = "index.html", 17 | }, 18 | }); 19 | 20 | const string indexContent = @" 21 | 22 | Hello S3 23 | 24 |

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 List 47 | { 48 | new Pulumi.Aws.Iam.Inputs.GetPolicyDocumentStatementArgs 49 | { 50 | Effect = "Allow", 51 | Principals = new List 52 | { 53 | new Pulumi.Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalArgs 54 | { 55 | Identifiers = new List { "*" }, 56 | Type = "AWS", 57 | }, 58 | }, 59 | Actions = new List { "s3:GetObject" }, 60 | Resources = new List { $"{bucketArn}/*" }, 61 | }, 62 | }, 63 | })); 64 | }); 65 | 66 | // set the access policy for the bucket so all objects are readable 67 | new Pulumi.Aws.S3.BucketPolicy( 68 | "bucket-policy", 69 | new Pulumi.Aws.S3.BucketPolicyArgs 70 | { 71 | Bucket = siteBucket.BucketName, 72 | Policy = bucketPolicyDocument.Apply(x => x.Json), 73 | }); 74 | 75 | WebsiteEndpoint = siteBucket.WebsiteEndpoint; 76 | } 77 | 78 | [Output] public Output WebsiteEndpoint { get; set; } 79 | } 80 | -------------------------------------------------------------------------------- /dotnet/InlineLocalHybrid/InlineLocalHybrid.Infra/InlineLocalHybrid.Infra.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /dotnet/InlineLocalHybrid/InlineLocalHybrid.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.32014.148 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InlineLocalHybrid.Infra", "InlineLocalHybrid.Infra\InlineLocalHybrid.Infra.csproj", "{DC41FCD4-EF7A-4D33-8248-DBAA7E4AE964}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InlineLocalHybrid.CLI", "InlineLocalHybrid.CLI\InlineLocalHybrid.CLI.csproj", "{0513E22A-41BB-4123-B1B8-614F89C90AD7}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InlineLocalHybrid.Automation", "InlineLocalHybrid.Automation\InlineLocalHybrid.Automation.csproj", "{A6681C97-C33C-40B1-86D2-BCDBAD388C34}" 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{32887BE1-83DA-4F8C-9F74-5945516B21B2}" 13 | ProjectSection(SolutionItems) = preProject 14 | README.md = README.md 15 | EndProjectSection 16 | EndProject 17 | Global 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | Debug|Any CPU = Debug|Any CPU 20 | Release|Any CPU = Release|Any CPU 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {DC41FCD4-EF7A-4D33-8248-DBAA7E4AE964}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {DC41FCD4-EF7A-4D33-8248-DBAA7E4AE964}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {DC41FCD4-EF7A-4D33-8248-DBAA7E4AE964}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {DC41FCD4-EF7A-4D33-8248-DBAA7E4AE964}.Release|Any CPU.Build.0 = Release|Any CPU 27 | {0513E22A-41BB-4123-B1B8-614F89C90AD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {0513E22A-41BB-4123-B1B8-614F89C90AD7}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {0513E22A-41BB-4123-B1B8-614F89C90AD7}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {0513E22A-41BB-4123-B1B8-614F89C90AD7}.Release|Any CPU.Build.0 = Release|Any CPU 31 | {A6681C97-C33C-40B1-86D2-BCDBAD388C34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {A6681C97-C33C-40B1-86D2-BCDBAD388C34}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {A6681C97-C33C-40B1-86D2-BCDBAD388C34}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {A6681C97-C33C-40B1-86D2-BCDBAD388C34}.Release|Any CPU.Build.0 = Release|Any CPU 35 | EndGlobalSection 36 | GlobalSection(SolutionProperties) = preSolution 37 | HideSolutionNode = FALSE 38 | EndGlobalSection 39 | GlobalSection(ExtensibilityGlobals) = postSolution 40 | SolutionGuid = {7CF33706-3C9E-4D32-B02A-84570A09FE77} 41 | EndGlobalSection 42 | EndGlobal 43 | -------------------------------------------------------------------------------- /dotnet/InlineLocalHybrid/README.md: -------------------------------------------------------------------------------- 1 | # Inline/Local Hybrid Program 2 | 3 | This program demonstrates how to setup a project to get the best of both worlds between `inline` and CLI driven programs. This project sets up a single automation program using an "inline" Pulumi program, that also has a "local" CLI driver. This allows us to have our fully debuggable automation driver with our Pulumi deployment as just another function, but maintain the ability to use the CLI for poking at outputs, manually doing previews, updates, destroys, etc. To accomplish this we have three separate modules: 4 | 5 | 1. `/InlineLocalHybrid.Infra`: This contains our inline program (`PulumiFn.Create()`). This is where all of our cloud resources are defined. In this case, we're creating an S3 website just like in the `InlineProgram` example. 6 | 2. `/InlineLocalHybrid.Automation`: This contains a `Program.cs` that uses the automation API. You can run or debug this like any other dotnet program `dotnet run`. This takes care all of the deployment orchestration. This program imports it's inline Pulumi stack from `/InlineLocalHybrid.Infra` 7 | 3. `/InlineLocalHybrid.CLI`: This `Program.cs` imports the Pulumi stack from `/InlineLocalHybrid.Infra` and a `Pulumi.yaml` file. This is just a thin wrapper that allows using the CLI for things like inspecting outputs `pulumi stack output` or driving a deployment manually. 8 | 9 | 10 | To run this example you'll need a few pre-reqs: 11 | 1. A Pulumi CLI installation ([v3.0.0](https://www.pulumi.com/docs/get-started/install/versions/) or later) 12 | 2. The AWS CLI, with appropriate credentials. 13 | 14 | First we'll run our automation program: 15 | 16 | ```shell 17 | $ cd ./InlineLocalHybrid.Automation 18 | $ dotnet run 19 | ``` 20 | 21 | Next we'll move to the CLI wrapper, and use the CLI to inspect the outputs: 22 | 23 | ```shell 24 | $ cd ../InlineLocalHybrid.CLI 25 | $ pulumi stack output 26 | ``` 27 | 28 | We can get more details about the stack with `pulumi stack`: 29 | ```shell 30 | $ pulumi stack 31 | ``` 32 | 33 | Finally we'll go back to our automation program to destroy the stack via `dotnet run destroy`: 34 | 35 | ```shell 36 | $ cd ../InlineLocalHybrid.Automation 37 | $ dotnet run destroy 38 | ``` 39 | -------------------------------------------------------------------------------- /dotnet/InlineProgram/InlineProgram.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /dotnet/InlineProgram/InlineProgram.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31005.135 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InlineProgram", "InlineProgram.csproj", "{DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {45337B5B-63BC-4A76-8AF6-27E1D3CC4280} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /dotnet/InlineSecretsProvider/InlineProgram.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /dotnet/InlineSecretsProvider/InlineProgram.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31005.135 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InlineProgram", "InlineProgram.csproj", "{DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {45337B5B-63BC-4A76-8AF6-27E1D3CC4280} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /dotnet/LocalProgram/automation/LocalProgram.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /dotnet/LocalProgram/automation/LocalProgram.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31005.135 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocalProgram", "LocalProgram.csproj", "{DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {45337B5B-63BC-4A76-8AF6-27E1D3CC4280} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /dotnet/LocalProgram/automation/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Threading.Tasks; 6 | using Pulumi.Automation; 7 | 8 | namespace LocalProgram 9 | { 10 | class Program 11 | { 12 | static async Task Main(string[] args) 13 | { 14 | // to destroy our program, we can run "dotnet run destroy" 15 | var destroy = args.Any() && args[0] == "destroy"; 16 | 17 | var stackName = "dev"; 18 | 19 | // need to account for the assembly executing from within the bin directory 20 | // when getting path to the local program 21 | var executingDir = new DirectoryInfo(Assembly.GetExecutingAssembly().Location).Parent.FullName; 22 | var workingDir = Path.Combine(executingDir, "..", "..", "..", "..", "website"); 23 | 24 | // create our stack using a local program in the ../../../../fargate directory 25 | var stackArgs = new LocalProgramArgs(stackName, workingDir); 26 | var stack = await LocalWorkspace.CreateOrSelectStackAsync(stackArgs); 27 | 28 | Console.WriteLine("successfully initialized stack"); 29 | 30 | // set stack configuration specifying the region to deploy 31 | Console.WriteLine("setting up config..."); 32 | await stack.SetConfigAsync("aws:region", new ConfigValue("us-west-2")); 33 | Console.WriteLine("config set"); 34 | 35 | Console.WriteLine("refreshing stack..."); 36 | await stack.RefreshAsync(new RefreshOptions { OnStandardOutput = Console.WriteLine }); 37 | Console.WriteLine("refresh complete"); 38 | 39 | if (destroy) 40 | { 41 | Console.WriteLine("destroying stack..."); 42 | await stack.DestroyAsync(new DestroyOptions { OnStandardOutput = Console.WriteLine }); 43 | Console.WriteLine("stack destroy complete"); 44 | } 45 | else 46 | { 47 | Console.WriteLine("updating stack..."); 48 | var result = await stack.UpAsync(new UpOptions { OnStandardOutput = Console.WriteLine }); 49 | 50 | if (result.Summary.ResourceChanges != null) 51 | { 52 | Console.WriteLine("update summary:"); 53 | foreach (var change in result.Summary.ResourceChanges) 54 | Console.WriteLine($" {change.Key}: {change.Value}"); 55 | } 56 | 57 | Console.WriteLine($"website url: {result.Outputs["WebsiteUrl"].Value}"); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /dotnet/LocalProgram/website/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Pulumi; 3 | 4 | namespace Website 5 | { 6 | class Program 7 | { 8 | static Task Main(string[] args) 9 | => Deployment.RunAsync(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /dotnet/LocalProgram/website/Pulumi.dev.yaml: -------------------------------------------------------------------------------- 1 | config: 2 | aws:region: us-west-2 3 | -------------------------------------------------------------------------------- /dotnet/LocalProgram/website/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: website 2 | runtime: dotnet 3 | description: A Pulumi AWS .NET program that deploys a static website. 4 | -------------------------------------------------------------------------------- /dotnet/LocalProgram/website/Website.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /dotnet/LocalProgram/website/Website.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31005.135 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Website", "Website.csproj", "{DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {DAF8A70D-78EE-4FC2-BD3E-E99C53C8C317}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {45337B5B-63BC-4A76-8AF6-27E1D3CC4280} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /dotnet/RemoteDeployment/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Pulumi.Automation; 3 | 4 | if (args.Length == 0) 5 | { 6 | Console.WriteLine("usage: dotnet run [destroy]"); 7 | Environment.Exit(1); 8 | } 9 | 10 | string org = args[0]; 11 | const string project = "aws-ts-s3-folder"; 12 | var stackName = $"{org}/{project}/dev"; 13 | const string awsRegion = "us-west-2"; 14 | 15 | var stackArgs = new RemoteGitProgramArgs(stackName, "https://github.com/pulumi/examples.git") 16 | { 17 | Branch = "refs/heads/master", 18 | ProjectPath = project, 19 | EnvironmentVariables = 20 | { 21 | { "AWS_REGION", new EnvironmentVariableValue(awsRegion) }, 22 | { "AWS_ACCESS_KEY_ID", RequireFromEnvironment("AWS_ACCESS_KEY_ID") }, 23 | { "AWS_SECRET_ACCESS_KEY", RequireFromEnvironment("AWS_SECRET_ACCESS_KEY", isSecret: true) }, 24 | { "AWS_SESSION_TOKEN", RequireFromEnvironment("AWS_SESSION_TOKEN", isSecret: true) }, 25 | }, 26 | }; 27 | var stack = await RemoteWorkspace.CreateOrSelectStackAsync(stackArgs); 28 | 29 | bool destroy = args.Length > 1 && args[1] == "destroy"; 30 | if (destroy) 31 | { 32 | await stack.DestroyAsync(new RemoteDestroyOptions { OnStandardOutput = Console.WriteLine }); 33 | Console.WriteLine("Stack successfully destroyed"); 34 | } 35 | else 36 | { 37 | var result = await stack.UpAsync(new RemoteUpOptions { OnStandardOutput = Console.WriteLine }); 38 | Console.WriteLine("Update succeeded!"); 39 | Console.WriteLine($"url: {result.Outputs["websiteUrl"].Value}"); 40 | } 41 | 42 | static EnvironmentVariableValue RequireFromEnvironment(string variable, bool isSecret = false) 43 | { 44 | var value = Environment.GetEnvironmentVariable(variable) 45 | ?? throw new InvalidOperationException($"Required environment variable {variable} not set."); 46 | return new EnvironmentVariableValue(value, isSecret); 47 | } 48 | -------------------------------------------------------------------------------- /dotnet/RemoteDeployment/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 .NET console application. You can run `dotnet run` from the project directory, or you could run the resulting `.exe` from the build directory in the `bin` folder. 11 | 12 | ```shell 13 | $ dotnet run 14 | ``` 15 | 16 | This will kick-off the remote deployment using Pulumi Deployments. 17 | 18 | To destroy the stack when you're done, invoke the program with an additional `destroy` argument: 19 | 20 | ```shell 21 | $ dotnet run destroy 22 | ``` 23 | -------------------------------------------------------------------------------- /dotnet/RemoteDeployment/RemoteDeployment.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /go/cli_installation/README.md: -------------------------------------------------------------------------------- 1 | # CLI Installation 2 | 3 | This program demonstrates how to use the installation capabilities of the Automation API. By default Automation API expects the `pulumi` binary to be available on your `$PATH`. Using the installation capabilities you can customize which binary should be used and let the Automation API manage the installation. 4 | 5 | Running this program is just like any other Go program. No invocation through the Pulumi CLI required: 6 | 7 | ```shell 8 | $ go run main.go 9 | Installing pulumi into /var/folders/4q/3skx3qb5191bjhkchcbbrmmm0000gn/T/cli_installation_exmple1292766419 10 | Created/Selected stack "dev" 11 | Starting update 12 | Updating (dev) 13 | 14 | View Live: https://app.pulumi.com/julienp/autoInstall/dev/updates/5 15 | 16 | 17 | + pulumi:pulumi:Stack autoInstall-dev creating (0s) 18 | @ Updating..... 19 | + random:index:RandomPet Fluffy creating (0s) 20 | + random:index:RandomPet Fluffy created (0.72s) 21 | @ Updating.... 22 | + pulumi:pulumi:Stack autoInstall-dev created (3s) 23 | Outputs: 24 | pet.id: "capable-swine" 25 | 26 | Resources: 27 | + 2 created 28 | 29 | Duration: 4s 30 | 31 | Update succeeded! 32 | pet: capable-swine 33 | ``` 34 | 35 | To destroy the stack when you're done, invoke the program with an additional `destroy` argument: 36 | 37 | ```shell 38 | $ go run main.go destroy 39 | Installing pulumi into /var/folders/4q/3skx3qb5191bjhkchcbbrmmm0000gn/T/cli_installation_exmple2829698449 40 | Created/Selected stack "dev" 41 | Starting stack destroy 42 | Destroying (dev) 43 | 44 | View Live: https://app.pulumi.com/julienp/autoInstall/dev/updates/6 45 | 46 | 47 | - random:index:RandomPet Fluffy deleting (0s) 48 | - random:index:RandomPet Fluffy deleted (0.63s) 49 | @ Destroying.... 50 | - pulumi:pulumi:Stack autoInstall-dev deleting (0s) 51 | @ Destroying.... 52 | - pulumi:pulumi:Stack autoInstall-dev deleted (0.92s) 53 | Outputs: 54 | - pet.id: "capable-swine" 55 | 56 | Resources: 57 | - 2 deleted 58 | 59 | Duration: 3s 60 | 61 | The resources in the stack have been deleted, but the history and configuration associated with the stack are still maintained. 62 | If you want to remove the stack completely, run `pulumi stack rm dev`. 63 | Stack successfully destroyed 64 | ``` 65 | -------------------------------------------------------------------------------- /go/cli_installation/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/blang/semver" 9 | random "github.com/pulumi/pulumi-random/sdk/v4/go/random" 10 | 11 | "github.com/pulumi/pulumi/sdk/v3/go/auto" 12 | "github.com/pulumi/pulumi/sdk/v3/go/auto/optdestroy" 13 | "github.com/pulumi/pulumi/sdk/v3/go/auto/optup" 14 | "github.com/pulumi/pulumi/sdk/v3/go/pulumi" 15 | ) 16 | 17 | func main() { 18 | // to destroy our program, we can run `go run main.go destroy` 19 | destroy := false 20 | argsWithoutProg := os.Args[1:] 21 | if len(argsWithoutProg) > 0 { 22 | if argsWithoutProg[0] == "destroy" { 23 | destroy = true 24 | } 25 | } 26 | 27 | deployFunc := func(ctx *pulumi.Context) error { 28 | pet, err := random.NewRandomPet(ctx, "Fluffy", &random.RandomPetArgs{}) 29 | if err != nil { 30 | return err 31 | } 32 | ctx.Export("pet.id", pet.ID()) 33 | return nil 34 | } 35 | 36 | ctx := context.Background() 37 | 38 | projectName := "autoInstall" 39 | stackName := "dev" 40 | 41 | tempDir, err := os.MkdirTemp("", "cli_installation_exmple") 42 | if err != nil { 43 | fmt.Printf("Failed to create temp dir: %v\n", err) 44 | os.Exit(1) 45 | } 46 | 47 | fmt.Printf("Installing pulumi into %s\n", tempDir) 48 | 49 | // Install pulumi v3.104.1 into $tmpDir 50 | pulumiCommand, err := auto.InstallPulumiCommand(ctx, &auto.PulumiCommandOptions{ 51 | // Version defaults to the version matching the current pulumi/sdk. 52 | Version: semver.MustParse("3.104.1"), 53 | // Root defaults to `$HOME/.pulumi/versions/$VERSION`. 54 | Root: tempDir, 55 | }) 56 | if err != nil { 57 | fmt.Printf("Failed to install pulumi command: %v\n", err) 58 | os.Exit(1) 59 | } 60 | 61 | // You can also retrieve an already installed version using NewPulumiCommand. 62 | // This will return an error if no pulumi binary can be found or a binary 63 | // is found but the version is older than the requested version. 64 | // 65 | // pulumiCommand, err := auto.NewPulumiCommand(&auto.PulumiCommandOptions{ 66 | // Version: semver.MustParse("3.104.1"), 67 | // Root: tempDir, 68 | // }) 69 | 70 | // Pass the PulumiCommand instance as an option for the underlying workspace. 71 | s, err := auto.UpsertStackInlineSource(ctx, stackName, projectName, deployFunc, auto.Pulumi(pulumiCommand)) 72 | if err != nil { 73 | fmt.Printf("Failed to set up a workspace: %v\n", err) 74 | os.Exit(1) 75 | } 76 | 77 | fmt.Printf("Created/Selected stack %q\n", stackName) 78 | 79 | if destroy { 80 | fmt.Println("Starting stack destroy") 81 | 82 | // wire up our destroy to stream progress to stdout 83 | stdoutStreamer := optdestroy.ProgressStreams(os.Stdout) 84 | 85 | // destroy our stack and exit early 86 | _, err := s.Destroy(ctx, stdoutStreamer) 87 | if err != nil { 88 | fmt.Printf("Failed to destroy stack: %v", err) 89 | } 90 | fmt.Println("Stack successfully destroyed") 91 | os.Exit(0) 92 | } 93 | 94 | fmt.Println("Starting update") 95 | 96 | // wire up our update to stream progress to stdout 97 | stdoutStreamer := optup.ProgressStreams(os.Stdout) 98 | 99 | // run the update 100 | res, err := s.Up(ctx, stdoutStreamer) 101 | if err != nil { 102 | fmt.Printf("Failed to update stack: %v\n\n", err) 103 | os.Exit(1) 104 | } 105 | 106 | fmt.Println("Update succeeded!") 107 | 108 | // get the URL from the stack outputs 109 | petID, ok := res.Outputs["pet.id"].Value.(string) 110 | if !ok { 111 | fmt.Println("Failed to unmarshall output pet.id") 112 | os.Exit(1) 113 | } 114 | 115 | fmt.Printf("pet: %s\n", petID) 116 | } 117 | -------------------------------------------------------------------------------- /go/database_migration/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/go/database_migration 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/go-sql-driver/mysql v1.5.0 7 | github.com/pulumi/pulumi-aws/sdk/v4 v4.0.0 8 | github.com/pulumi/pulumi/sdk/v3 v3.0.0 9 | ) 10 | -------------------------------------------------------------------------------- /go/git_repo_program/README.md: -------------------------------------------------------------------------------- 1 | # Git Repo Program 2 | 3 | This program demonstrates how to use Automation API with a Pulumi program from git remote. This example deploys the [aws-go-s3 project from the pulumi examples repo](https://github.com/pulumi/examples/tree/master/aws-go-s3-folder). The Automation API takes care of all of the work of cloning and setting up the repo. 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", and cloned program from git 14 | Successfully set config 15 | Starting refresh 16 | Refresh succeeded! 17 | Starting update 18 | Updating (dev) 19 | 20 | View Live: https://app.pulumi.com/EvanBoyle/aws-go-s3-folder/dev/updates/18 21 | 22 | 23 | + pulumi:pulumi:Stack aws-go-s3-folder-dev creating 24 | + aws:s3:Bucket s3-website-bucket creating 25 | + aws:s3:Bucket s3-website-bucket created 26 | + aws:s3:BucketPolicy bucketPolicy creating 27 | + aws:s3:BucketObject index.html creating 28 | + aws:s3:BucketObject favicon.png creating 29 | + aws:s3:BucketPolicy bucketPolicy created 30 | + aws:s3:BucketObject index.html created 31 | + aws:s3:BucketObject favicon.png created 32 | + pulumi:pulumi:Stack aws-go-s3-folder-dev created 33 | 34 | Outputs: 35 | bucketName: "s3-website-bucket-85aa86a" 36 | websiteUrl: "s3-website-bucket-85aa86a.s3-website-us-west-2.amazonaws.com" 37 | 38 | Resources: 39 | + 5 created 40 | 41 | Duration: 8s 42 | 43 | Update succeeded! 44 | URL: s3-website-bucket-85aa86a.s3-website-us-west-2.amazonaws.com 45 | ``` 46 | 47 | To destroy the stack when you're done, invoke the program with an additional `destroy` argument: 48 | 49 | ```shell 50 | $ go run main.go destroy 51 | Created/Selected stack "dev", and cloned program from git 52 | Successfully set config 53 | Starting refresh 54 | Refresh succeeded! 55 | Starting stack destroy 56 | Destroying (dev) 57 | 58 | View Live: https://app.pulumi.com/EvanBoyle/aws-go-s3-folder/dev/updates/20 59 | 60 | 61 | - aws:s3:BucketPolicy bucketPolicy deleting 62 | - aws:s3:BucketObject favicon.png deleting 63 | - aws:s3:BucketObject index.html deleting 64 | - aws:s3:BucketObject favicon.png deleted 65 | - aws:s3:BucketObject index.html deleted 66 | - aws:s3:BucketPolicy bucketPolicy deleted 67 | - aws:s3:Bucket s3-website-bucket deleting 68 | - aws:s3:Bucket s3-website-bucket deleted 69 | - pulumi:pulumi:Stack aws-go-s3-folder-dev deleting 70 | - pulumi:pulumi:Stack aws-go-s3-folder-dev deleted 71 | 72 | Outputs: 73 | - bucketName: "s3-website-bucket-85aa86a" 74 | - websiteUrl: "s3-website-bucket-85aa86a.s3-website-us-west-2.amazonaws.com" 75 | 76 | Resources: 77 | - 5 deleted 78 | 79 | Duration: 3s 80 | 81 | The resources in the stack have been deleted, but the history and configuration associated with the stack are still maintained. 82 | If you want to remove the stack completely, run 'pulumi stack rm dev'. 83 | Stack successfully destroyed 84 | ``` 85 | -------------------------------------------------------------------------------- /go/git_repo_program/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/pulumi/pulumi/sdk/v3/go/auto" 9 | "github.com/pulumi/pulumi/sdk/v3/go/auto/optdestroy" 10 | "github.com/pulumi/pulumi/sdk/v3/go/auto/optup" 11 | ) 12 | 13 | func main() { 14 | // to destroy our program, we can run `go run main.go destroy` 15 | destroy := false 16 | argsWithoutProg := os.Args[1:] 17 | if len(argsWithoutProg) > 0 { 18 | if argsWithoutProg[0] == "destroy" { 19 | destroy = true 20 | } 21 | } 22 | ctx := context.Background() 23 | 24 | projectName := "aws-go-s3-folder" 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 | // arguments used to setup the remote Pulumi program 30 | repo := auto.GitRepo{ 31 | URL: "https://github.com/pulumi/examples.git", 32 | ProjectPath: projectName, 33 | } 34 | 35 | // create or select an existing stack matching the given name. 36 | // this stack will use the Pulumi program from the specified git remote. 37 | s, err := auto.UpsertStackRemoteSource(ctx, stackName, repo) 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, and cloned program from git\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 s3 website 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["websiteUrl"].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/inline_local_hybrid/automation/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/go/inline_local_hybrid/automation 2 | 3 | go 1.14 4 | 5 | replace github.com/pulumi/automation-api-examples/go/inline_local_hybrid/infra => ../infra 6 | 7 | require ( 8 | github.com/pulumi/automation-api-examples/go/inline_local_hybrid/infra v0.0.0-00010101000000-000000000000 9 | github.com/pulumi/pulumi/sdk/v3 v3.0.0 10 | ) 11 | -------------------------------------------------------------------------------- /go/inline_local_hybrid/automation/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "path/filepath" 8 | 9 | "github.com/pulumi/automation-api-examples/go/inline_local_hybrid/infra" 10 | "github.com/pulumi/pulumi/sdk/v3/go/auto" 11 | "github.com/pulumi/pulumi/sdk/v3/go/auto/optdestroy" 12 | "github.com/pulumi/pulumi/sdk/v3/go/auto/optup" 13 | ) 14 | 15 | func main() { 16 | // to destroy our program, we can run `go run main.go destroy` 17 | destroy := false 18 | argsWithoutProg := os.Args[1:] 19 | if len(argsWithoutProg) > 0 { 20 | if argsWithoutProg[0] == "destroy" { 21 | destroy = true 22 | } 23 | } 24 | ctx := context.Background() 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 | // we're going to use the same working directory as our CLI driver. 30 | // doing this allows us to share the Project and Stack Settings (Pulumi.yaml and any Pulumi..yaml files) 31 | workDir := filepath.Join("..", "cli") 32 | 33 | // create or select an existing stack matching the given name. 34 | // using LocalSource sets up the workspace to use existing project/stack settings in our cli package. 35 | // here our inline program comes from a shared package. 36 | // this allows us to have both an automation program, and a manual CLI program for development sharing code. 37 | s, err := auto.UpsertStackLocalSource(ctx, stackName, workDir, auto.Program(infra.WebsiteDeployFunc)) 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 | fmt.Println("Installing the AWS plugin") 46 | 47 | w := s.Workspace() 48 | // for inline source programs, we must manage plugins ourselves 49 | err = w.InstallPlugin(ctx, "aws", "v4.0.0") 50 | if err != nil { 51 | fmt.Printf("Failed to install program plugins: %v\n", err) 52 | os.Exit(1) 53 | } 54 | 55 | fmt.Println("Successfully installed AWS plugin") 56 | 57 | // set stack configuration specifying the AWS region to deploy 58 | s.SetConfig(ctx, "aws:region", auto.ConfigValue{Value: "us-west-2"}) 59 | 60 | fmt.Println("Successfully set config") 61 | fmt.Println("Starting refresh") 62 | 63 | _, err = s.Refresh(ctx) 64 | if err != nil { 65 | fmt.Printf("Failed to refresh stack: %v\n", err) 66 | os.Exit(1) 67 | } 68 | 69 | fmt.Println("Refresh succeeded!") 70 | 71 | if destroy { 72 | fmt.Println("Starting stack destroy") 73 | 74 | // wire up our destroy to stream progress to stdout 75 | stdoutStreamer := optdestroy.ProgressStreams(os.Stdout) 76 | 77 | // destroy our stack and exit early 78 | _, err := s.Destroy(ctx, stdoutStreamer) 79 | if err != nil { 80 | fmt.Printf("Failed to destroy stack: %v", err) 81 | } 82 | fmt.Println("Stack successfully destroyed") 83 | os.Exit(0) 84 | } 85 | 86 | fmt.Println("Starting update") 87 | 88 | // wire up our update to stream progress to stdout 89 | stdoutStreamer := optup.ProgressStreams(os.Stdout) 90 | 91 | // run the update to deploy our s3 website 92 | res, err := s.Up(ctx, stdoutStreamer) 93 | if err != nil { 94 | fmt.Printf("Failed to update stack: %v\n\n", err) 95 | os.Exit(1) 96 | } 97 | 98 | fmt.Println("Update succeeded!") 99 | 100 | // get the URL from the stack outputs 101 | url, ok := res.Outputs["websiteUrl"].Value.(string) 102 | if !ok { 103 | fmt.Println("Failed to unmarshall output URL") 104 | os.Exit(1) 105 | } 106 | 107 | fmt.Printf("URL: %s\n", url) 108 | } 109 | -------------------------------------------------------------------------------- /go/inline_local_hybrid/cli/Pulumi.dev.yaml: -------------------------------------------------------------------------------- 1 | config: 2 | aws:region: us-west-2 3 | -------------------------------------------------------------------------------- /go/inline_local_hybrid/cli/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | 2 | name: hybridS3Project 3 | runtime: go 4 | description: A static website hosted on AWS S3 5 | template: 6 | config: 7 | aws:region: 8 | description: The AWS region to deploy into 9 | default: us-west-2 -------------------------------------------------------------------------------- /go/inline_local_hybrid/cli/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/go/inline_local_hybrid/cli 2 | 3 | go 1.14 4 | 5 | replace github.com/pulumi/automation-api-examples/go/inline_local_hybrid/infra => ../infra 6 | 7 | require ( 8 | github.com/pulumi/automation-api-examples/go/inline_local_hybrid/infra v0.0.0-00010101000000-000000000000 9 | github.com/pulumi/pulumi/sdk/v3 v3.0.0 10 | ) 11 | -------------------------------------------------------------------------------- /go/inline_local_hybrid/cli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/pulumi/automation-api-examples/go/inline_local_hybrid/infra" 5 | "github.com/pulumi/pulumi/sdk/v3/go/pulumi" 6 | ) 7 | 8 | // this is our pulumi CLI driver. 9 | // sometimes when iterating on infrastructure it's convenient to use the CLI to poke at your infrastructure. 10 | // with this package layout you can still have an inline program with full debugging capabilities, 11 | // without losing the ability to manually destroy, update, or inspect stack outputs with the CLI. 12 | func main() { 13 | pulumi.Run(infra.WebsiteDeployFunc) 14 | } 15 | -------------------------------------------------------------------------------- /go/inline_local_hybrid/infra/deployment.go: -------------------------------------------------------------------------------- 1 | package infra 2 | 3 | import ( 4 | "github.com/pulumi/pulumi-aws/sdk/v4/go/aws/s3" 5 | "github.com/pulumi/pulumi/sdk/v3/go/pulumi" 6 | ) 7 | 8 | // WebsiteDeployFunc is a Pulumi program that deploys a static S3 website 9 | func WebsiteDeployFunc(ctx *pulumi.Context) error { 10 | // similar go git_repo_program, our program defines a s3 website. 11 | // here we create the bucket 12 | siteBucket, err := s3.NewBucket(ctx, "s3-website-bucket", &s3.BucketArgs{ 13 | Website: s3.BucketWebsiteArgs{ 14 | IndexDocument: pulumi.String("index.html"), 15 | }, 16 | }) 17 | if err != nil { 18 | return err 19 | } 20 | 21 | // we define and upload our HTML inline. 22 | indexContent := ` 23 | Hello S3 24 | 25 |

Hello, 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.go 14 | ``` 15 | 16 | This will kick-off the remote deployment using Pulumi Deployments. 17 | 18 | To destroy the stack when you're done, invoke the program with an additional `destroy` argument: 19 | 20 | ```shell 21 | $ go run main.go destroy 22 | ``` 23 | -------------------------------------------------------------------------------- /go/remote_deployment/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/go/remote_deployment 2 | 3 | go 1.18 4 | 5 | require github.com/pulumi/pulumi/sdk/v3 v3.45.0 6 | 7 | require ( 8 | github.com/Microsoft/go-winio v0.5.2 // indirect 9 | github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect 10 | github.com/acomagu/bufpipe v1.0.3 // indirect 11 | github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect 12 | github.com/blang/semver v3.5.1+incompatible // indirect 13 | github.com/cheggaaa/pb v1.0.18 // indirect 14 | github.com/djherbis/times v1.2.0 // indirect 15 | github.com/emirpasic/gods v1.12.0 // indirect 16 | github.com/fsnotify/fsnotify v1.4.9 // indirect 17 | github.com/go-git/gcfg v1.5.0 // indirect 18 | github.com/go-git/go-billy/v5 v5.3.1 // indirect 19 | github.com/go-git/go-git/v5 v5.4.2 // indirect 20 | github.com/gofrs/uuid v3.3.0+incompatible // indirect 21 | github.com/gogo/protobuf v1.3.2 // indirect 22 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect 23 | github.com/golang/protobuf v1.4.2 // indirect 24 | github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect 25 | github.com/hashicorp/errwrap v1.0.0 // indirect 26 | github.com/hashicorp/go-multierror v1.0.0 // indirect 27 | github.com/imdario/mergo v0.3.12 // indirect 28 | github.com/inconshreveable/mousetrap v1.0.0 // indirect 29 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect 30 | github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect 31 | github.com/mattn/go-isatty v0.0.16 // indirect 32 | github.com/mattn/go-runewidth v0.0.8 // indirect 33 | github.com/mitchellh/go-homedir v1.1.0 // indirect 34 | github.com/mitchellh/go-ps v1.0.0 // indirect 35 | github.com/nxadm/tail v1.4.8 // indirect 36 | github.com/opentracing/basictracer-go v1.0.0 // indirect 37 | github.com/opentracing/opentracing-go v1.1.0 // indirect 38 | github.com/pkg/errors v0.9.1 // indirect 39 | github.com/pkg/term v1.1.0 // indirect 40 | github.com/rivo/uniseg v0.2.0 // indirect 41 | github.com/rogpeppe/go-internal v1.8.1 // indirect 42 | github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94 // indirect 43 | github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 // indirect 44 | github.com/sergi/go-diff v1.1.0 // indirect 45 | github.com/spf13/cobra v1.4.0 // indirect 46 | github.com/spf13/pflag v1.0.5 // indirect 47 | github.com/texttheater/golang-levenshtein v0.0.0-20191208221605-eb6844b05fc6 // indirect 48 | github.com/tweekmonster/luser v0.0.0-20161003172636-3fa38070dbd7 // indirect 49 | github.com/uber/jaeger-client-go v2.22.1+incompatible // indirect 50 | github.com/uber/jaeger-lib v2.2.0+incompatible // indirect 51 | github.com/xanzy/ssh-agent v0.3.2 // indirect 52 | go.uber.org/atomic v1.6.0 // indirect 53 | golang.org/x/crypto v0.0.0-20220824171710-5757bc0c5503 // indirect 54 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect 55 | golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24 // indirect 56 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect 57 | golang.org/x/text v0.3.6 // indirect 58 | google.golang.org/genproto v0.0.0-20200608115520-7c474a2e3482 // indirect 59 | google.golang.org/grpc v1.29.1 // indirect 60 | google.golang.org/protobuf v1.24.0 // indirect 61 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect 62 | gopkg.in/warnings.v0 v0.1.2 // indirect 63 | gopkg.in/yaml.v2 v2.4.0 // indirect 64 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect 65 | lukechampine.com/frand v1.4.2 // indirect 66 | sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0 // indirect 67 | ) 68 | -------------------------------------------------------------------------------- /go/remote_deployment/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/pulumi/pulumi/sdk/v3/go/auto" 9 | "github.com/pulumi/pulumi/sdk/v3/go/auto/optremotedestroy" 10 | "github.com/pulumi/pulumi/sdk/v3/go/auto/optremoteup" 11 | ) 12 | 13 | func main() { 14 | ctx := context.Background() 15 | 16 | args := os.Args[1:] 17 | if len(args) == 0 { 18 | fmt.Println("usage: go run main.go [destroy]") 19 | os.Exit(1) 20 | } 21 | 22 | org := args[0] 23 | project := "aws-ts-s3-folder" 24 | stackName := auto.FullyQualifiedStackName(org, project, "dev") 25 | awsRegion := "us-west-2" 26 | 27 | repo := auto.GitRepo{ 28 | URL: "https://github.com/pulumi/examples.git", 29 | Branch: "refs/heads/master", 30 | ProjectPath: project, 31 | } 32 | 33 | env := map[string]auto.EnvVarValue{ 34 | "AWS_REGION": {Value: awsRegion}, 35 | "AWS_ACCESS_KEY_ID": {Value: os.Getenv("AWS_ACCESS_KEY_ID")}, 36 | "AWS_SECRET_ACCESS_KEY": {Value: os.Getenv("AWS_SECRET_ACCESS_KEY"), Secret: true}, 37 | "AWS_SESSION_TOKEN": {Value: os.Getenv("AWS_SESSION_TOKEN"), Secret: true}, 38 | } 39 | 40 | // Create or select an existing stack matching the given name. 41 | s, err := auto.UpsertRemoteStackGitSource(ctx, stackName, repo, auto.RemoteEnvVars(env)) 42 | if err != nil { 43 | fmt.Printf("Failed to create or select stack: %v\n", err) 44 | os.Exit(1) 45 | } 46 | 47 | destroy := len(args) > 1 && args[1] == "destroy" 48 | if destroy { 49 | // Wire up our destroy to stream progress to stdout. 50 | stdoutStreamer := optremotedestroy.ProgressStreams(os.Stdout) 51 | // Destroy our stack and exit early. 52 | _, err := s.Destroy(ctx, stdoutStreamer) 53 | if err != nil { 54 | fmt.Printf("Failed to destroy stack: %v", err) 55 | } 56 | fmt.Println("Stack successfully destroyed") 57 | os.Exit(0) 58 | } 59 | 60 | // Wire up our update to stream progress to stdout. 61 | stdoutStreamer := optremoteup.ProgressStreams(os.Stdout) 62 | 63 | // Run the update to deploy our s3 website. 64 | res, err := s.Up(ctx, stdoutStreamer) 65 | if err != nil { 66 | fmt.Printf("Failed to update stack: %v\n\n", err) 67 | os.Exit(1) 68 | } 69 | 70 | fmt.Println("Update succeeded!") 71 | 72 | // Get the URL from the stack outputs 73 | url, ok := res.Outputs["websiteUrl"].Value.(string) 74 | if !ok { 75 | fmt.Println("Failed to unmarshall output URL") 76 | os.Exit(1) 77 | } 78 | 79 | fmt.Printf("URL: %s\n", url) 80 | } 81 | -------------------------------------------------------------------------------- /go/temporal_vm_mgr/README.md: -------------------------------------------------------------------------------- 1 | # Azure VM Manager (VMGR) 2 | 3 | In this example we use Temporal workflows and Pulumi Automation API to provision temporary VMs that are automatically destroyed after a fixed period. 4 | 5 | (Adapted from https://github.com/mikhailshilkov/pulumi-temporal-workflow) 6 | 7 | ## How to Run the Example 8 | 9 | ### 1. Install a local Temporal server 10 | 11 | Follow [Install Temporal](https://docs.temporal.io/kb/all-the-ways-to-run-a-cluster) to run a local Temporal server. 12 | 13 | ### 2. Run a worker 14 | 15 | Execute the following command from this example's root folder to start a new workflow host process: 16 | 17 | ``` 18 | $ go run *.go 19 | 2020/09/06 11:44:03 INFO No logger configured for temporal client. Created default one. 20 | 2020/09/06 11:44:03 INFO Started Worker Namespace default TaskQueue pulumi WorkerID 9084@hostname.lan@ 21 | ``` 22 | 23 | Leave the worker running until the end of the walkthrough. 24 | 25 | ### 3. Execute a workflow 26 | 27 | ``` 28 | $ docker run --network=host --rm temporalio/tctl:latest wf start --tq pulumi --wt TemporaryVirtualMachine --et 3600 -w myworkflow1 -i '"myvm1"' 29 | 30 | Started Workflow Id: myworkflow1, run Id: d32ca0ef-4b91-4d1d-a31a-d5c434d7ee27 31 | ``` 32 | 33 | The workflow would run and create a virtual machine called `myvm1`. 34 | 35 | ### 4. Clean Up 36 | 37 | After you are done experimenting, depstroy a resource group with a name starting with `server-rg` (e.g. `server-rg487452c`): 38 | 39 | ``` 40 | $ az group list -o table 41 | 42 | Name Location Status 43 | --------------------- --------- --------- 44 | server-rge487452c westus Succeeded 45 | 46 | $ az group delete -n server-rge487452c 47 | ``` 48 | -------------------------------------------------------------------------------- /go/temporal_vm_mgr/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | 6 | "go.temporal.io/sdk/client" 7 | "go.temporal.io/sdk/worker" 8 | 9 | "github.com/pierskarsenbarg/pulumi-temporal/workflow" 10 | ) 11 | 12 | func main() { 13 | // The client is a heavyweight object that should be created once 14 | clientOptions := client.Options{HostPort: "localhost:7233"} 15 | serviceClient, err := client.NewClient(clientOptions) 16 | 17 | if err != nil { 18 | log.Fatalf("Unable to create client. Error: %v", err) 19 | } 20 | 21 | w := worker.New(serviceClient, "pulumi", worker.Options{}) 22 | 23 | w.RegisterWorkflow(workflow.TemporaryVirtualMachine) 24 | w.RegisterActivity(workflow.EnsureNetwork) 25 | w.RegisterActivity(workflow.DeployVirtualMachine) 26 | w.RegisterActivity(workflow.TearDownVirtualMachine) 27 | 28 | err = w.Run(worker.InterruptCh()) 29 | if err != nil { 30 | log.Fatalf("Unable to start worker. Error: %v", err) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /go/temporal_vm_mgr/workflow/tearDown.go: -------------------------------------------------------------------------------- 1 | package workflow 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/pkg/errors" 7 | "github.com/pulumi/pulumi/sdk/v3/go/auto" 8 | "github.com/pulumi/pulumi/sdk/v3/go/common/tokens" 9 | "github.com/pulumi/pulumi/sdk/v3/go/common/workspace" 10 | "go.temporal.io/sdk/activity" 11 | ) 12 | 13 | func TearDownVirtualMachine(ctx context.Context, projectName, stackName string) error { 14 | logger := activity.GetLogger(ctx) 15 | project := workspace.Project{ 16 | Name: tokens.PackageName(projectName), 17 | Runtime: workspace.NewProjectRuntimeInfo("go", nil), 18 | } 19 | 20 | logger.Info("Setting up webserver stack...") 21 | 22 | w, err := auto.NewLocalWorkspace(ctx, auto.Project(project)) 23 | if err != nil { 24 | return errors.Wrap(err, "failed to create workspace") 25 | } 26 | 27 | err = w.InstallPlugin(ctx, "azure-native", "v1.102.0") 28 | if err != nil { 29 | return errors.Wrap(err, "failed to install program plugins") 30 | } 31 | err = w.InstallPlugin(ctx, "random", "v4.13.2") 32 | if err != nil { 33 | return errors.Wrap(err, "failed to install program plugins") 34 | } 35 | 36 | user, err := w.WhoAmI(ctx) 37 | if err != nil { 38 | return errors.Wrap(err, "failed to get authenticated user") 39 | } 40 | 41 | fqsn := auto.FullyQualifiedStackName(user, projectName, stackName) 42 | s, err := auto.SelectStack(ctx, fqsn, w) 43 | if err != nil { 44 | return errors.Wrap(err, "failed to select stack") 45 | } 46 | 47 | logger.Info("Destroying stack...", "stackName", stackName) 48 | 49 | _, err = s.Destroy(ctx) 50 | if err != nil { 51 | return errors.Wrap(err, "failed to destroy VM stack") 52 | } 53 | 54 | logger.Info("Deleting stack...", "stackName", stackName) 55 | 56 | err = w.RemoveStack(ctx, stackName) 57 | if err != nil { 58 | return errors.Wrap(err, "failed to remove stack") 59 | } 60 | 61 | return nil 62 | } 63 | -------------------------------------------------------------------------------- /go/temporal_vm_mgr/workflow/virtualMachine.go: -------------------------------------------------------------------------------- 1 | package workflow 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/pierskarsenbarg/pulumi-temporal/webserver" 8 | "github.com/pkg/errors" 9 | "github.com/pulumi/pulumi-random/sdk/v4/go/random" 10 | "github.com/pulumi/pulumi/sdk/v3/go/auto" 11 | "github.com/pulumi/pulumi/sdk/v3/go/common/tokens" 12 | "github.com/pulumi/pulumi/sdk/v3/go/common/workspace" 13 | "github.com/pulumi/pulumi/sdk/v3/go/pulumi" 14 | "go.temporal.io/sdk/activity" 15 | ) 16 | 17 | func DeployVirtualMachine(ctx context.Context, projectName, vmName string, network *Network) (string, error) { 18 | logger := activity.GetLogger(ctx) 19 | stackName := fmt.Sprintf("vmgr%s", vmName) 20 | project := workspace.Project{ 21 | Name: tokens.PackageName(projectName), 22 | Runtime: workspace.NewProjectRuntimeInfo("go", nil), 23 | } 24 | 25 | logger.Info("Setting up webserver stack " + vmName) 26 | 27 | w, err := auto.NewLocalWorkspace(ctx, auto.Project(project)) 28 | if err != nil { 29 | return "", errors.Wrap(err, "failed to create workspace") 30 | } 31 | 32 | err = w.InstallPlugin(ctx, "azure-native", "v1.102.0") 33 | if err != nil { 34 | return "", errors.Wrap(err, "failed to install program plugins") 35 | } 36 | err = w.InstallPlugin(ctx, "random", "v4.13.2") 37 | if err != nil { 38 | return "", errors.Wrap(err, "failed to install program plugins") 39 | } 40 | 41 | user, err := w.WhoAmI(ctx) 42 | if err != nil { 43 | return "", errors.Wrap(err, "failed to get authenticated user") 44 | } 45 | 46 | // create the stack user/vmgr/vmgrXXXXXXXX, could create these stacks under an org instead 47 | fqsn := auto.FullyQualifiedStackName(user, projectName, stackName) 48 | s, err := auto.UpsertStack(ctx, fqsn, w) 49 | if err != nil { 50 | return "", errors.Wrap(err, "failed to create stack") 51 | } 52 | 53 | err = s.SetConfig(ctx, "azure-native:location", auto.ConfigValue{Value: "westus"}) 54 | if err != nil { 55 | return "", errors.Wrap(err, "failed to set config") 56 | } 57 | 58 | // set out program for the deployment with the resulting network info 59 | w.SetProgram(GetDeployVMFunc(vmName, network)) 60 | 61 | logger.Info("Deploying a VM webserver...") 62 | 63 | res, err := s.Up(ctx) 64 | if err != nil { 65 | return "", errors.Wrap(err, "failed to deploy VM stack") 66 | } 67 | 68 | logger.Info("Deployed a new VM", "ip", res.Outputs["ip"].Value.(string)) 69 | 70 | return stackName, nil 71 | } 72 | 73 | func GetDeployVMFunc(vmName string, network *Network) pulumi.RunFunc { 74 | return func(ctx *pulumi.Context) error { 75 | username := "pulumi" 76 | password, err := random.NewRandomPassword(ctx, "password", &random.RandomPasswordArgs{ 77 | Length: pulumi.Int(16), 78 | Special: pulumi.Bool(true), 79 | }) 80 | if err != nil { 81 | return err 82 | } 83 | 84 | server, err := webserver.NewWebserver(ctx, vmName, &webserver.WebserverArgs{ 85 | Username: pulumi.String(username), 86 | Password: password.Result, 87 | BootScript: `#!/bin/bash 88 | echo "Hello, from VMGR!" > index.html 89 | nohup python -m SimpleHTTPServer 80 &`, 90 | ResourceGroupName: pulumi.String(network.ResourceGroupName), 91 | SubnetID: pulumi.String(network.SubnetID), 92 | }) 93 | if err != nil { 94 | return err 95 | } 96 | 97 | ctx.Export("ip", server.GetIPAddress(ctx)) 98 | return nil 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /go/temporal_vm_mgr/workflow/workflow.go: -------------------------------------------------------------------------------- 1 | package workflow 2 | 3 | import ( 4 | "errors" 5 | "time" 6 | 7 | "go.temporal.io/sdk/workflow" 8 | ) 9 | 10 | func TemporaryVirtualMachine(ctx workflow.Context, vmName string) error { 11 | logger := workflow.GetLogger(ctx) 12 | logger.Info("Workflow TemporaryVirtualMachine started") 13 | 14 | if vmName == "" { 15 | return errors.New("no VM name received") 16 | } 17 | 18 | ao := workflow.ActivityOptions{ 19 | ScheduleToStartTimeout: time.Hour, 20 | StartToCloseTimeout: time.Hour, 21 | } 22 | ctx = workflow.WithActivityOptions(ctx, ao) 23 | 24 | // You could also make it a workflow parameter. 25 | projectName := "vmgr" 26 | 27 | var network *Network 28 | err := workflow.ExecuteActivity(ctx, EnsureNetwork, projectName).Get(ctx, &network) 29 | if err != nil { 30 | return err 31 | } 32 | 33 | var stackName string 34 | err = workflow.ExecuteActivity(ctx, DeployVirtualMachine, projectName, vmName, network).Get(ctx, &stackName) 35 | if err != nil { 36 | return err 37 | } 38 | 39 | logger.Info("VM is ready", "stackName", stackName) 40 | 41 | err = workflow.NewTimer(ctx, time.Minute*5).Get(ctx, nil) 42 | if err != nil { 43 | return err 44 | } 45 | 46 | err = workflow.ExecuteActivity(ctx, TearDownVirtualMachine, projectName, stackName).Get(ctx, nil) 47 | if err != nil { 48 | return err 49 | } 50 | 51 | logger.Info("Temporary Virtual Machine workflow complete") 52 | return nil 53 | } 54 | -------------------------------------------------------------------------------- /go/vm_manager_azure/cmd/vmgr/add.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/pulumi/automation-api-examples/go/vm_manager_azure/infra/deploy" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func NewAddCmd() *cobra.Command { 9 | return &cobra.Command{ 10 | Use: "add", 11 | Short: "add deploys an additional additional vm stack", 12 | Long: `add deploys an additional additional vm stack. 13 | add could be extended to accept custom VM sizes, credentials, regions, etc.`, 14 | Run: func(cmd *cobra.Command, args []string) { 15 | // Deploy provisions a new VM running a webserver and prints out the public IP 16 | deploy.Deploy() 17 | }, 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /go/vm_manager_azure/cmd/vmgr/cron.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/pulumi/automation-api-examples/go/vm_manager_azure/infra/reap" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | func NewCronCmd() *cobra.Command { 12 | return &cobra.Command{ 13 | Use: "cron [expiry]", 14 | Short: "cron monitors and cleans up old vmgr deployments", 15 | Long: `cron monitors and cleans up old vmgr deployments. It looks for any deployments older than expirationPeriodInMinutes and destroys them.`, 16 | Example: "`cron 1h` `cron 1m` `cron 5d`", 17 | Args: cobra.ExactArgs(1), 18 | Run: func(cmd *cobra.Command, args []string) { 19 | duration, err := time.ParseDuration(args[0]) 20 | if err != nil { 21 | fmt.Printf("error, failed to parse expiry duration: %v\n", err) 22 | cmd.Usage() 23 | } 24 | for { 25 | fmt.Printf("Checking for VMs over %s old to reap...\n", args[0]) 26 | reap.Reap(duration) 27 | fmt.Println("Sleeping for 60 seconds before checking again...") 28 | fmt.Println() 29 | time.Sleep(60 * time.Second) 30 | } 31 | }, 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /go/vm_manager_azure/cmd/vmgr/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | func main() { 9 | if err := NewVmgrCmd().Execute(); err != nil { 10 | fmt.Println(err) 11 | os.Exit(1) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /go/vm_manager_azure/cmd/vmgr/vmgr.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | ) 6 | 7 | func NewVmgrCmd() *cobra.Command { 8 | cmd := &cobra.Command{ 9 | Use: "vmgr", 10 | Short: "vmgr vm management command line", 11 | Long: `Pupiter is an interpreter for Pulumi.`, 12 | Args: cobra.ArbitraryArgs, 13 | } 14 | 15 | cmd.AddCommand(NewAddCmd()) 16 | cmd.AddCommand(NewCronCmd()) 17 | return cmd 18 | } -------------------------------------------------------------------------------- /go/vm_manager_azure/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/go/vm_manager_azure 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/pulumi/pulumi-azure/sdk/v4 v4.0.0 7 | github.com/pulumi/pulumi-random/sdk/v4 v4.0.0 8 | github.com/pulumi/pulumi/sdk/v3 v3.0.0 9 | github.com/spf13/cobra v1.0.0 10 | ) 11 | -------------------------------------------------------------------------------- /go/vm_manager_azure/infra/reap/reap.go: -------------------------------------------------------------------------------- 1 | package reap 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "time" 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/common/tokens" 12 | "github.com/pulumi/pulumi/sdk/v3/go/common/workspace" 13 | "github.com/pulumi/pulumi/sdk/v3/go/pulumi" 14 | ) 15 | 16 | // Reap cleans up all vmgr stacks that are older than the specified threshold 17 | func Reap(threshold time.Duration) { 18 | ctx := context.Background() 19 | projectName := "vmgr" 20 | project := workspace.Project{ 21 | Name: tokens.PackageName(projectName), 22 | Runtime: workspace.NewProjectRuntimeInfo("go", nil), 23 | } 24 | 25 | // destroy doesn't run the program, so we have a placeholder here 26 | nilProgram := auto.Program(func(pCtx *pulumi.Context) error { return nil }) 27 | 28 | w, err := auto.NewLocalWorkspace(ctx, nilProgram, auto.Project(project)) 29 | if err != nil { 30 | fmt.Printf("Failed to create workspace: %v\n", err) 31 | os.Exit(1) 32 | } 33 | 34 | err = w.InstallPlugin(ctx, "azure", "v4.0.0") 35 | if err != nil { 36 | fmt.Printf("Failed to install program plugins: %v\n", err) 37 | os.Exit(1) 38 | } 39 | err = w.InstallPlugin(ctx, "random", "v4.0.0") 40 | if err != nil { 41 | fmt.Printf("Failed to install program plugins: %v\n", err) 42 | os.Exit(1) 43 | } 44 | 45 | stacks, err := w.ListStacks(ctx) 46 | if err != nil { 47 | fmt.Printf("failed to list stacks: %v\n", err) 48 | os.Exit(1) 49 | } 50 | 51 | expiration := time.Now().Add(-1 * threshold) 52 | 53 | var stacksToDestroy []string 54 | for _, stackSummary := range stacks { 55 | // don't clean up the networking stack or uninitialized stacks 56 | if stackSummary.LastUpdate == "" || stackSummary.Name == "networking" { 57 | continue 58 | } 59 | lastUpdateTime, err := time.Parse(time.RFC3339, stackSummary.LastUpdate) 60 | if err != nil { 61 | fmt.Printf("failed to parse stack update time: %v\n", err) 62 | os.Exit(1) 63 | } 64 | 65 | if lastUpdateTime.Before(expiration) { 66 | stacksToDestroy = append(stacksToDestroy, stackSummary.Name) 67 | fmt.Printf("Found expired stack %s last deployed at %s\n", stackSummary.Name, stackSummary.LastUpdate) 68 | } 69 | } 70 | 71 | fmt.Printf("Found %d stacks to clean up\n", len(stacksToDestroy)) 72 | 73 | fails := 0 74 | success := 0 75 | 76 | for _, sName := range stacksToDestroy { 77 | s, err := auto.SelectStack(ctx, sName, w) 78 | if err != nil { 79 | fmt.Printf("failed to select stack: %v\n", err) 80 | os.Exit(1) 81 | } 82 | 83 | fmt.Printf("destroying stack %s\n", sName) 84 | 85 | // wire up our destroy to stream progress to stdout 86 | stdoutStreamer := optdestroy.ProgressStreams(os.Stdout) 87 | 88 | _, err = s.Destroy(ctx, stdoutStreamer) 89 | if err != nil { 90 | fmt.Printf("failed to clean up stack %s: %v\n", sName, err) 91 | fmt.Println("will try again in 60 seconds") 92 | fails++ 93 | continue 94 | } 95 | success++ 96 | 97 | fmt.Printf("removing stack %s and all associated config and history\n", sName) 98 | 99 | err = w.RemoveStack(ctx, sName) 100 | if err != nil { 101 | fmt.Printf("failed to remove stack %s: %v\n", sName, err) 102 | } 103 | 104 | fmt.Printf("stack %s successfully reaped \n", sName) 105 | } 106 | 107 | fmt.Printf("destroyed %d stack(s)\n", success) 108 | if fails > 0 { 109 | fmt.Printf("failed to destroy %d stacks, will retry next iteration\n", fails) 110 | } 111 | fmt.Println("finished reaping stacks") 112 | 113 | } 114 | -------------------------------------------------------------------------------- /java/databaseMigration/.gitignore: -------------------------------------------------------------------------------- 1 | # Maven 2 | target/ 3 | pom.xml.tag 4 | pom.xml.releaseBackup 5 | pom.xml.versionsBackup 6 | pom.xml.next 7 | release.properties 8 | dependency-reduced-pom.xml 9 | buildNumber.properties 10 | .mvn/timing.properties 11 | 12 | # IDE files 13 | .idea/ 14 | *.iml 15 | .vscode/ 16 | .settings/ 17 | .project 18 | .classpath 19 | -------------------------------------------------------------------------------- /java/databaseMigration/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.example 8 | myproject 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 11 13 | 11 14 | 15 | 16 | 17 | 18 | com.pulumi 19 | pulumi 20 | [1.3,2.0) 21 | 22 | 23 | com.pulumi 24 | aws 25 | 6.68.0 26 | 27 | 28 | mysql 29 | mysql-connector-java 30 | 8.0.33 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.codehaus.mojo 38 | exec-maven-plugin 39 | 3.1.0 40 | 41 | com.example.App 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /java/inlineProgram/.gitignore: -------------------------------------------------------------------------------- 1 | # Java app 2 | .gradle/ 3 | .settings/ 4 | .project 5 | .classpath 6 | target/ 7 | *-test/ -------------------------------------------------------------------------------- /java/inlineProgram/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.pulumi 8 | InlineProgram 9 | 1.0-SNAPSHOT 10 | jar 11 | 12 | 13 | 11 14 | 11 15 | 16 | 17 | 18 | 19 | com.pulumi 20 | pulumi 21 | [1.3,2.0) 22 | 23 | 24 | com.pulumi 25 | aws 26 | 6.68.0 27 | 28 | 29 | 30 | 31 | 32 | 33 | org.codehaus.mojo 34 | exec-maven-plugin 35 | 3.1.0 36 | 37 | com.pulumi.App 38 | false 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /java/localProgram/.gitignore: -------------------------------------------------------------------------------- 1 | # Java app 2 | .gradle/ 3 | .settings/ 4 | .project 5 | .classpath 6 | target/ 7 | *-test/ -------------------------------------------------------------------------------- /java/localProgram/automation/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.pulumi 8 | LocalProgram 9 | 1.0-SNAPSHOT 10 | jar 11 | 12 | 13 | 11 14 | 11 15 | 16 | 17 | 18 | 19 | com.pulumi 20 | pulumi 21 | [1.3,2.0) 22 | 23 | 24 | 25 | 26 | 27 | 28 | org.codehaus.mojo 29 | exec-maven-plugin 30 | 3.1.0 31 | 32 | com.pulumi.App 33 | false 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /java/localProgram/automation/src/main/java/com/pulumi/App.java: -------------------------------------------------------------------------------- 1 | package com.pulumi; 2 | 3 | import java.nio.file.Paths; 4 | 5 | import com.pulumi.automation.*; 6 | 7 | public class App { 8 | public static void main(String[] args) { 9 | var stackName = "dev"; 10 | var workingDir = Paths.get("..", "website"); 11 | 12 | var destroy = args.length > 0 && args[0].equals("destroy"); 13 | try (var stack = LocalWorkspace.createOrSelectStack(stackName, workingDir)) { 14 | 15 | System.out.println("Successfully initialized stack"); 16 | 17 | // Set AWS region 18 | System.out.println("Setting up config..."); 19 | stack.setConfig("aws:region", new ConfigValue("us-west-2")); 20 | System.out.println("Config set"); 21 | 22 | // Refresh stack 23 | System.out.println("Refreshing stack..."); 24 | stack.refresh(RefreshOptions.builder().onStandardOutput(System.out::println).build()); 25 | System.out.println("Refresh complete"); 26 | 27 | if (destroy) { 28 | System.out.println("Destroying stack..."); 29 | stack.destroy(DestroyOptions.builder().onStandardOutput(System.out::println).build()); 30 | System.out.println("Stack destroy complete"); 31 | } else { 32 | System.out.println("Updating stack..."); 33 | var result = stack.up(UpOptions.builder().onStandardOutput(System.out::println).build()); 34 | 35 | var changes = result.summary().resourceChanges(); 36 | if (!changes.isEmpty()) { 37 | System.out.println("Update summary:"); 38 | changes.forEach((key, value) -> System.out.printf(" %s: %d%n", key, value)); 39 | } 40 | 41 | System.out.println("Website URL: " + result.outputs().get("website_url").value()); 42 | } 43 | } catch (Exception ex) { 44 | // Print the exception message 45 | System.err.println("An exception occured while running the inline Pulumi program: " + ex.getMessage()); 46 | 47 | System.err.print("Stack trace: "); 48 | ex.printStackTrace(); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /java/localProgram/website/Pulumi.dev.yaml: -------------------------------------------------------------------------------- 1 | config: 2 | aws:region: us-west-2 3 | -------------------------------------------------------------------------------- /java/localProgram/website/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: website 2 | description: A minimal AWS Java Pulumi program 3 | runtime: java 4 | config: 5 | pulumi:tags: 6 | value: 7 | pulumi:template: aws-java 8 | -------------------------------------------------------------------------------- /java/localProgram/website/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.pulumi 8 | website 9 | 1.0-SNAPSHOT 10 | 11 | 12 | UTF-8 13 | 11 14 | 11 15 | 11 16 | myproject.App 17 | 18 | 19 | 20 | 21 | 22 | com.pulumi 23 | pulumi 24 | [1.3,2.0) 25 | 26 | 27 | com.pulumi 28 | aws 29 | 6.68.0 30 | 31 | 32 | 33 | 34 | 35 | 36 | org.apache.maven.plugins 37 | maven-jar-plugin 38 | 3.2.2 39 | 40 | 41 | 42 | true 43 | ${mainClass} 44 | 45 | 46 | 47 | 48 | 49 | org.apache.maven.plugins 50 | maven-assembly-plugin 51 | 3.3.0 52 | 53 | 54 | 55 | true 56 | ${mainClass} 57 | 58 | 59 | 60 | jar-with-dependencies 61 | 62 | 63 | 64 | 65 | make-my-jar-with-dependencies 66 | package 67 | 68 | single 69 | 70 | 71 | 72 | 73 | 74 | org.codehaus.mojo 75 | exec-maven-plugin 76 | 3.0.0 77 | 78 | ${mainClass} 79 | ${mainArgs} 80 | 81 | 82 | 83 | org.apache.maven.plugins 84 | maven-wrapper-plugin 85 | 3.1.0 86 | 87 | 3.8.5 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /java/localProgram/website/src/main/java/myproject/App.java: -------------------------------------------------------------------------------- 1 | package myproject; 2 | 3 | import com.pulumi.Pulumi; 4 | import com.pulumi.aws.s3.BucketV2; 5 | import com.pulumi.aws.s3.BucketObject; 6 | import com.pulumi.aws.s3.BucketObjectArgs; 7 | import com.pulumi.aws.s3.BucketWebsiteConfigurationV2; 8 | import com.pulumi.aws.s3.BucketWebsiteConfigurationV2Args; 9 | import com.pulumi.aws.s3.inputs.BucketOwnershipControlsRuleArgs; 10 | import com.pulumi.aws.s3.inputs.BucketWebsiteConfigurationV2IndexDocumentArgs; 11 | import com.pulumi.aws.s3.BucketOwnershipControls; 12 | import com.pulumi.aws.s3.BucketOwnershipControlsArgs; 13 | import com.pulumi.aws.s3.BucketPublicAccessBlock; 14 | import com.pulumi.aws.s3.BucketPublicAccessBlockArgs; 15 | import com.pulumi.resources.CustomResourceOptions; 16 | 17 | public class App { 18 | public static void main(String[] args) { 19 | Pulumi.run(ctx -> { 20 | // Create an AWS resource (S3 Bucket) 21 | var siteBucket = new BucketV2("s3-website-bucket"); 22 | 23 | var website = new BucketWebsiteConfigurationV2("website", BucketWebsiteConfigurationV2Args.builder() 24 | .bucket(siteBucket.id()) 25 | .indexDocument(BucketWebsiteConfigurationV2IndexDocumentArgs.builder() 26 | .suffix("index.html") 27 | .build()) 28 | .build()); 29 | 30 | var ownershipControls = new BucketOwnershipControls("ownershipControls", BucketOwnershipControlsArgs.builder() 31 | .bucket(siteBucket.id()) 32 | .rule(BucketOwnershipControlsRuleArgs.builder() 33 | .objectOwnership("ObjectWriter") 34 | .build()) 35 | .build()); 36 | 37 | var publicAccessBlock = new BucketPublicAccessBlock("publicAccessBlock", BucketPublicAccessBlockArgs.builder() 38 | .bucket(siteBucket.id()) 39 | .blockPublicAcls(false) 40 | .build()); 41 | 42 | String indexContent = "\n" + 43 | " Hello S3\n" + 44 | " \n" + 45 | "

Hello, 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 S3 22 | 23 |

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 S3 24 | 25 |

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(): Promise { 14 | console.log("Initialising stack..."); 15 | const stack = await LocalWorkspace.createOrSelectStack(args); 16 | 17 | console.log("Setting region..."); 18 | await stack.setConfig("aws:region", {value: "us-west-1"}); 19 | 20 | console.log("Run update..."); 21 | const up = await stack.up({ onOutput: console.log }); 22 | 23 | return up.outputs; 24 | } 25 | 26 | export async function destroy() { 27 | console.log("Selecting stack..."); 28 | const stack = await LocalWorkspace.createOrSelectStack(args); 29 | 30 | console.log("Destroying stack"); 31 | await stack.destroy({onOutput: console.log}); 32 | } 33 | 34 | export async function getOutputs(): Promise { 35 | const stack = await LocalWorkspace.createOrSelectStack(args); 36 | 37 | var outputs = stack.outputs(); 38 | 39 | return outputs; 40 | } 41 | 42 | export default {deploy, getOutputs}; 43 | -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode-mochatests/index.ts: -------------------------------------------------------------------------------- 1 | import { deploy } from "./automation"; 2 | 3 | deploy().catch((error) => console.log(error)); 4 | -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode-mochatests/infrastructure/.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /node_modules/ 3 | -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode-mochatests/infrastructure/Pulumi.dev.yaml: -------------------------------------------------------------------------------- 1 | config: 2 | aws:region: us-west-1 3 | -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode-mochatests/infrastructure/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: automationS3website 2 | runtime: nodejs 3 | description: Pulumi project to set up S3 website 4 | -------------------------------------------------------------------------------- /nodejs/localProgram-tsnode-mochatests/infrastructure/index.ts: -------------------------------------------------------------------------------- 1 | import * as aws from "@pulumi/aws"; 2 | import * as pulumi from "@pulumi/pulumi"; 3 | 4 | const bucket = new aws.s3.Bucket("automation-website-bucket", { 5 | website: { 6 | indexDocument: "index.html", 7 | }, 8 | }); 9 | 10 | // HTML content that we're serving from the bucket 11 | let indexContent: string = ` 12 | Hello S3 13 | 14 |

Hello, 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 S3 29 | 30 |

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 start 14 | ``` 15 | 16 | This will kick-off the remote deployment using Pulumi Deployments. 17 | 18 | To destroy the stack when you're done, invoke the program with an additional `destroy` argument: 19 | 20 | ```shell 21 | $ npm run start destroy 22 | ``` 23 | -------------------------------------------------------------------------------- /nodejs/remoteDeployment-tsnode/index.ts: -------------------------------------------------------------------------------- 1 | import * as process from "process"; 2 | import { RemoteWorkspace, fullyQualifiedStackName } from "@pulumi/pulumi/automation"; 3 | 4 | const args = process.argv.slice(2); 5 | 6 | if (args.length === 0) { 7 | console.log("usage: npm run start [destroy]") 8 | process.exit(1); 9 | } 10 | 11 | const org = args[0]; 12 | const project = "aws-ts-s3-folder"; 13 | const stackName = fullyQualifiedStackName(org, project, "dev"); 14 | const awsRegion = "us-west-2"; 15 | 16 | (async function() { 17 | const stack = await RemoteWorkspace.createOrSelectStack({ 18 | stackName, 19 | url: "https://github.com/pulumi/examples.git", 20 | branch: "refs/heads/master", 21 | projectPath: project, 22 | }, { 23 | envVars: { 24 | AWS_REGION: awsRegion, 25 | AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID ?? "", 26 | AWS_SECRET_ACCESS_KEY: { secret: process.env.AWS_SECRET_ACCESS_KEY ?? "" }, 27 | AWS_SESSION_TOKEN: { secret: process.env.AWS_SESSION_TOKEN ?? "" }, 28 | }, 29 | }); 30 | 31 | const destroy = args.length > 1 && args[1] === "destroy"; 32 | if (destroy) { 33 | await stack.destroy({ onOutput: console.log }); 34 | console.log("Stack successfully destroyed"); 35 | process.exit(0); 36 | } 37 | 38 | const upRes = await stack.up({ onOutput: console.log }); 39 | console.log("Update succeeded!"); 40 | console.log(`url: ${upRes.outputs.websiteUrl.value}`); 41 | })(); 42 | -------------------------------------------------------------------------------- /nodejs/remoteDeployment-tsnode/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@types/node": "^14" 4 | }, 5 | "dependencies": { 6 | "@pulumi/pulumi": "^3.45.0", 7 | "ts-node": "^10.9.1" 8 | }, 9 | "scripts": { 10 | "start": "./node_modules/ts-node/dist/bin.js index.ts" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /nodejs/remoteDeployment-tsnode/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "outDir": "bin", 5 | "target": "es2017", 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/ssh-tunnel/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | Pulumi.*.yaml 4 | -------------------------------------------------------------------------------- /nodejs/ssh-tunnel/database/.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /node_modules/ 3 | -------------------------------------------------------------------------------- /nodejs/ssh-tunnel/database/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: database 2 | runtime: nodejs 3 | description: A minimal AWS TypeScript Pulumi program 4 | -------------------------------------------------------------------------------- /nodejs/ssh-tunnel/database/index.ts: -------------------------------------------------------------------------------- 1 | import * as pg from "@pulumi/postgresql"; 2 | 3 | const database1 = new pg.Database("main1"); 4 | const database2 = new pg.Database("main2"); 5 | const database3 = new pg.Database("main3"); 6 | -------------------------------------------------------------------------------- /nodejs/ssh-tunnel/database/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "database", 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/postgresql": "^3.0.0", 10 | "@pulumi/pulumi": "^3.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /nodejs/ssh-tunnel/database/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/ssh-tunnel/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "pulumi": "./node_modules/ts-node/dist/bin.js pulumi.ts" 4 | }, 5 | "devDependencies": { 6 | "typescript": "^4.2.3" 7 | }, 8 | "dependencies": { 9 | "@pulumi/aws": "^4.0.0", 10 | "@pulumi/pulumi": "^3.0.0", 11 | "ts-node": "^10.9.2" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /nodejs/ssh-tunnel/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "commonjs", 5 | "strict": true, 6 | "esModuleInterop": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /nodejs/ssh-tunnel/vpc/.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /node_modules/ 3 | -------------------------------------------------------------------------------- /nodejs/ssh-tunnel/vpc/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: vpc 2 | runtime: nodejs 3 | description: A minimal AWS TypeScript Pulumi program 4 | -------------------------------------------------------------------------------- /nodejs/ssh-tunnel/vpc/index.ts: -------------------------------------------------------------------------------- 1 | import * as aws from "@pulumi/aws"; 2 | import * as random from "@pulumi/random"; 3 | import * as pulumi from "@pulumi/pulumi"; 4 | 5 | const project = pulumi.getProject(); 6 | const stack = pulumi.getStack(); 7 | const tags = { project, stack, Name: `${project}-${stack}` }; 8 | const config = new pulumi.Config(); 9 | 10 | /** 11 | * Get details of default vpc to use for resources. 12 | */ 13 | const vpc = aws.ec2.getVpc({ default: true }); 14 | const vpcId = vpc.then(it => it.id); 15 | const vpcCidrBlock = vpc.then(it => it.cidrBlock); 16 | 17 | const subnets = vpc.then(it => aws.ec2.getSubnetIds({ vpcId: it.id })); 18 | const allSubnetIds = subnets.then(it => it.ids); 19 | const firstSubnetId = subnets.then(it => it.ids[0]); 20 | 21 | /** 22 | * Provision bastion resources. 23 | */ 24 | const amiId = aws.ec2.getAmi({ 25 | owners: ["099720109477"], // Ubuntu 26 | mostRecent: true, 27 | filters: [{ name: "name", values: ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"] }], 28 | }).then(it => it.id); 29 | 30 | const sshSg = new aws.ec2.SecurityGroup(`bastion`, { 31 | vpcId: vpcId, 32 | ingress: [{ protocol: "tcp", fromPort: 22, toPort: 22, cidrBlocks: ["0.0.0.0/0"] }], 33 | egress: [{ protocol: "-1", fromPort: 0, toPort: 0, cidrBlocks: ["0.0.0.0/0"] }], 34 | tags 35 | }); 36 | 37 | const sshKey = new aws.ec2.KeyPair("bastion", { publicKey: config.require("publicKey") }); 38 | 39 | const bastion = new aws.ec2.Instance("bastion", { 40 | instanceType: aws.ec2.InstanceTypes.T3_Small, 41 | ami: amiId, 42 | subnetId: firstSubnetId, 43 | vpcSecurityGroupIds: [sshSg.id], 44 | associatePublicIpAddress: true, 45 | keyName: sshKey.keyName, 46 | tags, 47 | }); 48 | 49 | export const bastionHost = bastion.publicIp; 50 | 51 | /** 52 | * Provision database resources. 53 | */ 54 | const postgresSg = new aws.ec2.SecurityGroup("db", { 55 | vpcId, 56 | ingress: [{ protocol: "tcp", fromPort: 5432, toPort: 5432, cidrBlocks: [vpcCidrBlock] }], 57 | egress: [{ protocol: "-1", fromPort: 0, toPort: 0, cidrBlocks: [vpcCidrBlock] }], 58 | }); 59 | const dbSubnets = new aws.rds.SubnetGroup("db", { 60 | subnetIds: allSubnetIds, 61 | tags, 62 | }); 63 | const password = new random.RandomPassword("db", { 64 | length: 32, 65 | // https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBInstance.html#API_CreateDBInstance_RequestParameters:~:text=The%20password%20for%20the%20master%20user.,character%20except%20%22%2F%22%2C%20%22%22%22%2C%20or%20%22%40%22. 66 | overrideSpecial: "!#$%&*()-_=+[]{}<>:?", 67 | }); 68 | const db = new aws.rds.Instance("db", { 69 | engine: "postgres", 70 | 71 | instanceClass: "db.t3.xlarge", 72 | allocatedStorage: 20, 73 | 74 | dbSubnetGroupName: dbSubnets.id, 75 | vpcSecurityGroupIds: [postgresSg.id], 76 | publiclyAccessible: false, 77 | 78 | username: "admin2021", 79 | password: password.result, 80 | 81 | skipFinalSnapshot: true, 82 | tags, 83 | }); 84 | 85 | export const dbHost = db.address; 86 | export const dbUsername = db.username; 87 | export const dbPassword = db.password; 88 | -------------------------------------------------------------------------------- /nodejs/ssh-tunnel/vpc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vpc", 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 | "@pulumi/random": "^4.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /nodejs/ssh-tunnel/vpc/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 | -------------------------------------------------------------------------------- /python/cross_language/.gitignore: -------------------------------------------------------------------------------- 1 | automation/venv 2 | -------------------------------------------------------------------------------- /python/cross_language/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 -------------------------------------------------------------------------------- /python/cross_language/app/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/python/cross_language/app 2 | 3 | go 1.14 4 | 5 | require github.com/gorilla/mux v1.8.0 6 | -------------------------------------------------------------------------------- /python/cross_language/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 | -------------------------------------------------------------------------------- /python/cross_language/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 | -------------------------------------------------------------------------------- /python/cross_language/automation/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import json 3 | import os 4 | from pulumi import automation as auto 5 | 6 | # To destroy our program, we can run python main.py destroy 7 | destroy = False 8 | args = sys.argv[1:] 9 | if len(args) > 0: 10 | if args[0] == "destroy": 11 | destroy = True 12 | 13 | stack_name = "dev" 14 | 15 | work_dir = os.path.join(os.path.dirname(__file__), "..", "fargate") 16 | 17 | # Create our stack using a local program in the ../fargate directory 18 | stack = auto.create_or_select_stack(stack_name="dev", work_dir=work_dir) 19 | print("successfully initialized stack") 20 | 21 | print("setting up config") 22 | stack.set_config("aws:region", auto.ConfigValue(value="us-west-2")) 23 | print("config set") 24 | 25 | print("refreshing stack") 26 | stack.refresh(on_output=print) 27 | print("refresh complete") 28 | 29 | if destroy: 30 | print("destroying stack...") 31 | stack.destroy(on_output=print) 32 | print("stack destroy complete") 33 | sys.exit() 34 | 35 | print("updating stack...") 36 | up_res = stack.up(on_output=print) 37 | print(f"update summary: \n{json.dumps(up_res.summary.resource_changes, indent=4)}") 38 | print(f"website url: {up_res.outputs['url'].value}") 39 | -------------------------------------------------------------------------------- /python/cross_language/automation/requirements.txt: -------------------------------------------------------------------------------- 1 | pulumi>=3.0.0,<4.0.0 2 | -------------------------------------------------------------------------------- /python/cross_language/fargate/Pulumi.dev.yaml: -------------------------------------------------------------------------------- 1 | config: 2 | aws:region: us-west-2 3 | -------------------------------------------------------------------------------- /python/cross_language/fargate/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: fargate 2 | runtime: go 3 | description: An end-to-end AWS ECS Fargate infrastructure as code project. 4 | -------------------------------------------------------------------------------- /python/cross_language/fargate/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pulumi/automation-api-examples/python/cross_language/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 | -------------------------------------------------------------------------------- /python/database_migration/.gitignore: -------------------------------------------------------------------------------- 1 | venv 2 | __pycache__ 3 | -------------------------------------------------------------------------------- /python/database_migration/requirements.txt: -------------------------------------------------------------------------------- 1 | pulumi>=3.0.0,<4.0.0 2 | pulumi-aws==4.0.0 3 | mysql-connector-python>=8.0.22,<9.0.0 4 | -------------------------------------------------------------------------------- /python/inline_program/.gitignore: -------------------------------------------------------------------------------- 1 | venv 2 | -------------------------------------------------------------------------------- /python/inline_program/README.md: -------------------------------------------------------------------------------- 1 | # Inline Program 2 | 3 | This program demonstrates how to 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__.py` and `Pulumi.yaml`. Inline programs are just functions, can be authored in the same python file 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 | First, set up your virtual environment: 10 | 1. ```shell 11 | $ python3 -m venv venv 12 | ``` 13 | 2. ```shell 14 | $ venv/bin/python3 -m pip install --upgrade pip 15 | ``` 16 | 3. ```shell 17 | $ venv/bin/pip install -r requirements.txt 18 | ``` 19 | 20 | Running this program is just like any other Python program. No invocation through the Pulumi CLI required: 21 | 22 | ```shell 23 | $ venv/bin/python main.py 24 | Created/Selected stack "dev" 25 | Installing the AWS plugin 26 | Successfully installed AWS plugin 27 | Successfully set config 28 | Starting refresh 29 | Refresh succeeded! 30 | Starting update 31 | Updating (dev) 32 | 33 | View Live: https://app.pulumi.com/EvanBoyle/inlineS3Project/dev/updates/22 34 | 35 | 36 | + pulumi:pulumi:Stack inlineS3Project-dev creating 37 | + aws:s3:Bucket s3-website-bucket creating 38 | + aws:s3:Bucket s3-website-bucket created 39 | + aws:s3:BucketObject index creating 40 | + aws:s3:BucketPolicy bucketPolicy creating 41 | + aws:s3:BucketObject index created 42 | + aws:s3:BucketPolicy bucketPolicy created 43 | + pulumi:pulumi:Stack inlineS3Project-dev created 44 | 45 | Outputs: 46 | websiteUrl: "s3-website-bucket-bf7e357.s3-website-us-west-2.amazonaws.com" 47 | 48 | Resources: 49 | + 4 created 50 | 51 | Duration: 10s 52 | 53 | Update succeeded! 54 | URL: s3-website-bucket-bf7e357.s3-website-us-west-2.amazonaws.com 55 | ``` 56 | 57 | To destroy the stack when you're done, invoke the program with an additional `destroy` argument: 58 | 59 | ```shell 60 | $ venv/bin/python main.py destroy 61 | Created/Selected stack "dev" 62 | Installing the AWS plugin 63 | Successfully installed AWS plugin 64 | Successfully set config 65 | Starting refresh 66 | Refresh succeeded! 67 | Starting stack destroy 68 | Destroying (dev) 69 | 70 | View Live: https://app.pulumi.com/EvanBoyle/inlineS3Project/dev/updates/24 71 | 72 | 73 | - aws:s3:BucketPolicy bucketPolicy deleting 74 | - aws:s3:BucketObject index deleting 75 | - aws:s3:BucketObject index deleted 76 | - aws:s3:BucketPolicy bucketPolicy deleted 77 | - aws:s3:Bucket s3-website-bucket deleting 78 | - aws:s3:Bucket s3-website-bucket deleted 79 | - pulumi:pulumi:Stack inlineS3Project-dev deleting 80 | - pulumi:pulumi:Stack inlineS3Project-dev deleted 81 | 82 | Outputs: 83 | - websiteUrl: "s3-website-bucket-bf7e357.s3-website-us-west-2.amazonaws.com" 84 | 85 | Resources: 86 | - 4 deleted 87 | 88 | Duration: 3s 89 | 90 | The resources in the stack have been deleted, but the history and configuration associated with the stack are still maintained. 91 | If you want to remove the stack completely, run 'pulumi stack rm dev'. 92 | Stack successfully destroyed 93 | ``` 94 | -------------------------------------------------------------------------------- /python/inline_program/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import json 3 | import pulumi 4 | from pulumi import automation as auto 5 | from pulumi_aws import s3 6 | 7 | 8 | # This is the pulumi program in "inline function" form 9 | def pulumi_program(): 10 | # Create a bucket and expose a website index document 11 | site_bucket = s3.Bucket("s3-website-bucket", website=s3.BucketWebsiteArgs(index_document="index.html")) 12 | index_content = """ 13 | 14 | Hello S3 15 | 16 |

Hello, 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 | {{title}} 8 | 9 | 13 | 14 | 15 | 16 |
17 |
18 | 19 |
20 |
21 | 22 | 23 | 24 |
25 |
26 |
{{button1}}: {{ value1 }} · {{button2}}: {{ value2 }}
27 | 28 |
29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /python/local_program/aws-py-voting-app/requirements.txt: -------------------------------------------------------------------------------- 1 | pulumi>=3.0.0,<4.0.0 2 | pulumi-aws>=4.0.0,<5.0.0 3 | pulumi-docker==3.1.0 4 | -------------------------------------------------------------------------------- /python/pulumi_over_htp_fastapi/.gitignore: -------------------------------------------------------------------------------- 1 | venv 2 | __pycache__ 3 | -------------------------------------------------------------------------------- /python/pulumi_over_htp_fastapi/README.md: -------------------------------------------------------------------------------- 1 | # Pulumi Over HTTP - Static Websites as a RESTful API with FastAPI 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 | First, set up your virtual environment: 10 | 1. ```shell 11 | $ python3 -m venv venv 12 | ``` 13 | 2. ```shell 14 | $ venv/bin/python3 -m pip install --upgrade pip 15 | ``` 16 | 3. ```shell 17 | $ venv/bin/pip install -r requirements.txt 18 | ``` 19 | 20 | In one terminal window, run the HTTP server that uses Automation API. It will also stream update logs: 21 | 22 | ```bash 23 | $ venv/bin/uvicorn main:app --port 8080 24 | INFO: Started server process [49190] 25 | INFO: Waiting for application startup. 26 | INFO: Application startup complete. 27 | INFO: Uvicorn running on http://127.0.0.1:8080 (Press CTRL+C to quit) 28 | ``` 29 | 30 | Open another terminal window to execute some `curl` commands and create some sites: 31 | 32 | ```bash 33 | # create "hello" site 34 | $ curl --header "Content-Type: application/json" --request POST --data '{"id":"hello","content":"hello world\n"}' http://localhost:8080/sites 35 | {"id":"hello","url":"s3-website-bucket-549d9d3.s3-website-us-west-2.amazonaws.com"} 36 | # curl our "hello" site 37 | $ curl s3-website-bucket-549d9d3.s3-website-us-west-2.amazonaws.com 38 | hello world 39 | # update our "hello" site content 40 | $ curl --header "Content-Type: application/json" --request PUT --data '{"id":"hello","content":"hello updated world!\n"}' http://localhost:8080/sites/hello 41 | {"id":"hello","url":"s3-website-bucket-549d9d3.s3-website-us-west-2.amazonaws.com"} 42 | # curl our update hello site 43 | $ curl s3-website-bucket-549d9d3.s3-website-us-west-2.amazonaws.com 44 | hello updated world! 45 | # add a "bye" site 46 | $ curl --header "Content-Type: application/json" --request POST --data '{"id":"bye","content":"good bye world\n"}' http://localhost:8080/sites 47 | {"id":"bye","url":"s3-website-bucket-2eaf3da.s3-website-us-west-2.amazonaws.com"} 48 | # curl our "bye" site 49 | $ curl s3-website-bucket-2eaf3da.s3-website-us-west-2.amazonaws.com 50 | good bye world 51 | # list our sites 52 | $ curl http://localhost:8080/sites 53 | {"ids":["bye","hello"]} 54 | # get the URL of a specific site 55 | $ curl http://localhost:8080/sites/hello 56 | {"id":"hello","url":"s3-website-bucket-549d9d3.s3-website-us-west-2.amazonaws.com"} 57 | # delete our "bye" site 58 | $ curl --header "Content-Type: application/json" --request DELETE http://localhost:8080/sites/bye 59 | # list sites again and see it's gone 60 | $ curl http://localhost:8080/sites 61 | {"ids":["hello"]} 62 | ``` 63 | -------------------------------------------------------------------------------- /python/pulumi_over_htp_fastapi/requirements.txt: -------------------------------------------------------------------------------- 1 | pulumi 2 | fastapi 3 | uvicorn[standard] 4 | pydantic 5 | pulumi-aws -------------------------------------------------------------------------------- /python/pulumi_over_http/.gitignore: -------------------------------------------------------------------------------- 1 | venv 2 | __pycache__ 3 | -------------------------------------------------------------------------------- /python/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 | First, set up your virtual environment: 10 | 1. ```shell 11 | $ python3 -m venv venv 12 | ``` 13 | 2. ```shell 14 | $ venv/bin/python3 -m pip install --upgrade pip 15 | ``` 16 | 3. ```shell 17 | $ venv/bin/pip install -r requirements.txt 18 | ``` 19 | 20 | In one terminal window, run the HTTP server that uses Automation API. It will also stream update logs: 21 | 22 | ```bash 23 | $ FLASK_RUN_PORT=1337 FLASK_ENV=development venv/bin/flask run 24 | * Environment: development 25 | * Debug mode: on 26 | * Running on http://127.0.0.1:1337/ (Press CTRL+C to quit) 27 | * Restarting with stat 28 | * Debugger is active! 29 | * Debugger PIN: 328-006-235 30 | ``` 31 | 32 | Open another terminal window to execute some `curl` commands and create some sites: 33 | 34 | ```bash 35 | # create "hello" site 36 | $ curl --header "Content-Type: application/json" --request POST --data '{"id":"hello","content":"hello world\n"}' http://localhost:1337/sites 37 | {"id":"hello","url":"s3-website-bucket-549d9d3.s3-website-us-west-2.amazonaws.com"} 38 | # curl our "hello" site 39 | $ curl s3-website-bucket-549d9d3.s3-website-us-west-2.amazonaws.com 40 | hello world 41 | # update our "hello" site content 42 | $ curl --header "Content-Type: application/json" --request PUT --data '{"id":"hello","content":"hello updated world!\n"}' http://localhost:1337/sites/hello 43 | {"id":"hello","url":"s3-website-bucket-549d9d3.s3-website-us-west-2.amazonaws.com"} 44 | # curl our update hello site 45 | $ curl s3-website-bucket-549d9d3.s3-website-us-west-2.amazonaws.com 46 | hello updated world! 47 | # add a "bye" site 48 | $ curl --header "Content-Type: application/json" --request POST --data '{"id":"bye","content":"good bye world\n"}' http://localhost:1337/sites 49 | {"id":"bye","url":"s3-website-bucket-2eaf3da.s3-website-us-west-2.amazonaws.com"} 50 | # curl our "bye" site 51 | $ curl s3-website-bucket-2eaf3da.s3-website-us-west-2.amazonaws.com 52 | good bye world 53 | # list our sites 54 | $ curl http://localhost:1337/sites 55 | {"ids":["bye","hello"]} 56 | # get the URL of a specific site 57 | $ curl http://localhost:1337/sites/hello 58 | {"id":"hello","url":"s3-website-bucket-549d9d3.s3-website-us-west-2.amazonaws.com"} 59 | # delete our "bye" site 60 | $ curl --header "Content-Type: application/json" --request DELETE http://localhost:1337/sites/bye 61 | # list sites again and see it's gone 62 | $ curl http://localhost:1337/sites 63 | {"ids":["hello"]} 64 | ``` 65 | -------------------------------------------------------------------------------- /python/pulumi_over_http/requirements.txt: -------------------------------------------------------------------------------- 1 | pulumi>=3.0.0,<4.0.0 2 | pulumi-aws>=4.0.0,<5.0.0 3 | flask>=1.1.2,<2.0.0 4 | markupsafe==2.0.1 5 | -------------------------------------------------------------------------------- /python/pulumi_via_jupyter/.gitignore: -------------------------------------------------------------------------------- 1 | venv 2 | .ipynb_checkpoints 3 | -------------------------------------------------------------------------------- /python/pulumi_via_jupyter/README.md: -------------------------------------------------------------------------------- 1 | # Pulumi Via Jupyter 2 | 3 | This project explores running Pulumi through a Jupyter Notebook. 4 | 5 | ### Demo 6 | 7 | ![demo](auto-api.gif) 8 | 9 | ### Notebooks 10 | 11 | This example contains two notebooks: 12 | 13 | 1. `automation_api.ipynb`: (est. runtime 3 minutes) A simple overview of Automation API that demonstrates doing a basic deployment of a static website from within a Jupyter notebook. 14 | 2. `database_migration.ipynb`: (est. runtime 15 minutes) Set up data science infrastructure from your notebook. We create an AWS RDS SQL database, configure the schema, and load data. 15 | 16 | ### Requirements 17 | 18 | To run this example you'll need a few pre-reqs: 19 | 1. A Pulumi CLI installation ([v3.0.0](https://www.pulumi.com/docs/get-started/install/versions/) or later) 20 | 2. The AWS CLI, with appropriate credentials. 21 | 22 | ### Set up your virtual environment 23 | 24 | 1. ```shell 25 | $ python3 -m venv venv 26 | ``` 27 | 2. ```shell 28 | $ venv/bin/python3 -m pip install --upgrade pip 29 | ``` 30 | 3. ```shell 31 | $ venv/bin/pip install -r requirements.txt 32 | ``` 33 | 34 | ### Running a notebook 35 | 36 | 1. Start up the notebook server. This will open up the directory in your default browser. 37 | ```shell 38 | $ venv/bin/jupyter notebook 39 | ``` 40 | 2. Click on a notebook (`.ipynb` file) to open it up. 41 | 3. Work through the notebook by running each cell in order. You can run a cell with `Shift + Enter` or by using the Play button at the top of the notebook. 42 | -------------------------------------------------------------------------------- /python/pulumi_via_jupyter/auto-api.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulumi/automation-api-examples/124e3e3ed839f1dc026f686e826b6b646d9f136a/python/pulumi_via_jupyter/auto-api.gif -------------------------------------------------------------------------------- /python/pulumi_via_jupyter/notebook-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pulumi/automation-api-examples/124e3e3ed839f1dc026f686e826b6b646d9f136a/python/pulumi_via_jupyter/notebook-screenshot.png -------------------------------------------------------------------------------- /python/pulumi_via_jupyter/requirements.txt: -------------------------------------------------------------------------------- 1 | pulumi>=3.0.0,<4.0.0 2 | pulumi-aws>=4.0.0,<5.0.0 3 | jupyter>=1.0.0 4 | requests>=2.25.1 5 | mysql-connector-python>=8.0.22,<9.0.0 6 | -------------------------------------------------------------------------------- /python/remote_deployment/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | venv/ 3 | -------------------------------------------------------------------------------- /python/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 | Before running the program, set up a virtual environment: 11 | 12 | 1. ```shell 13 | $ python3 -m venv venv 14 | ``` 15 | 2. ```shell 16 | $ venv/bin/python -m pip install --upgrade pip 17 | ``` 18 | 3. ```shell 19 | $ venv/bin/pip install -r requirements.txt 20 | ``` 21 | 22 | To run the program, run: 23 | 24 | ```shell 25 | $ venv/bin/python main.py 26 | ``` 27 | 28 | This will kick-off the remote deployment using Pulumi Deployments. 29 | 30 | To destroy the stack when you're done, invoke the program with an additional `destroy` argument: 31 | 32 | ```shell 33 | $ venv/bin/python main.py destroy 34 | ``` 35 | -------------------------------------------------------------------------------- /python/remote_deployment/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | 4 | import pulumi.automation as auto 5 | 6 | 7 | args = sys.argv[1:] 8 | if len(args) == 0: 9 | print("usage: python main.py [destroy]") 10 | sys.exit(1) 11 | 12 | org = args[0] 13 | project = "aws-ts-s3-folder" 14 | stack_name = auto.fully_qualified_stack_name(org, project, "dev") 15 | aws_region = "us-west-2" 16 | 17 | stack = auto.create_or_select_remote_stack_git_source( 18 | stack_name=stack_name, 19 | url="https://github.com/pulumi/examples.git", 20 | branch="refs/heads/master", 21 | project_path=project, 22 | opts=auto.RemoteWorkspaceOptions( 23 | env_vars={ 24 | "AWS_REGION": aws_region, 25 | "AWS_ACCESS_KEY_ID": os.environ["AWS_ACCESS_KEY_ID"], 26 | "AWS_SECRET_ACCESS_KEY": auto.Secret(os.environ["AWS_SECRET_ACCESS_KEY"]), 27 | "AWS_SESSION_TOKEN": auto.Secret(os.environ["AWS_SESSION_TOKEN"]), 28 | }, 29 | ), 30 | ) 31 | 32 | destroy = len(args) > 1 and args[1] == "destroy" 33 | if destroy: 34 | stack.destroy(on_output=print) 35 | print("Stack successfully destroyed") 36 | sys.exit() 37 | 38 | up_res = stack.up(on_output=print) 39 | print("Update succeeded!") 40 | print(f"url: {up_res.outputs['websiteUrl'].value}") 41 | -------------------------------------------------------------------------------- /python/remote_deployment/requirements.txt: -------------------------------------------------------------------------------- 1 | pulumi>=3.45.0,<4.0.0 2 | -------------------------------------------------------------------------------- /python/testing_local_program/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | venv/ 3 | __pychache__ 4 | -------------------------------------------------------------------------------- /python/testing_local_program/README.md: -------------------------------------------------------------------------------- 1 | # Testing a local program 2 | 3 | This example uses the Automation API alongside the `unittest` Python package to deploy an S3 bucket as a website with some website content, then run some tests against this and finally destroy the infrastructure. It uses `unittest`'s `setUp()` and `tearDown()` methods to do this. 4 | 5 | ## Running this example 6 | 7 | First, set up your virtual environment and install the required packages: 8 | 9 | 1. `python3 -m venv venv` 10 | 1. `venv/bin/python3 -m pip install --upgrade pip` 11 | 1. `venv/bin/pip install -r requirements.txt` 12 | 13 | Next, run the tests: 14 | 15 | `venv/bin/python3 -m unittest` 16 | 17 | You should see output like the following: 18 | 19 | ```zsh 20 | preparing virtual environment... 21 | virtual environment is ready! 22 | successfully initialized stack 23 | setting up config 24 | config set 25 | refreshing stack 26 | Refreshing (dev) 27 | 28 | View Live: https://app.pulumi.com/pierskarsenbarg/testing_infrastructure/dev/updates/2 29 | 30 | 31 | 32 | Resources: 33 | 34 | Duration: 1s 35 | 36 | refresh complete 37 | deploying infrastructure 38 | Updating (dev) 39 | 40 | View Live: https://app.pulumi.com/pierskarsenbarg/testing_infrastructure/dev/updates/3 41 | 42 | 43 | + pulumi:pulumi:Stack testing_infrastructure-dev creating 44 | + aws:s3:Bucket auto-api-bucket creating 45 | + aws:s3:Bucket auto-api-bucket created 46 | + aws:s3:BucketObject index_html creating 47 | + aws:s3:BucketObject index_html created 48 | + aws:s3:BucketPolicy bucket_policy creating 49 | + aws:s3:BucketPolicy bucket_policy created 50 | + pulumi:pulumi:Stack testing_infrastructure-dev created 51 | 52 | Outputs: 53 | url: "http://auto-api-bucket-31b4e6d.s3-website-eu-west-1.amazonaws.com/index.html" 54 | 55 | Resources: 56 | + 4 created 57 | 58 | Duration: 13s 59 | 60 | infrastructure deployed 61 | destroying infrastructure 62 | Destroying (dev) 63 | 64 | View Live: https://app.pulumi.com/pierskarsenbarg/testing_infrastructure/dev/updates/4 65 | 66 | 67 | - aws:s3:BucketPolicy bucket_policy deleting 68 | - aws:s3:BucketObject index_html deleting 69 | - aws:s3:BucketObject index_html deleted 70 | - aws:s3:BucketPolicy bucket_policy deleted 71 | - aws:s3:Bucket auto-api-bucket deleting 72 | - aws:s3:Bucket auto-api-bucket deleted 73 | - pulumi:pulumi:Stack testing_infrastructure-dev deleting 74 | - pulumi:pulumi:Stack testing_infrastructure-dev deleted 75 | 76 | Outputs: 77 | - url: "http://auto-api-bucket-31b4e6d.s3-website-eu-west-1.amazonaws.com/index.html" 78 | 79 | Resources: 80 | - 4 deleted 81 | 82 | Duration: 6s 83 | 84 | The resources in the stack have been deleted, but the history and configuration associated with the stack are still maintained. 85 | If you want to remove the stack completely, run `pulumi stack rm dev`. 86 | infrastructure destroyed 87 | deleting stack 88 | stack deleted 89 | . 90 | ---------------------------------------------------------------------- 91 | Ran 1 test in 65.580s 92 | 93 | OK 94 | ``` -------------------------------------------------------------------------------- /python/testing_local_program/infrastructure/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | venv/ 3 | Pulumi.*.yaml 4 | -------------------------------------------------------------------------------- /python/testing_local_program/infrastructure/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: testing_infrastructure 2 | description: Small program to test with automation api 3 | runtime: 4 | name: python 5 | options: 6 | virtualenv: venv 7 | -------------------------------------------------------------------------------- /python/testing_local_program/infrastructure/__main__.py: -------------------------------------------------------------------------------- 1 | """An AWS Python Pulumi program""" 2 | 3 | import re 4 | import pulumi 5 | from pulumi_aws import s3, iam 6 | 7 | # Create an AWS resource (S3 Bucket) 8 | bucket = s3.Bucket('auto-api-bucket', 9 | website=s3.BucketWebsiteArgs( 10 | index_document="index.html" 11 | ) 12 | ) 13 | 14 | content = """ 15 | Hello S3 16 | 17 |

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 | --------------------------------------------------------------------------------