\n`,
30 | };
31 | },
32 | }],
33 | });
34 | export const url = site.url;
35 |
--------------------------------------------------------------------------------
/labs/aws/in-person/csharp/lab-01/code/05-making-your-stack-configurable/step4.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using Pulumi;
3 | using Pulumi.Aws.S3;
4 | using Pulumi.Aws.S3.Inputs;
5 | using Aws = Pulumi.Aws;
6 |
7 | class MyStack : Stack
8 | {
9 | public MyStack()
10 | {
11 | var config = new Pulumi.Config();
12 | var siteDir = config.Get("siteDir");
13 |
14 | var bucket = new Aws.S3.Bucket("my-bucket", new BucketArgs
15 | {
16 | Website = new BucketWebsiteArgs
17 | {
18 | IndexDocument = "index.html",
19 | }
20 | });
21 | this.BucketName = bucket.BucketName;
22 | this.WebsiteEndpoint = bucket.WebsiteEndpoint;
23 |
24 | foreach (var file in Directory.EnumerateFiles(siteDir))
25 | {
26 | var name = Path.GetFileName(file);
27 | var bucketObject = new Aws.S3.BucketObject(name, new BucketObjectArgs
28 | {
29 | Bucket = bucket.BucketName,
30 | Source = new FileAsset(Path.Combine(siteDir, Path.GetFileName(file))),
31 | Acl = "public-read",
32 | ContentType = "text/html",
33 | });
34 | }
35 | }
36 |
37 | [Output] public Output BucketName { get; set; }
38 | [Output] public Output WebsiteEndpoint { get; set; }
39 | }
40 |
--------------------------------------------------------------------------------
/labs/aws/in-person/go/lab-05/code/step2.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/json"
5 |
6 | corev1 "github.com/pulumi/pulumi-kubernetes/sdk/go/kubernetes/core/v1"
7 | metav1 "github.com/pulumi/pulumi-kubernetes/sdk/go/kubernetes/meta/v1"
8 | "github.com/pulumi/pulumi-kubernetes/sdk/go/kubernetes/providers"
9 | "github.com/pulumi/pulumi/sdk/go/pulumi"
10 | "github.com/pulumi/pulumi/sdk/go/pulumi/config"
11 | )
12 |
13 | func main() {
14 | pulumi.Run(func(ctx *pulumi.Context) error {
15 | c := config.New(ctx, "")
16 | stackRef := c.Require("clusterStackRef")
17 | infra, err := pulumi.NewStackReference(ctx, stackRef, nil)
18 |
19 | kubeconfig := infra.GetOutput(pulumi.String("kubeconfig")).ApplyString(
20 | func(in interface{}) string {
21 | kc, err := json.Marshal(in)
22 | if err != nil {
23 | panic(err)
24 | }
25 | return string(kc)
26 | },
27 | )
28 | k8sProvider, err := providers.NewProvider(ctx, "k8sprovider", &providers.ProviderArgs{
29 | Kubeconfig: kubeconfig,
30 | })
31 | if err != nil {
32 | return err
33 | }
34 |
35 | namespace, err := corev1.NewNamespace(ctx, "app-ns", &corev1.NamespaceArgs{
36 | Metadata: &metav1.ObjectMetaArgs{
37 | Name: pulumi.String("joe-duffy"),
38 | },
39 | }, pulumi.Provider(k8sProvider))
40 | if err != nil {
41 | return err
42 | }
43 |
44 | return nil
45 | })
46 | }
47 |
--------------------------------------------------------------------------------
/labs/aws/in-person/csharp/README.md:
--------------------------------------------------------------------------------
1 | ### Lab 1 — Modern Infrastructure as Code
2 |
3 | The first lab takes you on a tour of infrastructure as code concepts:
4 |
5 | 1. [Creating a New Project](./lab-01/01-creating-a-new-project.md)
6 | 2. [Configuring AWS](./lab-01/02-configuring-aws.md)
7 | 3. [Provisioning Infrastructure](./lab-01/03-provisioning-infrastructure.md)
8 | 4. [Updating your Infrastructure](./lab-01/04-updating-your-infrastructure.md)
9 | 5. [Making Your Stack Configurable](./lab-01/05-making-your-stack-configurable.md)
10 | 6. [Creating a Second Stack](./lab-01/06-creating-a-second-stack.md)
11 | 7. [Destroying Your Infrastructure](./lab-01/07-destroying-your-infrastructure.md)
12 |
13 | ### Lab 2 - Provision EC2 Virtual Machines
14 |
15 | In this [lab](./lab-02/README.md), you will learn about the creation of Virtual Machines in EC2. This lab will include
16 | the use of loops to create loadbalanced infrastructure in EC2.
17 |
18 | ### Lab 3 - Deploying Containers to Elastic Container Service (ECS)
19 |
20 | In this [lab](./lab-03/README.md), you will learn about how to create and deploy container based applications to Elastic
21 | Container Service (ECS).
22 |
23 | ### Lab 4 - Deploying Containers to a Kubernetes Cluster
24 |
25 | In this [lab](./lab-04/README.md), you will learn about how to create and deploy container based applications to a Kubernetes
26 | Cluster.
27 |
28 |
--------------------------------------------------------------------------------
/labs/aws/in-person/go/lab-01/code/05-making-your-stack-configurable/step2.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "mime"
5 | "path"
6 | "path/filepath"
7 |
8 | "github.com/pulumi/pulumi-aws/sdk/go/aws/s3"
9 | "github.com/pulumi/pulumi/sdk/go/pulumi"
10 | "github.com/pulumi/pulumi/sdk/go/pulumi/config"
11 | )
12 |
13 | func main() {
14 | pulumi.Run(func(ctx *pulumi.Context) error {
15 | conf := config.New(ctx, "")
16 | siteDir := conf.Get("siteDir")
17 |
18 | bucket, err := s3.NewBucket(ctx, "my-bucket", &s3.BucketArgs{
19 | Website: s3.BucketWebsiteArgs{
20 | IndexDocument: pulumi.String("index.html"),
21 | },
22 | })
23 | if err != nil {
24 | return err
25 | }
26 |
27 | bucketFile := filepath.Join(siteDir, "index.html")
28 | mimeType := mime.TypeByExtension(path.Ext(bucketFile))
29 | _, err = s3.NewBucketObject(ctx, "index.html", &s3.BucketObjectArgs{
30 | Bucket: bucket.Bucket,
31 | Source: pulumi.NewFileAsset(bucketFile),
32 | Acl: pulumi.String("public-read"),
33 | ContentType: pulumi.String(mimeType),
34 | })
35 |
36 | ctx.Export("bucketName", bucket.Bucket)
37 | ctx.Export("bucketEndpoint", bucket.WebsiteEndpoint)
38 |
39 | return nil
40 | })
41 | }
42 |
--------------------------------------------------------------------------------
/labs/aws/in-person/typescript/lab-05/code/step3.ts:
--------------------------------------------------------------------------------
1 | import * as k8s from "@pulumi/kubernetes";
2 | import * as pulumi from "@pulumi/pulumi";
3 |
4 | let pulumiConfig = new pulumi.Config();
5 |
6 | // Existing Pulumi stack reference in the format:
7 | // // e.g. "myUser/myProject/dev"
8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef"));
9 |
10 | // Get the kubeconfig from the cluster stack output.
11 | const kubeconfig = clusterStackRef.getOutput("kubeconfig").apply(JSON.stringify);
12 |
13 | // Create the k8s provider with the kubeconfig.
14 | const provider = new k8s.Provider("k8sProvider", {kubeconfig});
15 |
16 | const ns = new k8s.core.v1.Namespace("app-ns", {
17 | metadata: { name: "joe-duffy" },
18 | }, {provider});
19 |
20 | const appLabels = { app: "iac-workshop" };
21 | const deployment = new k8s.apps.v1.Deployment("app-dep", {
22 | metadata: { namespace: ns.metadata.name },
23 | spec: {
24 | selector: { matchLabels: appLabels },
25 | replicas: 1,
26 | template: {
27 | metadata: { labels: appLabels },
28 | spec: {
29 | containers: [{
30 | name: "iac-workshop",
31 | image: "gcr.io/google-samples/kubernetes-bootcamp:v1",
32 | }],
33 | },
34 | },
35 | },
36 | }, {provider});
37 |
--------------------------------------------------------------------------------
/labs/azure/csharp/03-aci/code/step2.cs:
--------------------------------------------------------------------------------
1 | using Pulumi;
2 | using Pulumi.Serialization;
3 |
4 | using Azure = Pulumi.Azure;
5 | using Pulumi.Azure.ContainerService;
6 | using Pulumi.Azure.ContainerService.Inputs;
7 |
8 | class MyStack : Stack
9 | {
10 | public MyStack()
11 | {
12 | var resourceGroup = new Azure.Core.ResourceGroup("my-group");
13 |
14 | var group = new Group("aci", new GroupArgs
15 | {
16 | ResourceGroupName = resourceGroup.Name,
17 | OsType = "Linux",
18 | Containers =
19 | {
20 | new GroupContainersArgs
21 | {
22 | Cpu = 0.5,
23 | Image = "mcr.microsoft.com/azuredocs/aci-helloworld",
24 | Memory = 1.5,
25 | Name = "hello-world",
26 | Ports =
27 | {
28 | new GroupContainersPortsArgs
29 | {
30 | Port = 80,
31 | Protocol = "TCP"
32 | }
33 | }
34 | }
35 | },
36 | IpAddressType = "public",
37 | DnsNameLabel = "my-unique-string"
38 | });
39 |
40 | this.Endpoint = Output.Format($"http://{group.Fqdn}");
41 | }
42 |
43 | [Output]
44 | public Output Endpoint { get; set; }
45 | }
46 |
--------------------------------------------------------------------------------
/labs/aws/in-person/typescript/lab-06/code/step3.ts:
--------------------------------------------------------------------------------
1 | import * as AWS from "aws-sdk";
2 | import * as aws from "@pulumi/aws";
3 | import * as awsx from "@pulumi/awsx";
4 | import * as pulumi from "@pulumi/pulumi";
5 |
6 | const hits = new aws.dynamodb.Table("hits", {
7 | attributes: [{ name: "Site", type: "S" }],
8 | hashKey: "Site",
9 | billingMode: "PAY_PER_REQUEST",
10 | });
11 |
12 | const handlerRole = new aws.iam.Role("handler-role", {
13 | assumeRolePolicy: {
14 | Version: "2012-10-17",
15 | Statement: [{
16 | Action: "sts:AssumeRole",
17 | Principal: {
18 | Service: "lambda.amazonaws.com"
19 | },
20 | Effect: "Allow",
21 | Sid: "",
22 | }],
23 | },
24 | });
25 |
26 | const handlerPolicy = new aws.iam.RolePolicy("handler-policy", {
27 | role: handlerRole,
28 | policy: hits.arn.apply(arn => JSON.stringify({
29 | Version: "2012-10-17",
30 | Statement: [
31 | {
32 | Action: [
33 | "dynamodb:UpdateItem",
34 | "dynamodb:PutItem",
35 | "dynamodb:GetItem",
36 | "dynamodb:DescribeTable",
37 | ],
38 | Resource: arn,
39 | Effect: "Allow",
40 | },
41 | {
42 | Action: ["logs:*", "cloudwatch:*"],
43 | Resource: "*",
44 | Effect: "Allow",
45 | },
46 | ],
47 | })),
48 | });
49 |
--------------------------------------------------------------------------------
/labs/aws/in-person/python/README.md:
--------------------------------------------------------------------------------
1 | ### Lab 1 — Modern Infrastructure as Code
2 |
3 | The first lab takes you on a tour of infrastructure as code concepts:
4 |
5 | 1. [Creating a New Project](./lab-01/01-creating-a-new-project.md)
6 | 2. [Configuring AWS](./lab-01/02-configuring-aws.md)
7 | 3. [Provisioning Infrastructure](./lab-01/03-provisioning-infrastructure.md)
8 | 4. [Updating your Infrastructure](./lab-01/04-updating-your-infrastructure.md)
9 | 5. [Making Your Stack Configurable](./lab-01/05-making-your-stack-configurable.md)
10 | 6. [Creating a Second Stack](./lab-01/06-creating-a-second-stack.md)
11 | 7. [Destroying Your Infrastructure](./lab-01/07-destroying-your-infrastructure.md)
12 |
13 | ### Lab 2 - Provision EC2 Virtual Machines
14 |
15 | In this [lab](./lab-02/README.md), you will learn about the creation of Virtual Machines in EC2. This lab will include
16 | the use of loops to create loadbalanced infrastructure in EC2.
17 |
18 | ### Lab 3 - Deploying Containers to Elastic Container Service (ECS)
19 |
20 | In this [lab](./lab-03/README.md), you will learn about how to create and deploy container based applications to Elastic
21 | Container Service (ECS).
22 |
23 | ### Lab 4 - Deploying a Kubernetes Cluster
24 |
25 | In this [lab](./lab-04/README.md), you will learn about how to create and deploy a Kubernetes Cluster in EKS.
26 |
27 | ### Lab 5 - Deploying Containers to a Kubernetes Cluster
28 |
29 | In this [lab](./lab-05/README.md), you will learn about how to create and deploy container based applications to a Kubernetes
30 | Cluster.
31 |
--------------------------------------------------------------------------------
/labs/aws/in-person/go/README.md:
--------------------------------------------------------------------------------
1 | ### Lab 1 — Modern Infrastructure as Code
2 |
3 | The first lab takes you on a tour of infrastructure as code concepts:
4 |
5 | 1. [Creating a New Project](./lab-01/01-creating-a-new-project.md)
6 | 2. [Configuring AWS](./lab-01/02-configuring-aws.md)
7 | 3. [Provisioning Infrastructure](./lab-01/03-provisioning-infrastructure.md)
8 | 4. [Updating your Infrastructure](./lab-01/04-updating-your-infrastructure.md)
9 | 5. [Making Your Stack Configurable](./lab-01/05-making-your-stack-configurable.md)
10 | 6. [Creating a Second Stack](./lab-01/06-creating-a-second-stack.md)
11 | 7. [Destroying Your Infrastructure](./lab-01/07-destroying-your-infrastructure.md)
12 |
13 | ### Lab 2 - Provision EC2 Virtual Machines
14 |
15 | In this [lab](./lab-02/README.md), you will learn about the creation of Virtual Machines in EC2. This lab will include
16 | the use of loops to create loadbalanced infrastructure in EC2.
17 |
18 | ### Lab 3 - Deploying Containers to Elastic Container Service (ECS)
19 |
20 | In this [lab](./lab-03/README.md), you will learn about how to create and deploy container based applications to Elastic
21 | Container Service (ECS).
22 |
23 | ### Lab 4 - Deploying a Kubernetes Cluster
24 |
25 | In this [lab](./lab-04/README.md), you will learn about how to create and deploy a Kubernetes Cluster in EKS.
26 | Cluster.
27 |
28 | ### Lab 5 - Deploying Containers to a Kubernetes Cluster
29 |
30 | In this [lab](./lab-05/README.md), you will learn about how to create and deploy container based applications to a Kubernetes
31 | Cluster.
32 |
33 |
--------------------------------------------------------------------------------
/labs/azure/csharp/02-serverless/code/step3.cs:
--------------------------------------------------------------------------------
1 | using Pulumi;
2 |
3 | using Azure = Pulumi.Azure;
4 |
5 | class MyStack : Stack
6 | {
7 | public MyStack()
8 | {
9 | var resourceGroup = new Azure.Core.ResourceGroup("my-group");
10 |
11 | var storageAccount = new Azure.Storage.Account("storage", new Azure.Storage.AccountArgs
12 | {
13 | ResourceGroupName = resourceGroup.Name,
14 | AccountReplicationType = "LRS",
15 | AccountTier = "Standard"
16 | });
17 |
18 | var plan = new Azure.AppService.Plan("asp", new Azure.AppService.PlanArgs
19 | {
20 | ResourceGroupName = resourceGroup.Name,
21 | Kind = "FunctionApp",
22 | Sku = new Azure.AppService.Inputs.PlanSkuArgs
23 | {
24 | Tier = "Dynamic",
25 | Size = "Y1"
26 | }
27 | });
28 |
29 | var app = new Azure.AppService.FunctionApp("fa", new Azure.AppService.FunctionAppArgs
30 | {
31 | ResourceGroupName = resourceGroup.Name,
32 | AppServicePlanId = plan.Id,
33 | StorageConnectionString = storageAccount.PrimaryConnectionString,
34 | Version = "~2",
35 | AppSettings =
36 | {
37 | { "FUNCTIONS_WORKER_RUNTIME", "node" },
38 | { "WEBSITE_NODE_DEFAULT_VERSION", "10.14.1" },
39 | { "WEBSITE_RUN_FROM_PACKAGE", "https://mikhailworkshop.blob.core.windows.net/zips/app.zip" }
40 | }
41 | });
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/labs/aws/in-person/python/lab-01/02-configuring-aws.md:
--------------------------------------------------------------------------------
1 | # Configuring AWS
2 |
3 | Now that you have a basic project, let's configure AWS support for it.
4 |
5 | ## Step 1 — Install the AWS Package
6 |
7 | Run the following command to install the AWS package:
8 |
9 | ```bash
10 | pip3 install pulumi-aws
11 | ```
12 |
13 | ## Step 2 — Import the AWS Package
14 |
15 | Now that the AWS package is installed, add the following line to `__main__.py` to import it:
16 |
17 | ```python
18 | # ...
19 | import pulumi_aws as aws
20 | ```
21 |
22 | > :white_check_mark: After this change, your `__main__.py` should [look like this](./code/02-configuring-aws/step2.py).
23 |
24 | ## Step 3 — Configure an AWS Region
25 |
26 | Configure the AWS region you would like to deploy to:
27 |
28 | ```bash
29 | pulumi config set aws:region us-east-1
30 | ```
31 |
32 | > If you are doing an interactive lab, please use the recommended region. This will ensure AWS limits are not exceeded during the labs.
33 |
34 | Feel free to choose any AWS region that supports the services used in these labs ([see this table](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions) for a list of available regions).
35 |
36 | ## (Optional) Step 4 — Configure an AWS Profile
37 |
38 | If you're using an alternative AWS profile, you can tell Pulumi which to use in one of two ways:
39 |
40 | * Using an environment variable: `export AWS_PROFILE=`
41 | * Using configuration: `pulumi config set aws:profile `
42 |
43 | ## Next Steps
44 |
45 | * [Provisioning a S3 Bucket](./03-provisioning-infrastructure.md)
46 |
--------------------------------------------------------------------------------
/labs/aws/in-person/python/lab-05/code/step3.py:
--------------------------------------------------------------------------------
1 | from pulumi import export, StackReference, Output, ResourceOptions
2 | from pulumi_kubernetes import Provider
3 | from pulumi_kubernetes.apps.v1 import Deployment
4 | from pulumi_kubernetes.core.v1 import Service, Namespace
5 | import pulumi
6 |
7 | # Create StackReference to the Kubernetes cluster stack
8 | config = pulumi.Config()
9 | stackRef = config.require("clusterStackRef");
10 | infra = StackReference(f"{stackRef}")
11 |
12 | # Declare a provider using the KubeConfig we created
13 | # This will be used to interact with the EKS cluster
14 | k8s_provider = Provider("k8s-provider", kubeconfig=infra.get_output("kubeconfig"))
15 |
16 | # Create a Namespace object https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
17 | ns = Namespace("app-ns",
18 | metadata={
19 | "name": "joe-duffy",
20 | },
21 | opts=ResourceOptions(provider=k8s_provider)
22 | )
23 |
24 | app_labels = {
25 | "app": "iac-workshop"
26 | }
27 | app_deployment = Deployment("app-dep",
28 | metadata={
29 | "namespace": ns.metadata["name"]
30 | },
31 | spec={
32 | "selector": {
33 | "match_labels": app_labels,
34 | },
35 | "replicas": 1,
36 | "template": {
37 | "metadata": {
38 | "labels": app_labels,
39 | },
40 | "spec": {
41 | "containers": [{
42 | "name": "iac-workshop",
43 | "image": "gcr.io/google-samples/kubernetes-bootcamp:v1",
44 | }],
45 | },
46 | },
47 | },
48 | opts=ResourceOptions(provider=k8s_provider)
49 | )
50 |
--------------------------------------------------------------------------------
/labs/aws/in-person/csharp/lab-01/02-configuring-aws.md:
--------------------------------------------------------------------------------
1 | # Configuring AWS
2 |
3 | Now that you have a basic project, let's configure AWS support for it.
4 |
5 | ## Step 1 — Install the AWS Package
6 |
7 | To install the AWS package, run the following command:
8 |
9 | ```bash
10 | dotnet add package Pulumi.Aws --version 1.28.0-preview
11 | ```
12 |
13 | ## Step 2 — Import the AWS Package
14 |
15 | Now that the AWS package is installed, add the following line to our using statements in `MyStack.cs` to import it:
16 |
17 | ```csharp
18 | using Aws = Pulumi.Aws;
19 | ```
20 |
21 |
22 | > :white_check_mark: After this change, your `MyStack.cs` should [look like this](code/02-configuring-aws/step2.cs).
23 |
24 | ## Step 3 — Configure an AWS Region
25 |
26 | Configure the AWS region you would like to deploy to:
27 |
28 | ```bash
29 | pulumi config set aws:region us-east-1
30 | ```
31 |
32 | > If you are doing an interactive lab, please use the recommended region. This will ensure AWS limits are not exceeded during the labs.
33 |
34 | Feel free to choose any AWS region that supports the services used in these labs ([see this table](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions) for a list of available regions).
35 |
36 | ## (Optional) Step 4 — Configure an AWS Profile
37 |
38 | If you're using an alternative AWS profile, you can tell Pulumi which to use in one of two ways:
39 |
40 | * Using an environment variable: `export AWS_PROFILE=`
41 | * Using configuration: `pulumi config set aws:profile `
42 |
43 | ## Next Steps
44 |
45 | * [Provisioning a S3 Bucket](./03-provisioning-infrastructure.md)
46 |
--------------------------------------------------------------------------------
/labs/azure/csharp/05-kubernetes/code/step4.cs:
--------------------------------------------------------------------------------
1 | using Pulumi;
2 |
3 | using K8s = Pulumi.Kubernetes;
4 |
5 | class MyStack : Stack
6 | {
7 | public MyStack()
8 | {
9 | var ns = new K8s.Core.V1.Namespace("app-ns", new K8s.Types.Inputs.Core.V1.NamespaceArgs
10 | {
11 | Metadata = new K8s.Types.Inputs.Meta.V1.ObjectMetaArgs { Name = "my-name" }
12 | });
13 |
14 | var appLabels = new InputMap { { "app", "iac-workshop" } };
15 | var deployment = new K8s.Apps.V1.Deployment("app-dep", new K8s.Types.Inputs.Apps.V1.DeploymentArgs
16 | {
17 | Metadata = new K8s.Types.Inputs.Meta.V1.ObjectMetaArgs { Namespace = ns.Metadata.Apply(m => m.Name) },
18 | Spec = new K8s.Types.Inputs.Apps.V1.DeploymentSpecArgs
19 | {
20 | Selector = new K8s.Types.Inputs.Meta.V1.LabelSelectorArgs { MatchLabels = appLabels },
21 | Replicas = 1,
22 | Template = new K8s.Types.Inputs.Core.V1.PodTemplateSpecArgs
23 | {
24 | Metadata = new K8s.Types.Inputs.Meta.V1.ObjectMetaArgs { Labels = appLabels },
25 | Spec = new K8s.Types.Inputs.Core.V1.PodSpecArgs
26 | {
27 | Containers =
28 | {
29 | new K8s.Types.Inputs.Core.V1.ContainerArgs
30 | {
31 | Name = "iac-workshop",
32 | Image = "gcr.io/google-samples/kubernetes-bootcamp:v1"
33 | }
34 | }
35 | }
36 | }
37 | }
38 | });
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/labs/aws/pulumi-in-practice/python/README.md:
--------------------------------------------------------------------------------
1 | ### Lab 1 - Preparing to use Pulumi with AWS
2 |
3 | The first lab shows you how to set up your Pulumi project so that you can use Pulumi with AWS.
4 |
5 | We'll cover:
6 |
7 | - Bootstrapping your Pulumi + AWS Python project
8 | - Setting up AWS credentials
9 | - Verifying your access to AWS is valid
10 | - Setting AWS config options in your program
11 |
12 | ### Lab 2 - Managing an S3 Bucket
13 |
14 | The [second lab](./lab-02/README.md) shows a very simple static website deployed with Pulumi. It introduces some key Pulumi features, namely the ability to use standard programming loops. Also in this lab, we'll introduce the Pulumi concept of an Output, and how to manage these outputs when managing standard programming strings.
15 |
16 | Once you have completed this lab, you should feel comfortable with:
17 |
18 | - Running your first Pulumi program in AWS
19 | - Pulumi's Python SDK and its type system
20 | - More steps in understanding Pulumi's programming model
21 | - How you can use traditional programming constructs in Pulumi
22 |
23 | ### Lab 3 - Deploying a Webserver
24 |
25 | The [third lab](./lab-03/README.md) shows how to deploy a simple, python webserver to multiple AWS regions. Once you've completed this lab, you'll feel comfortable with:
26 |
27 | - Retrieving existing resources in AWS using Pulumi's `get` methods
28 | - Looping over retrieved resources to deploy new resources using familiar programming methods
29 |
30 | ### Lab 4 - Deploying Containers to Elastic Container Service (ECS)
31 |
32 | In this lab, you will learn about how to create and deploy container based applications to Elastic Container Service (ECS).
33 |
34 | - You'll gain familiarity with with the AWS Elastic Container Service
35 |
--------------------------------------------------------------------------------
/labs/azure/csharp/02-serverless/code/step4.cs:
--------------------------------------------------------------------------------
1 | using Pulumi;
2 | using Pulumi.Serialization;
3 |
4 | using Azure = Pulumi.Azure;
5 |
6 | class MyStack : Stack
7 | {
8 | public MyStack()
9 | {
10 | var resourceGroup = new Azure.Core.ResourceGroup("my-group");
11 |
12 | var storageAccount = new Azure.Storage.Account("storage", new Azure.Storage.AccountArgs
13 | {
14 | ResourceGroupName = resourceGroup.Name,
15 | AccountReplicationType = "LRS",
16 | AccountTier = "Standard"
17 | });
18 |
19 | var plan = new Azure.AppService.Plan("asp", new Azure.AppService.PlanArgs
20 | {
21 | ResourceGroupName = resourceGroup.Name,
22 | Kind = "FunctionApp",
23 | Sku = new Azure.AppService.Inputs.PlanSkuArgs
24 | {
25 | Tier = "Dynamic",
26 | Size = "Y1"
27 | }
28 | });
29 |
30 | var app = new Azure.AppService.FunctionApp("fa", new Azure.AppService.FunctionAppArgs
31 | {
32 | ResourceGroupName = resourceGroup.Name,
33 | AppServicePlanId = plan.Id,
34 | StorageConnectionString = storageAccount.PrimaryConnectionString,
35 | Version = "~2",
36 | AppSettings =
37 | {
38 | { "FUNCTIONS_WORKER_RUNTIME", "node" },
39 | { "WEBSITE_NODE_DEFAULT_VERSION", "10.14.1" },
40 | { "WEBSITE_RUN_FROM_PACKAGE", "https://mikhailworkshop.blob.core.windows.net/zips/app.zip" }
41 | }
42 | });
43 |
44 | this.Endpoint = Output.Format($"https://{app.DefaultHostname}/api/hello");
45 | }
46 |
47 | [Output]
48 | public Output Endpoint { get; set; }
49 | }
50 |
--------------------------------------------------------------------------------
/labs/azure/csharp/README.md:
--------------------------------------------------------------------------------
1 | ### Prerequisites
2 |
3 | Please follow [this guide](./00-installing-prerequisites.md) to install all the binaries needed to complete the labs.
4 |
5 | ### Lab 1 — Modern Infrastructure as Code
6 |
7 | The first lab takes you on a tour of infrastructure as code concepts:
8 |
9 | 1. [Creating a New Project](./01-iac/01-creating-a-new-project.md)
10 | 2. [Configuring Azure](./01-iac/02-configuring-azure.md)
11 | 3. [Provisioning Infrastructure](./01-iac/03-provisioning-infrastructure.md)
12 | 4. [Updating your Infrastructure](./01-iac/04-updating-your-infrastructure.md)
13 | 5. [Making Your Stack Configurable](./01-iac/05-making-your-stack-configurable.md)
14 | 6. [Creating a Second Stack](./01-iac/06-creating-a-second-stack.md)
15 | 7. [Destroying Your Infrastructure](./01-iac/07-destroying-your-infrastructure.md)
16 |
17 | [Get Started with Lab 1](./01-iac/01-creating-a-new-project.md)
18 |
19 | ### Lab 2 - Deploy Serverless Applications with Azure Functions
20 |
21 | In this lab, you will create a serverless web application that uses Azure Functions.
22 |
23 | [Get Started with Lab 2](./02-serverless/README.md)
24 |
25 | ### Lab 3 - Deploy Containers to Azure Container Instances (ACI)
26 |
27 | In this lab, you will deploy a containerized application to Azure Container Instances.
28 |
29 | [Get Started with Lab 3](./03-aci/README.md)
30 |
31 | ### Lab 4 - Provision Virtual Machines
32 |
33 | In this lab, you will learn about the creation of Virtual Machines in Azure.
34 |
35 | [Get Started with Lab 4](./04-vms/README.md)
36 |
37 | ### Lab 5 - Deploy Containers to a Kubernetes Cluster
38 |
39 | In this lab, you will deploy a containerized application to a Kubernetes cluster.
40 |
41 | [Get Started with Lab 5](./05-kubernetes/README.md)
42 |
--------------------------------------------------------------------------------
/labs/aws/in-person/typescript/lab-01/02-configuring-aws.md:
--------------------------------------------------------------------------------
1 | # Configuring AWS
2 |
3 | Now that you have a basic project, let's configure AWS support for it.
4 |
5 | ## Step 1 — Install the AWS Package
6 |
7 | Run the following command to install the AWS package:
8 |
9 | ```bash
10 | npm install @pulumi/aws
11 | ```
12 |
13 | The package will be added to `node_modules/`, `package.json`, and `package-lock.json`.
14 |
15 | ## Step 2 — Import the AWS Package
16 |
17 | Now that the AWS package is installed, add the following line to `index.ts` to import it:
18 |
19 | ```typescript
20 | ...
21 | import * as aws from "@pulumi/aws";
22 | ```
23 |
24 | > :white_check_mark: After this change, your `index.ts` should [look like this](./code/02-configuring-aws/step2.ts).
25 |
26 | ## Step 3 — Configure an AWS Region
27 |
28 | Configure the AWS region you would like to deploy to:
29 |
30 | ```bash
31 | pulumi config set aws:region us-east-1
32 | ```
33 |
34 | > If you are doing an interactive lab, please use the recommended region. This will ensure AWS limits are not exceeded during the labs.
35 |
36 | Feel free to choose any AWS region that supports the services used in these labs ([see this table](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions) for a list of available regions).
37 |
38 | ## (Optional) Step 4 — Configure an AWS Profile
39 |
40 | If you're using an alternative AWS profile, you can tell Pulumi which to use in one of two ways:
41 |
42 | * Using an environment variable: `export AWS_PROFILE=`
43 | * Using configuration: `pulumi config set aws:profile `
44 |
45 | ## Next Steps
46 |
47 | * [Provisioning a S3 Bucket](./03-provisioning-infrastructure.md)
48 |
--------------------------------------------------------------------------------
/labs/aws/in-person/go/lab-01/02-configuring-aws.md:
--------------------------------------------------------------------------------
1 | # Configuring AWS
2 |
3 | Now that you have a basic project, let's configure AWS support for it.
4 |
5 | ## Step 1 — Install the AWS Package
6 |
7 | We can edit the contents of our Gopkg.toml file to install the AWS Package. Add the following:
8 |
9 | ```toml
10 | [[constraint]]
11 | name = "github.com/pulumi/pulumi-aws"
12 | version = "1.27.0"
13 | ```
14 |
15 | ## Step 2 — Import the AWS Package
16 |
17 | Now that the AWS package is installed, add the following line to our imports in `main.go` to import it:
18 |
19 | ```go
20 | github.com/pulumi/pulumi-aws/sdk/go/aws/s3
21 | ```
22 |
23 |
24 | > :white_check_mark: After this change, your `main.go` should [look like this](code/02-configuring-aws/step2.go).
25 |
26 | ## Step 3 — Configure an AWS Region
27 |
28 | Configure the AWS region you would like to deploy to:
29 |
30 | ```bash
31 | pulumi config set aws:region us-east-1
32 | ```
33 |
34 | > If you are doing an interactive lab, please use the recommended region. This will ensure AWS limits are not exceeded during the labs.
35 |
36 | Feel free to choose any AWS region that supports the services used in these labs ([see this table](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions) for a list of available regions).
37 |
38 | ## (Optional) Step 4 — Configure an AWS Profile
39 |
40 | If you're using an alternative AWS profile, you can tell Pulumi which to use in one of two ways:
41 |
42 | * Using an environment variable: `export AWS_PROFILE=`
43 | * Using configuration: `pulumi config set aws:profile `
44 |
45 | ## Next Steps
46 |
47 | * [Provisioning a S3 Bucket](./03-provisioning-infrastructure.md)
48 |
--------------------------------------------------------------------------------
/labs/aws/in-person/typescript/README.md:
--------------------------------------------------------------------------------
1 | ### Lab 1 — Modern Infrastructure as Code
2 |
3 | The first lab takes you on a tour of infrastructure as code concepts:
4 |
5 | 1. [Creating a New Project](./lab-01/01-creating-a-new-project.md)
6 | 2. [Configuring AWS](./lab-01/02-configuring-aws.md)
7 | 3. [Provisioning Infrastructure](./lab-01/03-provisioning-infrastructure.md)
8 | 4. [Updating your Infrastructure](./lab-01/04-updating-your-infrastructure.md)
9 | 5. [Making Your Stack Configurable](./lab-01/05-making-your-stack-configurable.md)
10 | 6. [Creating a Second Stack](./lab-01/06-creating-a-second-stack.md)
11 | 7. [Destroying Your Infrastructure](./lab-01/07-destroying-your-infrastructure.md)
12 |
13 |
14 | ### Lab 2 - Provision EC2 Virtual Machines
15 |
16 | In this [lab](./lab-02/README.md), you will learn about the creation of Virtual Machines in EC2. This lab will include
17 | the use of loops to create loadbalanced infrastructure in EC2.
18 |
19 | ### Lab 3 - Deploying Containers to Elastic Container Service (ECS)
20 |
21 | In this [lab](./lab-03/README.md), you will learn about how to create and deploy container based applications to Elastic
22 | Container Service (ECS).
23 |
24 | ### Lab 4 - Deploying a Kubernetes Cluster
25 |
26 | In this [lab](./lab-04/README.md), you will learn about how to create and deploy a Kubernetes Cluster in EKS.
27 | Cluster.
28 |
29 | ### Lab 5 - Deploying Containers to a Kubernetes Cluster
30 |
31 | In this [lab](./lab-05/README.md), you will learn about how to create and deploy container based applications to a Kubernetes
32 | Cluster.
33 |
34 | ### Lab 6 - Using AWS Lambda for Serverless Application Patterns
35 |
36 | In this [lab](./lab-06/README.md), you will learn about how to create and deploy serverless applications to AWS Lambda.
37 |
--------------------------------------------------------------------------------
/labs/aws/in-person/go/lab-01/code/05-making-your-stack-configurable/step4.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "io/ioutil"
5 | "mime"
6 | "path"
7 | "path/filepath"
8 |
9 | "github.com/pulumi/pulumi-aws/sdk/go/aws/s3"
10 | "github.com/pulumi/pulumi/sdk/go/pulumi"
11 | "github.com/pulumi/pulumi/sdk/go/pulumi/config"
12 | )
13 |
14 | func main() {
15 | pulumi.Run(func(ctx *pulumi.Context) error {
16 | conf := config.New(ctx, "")
17 | siteDir := conf.Get("siteDir")
18 |
19 | bucket, err := s3.NewBucket(ctx, "my-bucket", &s3.BucketArgs{
20 | Website: s3.BucketWebsiteArgs{
21 | IndexDocument: pulumi.String("index.html"),
22 | },
23 | })
24 | if err != nil {
25 | return err
26 | }
27 |
28 | // For each file in the directory, create an S3 object stored in `bucket`
29 | files, err := ioutil.ReadDir(siteDir)
30 | if err != nil {
31 | return err
32 | }
33 | for _, item := range files {
34 | name := item.Name()
35 | if _, err := s3.NewBucketObject(ctx, name, &s3.BucketObjectArgs{
36 | Bucket: bucket.Bucket, // reference to the s3.Bucket object
37 | Source: pulumi.NewFileAsset(filepath.Join(siteDir, name)), // use FileAsset to point to a file
38 | ContentType: pulumi.String(mime.TypeByExtension(path.Ext(name))), // set the MIME type of the file
39 | Acl: pulumi.String("public-read"),
40 | }); err != nil {
41 | return err
42 | }
43 | }
44 |
45 | ctx.Export("bucketName", bucket.Bucket)
46 | ctx.Export("bucketEndpoint", bucket.WebsiteEndpoint)
47 |
48 | return nil
49 | })
50 | }
51 |
--------------------------------------------------------------------------------
/labs/aws/in-person/typescript/lab-05/code/step6.ts:
--------------------------------------------------------------------------------
1 | import * as k8s from "@pulumi/kubernetes";
2 | import * as pulumi from "@pulumi/pulumi";
3 |
4 | let pulumiConfig = new pulumi.Config();
5 |
6 | // Existing Pulumi stack reference in the format:
7 | // // e.g. "myUser/myProject/dev"
8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef"));
9 |
10 | // Get the kubeconfig from the cluster stack output.
11 | const kubeconfig = clusterStackRef.getOutput("kubeconfig").apply(JSON.stringify);
12 |
13 | // Create the k8s provider with the kubeconfig.
14 | const provider = new k8s.Provider("k8sProvider", {kubeconfig});
15 |
16 | const ns = new k8s.core.v1.Namespace("app-ns", {
17 | metadata: { name: "joe-duffy" },
18 | }, {provider});
19 |
20 | const appLabels = { app: "iac-workshop" };
21 | const deployment = new k8s.apps.v1.Deployment("app-dep", {
22 | metadata: { namespace: ns.metadata.name },
23 | spec: {
24 | selector: { matchLabels: appLabels },
25 | replicas: 3,
26 | template: {
27 | metadata: { labels: appLabels },
28 | spec: {
29 | containers: [{
30 | name: "iac-workshop",
31 | image: "jocatalin/kubernetes-bootcamp:v2",
32 | }],
33 | },
34 | },
35 | },
36 | }, {provider});
37 |
38 | const service = new k8s.core.v1.Service("app-svc", {
39 | metadata: { namespace: ns.metadata.name },
40 | spec: {
41 | selector: appLabels,
42 | ports: [{ port: 80, targetPort: 8080 }],
43 | type: "LoadBalancer",
44 | },
45 | }, {provider});
46 |
47 | const address = service.status.loadBalancer.ingress[0].hostname;
48 | const port = service.spec.ports[0].port;
49 | export const url = pulumi.interpolate`http://${address}:${port}`;
50 |
--------------------------------------------------------------------------------
/labs/aws/in-person/typescript/lab-05/code/step4.ts:
--------------------------------------------------------------------------------
1 | import * as k8s from "@pulumi/kubernetes";
2 | import * as pulumi from "@pulumi/pulumi";
3 |
4 | let pulumiConfig = new pulumi.Config();
5 |
6 | // Existing Pulumi stack reference in the format:
7 | // // e.g. "myUser/myProject/dev"
8 | const clusterStackRef = new pulumi.StackReference(pulumiConfig.require("clusterStackRef"));
9 |
10 | // Get the kubeconfig from the cluster stack output.
11 | const kubeconfig = clusterStackRef.getOutput("kubeconfig").apply(JSON.stringify);
12 |
13 | // Create the k8s provider with the kubeconfig.
14 | const provider = new k8s.Provider("k8sProvider", {kubeconfig});
15 |
16 | const ns = new k8s.core.v1.Namespace("app-ns", {
17 | metadata: { name: "joe-duffy" },
18 | }, {provider});
19 |
20 | const appLabels = { app: "iac-workshop" };
21 | const deployment = new k8s.apps.v1.Deployment("app-dep", {
22 | metadata: { namespace: ns.metadata.name },
23 | spec: {
24 | selector: { matchLabels: appLabels },
25 | replicas: 1,
26 | template: {
27 | metadata: { labels: appLabels },
28 | spec: {
29 | containers: [{
30 | name: "iac-workshop",
31 | image: "gcr.io/google-samples/kubernetes-bootcamp:v1",
32 | }],
33 | },
34 | },
35 | },
36 | }, {provider});
37 |
38 | const service = new k8s.core.v1.Service("app-svc", {
39 | metadata: { namespace: ns.metadata.name },
40 | spec: {
41 | selector: appLabels,
42 | ports: [{ port: 80, targetPort: 8080 }],
43 | type: "LoadBalancer",
44 | },
45 | }, {provider});
46 |
47 | const address = service.status.loadBalancer.ingress[0].hostname;
48 | const port = service.spec.ports[0].port;
49 | export const url = pulumi.interpolate`http://${address}:${port}`;
50 |
--------------------------------------------------------------------------------
/labs/aws/in-person/go/lab-02/code/step1.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/pulumi/pulumi-aws/sdk/go/aws"
5 | "github.com/pulumi/pulumi-aws/sdk/go/aws/ec2"
6 | "github.com/pulumi/pulumi/sdk/go/pulumi"
7 | )
8 |
9 | func main() {
10 | pulumi.Run(func(ctx *pulumi.Context) error {
11 | mostRecent := true
12 | ami, err := aws.GetAmi(ctx, &aws.GetAmiArgs{
13 | Filters: []aws.GetAmiFilter{
14 | {
15 | Name: "name",
16 | Values: []string{"amzn2-ami-k*-hvm-*-x86_64-gp2"},
17 | },
18 | },
19 | Owners: []string{"amazon"},
20 | MostRecent: &mostRecent,
21 | })
22 | if err != nil {
23 | return err
24 | }
25 |
26 | group, err := ec2.NewSecurityGroup(ctx, "web-secgrp", &ec2.SecurityGroupArgs{
27 | Ingress: ec2.SecurityGroupIngressArray{
28 | ec2.SecurityGroupIngressArgs{
29 | Protocol: pulumi.String("tcp"),
30 | FromPort: pulumi.Int(80),
31 | ToPort: pulumi.Int(80),
32 | CidrBlocks: pulumi.StringArray{pulumi.String("0.0.0.0/0")},
33 | },
34 | ec2.SecurityGroupIngressArgs{
35 | Protocol: pulumi.String("icmp"),
36 | FromPort: pulumi.Int(8),
37 | ToPort: pulumi.Int(80),
38 | CidrBlocks: pulumi.StringArray{pulumi.String("0.0.0.0/0")},
39 | },
40 | },
41 | })
42 | if err != nil {
43 | return err
44 | }
45 |
46 | srv, err := ec2.NewInstance(ctx, "web-server-www", &ec2.InstanceArgs{
47 | Tags: pulumi.Map{"Name": pulumi.String("web-server-www")},
48 | InstanceType: pulumi.String("t2.micro"), // t2.micro is available in the AWS free tier.
49 | VpcSecurityGroupIds: pulumi.StringArray{group.ID()},
50 | Ami: pulumi.String(ami.Id),
51 | UserData: pulumi.String(`#!/bin/bash
52 | echo "Hello, World!" > index.html
53 | nohup python -m SimpleHTTPServer 80 &`),
54 | })
55 |
56 | ctx.Export("publicIp", srv.PublicIp)
57 | ctx.Export("publicHostName", srv.PublicDns)
58 | return nil
59 | })
60 | }
61 |
--------------------------------------------------------------------------------
/labs/aws/in-person/csharp/lab-01/01-creating-a-new-project.md:
--------------------------------------------------------------------------------
1 | # Creating a New Project
2 |
3 | Infrastructure in Pulumi is organized into projects. Each project is a single program that, when run, declares the desired infrastructure for Pulumi to manage.
4 |
5 | ## Step 1 — Create a Directory
6 |
7 | Each Pulumi project lives in its own directory. Create one now and change into it:
8 |
9 | ```bash
10 | mkdir iac-workshop
11 | cd iac-workshop
12 | ```
13 |
14 | > Pulumi will use the directory name as your project name by default. To create an independent project, simply name the directory differently.
15 |
16 | ## Step 2 — Initialize Your Project
17 |
18 | A Pulumi project is just a directory with some files in it. It's possible for you to create a new one by hand. The `pulumi new` command, however, automates the process:
19 |
20 | ```bash
21 | pulumi new csharp -y
22 | ```
23 |
24 | This will print output similar to the following with a bit more information and status as it goes:
25 |
26 | ```
27 | Created project 'iac-workshop'
28 | Created stack 'dev'
29 |
30 | .....
31 |
32 | Your new project is ready to go! ✨
33 |
34 | To perform an initial deployment, run 'pulumi up'
35 | ```
36 |
37 | ## Step 3 — Inspect Your New Project
38 |
39 | Our project is comprised of multiple files:
40 |
41 | * **`MyStack.cs`**: your program's file for resource management
42 | * **`Program.cs`**: your program's main entrypoint file
43 | * **`iac-workshop.csproj`**: your project's project file
44 | * **`Pulumi.yaml`**: your project's metadata, containing its name and language
45 |
46 | Run `cat MyStack.cs` to see the contents of your project's empty program:
47 |
48 | ```csharp
49 | using Pulumi;
50 |
51 | class MyStack : Stack
52 | {
53 | public MyStack()
54 | {
55 | // Add your resources here
56 | }
57 | }
58 | ```
59 |
60 | Feel free to explore the other files, although we won't be editing any of them by hand.
61 |
62 | # Next Steps
63 |
64 | * [Configuring AWS](./02-configuring-aws.md)
65 |
--------------------------------------------------------------------------------
/labs/aws/in-person/csharp/lab-02/code/step1.cs:
--------------------------------------------------------------------------------
1 | using Pulumi;
2 |
3 | class MyStack : Stack
4 | {
5 | public MyStack()
6 | {
7 | var ami = Output.Create(Pulumi.Aws.Invokes.GetAmi(new Pulumi.Aws.GetAmiArgs
8 | {
9 | MostRecent = true,
10 | Owners = {"amazon"},
11 | Filters = {new Pulumi.Aws.Inputs.GetAmiFiltersArgs
12 | {
13 | Name = "name", Values = {"amzn2-ami-k*-hvm-*-x86_64-gp2"}
14 | }}
15 | }));
16 |
17 | var group = new Pulumi.Aws.Ec2.SecurityGroup("web-secgrp", new Pulumi.Aws.Ec2.SecurityGroupArgs
18 | {
19 | Description = "Enable HTTP access",
20 | Ingress =
21 | {
22 | new Pulumi.Aws.Ec2.Inputs.SecurityGroupIngressArgs
23 | {
24 | Protocol = "tcp",
25 | FromPort = 80,
26 | ToPort = 80,
27 | CidrBlocks = {"0.0.0.0/0"}
28 | },
29 | new Pulumi.Aws.Ec2.Inputs.SecurityGroupIngressArgs
30 | {
31 | Protocol = "icmp",
32 | FromPort = 8,
33 | ToPort = 80,
34 | CidrBlocks = {"0.0.0.0/0"}
35 | }
36 | }
37 | });
38 |
39 | var userData = @"
40 | #!/bin/bash
41 | echo ""Hello, World!"" > index.html
42 | nohup python -m SimpleHTTPServer 80 &
43 | ";
44 |
45 | var server = new Pulumi.Aws.Ec2.Instance("web-server-www", new Pulumi.Aws.Ec2.InstanceArgs
46 | {
47 | InstanceType = "t2.micro",
48 | VpcSecurityGroupIds = {group.Id},
49 | UserData = userData,
50 | Ami = ami.Apply(a => a.Id)
51 | });
52 |
53 | this.PublicIp = server.PublicIp;
54 | this.PublicDns = server.PublicDns;
55 | }
56 |
57 | [Output] public Output PublicIp { get; set; }
58 | [Output] public Output PublicDns { get; set; }
59 | }
60 |
--------------------------------------------------------------------------------
/labs/aws/in-person/python/lab-04/code/step2.py:
--------------------------------------------------------------------------------
1 | from pulumi import export, Output
2 | import pulumi_aws as aws
3 | import json, hashlib
4 |
5 | h = hashlib.new('sha1')
6 |
7 | # Create the EKS Service Role and the correct role attachments
8 | service_role = aws.iam.Role("eks-service-role",
9 | assume_role_policy=json.dumps({
10 | "Version": "2012-10-17",
11 | "Statement": [{
12 | "Sid": "",
13 | "Effect": "Allow",
14 | "Principal": {
15 | "Service": "eks.amazonaws.com"
16 | },
17 | "Action": "sts:AssumeRole"
18 | }]
19 | })
20 | )
21 |
22 | service_role_managed_policy_arns = [
23 | "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy",
24 | "arn:aws:iam::aws:policy/AmazonEKSServicePolicy"
25 | ]
26 |
27 | for policy in service_role_managed_policy_arns:
28 | h.update(policy.encode('utf-8'))
29 | role_policy_attachment = aws.iam.RolePolicyAttachment(f"eks-service-role-{h.hexdigest()[0:8]}",
30 | policy_arn=policy,
31 | role=service_role.name
32 | )
33 |
34 | # Create the EKS NodeGroup Role and the correct role attachments
35 | node_group_role = aws.iam.Role("eks-nodegroup-role",
36 | assume_role_policy=json.dumps({
37 | "Version": "2012-10-17",
38 | "Statement": [{
39 | "Sid": "",
40 | "Effect": "Allow",
41 | "Principal": {
42 | "Service": "ec2.amazonaws.com"
43 | },
44 | "Action": "sts:AssumeRole"
45 | }]
46 | })
47 | )
48 |
49 | nodegroup_role_managed_policy_arns = [
50 | "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy",
51 | "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy",
52 | "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
53 | ]
54 |
55 | for policy in nodegroup_role_managed_policy_arns:
56 | h.update(policy.encode('utf-8'))
57 | role_policy_attachment = aws.iam.RolePolicyAttachment(f"eks-nodegroup-role-{h.hexdigest()[0:8]}",
58 | policy_arn=policy,
59 | role=node_group_role.name
60 | )
61 |
--------------------------------------------------------------------------------
/labs/azure/csharp/01-iac/02-configuring-azure.md:
--------------------------------------------------------------------------------
1 | # Configuring Azure
2 |
3 | Now that you have a basic project, let's configure Azure support for it.
4 |
5 | ## Step 1 — Install the Azure Package
6 |
7 | Run the following command to install the Azure package:
8 |
9 | ```bash
10 | dotnet add package Pulumi.Azure
11 | ```
12 |
13 | The package will be added to `csproj` and the binaries will be restored.
14 |
15 | ## Step 2 — Use the Azure Package
16 |
17 | Now that the Azure package is installed, add the following line to `MyStack.cs` to import it:
18 |
19 | ```cs
20 | ...
21 | using Azure = Pulumi.Azure;
22 | ...
23 | ```
24 |
25 | > :white_check_mark: After this change, your `MyStack.cs` should [look like this](./code/02-configuring-azure/step2.cs).
26 |
27 | ## Step 3 — Configure an Azure Region
28 |
29 | Configure the Azure region you would like to deploy to:
30 |
31 | ```bash
32 | pulumi config set azure:location westus2
33 | ```
34 |
35 | Feel free to choose any Azure region that supports the services used in these labs ([see this infographic](https://azure.microsoft.com/en-us/global-infrastructure/regions/) for a list of available regions).
36 |
37 | The command persists the value to the local `Pulumi.dev.yaml` file. You can view or edit this file at any time to effect the configuration of the current stack.
38 |
39 | ## Step 4 — Login to Azure
40 |
41 | Simply login to the Azure CLI and Pulumi will automatically use your credentials:
42 |
43 | ```
44 | az login
45 | ...
46 | You have logged in. Now let us find all the subscriptions to which you have access...
47 | ...
48 | ```
49 |
50 | The Azure CLI, and thus Pulumi, will use the Default Subscription by default, however it is possible to override the subscription, by simply setting your subscription ID to the id output from `az account list`’s output:
51 |
52 | ```
53 | $ az account list
54 | ```
55 |
56 | Pick out the `` from the list and run:
57 |
58 | ```
59 | $ az account set --subscription=
60 | ```
61 |
62 | ## Next Steps
63 |
64 | * [Provisioning a Resource Group](./03-provisioning-infrastructure.md)
65 |
--------------------------------------------------------------------------------
/labs/azure/csharp/01-iac/06-creating-a-second-stack.md:
--------------------------------------------------------------------------------
1 | # Creating a Second Stack
2 |
3 | It is easy to create multiple instances of the same project. This is called a stack. This is handy for multiple development or test environments, staging versus production, and scaling a given infrastructure across many regions.
4 |
5 | ## Step 1 — Create and Configure a New Stack
6 |
7 | Create a new stack:
8 |
9 | ```bash
10 | pulumi stack init prod
11 | ```
12 |
13 | Next, configure its two required variables:
14 |
15 | ```bash
16 | pulumi config set azure:location westeurope
17 | pulumi config set iac-workshop:container htmlprod
18 | ```
19 |
20 | If you are ever curious to see the list of stacks for your current project, run this command:
21 |
22 | ```bash
23 | pulumi stack ls
24 | ```
25 |
26 | It will print all stacks for this project that are available to you:
27 |
28 | ```
29 | NAME LAST UPDATE RESOURCE COUNT URL
30 | dev 30 minutes ago 4 https://app.pulumi.com/myuser/iac-workshop/dev
31 | prod* 3 minutes ago 0 https://app.pulumi.com/myuser/iac-workshop/prod
32 | ```
33 |
34 | ## Step 2 — Deploy the New Stack
35 |
36 | Now deploy all of the changes:
37 |
38 | ```bash
39 | pulumi up
40 | ```
41 |
42 | This will create an entirely new set of resources from scratch, unrelated to the existing `dev` stack's resources.
43 |
44 | ```
45 | Updating (prod):
46 |
47 | Type Name Status
48 | + pulumi:pulumi:Stack iac-workshop-prod created
49 | + ├─ azure:core:ResourceGroup my-group created
50 | + ├─ azure:storage:Account mystorage created
51 | + └─ azure:storage:Container mycontainer created
52 |
53 | Outputs:
54 | AccountName: "mystorage4a3f2830"
55 |
56 | Resources:
57 | + 4 created
58 |
59 | Duration: 30s
60 |
61 | Permalink: https://app.pulumi.com/myuser/iac-workshop/prod/updates/1
62 | ```
63 |
64 | A new set of resources has been created for the `prod` stack.
65 |
66 | ## Next Steps
67 |
68 | * [Destroying Your Infrastructure](./07-destroying-your-infrastructure.md)
69 |
--------------------------------------------------------------------------------
/labs/azure/python/01-iac/06-creating-a-second-stack.md:
--------------------------------------------------------------------------------
1 | # Creating a Second Stack
2 |
3 | It is easy to create multiple instances of the same project. This is called a stack. This is handy for multiple development or test environments, staging versus production, and scaling a given infrastructure across many regions.
4 |
5 | ## Step 1 — Create and Configure a New Stack
6 |
7 | Create a new stack:
8 |
9 | ```bash
10 | pulumi stack init prod
11 | ```
12 |
13 | Next, configure its two required variables:
14 |
15 | ```bash
16 | pulumi config set azure:location westeurope
17 | pulumi config set iac-workshop:container htmlprod
18 | ```
19 |
20 | If you are ever curious to see the list of stacks for your current project, run this command:
21 |
22 | ```bash
23 | pulumi stack ls
24 | ```
25 |
26 | It will print all stacks for this project that are available to you:
27 |
28 | ```
29 | NAME LAST UPDATE RESOURCE COUNT URL
30 | dev 30 minutes ago 4 https://app.pulumi.com/myuser/iac-workshop/dev
31 | prod* 3 minutes ago 0 https://app.pulumi.com/myuser/iac-workshop/prod
32 | ```
33 |
34 | ## Step 2 — Deploy the New Stack
35 |
36 | Now deploy all of the changes:
37 |
38 | ```bash
39 | pulumi up
40 | ```
41 |
42 | This will create an entirely new set of resources from scratch, unrelated to the existing `dev` stack's resources.
43 |
44 | ```
45 | Updating (prod):
46 |
47 | Type Name Status
48 | + pulumi:pulumi:Stack iac-workshop-prod created
49 | + ├─ azure:core:ResourceGroup my-group created
50 | + ├─ azure:storage:Account mystorage created
51 | + └─ azure:storage:Container mycontainer created
52 |
53 | Outputs:
54 | AccountName: "mystorage4a3f2830"
55 |
56 | Resources:
57 | + 4 created
58 |
59 | Duration: 30s
60 |
61 | Permalink: https://app.pulumi.com/myuser/iac-workshop/prod/updates/1
62 | ```
63 |
64 | A new set of resources has been created for the `prod` stack.
65 |
66 | ## Next Steps
67 |
68 | * [Destroying Your Infrastructure](./07-destroying-your-infrastructure.md)
69 |
--------------------------------------------------------------------------------
/labs/aws/in-person/go/lab-01/01-creating-a-new-project.md:
--------------------------------------------------------------------------------
1 | # Creating a New Project
2 |
3 | Infrastructure in Pulumi is organized into projects. Each project is a single program that, when run, declares the desired infrastructure for Pulumi to manage.
4 |
5 | ## Step 1 — Create a Directory
6 |
7 | Each Pulumi project lives in its own directory. Create one now and change into it:
8 |
9 | ```bash
10 | mkdir iac-workshop
11 | cd iac-workshop
12 | ```
13 |
14 | > Pulumi will use the directory name as your project name by default. To create an independent project, simply name the directory differently.
15 |
16 | ## Step 2 — Initialize Your Project
17 |
18 | A Pulumi project is just a directory with some files in it. It's possible for you to create a new one by hand. The `pulumi new` command, however, automates the process:
19 |
20 | ```bash
21 | pulumi new go -y
22 | ```
23 |
24 | This will print output similar to the following with a bit more information and status as it goes:
25 |
26 | ```
27 | Created project 'iac-workshop'
28 | Created stack 'dev'
29 |
30 | Your new project is ready to go! ✨
31 |
32 | To perform an initial deployment, run 'dep ensure', then, run 'pulumi up'
33 | ```
34 |
35 | This command has created all the files we need, initialized a new stack named `dev` (an instance of our project). We now need
36 | to install our dependencies using [`go dep`](https://github.com/golang/dep).
37 |
38 | ## Step 3 — Inspect Your New Project
39 |
40 | Our project is comprised of multiple files:
41 |
42 | * **`main.go`**: your program's main entrypoint file
43 | * **`Gopkg.toml`**: your project's go dependency information
44 | * **`Pulumi.yaml`**: your project's metadata, containing its name and language
45 |
46 | Run `cat main.go` to see the contents of your project's empty program:
47 |
48 | ```go
49 | package main
50 |
51 | import (
52 | "github.com/pulumi/pulumi/sdk/go/pulumi"
53 | )
54 |
55 | func main() {
56 | pulumi.Run(func(ctx *pulumi.Context) error {
57 | return nil
58 | })
59 | }
60 | ```
61 |
62 | Feel free to explore the other files, although we won't be editing any of them by hand.
63 |
64 | # Next Steps
65 |
66 | * [Configuring AWS](./02-configuring-aws.md)
67 |
--------------------------------------------------------------------------------
/labs/intro/typescript/lab-01/README.md:
--------------------------------------------------------------------------------
1 | # Creating a New Project
2 |
3 | Infrastructure in Pulumi is organized into projects. Each project is a single program that, when run, declares the desired infrastructure for Pulumi to manage.
4 |
5 | ## Step 1 — Create a Directory
6 |
7 | Each Pulumi project lives in its own directory. Create one now and change into it:
8 |
9 | ```bash
10 | mkdir my-first-app
11 | cd my-first-app
12 | ```
13 |
14 | > Pulumi will use the directory name as your project name by default. To create an independent project, simply name the directory differently.
15 |
16 | ## Step 2 — Initialize Your Project
17 |
18 | A Pulumi project is just a directory with some files in it. It's possible for you to create a new one by hand. The `pulumi new` command, however, automates the process:
19 |
20 | ```bash
21 | pulumi new typescript
22 | ```
23 |
24 | This will print output similar to the following with a bit more information and status as it goes:
25 |
26 | ```
27 | Created project 'my-first-app'
28 | Created stack 'dev'
29 | Saved config
30 | Installing dependencies...
31 | Finished installing dependencies
32 |
33 | Your new project is ready to go!
34 | ```
35 |
36 | This command has created all the files we need, initialized a new stack named `dev` (an instance of our project), and installed the needed package dependencies from NPM.
37 |
38 | ## Step 3 — Inspect Your New Project
39 |
40 | Our project is comprised of multiple files:
41 |
42 | * **`index.ts`**: your program's main entrypoint file
43 | * **`package.json`** and **`package-lock.json`**: your project's NPM dependency information
44 | * **`Pulumi.yaml`**: your project's metadata, containing its name and language
45 | * **`tsconfig.json`**: your project's TypeScript settings
46 | * **`node_modules/`**: a directory containing your project's installed NPM dependencies
47 |
48 | Run `cat index.ts` to see the contents of your project's empty program:
49 |
50 | ```typescript
51 | import * as pulumi from "@pulumi/pulumi";
52 | ```
53 |
54 | Feel free to explore the other files, although we won't be editing any of them by hand.
55 |
56 | # Next Steps
57 |
58 | * [Create your first resource](../lab-02/README.md)
59 |
--------------------------------------------------------------------------------
/labs/aws/in-person/typescript/lab-01/01-creating-a-new-project.md:
--------------------------------------------------------------------------------
1 | # Creating a New Project
2 |
3 | Infrastructure in Pulumi is organized into projects. Each project is a single program that, when run, declares the desired infrastructure for Pulumi to manage.
4 |
5 | ## Step 1 — Create a Directory
6 |
7 | Each Pulumi project lives in its own directory. Create one now and change into it:
8 |
9 | ```bash
10 | mkdir iac-workshop
11 | cd iac-workshop
12 | ```
13 |
14 | > Pulumi will use the directory name as your project name by default. To create an independent project, simply name the directory differently.
15 |
16 | ## Step 2 — Initialize Your Project
17 |
18 | A Pulumi project is just a directory with some files in it. It's possible for you to create a new one by hand. The `pulumi new` command, however, automates the process:
19 |
20 | ```bash
21 | pulumi new typescript -y
22 | ```
23 |
24 | This will print output similar to the following with a bit more information and status as it goes:
25 |
26 | ```
27 | Created project 'iac-workshop'
28 | Created stack 'dev'
29 | Saved config
30 | Installing dependencies...
31 | Finished installing dependencies
32 |
33 | Your new project is ready to go!
34 | ```
35 |
36 | This command has created all the files we need, initialized a new stack named `dev` (an instance of our project), and installed the needed package dependencies from NPM.
37 |
38 | ## Step 3 — Inspect Your New Project
39 |
40 | Our project is comprised of multiple files:
41 |
42 | * **`index.ts`**: your program's main entrypoint file
43 | * **`package.json`** and **`package-lock.json`**: your project's NPM dependency information
44 | * **`Pulumi.yaml`**: your project's metadata, containing its name and language
45 | * **`tsconfig.json`**: your project's TypeScript settings
46 | * **`node_modules/`**: a directory containing your project's installed NPM dependencies
47 |
48 | Run `cat index.ts` to see the contents of your project's empty program:
49 |
50 | ```typescript
51 | import * as pulumi from "@pulumi/pulumi";
52 | ```
53 |
54 | Feel free to explore the other files, although we won't be editing any of them by hand.
55 |
56 | # Next Steps
57 |
58 | * [Configuring AWS](./02-configuring-aws.md)
59 |
--------------------------------------------------------------------------------
/labs/intro/python/lab-01/README.md:
--------------------------------------------------------------------------------
1 | # Creating a New Project
2 |
3 | Infrastructure in Pulumi is organized into projects. Each project is a single program that, when run, declares the desired infrastructure for Pulumi to manage.
4 |
5 | ## Step 1 — Create a Directory
6 |
7 | Each Pulumi project lives in its own directory. Create one now and change into it:
8 |
9 | ```bash
10 | mkdir my-first-app
11 | cd my-first-app
12 | ```
13 |
14 | > Pulumi will use the directory name as your project name by default. To create an independent project, simply name the directory differently.
15 |
16 | ## Step 2 — Initialize Your Project
17 |
18 | A Pulumi project is just a directory with some files in it. It's possible for you to create a new one by hand. The `pulumi new` command, however, automates the process:
19 |
20 | ```bash
21 | pulumi new python -y
22 | ```
23 |
24 | This will print output similar to the following with a bit more information and status as it goes:
25 |
26 | ```
27 | Created stack 'dev'
28 |
29 | Creating virtual environment...
30 |
31 | Finished creating virtual environment
32 |
33 | Updating pip, setuptools, and wheel in virtual environment...
34 | ...
35 | Your new project is ready to go! ✨
36 |
37 | To perform an initial deployment, run 'pulumi up'
38 | ```
39 |
40 | This command has created all the files we need, initialized a new stack named `dev` (an instance of our project), and installed the needed package dependencies from PyPi.
41 |
42 | ## Step 3 — Inspect Your New Project
43 |
44 | Our project is comprised of multiple files:
45 |
46 | * **`__main__.py`**: your program's main entrypoint file
47 | * **`requirements.txt`**: your project's Python dependency information
48 | * **`Pulumi.yaml`**: your project's metadata, containing its name and language
49 | * **`venv`**: a [virtualenv](https://pypi.org/project/virtualenv/) for your project
50 |
51 | Run `cat __main__.py` to see the contents of your project's empty program:
52 |
53 | ```python
54 | """A Python Pulumi program"""
55 |
56 | import pulumi
57 | ```
58 |
59 | Feel free to explore the other files, although we won't be editing any of them by hand.
60 |
61 | # Next Steps
62 |
63 | * [Create your first resource](../lab-02/README.md)
64 |
--------------------------------------------------------------------------------
/labs/aws/in-person/go/lab-04/code/step2.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/pulumi/pulumi-aws/sdk/go/aws/iam"
7 | "github.com/pulumi/pulumi/sdk/go/pulumi"
8 | )
9 |
10 | func main() {
11 | pulumi.Run(func(ctx *pulumi.Context) error {
12 | eksRole, err := iam.NewRole(ctx, "eks-iam-eksRole", &iam.RoleArgs{
13 | AssumeRolePolicy: pulumi.String(`{
14 | "Version": "2008-10-17",
15 | "Statement": [{
16 | "Sid": "",
17 | "Effect": "Allow",
18 | "Principal": {
19 | "Service": "eks.amazonaws.com"
20 | },
21 | "Action": "sts:AssumeRole"
22 | }]
23 | }`),
24 | })
25 | if err != nil {
26 | return err
27 | }
28 | eksPolicies := []string{
29 | "arn:aws:iam::aws:policy/AmazonEKSServicePolicy",
30 | "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy",
31 | }
32 | for i, eksPolicy := range eksPolicies {
33 | _, err := iam.NewRolePolicyAttachment(ctx, fmt.Sprintf("rpa-%d", i), &iam.RolePolicyAttachmentArgs{
34 | PolicyArn: pulumi.String(eksPolicy),
35 | Role: eksRole.Name,
36 | })
37 | if err != nil {
38 | return err
39 | }
40 | }
41 | // Create the EC2 NodeGroup Role
42 | nodeGroupRole, err := iam.NewRole(ctx, "nodegroup-iam-role", &iam.RoleArgs{
43 | AssumeRolePolicy: pulumi.String(`{
44 | "Version": "2012-10-17",
45 | "Statement": [{
46 | "Sid": "",
47 | "Effect": "Allow",
48 | "Principal": {
49 | "Service": "ec2.amazonaws.com"
50 | },
51 | "Action": "sts:AssumeRole"
52 | }]
53 | }`),
54 | })
55 | if err != nil {
56 | return err
57 | }
58 | nodeGroupPolicies := []string{
59 | "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy",
60 | "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy",
61 | "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",
62 | }
63 | for i, nodeGroupPolicy := range nodeGroupPolicies {
64 | _, err := iam.NewRolePolicyAttachment(ctx, fmt.Sprintf("ngpa-%d", i), &iam.RolePolicyAttachmentArgs{
65 | Role: nodeGroupRole.Name,
66 | PolicyArn: pulumi.String(nodeGroupPolicy),
67 | })
68 | if err != nil {
69 | return err
70 | }
71 | }
72 |
73 | return nil
74 | })
75 | }
76 |
--------------------------------------------------------------------------------
/labs/aws/in-person/typescript/lab-06/code/step4.ts:
--------------------------------------------------------------------------------
1 | import * as AWS from "aws-sdk";
2 | import * as aws from "@pulumi/aws";
3 | import * as awsx from "@pulumi/awsx";
4 | import * as pulumi from "@pulumi/pulumi";
5 |
6 | const hits = new aws.dynamodb.Table("hits", {
7 | attributes: [{ name: "Site", type: "S" }],
8 | hashKey: "Site",
9 | billingMode: "PAY_PER_REQUEST",
10 | });
11 |
12 | const handlerRole = new aws.iam.Role("handler-role", {
13 | assumeRolePolicy: {
14 | Version: "2012-10-17",
15 | Statement: [{
16 | Action: "sts:AssumeRole",
17 | Principal: {
18 | Service: "lambda.amazonaws.com"
19 | },
20 | Effect: "Allow",
21 | Sid: "",
22 | }],
23 | },
24 | });
25 |
26 | const handlerPolicy = new aws.iam.RolePolicy("handler-policy", {
27 | role: handlerRole,
28 | policy: hits.arn.apply(arn => JSON.stringify({
29 | Version: "2012-10-17",
30 | Statement: [
31 | {
32 | Action: [
33 | "dynamodb:UpdateItem",
34 | "dynamodb:PutItem",
35 | "dynamodb:GetItem",
36 | "dynamodb:DescribeTable",
37 | ],
38 | Resource: arn,
39 | Effect: "Allow",
40 | },
41 | {
42 | Action: ["logs:*", "cloudwatch:*"],
43 | Resource: "*",
44 | Effect: "Allow",
45 | },
46 | ],
47 | })),
48 | });
49 |
50 | const site = new awsx.apigateway.API("site", {
51 | routes: [{
52 | path: "/",
53 | method: "GET",
54 | eventHandler: new aws.lambda.Function("get-handler", {
55 | runtime: aws.lambda.NodeJS10dXRuntime,
56 | code: new pulumi.asset.AssetArchive({
57 | ".": new pulumi.asset.FileArchive("handler"),
58 | }),
59 | handler: "index.handler",
60 | role: handlerRole.arn,
61 | environment: {
62 | variables: {
63 | "HITS_TABLE": hits.name,
64 | },
65 | },
66 | }, { dependsOn: handlerPolicy }),
67 | }],
68 | });
69 | export const url = site.url;
70 |
--------------------------------------------------------------------------------
/labs/aws/in-person/python/lab-05/code/step6.py:
--------------------------------------------------------------------------------
1 | from pulumi import export, StackReference, Output, ResourceOptions
2 | from pulumi_kubernetes import Provider
3 | from pulumi_kubernetes.apps.v1 import Deployment
4 | from pulumi_kubernetes.core.v1 import Service, Namespace
5 | import pulumi
6 |
7 | # Create StackReference to the Kubernetes cluster stack
8 | config = pulumi.Config()
9 | stackRef = config.require("clusterStackRef");
10 | infra = StackReference(f"{stackRef}")
11 |
12 | # Declare a provider using the KubeConfig we created
13 | # This will be used to interact with the EKS cluster
14 | k8s_provider = Provider("k8s-provider", kubeconfig=infra.get_output("kubeconfig"))
15 |
16 | # Create a Namespace object https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
17 | ns = Namespace("app-ns",
18 | metadata={
19 | "name": "joe-duffy",
20 | },
21 | opts=ResourceOptions(provider=k8s_provider)
22 | )
23 |
24 | app_labels = {
25 | "app": "iac-workshop"
26 | }
27 | app_deployment = Deployment("app-dep",
28 | metadata={
29 | "namespace": ns.metadata["name"]
30 | },
31 | spec={
32 | "selector": {
33 | "match_labels": app_labels,
34 | },
35 | "replicas": 3,
36 | "template": {
37 | "metadata": {
38 | "labels": app_labels,
39 | },
40 | "spec": {
41 | "containers": [{
42 | "name": "iac-workshop",
43 | "image": "jocatalin/kubernetes-bootcamp:v2",
44 | }],
45 | },
46 | },
47 | },
48 | opts=ResourceOptions(provider=k8s_provider)
49 | )
50 |
51 | service = Service("app-service",
52 | metadata={
53 | "namespace": ns.metadata["name"],
54 | "labels": app_labels
55 | },
56 | spec={
57 | "ports": [{
58 | "port": 80,
59 | "target_port": 8080,
60 | }],
61 | "selector": app_labels,
62 | "type": "LoadBalancer",
63 | },
64 | opts=ResourceOptions(provider=k8s_provider)
65 | )
66 |
67 | export('url', Output.all(service.status['load_balancer']['ingress'][0]['hostname'], service.spec['ports'][0]['port']) \
68 | .apply(lambda args: f"http://{args[0]}:{round(args[1])}"))
69 |
--------------------------------------------------------------------------------
/labs/azure/csharp/01-iac/01-creating-a-new-project.md:
--------------------------------------------------------------------------------
1 | # Creating a New Project
2 |
3 | Infrastructure in Pulumi is organized into projects. Each project is a single program that, when run, declares the desired infrastructure for Pulumi to manage.
4 |
5 | ## Step 1 — Create a Directory
6 |
7 | Each Pulumi project lives in its own directory. Create one now and change into it:
8 |
9 | ```bash
10 | mkdir iac-workshop
11 | cd iac-workshop
12 | ```
13 |
14 | > Pulumi will use the directory name as your project name by default. To create an independent project, simply name the directory differently.
15 |
16 | ## Step 2 — Initialize Your Project
17 |
18 | A Pulumi project is just a directory with some files in it. It's possible for you to create a new one by hand. The `pulumi new` command, however, automates the process:
19 |
20 | ```bash
21 | pulumi new csharp -y
22 | ```
23 |
24 | This will print output similar to the following with a bit more information and status as it goes:
25 |
26 | ```
27 | Created project 'iac-workshop'
28 | Created stack 'dev'
29 | Installing dependencies...
30 | Build succeeded.
31 | Finished installing dependencies
32 |
33 | Your new project is ready to go!
34 | ```
35 |
36 | This command has created all the files we need, initialized a new stack named `dev` (an instance of our project), and installed the needed package dependencies from NuGet.
37 |
38 | ## Step 3 — Inspect Your New Project
39 |
40 | Our project is comprised of multiple files:
41 |
42 | * **`Program.cs`**: your program's main entrypoint file
43 | * **`MyStack.cs`**: your stack definition file
44 | * **`iac-workshop.csproj`**: your C# project file
45 | * **`Pulumi.yaml`**: your project's metadata, containing its name and language
46 | * **`bin/`** and **`obj/`**: directories containing your project's build artifacts
47 |
48 | Open `MyStack.cs` to see the contents of the empty program of your infrastructure stack:
49 |
50 | ```csharp
51 | using Pulumi;
52 |
53 | class MyStack : Stack
54 | {
55 | public MyStack()
56 | {
57 | // Add your resources here
58 | }
59 | }
60 | ```
61 |
62 | Feel free to explore the other files, although we won't be editing any of them by hand.
63 |
64 | # Next Steps
65 |
66 | * [Configuring Azure](./02-configuring-azure.md)
67 |
--------------------------------------------------------------------------------
/labs/aws/in-person/python/lab-05/code/step4.py:
--------------------------------------------------------------------------------
1 | from pulumi import export, StackReference, Output, ResourceOptions
2 | from pulumi_kubernetes import Provider
3 | from pulumi_kubernetes.apps.v1 import Deployment
4 | from pulumi_kubernetes.core.v1 import Service, Namespace
5 | import pulumi
6 |
7 | # Create StackReference to the Kubernetes cluster stack
8 | config = pulumi.Config()
9 | stackRef = config.require("clusterStackRef");
10 | infra = StackReference(f"{stackRef}")
11 |
12 | # Declare a provider using the KubeConfig we created
13 | # This will be used to interact with the EKS cluster
14 | k8s_provider = Provider("k8s-provider", kubeconfig=infra.get_output("kubeconfig"))
15 |
16 | # Create a Namespace object https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
17 | ns = Namespace("app-ns",
18 | metadata={
19 | "name": "joe-duffy",
20 | },
21 | opts=ResourceOptions(provider=k8s_provider)
22 | )
23 |
24 | app_labels = {
25 | "app": "iac-workshop"
26 | }
27 | app_deployment = Deployment("app-dep",
28 | metadata={
29 | "namespace": ns.metadata["name"]
30 | },
31 | spec={
32 | "selector": {
33 | "match_labels": app_labels,
34 | },
35 | "replicas": 1,
36 | "template": {
37 | "metadata": {
38 | "labels": app_labels,
39 | },
40 | "spec": {
41 | "containers": [{
42 | "name": "iac-workshop",
43 | "image": "gcr.io/google-samples/kubernetes-bootcamp:v1",
44 | }],
45 | },
46 | },
47 | },
48 | opts=ResourceOptions(provider=k8s_provider)
49 | )
50 |
51 | service = Service("app-service",
52 | metadata={
53 | "namespace": ns.metadata["name"],
54 | "labels": app_labels
55 | },
56 | spec={
57 | "ports": [{
58 | "port": 80,
59 | "target_port": 8080,
60 | }],
61 | "selector": app_labels,
62 | "type": "LoadBalancer",
63 | },
64 | opts=ResourceOptions(provider=k8s_provider)
65 | )
66 |
67 | export('url', Output.all(service.status['load_balancer']['ingress'][0]['hostname'], service.spec['ports'][0]['port']) \
68 | .apply(lambda args: f"http://{args[0]}:{round(args[1])}"))
69 |
--------------------------------------------------------------------------------
/labs/aws/pulumi-in-practice/python/lab-03/code/step4.py:
--------------------------------------------------------------------------------
1 | from pulumi import export
2 | import pulumi_aws as aws
3 |
4 | ami = aws.get_ami(
5 | most_recent="true",
6 | owners=["137112412989"],
7 | filters=[{"name":"name","values":["amzn-ami-hvm-*-x86_64-ebs"]}])
8 |
9 | group = aws.ec2.SecurityGroup(
10 | "web-secgrp",
11 | ingress=[
12 | { 'protocol': 'icmp', 'from_port': 8, 'to_port': 0, 'cidr_blocks': ['0.0.0.0/0'] },
13 | { 'protocol': 'tcp', 'from_port': 80, 'to_port': 80, 'cidr_blocks': ['0.0.0.0/0'] },
14 | ],
15 | egress=[
16 | { 'protocol': 'tcp', 'from_port': 80, 'to_port': 80, 'cidr_blocks': ['0.0.0.0/0'] },
17 | ]
18 | )
19 |
20 | default_vpc = aws.ec2.get_vpc(default="true")
21 | default_vpc_subnets = aws.ec2.get_subnet_ids(vpc_id=default_vpc.id)
22 |
23 | lb = aws.lb.LoadBalancer("external-loadbalancer",
24 | internal="false",
25 | security_groups=[group.id],
26 | subnets=default_vpc_subnets.ids,
27 | load_balancer_type="application",
28 | )
29 |
30 | target_group = aws.lb.TargetGroup("target-group",
31 | port=80,
32 | protocol="HTTP",
33 | target_type="ip",
34 | vpc_id=default_vpc.id
35 | )
36 |
37 | listener = aws.lb.Listener("listener",
38 | load_balancer_arn=lb.arn,
39 | port=80,
40 | default_actions=[{
41 | "type": "forward",
42 | "target_group_arn": target_group.arn
43 | }]
44 | )
45 |
46 | ips = []
47 | hostnames = []
48 | for az in aws.get_availability_zones().names:
49 | server = aws.ec2.Instance(f'web-server-{az}',
50 | instance_type="t2.micro",
51 | security_groups=[group.name],
52 | ami=ami.id,
53 | user_data="""#!/bin/bash
54 | echo \"Hello, World -- from {}!\" > index.html
55 | nohup python -m SimpleHTTPServer 80 &
56 | """.format(az),
57 | availability_zone=az,
58 | tags={
59 | "Name": "web-server",
60 | },
61 | )
62 | ips.append(server.public_ip)
63 | hostnames.append(server.public_dns)
64 |
65 | attachment = aws.lb.TargetGroupAttachment(f'web-server-{az}',
66 | target_group_arn=target_group.arn,
67 | target_id=server.private_ip,
68 | port=80,
69 | )
70 |
71 | export('ips', ips)
72 | export('hostnames', hostnames)
73 | export("url", lb.dns_name)
74 |
75 |
76 |
--------------------------------------------------------------------------------
/labs/aws/in-person/typescript/lab-02/code/step2.ts:
--------------------------------------------------------------------------------
1 | import * as awsx from "@pulumi/awsx";
2 | import * as aws from "@pulumi/aws";
3 |
4 | // Variable we will use for naming purpose
5 | const name = "demo";
6 |
7 | // Creating a VPC with a Single Nat Gateway Strategy (To save cost)
8 | const myvpc = new awsx.ec2.Vpc(`${name}-vpc`, {
9 | cidrBlock: "10.0.0.0/24",
10 | numberOfAvailabilityZones: 3,
11 | enableDnsHostnames: true,
12 | natGateways: {
13 | strategy: "Single", // This is mainly to save cost. You do this only in dev
14 | },
15 | });
16 |
17 | // VPC Outputs
18 | export const vpc_id = myvpc.vpcId;
19 | export const vpc_natgateways = myvpc.natGateways[0].id;
20 | export const vpc_public_subnetids = myvpc.publicSubnetIds;
21 | export const vpc_private_subnetids = myvpc.privateSubnetIds;
22 |
23 | // Creating Security Group within VPC
24 | const mysecuritygroup = new aws.ec2.SecurityGroup(`${name}-securitygroup`, {
25 | vpcId:myvpc.vpcId,
26 | ingress: [
27 | { protocol: "tcp",
28 | fromPort: 443,
29 | toPort: 443,
30 | cidrBlocks: ["0.0.0.0/0"],
31 | description: "Allow inbound access via https",
32 | self: true, // Add the securitygroup itself as a source
33 | },
34 | {
35 | protocol: "tcp",
36 | fromPort: 80,
37 | toPort: 80,
38 | cidrBlocks: ["0.0.0.0/0"],
39 | description: "Allow inbound access via http",
40 | self: true, // Add the securitygroup itself as a source
41 | },
42 | ],
43 | egress: [
44 | { protocol: "tcp",
45 | fromPort: 443,
46 | toPort: 443,
47 | cidrBlocks: ["0.0.0.0/0"],
48 | description: "Allow outbound access via https"
49 | },
50 | {
51 | protocol: "tcp",
52 | fromPort: 80,
53 | toPort: 80,
54 | cidrBlocks: ["0.0.0.0/0"],
55 | description: "Allow outbound access via http"
56 | },
57 | ],
58 | tags: {"Name": `${name}-securitygroup`},
59 | }, { parent: myvpc, dependsOn: myvpc });
60 |
61 | // Exporting security group outputs
62 | export const security_group_name = mysecuritygroup.id;
63 | export const security_group_vpc = mysecuritygroup.vpcId;
64 | export const security_group_egress = mysecuritygroup.egress;
65 | export const security_group_ingress = mysecuritygroup.ingress;
--------------------------------------------------------------------------------
/labs/aws/in-person/python/lab-02/code/step4.py:
--------------------------------------------------------------------------------
1 | from pulumi import export
2 | import pulumi_aws as aws
3 |
4 | ami = aws.ec2.get_ami(
5 | most_recent="true",
6 | owners=["amazon"],
7 | filters=[{"name":"name","values":["amzn2-ami-k*-hvm-*-x86_64-gp2"]}])
8 |
9 | group = aws.ec2.SecurityGroup(
10 | "web-secgrp",
11 | description='Enable HTTP access',
12 | ingress=[
13 | { 'protocol': 'icmp', 'from_port': 8, 'to_port': 0, 'cidr_blocks': ['0.0.0.0/0'] },
14 | { 'protocol': 'tcp', 'from_port': 80, 'to_port': 80, 'cidr_blocks': ['0.0.0.0/0'] },
15 | ],
16 | egress=[
17 | { 'protocol': 'tcp', 'from_port': 80, 'to_port': 80, 'cidr_blocks': ['0.0.0.0/0'] },
18 | ]
19 | )
20 |
21 | default_vpc = aws.ec2.get_vpc(default="true")
22 | default_vpc_subnets = aws.ec2.get_subnet_ids(vpc_id=default_vpc.id)
23 |
24 | lb = aws.lb.LoadBalancer("external-loadbalancer",
25 | internal="false",
26 | security_groups=[group.id],
27 | subnets=default_vpc_subnets.ids,
28 | load_balancer_type="application",
29 | )
30 |
31 | target_group = aws.lb.TargetGroup("target-group",
32 | port=80,
33 | protocol="HTTP",
34 | target_type="ip",
35 | vpc_id=default_vpc.id
36 | )
37 |
38 | listener = aws.lb.Listener("listener",
39 | load_balancer_arn=lb.arn,
40 | port=80,
41 | default_actions=[{
42 | "type": "forward",
43 | "target_group_arn": target_group.arn
44 | }]
45 | )
46 |
47 | ips = []
48 | hostnames = []
49 | for az in aws.get_availability_zones().names:
50 | server = aws.ec2.Instance(f'web-server-{az}',
51 | instance_type="t2.micro",
52 | vpc_security_group_ids=[group.id],
53 | ami=ami.id,
54 | user_data="""#!/bin/bash
55 | echo \"Hello, World -- from {}!\" > index.html
56 | nohup python -m SimpleHTTPServer 80 &
57 | """.format(az),
58 | availability_zone=az,
59 | tags={
60 | "Name": "web-server",
61 | },
62 | )
63 | ips.append(server.public_ip)
64 | hostnames.append(server.public_dns)
65 |
66 | attachment = aws.lb.TargetGroupAttachment(f'web-server-{az}',
67 | target_group_arn=target_group.arn,
68 | target_id=server.private_ip,
69 | port=80,
70 | )
71 |
72 | export('ips', ips)
73 | export('hostnames', hostnames)
74 | export("url", lb.dns_name)
75 |
76 |
77 |
--------------------------------------------------------------------------------
/labs/azure/csharp/02-serverless/code/step6.cs:
--------------------------------------------------------------------------------
1 | using Pulumi;
2 | using Pulumi.Serialization;
3 |
4 | using Azure = Pulumi.Azure;
5 |
6 | class MyStack : Stack
7 | {
8 | public MyStack()
9 | {
10 | var resourceGroup = new Azure.Core.ResourceGroup("my-group");
11 |
12 | var storageAccount = new Azure.Storage.Account("storage", new Azure.Storage.AccountArgs
13 | {
14 | ResourceGroupName = resourceGroup.Name,
15 | AccountReplicationType = "LRS",
16 | AccountTier = "Standard"
17 | });
18 |
19 | var plan = new Azure.AppService.Plan("asp", new Azure.AppService.PlanArgs
20 | {
21 | ResourceGroupName = resourceGroup.Name,
22 | Kind = "FunctionApp",
23 | Sku = new Azure.AppService.Inputs.PlanSkuArgs
24 | {
25 | Tier = "Dynamic",
26 | Size = "Y1"
27 | }
28 | });
29 |
30 | var container = new Azure.Storage.Container("zips", new Azure.Storage.ContainerArgs
31 | {
32 | StorageAccountName = storageAccount.Name,
33 | ContainerAccessType = "private",
34 | });
35 |
36 | var blob = new Azure.Storage.Blob("zip", new Azure.Storage.BlobArgs
37 | {
38 | StorageAccountName = storageAccount.Name,
39 | StorageContainerName = container.Name,
40 | Type = "Block",
41 | Source = new FileArchive("./functions"),
42 | });
43 |
44 | var codeBlobUrl = Azure.Storage.SharedAccessSignature.SignedBlobReadUrl(blob, storageAccount);
45 |
46 | var app = new Azure.AppService.FunctionApp("fa", new Azure.AppService.FunctionAppArgs
47 | {
48 | ResourceGroupName = resourceGroup.Name,
49 | AppServicePlanId = plan.Id,
50 | StorageConnectionString = storageAccount.PrimaryConnectionString,
51 | Version = "~2",
52 | AppSettings =
53 | {
54 | { "FUNCTIONS_WORKER_RUNTIME", "node" },
55 | { "WEBSITE_NODE_DEFAULT_VERSION", "10.14.1" },
56 | { "WEBSITE_RUN_FROM_PACKAGE", codeBlobUrl }
57 | }
58 | });
59 |
60 | this.Endpoint = Output.Format($"https://{app.DefaultHostname}/api/hello");
61 | }
62 |
63 | [Output]
64 | public Output Endpoint { get; set; }
65 | }
66 |
--------------------------------------------------------------------------------
/labs/aws/in-person/go/lab-05/code/step3.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/json"
5 |
6 | appsv1 "github.com/pulumi/pulumi-kubernetes/sdk/go/kubernetes/apps/v1"
7 | corev1 "github.com/pulumi/pulumi-kubernetes/sdk/go/kubernetes/core/v1"
8 | metav1 "github.com/pulumi/pulumi-kubernetes/sdk/go/kubernetes/meta/v1"
9 | "github.com/pulumi/pulumi-kubernetes/sdk/go/kubernetes/providers"
10 | "github.com/pulumi/pulumi/sdk/go/pulumi"
11 | "github.com/pulumi/pulumi/sdk/go/pulumi/config"
12 | )
13 |
14 | func main() {
15 | pulumi.Run(func(ctx *pulumi.Context) error {
16 | c := config.New(ctx, "")
17 | stackRef := c.Require("clusterStackRef")
18 | infra, err := pulumi.NewStackReference(ctx, stackRef, nil)
19 |
20 | kubeconfig := infra.GetOutput(pulumi.String("kubeconfig")).ApplyString(
21 | func(in interface{}) string {
22 | kc, err := json.Marshal(in)
23 | if err != nil {
24 | panic(err)
25 | }
26 | return string(kc)
27 | },
28 | )
29 | k8sProvider, err := providers.NewProvider(ctx, "k8sprovider", &providers.ProviderArgs{
30 | Kubeconfig: kubeconfig,
31 | })
32 | if err != nil {
33 | return err
34 | }
35 |
36 | namespace, err := corev1.NewNamespace(ctx, "app-ns", &corev1.NamespaceArgs{
37 | Metadata: &metav1.ObjectMetaArgs{
38 | Name: pulumi.String("joe-duffy"),
39 | },
40 | }, pulumi.Provider(k8sProvider))
41 | if err != nil {
42 | return err
43 | }
44 |
45 | appLabels := pulumi.StringMap{
46 | "app": pulumi.String("iac-workshop"),
47 | }
48 | _, err = appsv1.NewDeployment(ctx, "app-dep", &appsv1.DeploymentArgs{
49 | Metadata: &metav1.ObjectMetaArgs{
50 | Namespace: namespace.Metadata.Elem().Name(),
51 | },
52 | Spec: appsv1.DeploymentSpecArgs{
53 | Selector: &metav1.LabelSelectorArgs{
54 | MatchLabels: appLabels,
55 | },
56 | Replicas: pulumi.Int(1),
57 | Template: &corev1.PodTemplateSpecArgs{
58 | Metadata: &metav1.ObjectMetaArgs{
59 | Labels: appLabels,
60 | },
61 | Spec: &corev1.PodSpecArgs{
62 | Containers: corev1.ContainerArray{
63 | corev1.ContainerArgs{
64 | Name: pulumi.String("iac-workshop"),
65 | Image: pulumi.String("jocatalin/kubernetes-bootcamp:v2"),
66 | }},
67 | },
68 | },
69 | },
70 | }, pulumi.Provider(k8sProvider))
71 | if err != nil {
72 | return err
73 | }
74 |
75 | return nil
76 | })
77 | }
78 |
--------------------------------------------------------------------------------
/labs/aws/in-person/go/lab-02/code/step3.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/pulumi/pulumi-aws/sdk/go/aws"
7 | "github.com/pulumi/pulumi-aws/sdk/go/aws/ec2"
8 | "github.com/pulumi/pulumi/sdk/go/pulumi"
9 | )
10 |
11 | func main() {
12 | pulumi.Run(func(ctx *pulumi.Context) error {
13 | mostRecent := true
14 | ami, err := aws.GetAmi(ctx, &aws.GetAmiArgs{
15 | Filters: []aws.GetAmiFilter{
16 | {
17 | Name: "name",
18 | Values: []string{"amzn2-ami-k*-hvm-*-x86_64-gp2"},
19 | },
20 | },
21 | Owners: []string{"amazon"},
22 | MostRecent: &mostRecent,
23 | })
24 | if err != nil {
25 | return err
26 | }
27 |
28 | group, err := ec2.NewSecurityGroup(ctx, "web-secgrp", &ec2.SecurityGroupArgs{
29 | Ingress: ec2.SecurityGroupIngressArray{
30 | ec2.SecurityGroupIngressArgs{
31 | Protocol: pulumi.String("tcp"),
32 | FromPort: pulumi.Int(80),
33 | ToPort: pulumi.Int(80),
34 | CidrBlocks: pulumi.StringArray{pulumi.String("0.0.0.0/0")},
35 | },
36 | ec2.SecurityGroupIngressArgs{
37 | Protocol: pulumi.String("icmp"),
38 | FromPort: pulumi.Int(8),
39 | ToPort: pulumi.Int(80),
40 | CidrBlocks: pulumi.StringArray{pulumi.String("0.0.0.0/0")},
41 | },
42 | },
43 | })
44 | if err != nil {
45 | return err
46 | }
47 |
48 | azs, err := aws.GetAvailabilityZones(ctx, nil)
49 | if err != nil {
50 | return err
51 | }
52 |
53 | var ips pulumi.StringArray
54 | var hostnames pulumi.StringArray
55 | for _, az := range azs.Names {
56 | srv, err := ec2.NewInstance(ctx, fmt.Sprintf("web-server-%s", az), &ec2.InstanceArgs{
57 | Tags: pulumi.Map{"Name": pulumi.String("web-server-www")},
58 | InstanceType: pulumi.String("t2.micro"), // t2.micro is available in the AWS free tier.
59 | VpcSecurityGroupIds: pulumi.StringArray{group.ID()},
60 | Ami: pulumi.String(ami.Id),
61 | AvailabilityZone: pulumi.String(az),
62 | UserData: pulumi.String(fmt.Sprintf(`#!/bin/bash
63 | echo "Hello, World -- from %s!" > index.html
64 | nohup python -m SimpleHTTPServer 80 &`, az)),
65 | })
66 | if err != nil {
67 | return err
68 | }
69 |
70 | ips = append(ips, srv.PublicIp)
71 | hostnames = append(hostnames, srv.PublicDns)
72 | }
73 |
74 | ctx.Export("ips", ips)
75 | ctx.Export("hostnames", hostnames)
76 | return nil
77 | })
78 | }
79 |
--------------------------------------------------------------------------------
/labs/intro/python/lab-02/README.md:
--------------------------------------------------------------------------------
1 | # Lab 02 - Create & Run a Docker Container
2 |
3 | In this lab, we'll create our first Pulumi resource. We'll run a Docker container we build locally using infrastructure as code.
4 |
5 | ## Step 1 - Create your application
6 |
7 | Now, let's make a very simple HTTP application with Python. Inside your project directory, create an application directory:
8 |
9 | ```bash
10 | mkdir app
11 | ```
12 |
13 | Inside this `app` directory should be two files. We need to bootstrap a webserver application. We can use native python for this:
14 |
15 | In a file called `app/__main__.py` add the following contents:
16 |
17 | ```python
18 | import http.server
19 | import socketserver
20 | from http import HTTPStatus
21 |
22 |
23 | class Handler(http.server.SimpleHTTPRequestHandler):
24 | def do_GET(self):
25 | self.send_response(HTTPStatus.OK)
26 | self.end_headers()
27 | self.wfile.write(b'Hello Lee')
28 |
29 |
30 | httpd = socketserver.TCPServer(('', 3000), Handler)
31 | httpd.serve_forever()
32 | ```
33 |
34 | Next, create a `Dockerfile` which will be built and will include this webserver
35 |
36 | ```
37 | FROM python:3.8.6-alpine
38 |
39 | WORKDIR /app
40 |
41 | COPY __main__.py /app
42 |
43 | CMD [ "python", "/app/__main__.py" ]
44 | ```
45 |
46 | ## Step 2 - Build your Docker Image with Pulumi
47 |
48 | Back inside your pulumi program, let's build your Docker image. Inside your Pulumi program's `__main__.py` add the following:
49 |
50 |
51 | ```python
52 | import pulumi
53 | from pulumi_docker import Image, DockerBuild
54 |
55 | stack = pulumi.get_stack()
56 | image_name = "my-first-app"
57 |
58 | # build our image!
59 | image = Image(image_name,
60 | build=DockerBuild(context="app"),
61 | image_name=f"{image_name}:{stack}",
62 | skip_push=True)
63 | ```
64 |
65 | Make sure you install the `pulumi_docker` provider from pip inside your virtualenv:
66 |
67 | ```
68 | source venv/bin/activate
69 | pip3 install pulumi_docker
70 | ```
71 |
72 | You should see some output showing the pip package and the provider being installed
73 |
74 | Run `pulumi up` and it should build your docker image
75 |
76 | If you run `docker images` you should see your built container.
77 |
78 | Now that we've provisioned our first piece of infrastructure, let's look at how we can use configuration in our Pulumi programs.
79 |
80 | # Next Steps
81 |
82 | * [Use configuration](../lab-03/README.md)
83 |
--------------------------------------------------------------------------------
/labs/aws/in-person/python/lab-01/01-creating-a-new-project.md:
--------------------------------------------------------------------------------
1 | # Creating a New Project
2 |
3 | Infrastructure in Pulumi is organized into projects. Each project is a single program that, when run, declares the desired infrastructure for Pulumi to manage.
4 |
5 | ## Step 1 — Create a Directory
6 |
7 | Each Pulumi project lives in its own directory. Create one now and change into it:
8 |
9 | ```bash
10 | mkdir iac-workshop
11 | cd iac-workshop
12 | ```
13 |
14 | > Pulumi will use the directory name as your project name by default. To create an independent project, simply name the directory differently.
15 |
16 | ## Step 2 — Initialize Your Project
17 |
18 | A Pulumi project is just a directory with some files in it. It's possible for you to create a new one by hand. The `pulumi new` command, however, automates the process:
19 |
20 | ```bash
21 | pulumi new python -y
22 | ```
23 |
24 | This will print output similar to the following with a bit more information and status as it goes:
25 |
26 | ```
27 | Created project 'iac-workshop'
28 | Created stack 'dev'
29 |
30 | Your new project is ready to go! ✨
31 |
32 | To perform an initial deployment, run the following commands:
33 |
34 | 1. python3 -m venv venv
35 | 2. source venv/bin/activate
36 | 3. pip3 install -r requirements.txt
37 |
38 | Then, run 'pulumi up'
39 | ```
40 |
41 | This command has created all the files we need, initialized a new stack named `dev` (an instance of our project). We now need
42 | to install our dependencies as part of our virtualenv
43 |
44 | ## Step 3 — Setup Virtual Environment
45 |
46 | We now need to create our virtual environment as suggested in the output of `pulumi new` in step 2 by following the commands:
47 |
48 | ```bash
49 | $ python3 -m venv venv
50 | ```
51 |
52 | ```bash
53 | $ source venv/bin/activate
54 | ```
55 |
56 | ```bash
57 | pip3 install -r requirements.txt
58 | ```
59 |
60 | ## Step 4 — Inspect Your New Project
61 |
62 | Our project is comprised of multiple files:
63 |
64 | * **`__main__.py`**: your program's main entrypoint file
65 | * **`requirements.txt`**: your project's pip dependency information
66 | * **`Pulumi.yaml`**: your project's metadata, containing its name and language
67 |
68 | Run `cat __main__.py` to see the contents of your project's empty program:
69 |
70 | ```python
71 | import pulumi
72 | ```
73 |
74 | Feel free to explore the other files, although we won't be editing any of them by hand.
75 |
76 | # Next Steps
77 |
78 | * [Configuring AWS](./02-configuring-aws.md)
79 |
--------------------------------------------------------------------------------
/labs/azure/csharp/03-aci/code/step4.cs:
--------------------------------------------------------------------------------
1 | using Pulumi;
2 | using Pulumi.Serialization;
3 |
4 | using Azure = Pulumi.Azure;
5 | using Pulumi.Azure.ContainerService;
6 | using Pulumi.Azure.ContainerService.Inputs;
7 |
8 | class MyStack : Stack
9 | {
10 | public MyStack()
11 | {
12 | var resourceGroup = new Azure.Core.ResourceGroup("my-group");
13 |
14 | var registry = new Registry("registry", new RegistryArgs
15 | {
16 | ResourceGroupName = resourceGroup.Name,
17 | AdminEnabled = true,
18 | Sku = "Standard"
19 | });
20 |
21 | var dockerImage = new Pulumi.Docker.Image("node-app", new Pulumi.Docker.ImageArgs
22 | {
23 | ImageName = Output.Format($"{registry.LoginServer}/myapp"),
24 | Build = "./app",
25 | Registry = new Pulumi.Docker.ImageRegistry
26 | {
27 | Server = registry.LoginServer,
28 | Username = registry.AdminUsername,
29 | Password = registry.AdminPassword
30 | }
31 | });
32 |
33 | var group = new Group("aci", new GroupArgs
34 | {
35 | ResourceGroupName = resourceGroup.Name,
36 | OsType = "Linux",
37 | Containers =
38 | {
39 | new GroupContainersArgs
40 | {
41 | Cpu = 0.5,
42 | Image = dockerImage.ImageName,
43 | Memory = 1.5,
44 | Name = "hello-world",
45 | Ports =
46 | {
47 | new GroupContainersPortsArgs
48 | {
49 | Port = 80,
50 | Protocol = "TCP"
51 | }
52 | }
53 | }
54 | },
55 | ImageRegistryCredentials =
56 | {
57 | new GroupImageRegistryCredentialsArgs
58 | {
59 | Server = registry.LoginServer,
60 | Username = registry.AdminUsername,
61 | Password = registry.AdminPassword
62 | }
63 | },
64 | IpAddressType = "public",
65 | DnsNameLabel = "my-unique-name"
66 | }, new CustomResourceOptions { DeleteBeforeReplace = true });
67 |
68 | this.Endpoint = Output.Format($"http://{group.Fqdn}");
69 | }
70 |
71 | [Output]
72 | public Output Endpoint { get; set; }
73 | }
74 |
--------------------------------------------------------------------------------
/labs/azure/python/01-iac/05-making-your-stack-configurable.md:
--------------------------------------------------------------------------------
1 | # Making Your Stack Configurable
2 |
3 | Right now, the container's name is hard-coded. Next, you'll make the name configurable.
4 |
5 | ## Step 1 — Adding a Config Variable
6 |
7 | Instead of hard-coding the `"files"` container, we will use configuration to make it easy to change the name without editing the program.
8 |
9 | Add this line to `__main__.py` right after your import statements:
10 |
11 | ```python
12 | config = pulumi.Config()
13 | ```
14 |
15 | ## Step 2 — Populating the Container Based on Config
16 |
17 | Replace the hard-coded `"Name"` property value with the one from configuration:
18 |
19 | ```python
20 | container = storage.Container('mycontainer',
21 | name = config.require('container'),
22 | storage_account_name = account.name)
23 | ```
24 |
25 | > :white_check_mark: After these changes, your `__main__.py` should [look like this](./code/05-making-your-stack-configurable/step2.py).
26 |
27 | ## Step 3 — Deploying the Changes
28 |
29 | Now, deploy your changes. To do so, first configure your stack. If you don't, you'll get an error:
30 |
31 | ```bash
32 | pulumi up
33 | ```
34 |
35 | This results in an error like the following:
36 |
37 | ```
38 | ...
39 | ConfigMissingException: Missing Required configuration variable 'iac-workshop:container'
40 | please set a value using the command `pulumi config set iac-workshop:container `
41 | ...
42 | ```
43 |
44 | Configure the `iac-workshop:container` variable very much like the `azure:location` variable:
45 |
46 | ```bash
47 | pulumi config set iac-workshop:container html
48 | ```
49 |
50 | To make things interesting, I set the name to `html` which is different from the previously hard-coded value `files`.
51 |
52 | Run `pulumi up` again. This detects that the container has changed and will perform a simple update:
53 |
54 | ```
55 | Updating (dev):
56 |
57 | Type Name Status Info
58 | pulumi:pulumi:Stack iac-workshop-dev
59 | +- └─ azure:storage:Container mycontainer replaced [diff: ~name]
60 |
61 | Outputs:
62 | AccountName: "mystorage872202e1"
63 |
64 | Resources:
65 | +-1 replaced
66 | 3 unchanged
67 |
68 | Duration: 10s
69 |
70 | Permalink: https://app.pulumi.com/myuser/iac-workshop/dev/updates/5
71 | ```
72 |
73 | And you will see the contents added above.
74 |
75 | ## Next Steps
76 |
77 | * [Creating a Second Stack](./06-creating-a-second-stack.md)
78 |
--------------------------------------------------------------------------------
/labs/azure/csharp/05-kubernetes/code/step7.cs:
--------------------------------------------------------------------------------
1 | using Pulumi;
2 | using Pulumi.Serialization;
3 |
4 | using K8s = Pulumi.Kubernetes;
5 |
6 | class MyStack : Stack
7 | {
8 | public MyStack()
9 | {
10 | var ns = new K8s.Core.V1.Namespace("app-ns", new K8s.Types.Inputs.Core.V1.NamespaceArgs
11 | {
12 | Metadata = new K8s.Types.Inputs.Meta.V1.ObjectMetaArgs { Name = "my-name" }
13 | });
14 |
15 | var appLabels = new InputMap { { "app", "iac-workshop" } };
16 | var deployment = new K8s.Apps.V1.Deployment("app-dep", new K8s.Types.Inputs.Apps.V1.DeploymentArgs
17 | {
18 | Metadata = new K8s.Types.Inputs.Meta.V1.ObjectMetaArgs { Namespace = ns.Metadata.Apply(m => m.Name) },
19 | Spec = new K8s.Types.Inputs.Apps.V1.DeploymentSpecArgs
20 | {
21 | Selector = new K8s.Types.Inputs.Meta.V1.LabelSelectorArgs { MatchLabels = appLabels },
22 | Replicas = 3,
23 | Template = new K8s.Types.Inputs.Core.V1.PodTemplateSpecArgs
24 | {
25 | Metadata = new K8s.Types.Inputs.Meta.V1.ObjectMetaArgs { Labels = appLabels },
26 | Spec = new K8s.Types.Inputs.Core.V1.PodSpecArgs
27 | {
28 | Containers =
29 | {
30 | new K8s.Types.Inputs.Core.V1.ContainerArgs
31 | {
32 | Name = "iac-workshop",
33 | Image = "jocatalin/kubernetes-bootcamp:v2"
34 | }
35 | }
36 | }
37 | }
38 | }
39 | });
40 |
41 | var service = new K8s.Core.V1.Service("app-svc", new K8s.Types.Inputs.Core.V1.ServiceArgs
42 | {
43 | Metadata = new K8s.Types.Inputs.Meta.V1.ObjectMetaArgs { Namespace = ns.Metadata.Apply(m => m.Name) },
44 | Spec = new K8s.Types.Inputs.Core.V1.ServiceSpecArgs
45 | {
46 | Selector = appLabels,
47 | Ports = { new K8s.Types.Inputs.Core.V1.ServicePortArgs { Port = 80, TargetPort = 8080 }},
48 | Type = "LoadBalancer"
49 | }
50 | });
51 |
52 | var address = service.Status
53 | .Apply(s => s.LoadBalancer)
54 | .Apply(lb => lb.Ingress)
55 | .GetAt(0)
56 | .Apply(i => i.Ip);
57 |
58 | this.Url = Output.Format($"http://{address}");
59 | }
60 |
61 | [Output]
62 | public Output Url { get; set; }
63 | }
64 |
--------------------------------------------------------------------------------
/labs/aws/in-person/csharp/lab-03/code/step2.cs:
--------------------------------------------------------------------------------
1 | using Pulumi;
2 |
3 | class MyStack : Stack
4 | {
5 | public MyStack()
6 | {
7 | var cluster = new Pulumi.Aws.Ecs.Cluster("app-cluster");
8 |
9 | // Read back the default VPC and public subnets, which we will use.
10 | var vpc = Output.Create(Pulumi.Aws.Ec2.GetVpc.InvokeAsync(new Pulumi.Aws.Ec2.GetVpcArgs { Default = true }));
11 | var vpcId = vpc.Apply(vpc => vpc.Id);
12 | var subnet = vpcId.Apply(id => Pulumi.Aws.Ec2.GetSubnetIds.InvokeAsync(new Pulumi.Aws.Ec2.GetSubnetIdsArgs { VpcId = id }));
13 | var subnetIds = subnet.Apply(s => s.Ids);
14 |
15 | // Create a SecurityGroup that permits HTTP ingress and unrestricted egress.
16 | var webSg = new Pulumi.Aws.Ec2.SecurityGroup("web-sg", new Pulumi.Aws.Ec2.SecurityGroupArgs
17 | {
18 | VpcId = vpcId,
19 | Egress =
20 | {
21 | new Pulumi.Aws.Ec2.Inputs.SecurityGroupEgressArgs
22 | {
23 | Protocol = "-1",
24 | FromPort = 0,
25 | ToPort = 0,
26 | CidrBlocks = {"0.0.0.0/0"}
27 | }
28 | },
29 | Ingress =
30 | {
31 | new Pulumi.Aws.Ec2.Inputs.SecurityGroupIngressArgs
32 | {
33 | Protocol = "tcp",
34 | FromPort = 80,
35 | ToPort = 80,
36 | CidrBlocks = {"0.0.0.0/0"}
37 | }
38 | }
39 | });
40 |
41 | // Create a load balancer to listen for HTTP traffic on port 80.
42 | var webLb = new Pulumi.Aws.LB.LoadBalancer("web-lb", new Pulumi.Aws.LB.LoadBalancerArgs
43 | {
44 | Subnets = subnetIds,
45 | SecurityGroups = { webSg.Id }
46 | });
47 | var webTg = new Pulumi.Aws.LB.TargetGroup("web-tg", new Pulumi.Aws.LB.TargetGroupArgs
48 | {
49 | Port = 80,
50 | Protocol = "HTTP",
51 | TargetType = "ip",
52 | VpcId = vpcId
53 | });
54 | var webListener = new Pulumi.Aws.LB.Listener("web-listener", new Pulumi.Aws.LB.ListenerArgs
55 | {
56 | LoadBalancerArn = webLb.Arn,
57 | Port = 80,
58 | DefaultActions =
59 | {
60 | new Pulumi.Aws.LB.Inputs.ListenerDefaultActionArgs
61 | {
62 | Type = "forward",
63 | TargetGroupArn = webTg.Arn,
64 | }
65 | }
66 | });
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/labs/azure/csharp/05-kubernetes/code/step5.cs:
--------------------------------------------------------------------------------
1 | using Pulumi;
2 | using Pulumi.Serialization;
3 |
4 | using K8s = Pulumi.Kubernetes;
5 |
6 | class MyStack : Stack
7 | {
8 | public MyStack()
9 | {
10 | var ns = new K8s.Core.V1.Namespace("app-ns", new K8s.Types.Inputs.Core.V1.NamespaceArgs
11 | {
12 | Metadata = new K8s.Types.Inputs.Meta.V1.ObjectMetaArgs { Name = "my-name" }
13 | });
14 |
15 | var appLabels = new InputMap { { "app", "iac-workshop" } };
16 | var deployment = new K8s.Apps.V1.Deployment("app-dep", new K8s.Types.Inputs.Apps.V1.DeploymentArgs
17 | {
18 | Metadata = new K8s.Types.Inputs.Meta.V1.ObjectMetaArgs { Namespace = ns.Metadata.Apply(m => m.Name) },
19 | Spec = new K8s.Types.Inputs.Apps.V1.DeploymentSpecArgs
20 | {
21 | Selector = new K8s.Types.Inputs.Meta.V1.LabelSelectorArgs { MatchLabels = appLabels },
22 | Replicas = 1,
23 | Template = new K8s.Types.Inputs.Core.V1.PodTemplateSpecArgs
24 | {
25 | Metadata = new K8s.Types.Inputs.Meta.V1.ObjectMetaArgs { Labels = appLabels },
26 | Spec = new K8s.Types.Inputs.Core.V1.PodSpecArgs
27 | {
28 | Containers =
29 | {
30 | new K8s.Types.Inputs.Core.V1.ContainerArgs
31 | {
32 | Name = "iac-workshop",
33 | Image = "gcr.io/google-samples/kubernetes-bootcamp:v1"
34 | }
35 | }
36 | }
37 | }
38 | }
39 | });
40 |
41 | var service = new K8s.Core.V1.Service("app-svc", new K8s.Types.Inputs.Core.V1.ServiceArgs
42 | {
43 | Metadata = new K8s.Types.Inputs.Meta.V1.ObjectMetaArgs { Namespace = ns.Metadata.Apply(m => m.Name) },
44 | Spec = new K8s.Types.Inputs.Core.V1.ServiceSpecArgs
45 | {
46 | Selector = appLabels,
47 | Ports = { new K8s.Types.Inputs.Core.V1.ServicePortArgs { Port = 80, TargetPort = 8080 }},
48 | Type = "LoadBalancer"
49 | }
50 | });
51 |
52 | var address = service.Status
53 | .Apply(s => s.LoadBalancer)
54 | .Apply(lb => lb.Ingress)
55 | .GetAt(0)
56 | .Apply(i => i.Ip);
57 |
58 | this.Url = Output.Format($"http://{address}");
59 | }
60 |
61 | [Output]
62 | public Output Url { get; set; }
63 | }
64 |
--------------------------------------------------------------------------------
/labs/aws/in-person/typescript/lab-02/code/step3.ts:
--------------------------------------------------------------------------------
1 | import * as awsx from "@pulumi/awsx";
2 | import * as aws from "@pulumi/aws";
3 |
4 | // Variable we will use for naming purpose
5 | const name = "demo";
6 |
7 | // Creating a VPC with a Single Nat Gateway Strategy (To save cost)
8 | const myvpc = new awsx.ec2.Vpc(`${name}-vpc`, {
9 | cidrBlock: "10.0.0.0/24",
10 | numberOfAvailabilityZones: 3,
11 | enableDnsHostnames: true,
12 | natGateways: {
13 | strategy: "Single", // This is mainly to save cost. You do this only in dev
14 | },
15 | });
16 |
17 | // VPC Outputs
18 | export const vpc_id = myvpc.vpcId;
19 | export const vpc_natgateways = myvpc.natGateways[0].id;
20 | export const vpc_public_subnetids = myvpc.publicSubnetIds;
21 | export const vpc_private_subnetids = myvpc.privateSubnetIds;
22 |
23 | // Creating Security Group within VPC
24 | const mysecuritygroup = new aws.ec2.SecurityGroup(`${name}-securitygroup`, {
25 | vpcId:myvpc.vpcId,
26 | ingress: [
27 | { protocol: "tcp",
28 | fromPort: 443,
29 | toPort: 443,
30 | cidrBlocks: ["0.0.0.0/0"],
31 | description: "Allow inbound access via https",
32 | self: true, // Add the securitygroup itself as a source
33 | },
34 | {
35 | protocol: "tcp",
36 | fromPort: 80,
37 | toPort: 80,
38 | cidrBlocks: ["0.0.0.0/0"],
39 | description: "Allow inbound access via http",
40 | self: true, // Add the securitygroup itself as a source
41 | },
42 | ],
43 | egress: [
44 | { protocol: "tcp",
45 | fromPort: 443,
46 | toPort: 443,
47 | cidrBlocks: ["0.0.0.0/0"],
48 | description: "Allow outbound access via https"
49 | },
50 | {
51 | protocol: "tcp",
52 | fromPort: 80,
53 | toPort: 80,
54 | cidrBlocks: ["0.0.0.0/0"],
55 | description: "Allow outbound access via http"
56 | },
57 | ],
58 | tags: {"Name": `${name}-securitygroup`},
59 | }, { parent: myvpc, dependsOn: myvpc });
60 |
61 | // Exporting security group outputs
62 | export const security_group_name = mysecuritygroup.id;
63 | export const security_group_vpc = mysecuritygroup.vpcId;
64 | export const security_group_egress = mysecuritygroup.egress;
65 | export const security_group_ingress = mysecuritygroup.ingress;
66 |
67 | // get Function for AMI
68 | const myami = aws.ec2.getAmi({
69 | filters: [{ name: "name", values: ["amzn2-ami-k*-hvm-*-x86_64-gp2"] }],
70 | owners: [ "amazon" ],
71 | mostRecent: true,
72 | });
73 |
74 | // Exporting AMI_ID First Time
75 | //export const ami_id = myami;
76 |
77 | // Exporting AMI_ID with what we want.
78 | export const ami_id = myami.then(ami=>ami.id);
--------------------------------------------------------------------------------
/labs/aws/in-person/csharp/lab-02/code/step3.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.Immutable;
4 | using System.Linq;
5 | using Pulumi;
6 |
7 | class MyStack : Stack
8 | {
9 | public MyStack()
10 | {
11 | var ami = Output.Create(Pulumi.Aws.GetAmi.InvokeAsync(new Pulumi.Aws.GetAmiArgs
12 | {
13 | MostRecent = true,
14 | Owners = {"amazon"},
15 | Filters = {new Pulumi.Aws.Inputs.GetAmiFiltersArgs
16 | {
17 | Name = "name", Values = {"amzn2-ami-k*-hvm-*-x86_64-gp2"}
18 | }}
19 | }));
20 |
21 | var group = new Pulumi.Aws.Ec2.SecurityGroup("web-secgrp", new Pulumi.Aws.Ec2.SecurityGroupArgs
22 | {
23 | Description = "Enable HTTP access",
24 | Ingress =
25 | {
26 | new Pulumi.Aws.Ec2.Inputs.SecurityGroupIngressArgs
27 | {
28 | Protocol = "tcp",
29 | FromPort = 80,
30 | ToPort = 80,
31 | CidrBlocks = {"0.0.0.0/0"}
32 | },
33 | new Pulumi.Aws.Ec2.Inputs.SecurityGroupIngressArgs
34 | {
35 | Protocol = "icmp",
36 | FromPort = 8,
37 | ToPort = 80,
38 | CidrBlocks = {"0.0.0.0/0"}
39 | }
40 | }
41 | });
42 |
43 | var userData = @"
44 | #!/bin/bash
45 | echo ""Hello, World!"" > index.html
46 | nohup python -m SimpleHTTPServer 80 &
47 | ";
48 |
49 | var azs = Pulumi.Aws.GetAvailabilityZones.InvokeAsync(new Pulumi.Aws.GetAvailabilityZonesArgs()).Result;
50 | var hostnames = new List>();
51 | var ips = new List>();
52 | foreach (var az in azs.Names)
53 | {
54 | var server = new Pulumi.Aws.Ec2.Instance($"web-server-{az}", new Pulumi.Aws.Ec2.InstanceArgs
55 | {
56 | InstanceType = "t2.micro",
57 | VpcSecurityGroupIds = {group.Id},
58 | UserData = userData,
59 | Ami = ami.Apply(a => a.Id),
60 | AvailabilityZone = az,
61 | });
62 |
63 | hostnames.Add(server.PublicDns);
64 | ips.Add(server.PublicIp);
65 | }
66 |
67 | this.PublicIps = Output.All(ips.ToImmutableArray());
68 | this.PublicDns = Output.All(hostnames.ToImmutableArray());
69 | }
70 |
71 | [Output] public Output> PublicIps { get; set; }
72 | [Output] public Output> PublicDns { get; set; }
73 | }
74 |
--------------------------------------------------------------------------------
/labs/azure/csharp/01-iac/05-making-your-stack-configurable.md:
--------------------------------------------------------------------------------
1 | # Making Your Stack Configurable
2 |
3 | Right now, the container's name is hard-coded. Next, you'll make the name configurable.
4 |
5 | ## Step 1 — Adding a Config Variable
6 |
7 | Instead of hard-coding the `"files"` container, we will use configuration to make it easy to change the name without editing the program.
8 |
9 | Create a file `Config.cs` and add this to it:
10 |
11 | ```csharp
12 | using Pulumi;
13 |
14 | static class Settings
15 | {
16 | static Settings()
17 | {
18 | var config = new Config();
19 | ContainerName = config.Require("container");
20 | }
21 |
22 | public static string ContainerName { get; }
23 | }
24 | ```
25 |
26 | ## Step 2 — Populating the Container Based on Config
27 |
28 | Replace the hard-coded `"Name"` property value with the one from configuration:
29 |
30 | ```csharp
31 | var container = new Azure.Storage.Container("mycontainer", new Azure.Storage.ContainerArgs
32 | {
33 | Name = Settings.ContainerName,
34 | StorageAccountName = storageAccount.Name
35 | });
36 | ```
37 |
38 | > :white_check_mark: After these changes, your `MyStack.cs` should [look like this](./code/05-making-your-stack-configurable/step2.cs).
39 |
40 | ## Step 3 — Deploying the Changes
41 |
42 | Now, deploy your changes. To do so, first configure your stack. If you don't, you'll get an error:
43 |
44 | ```bash
45 | pulumi up
46 | ```
47 |
48 | This results in an error like the following:
49 |
50 | ```
51 | ...
52 | ConfigMissingException: Missing Required configuration variable 'iac-workshop:container'
53 | please set a value using the command `pulumi config set iac-workshop:container `
54 | ...
55 | ```
56 |
57 | Configure the `iac-workshop:container` variable very much like the `azure:location` variable:
58 |
59 | ```bash
60 | pulumi config set iac-workshop:container html
61 | ```
62 |
63 | To make things interesting, I set the name to `html` which is different from the previously hard-coded value `files`.
64 |
65 | Run `pulumi up` again. This detects that the container has changed and will perform a simple update:
66 |
67 | ```
68 | Updating (dev):
69 |
70 | Type Name Status Info
71 | pulumi:pulumi:Stack iac-workshop-dev
72 | +- └─ azure:storage:Container mycontainer replaced [diff: ~name]
73 |
74 | Outputs:
75 | AccountName: "mystorage872202e1"
76 |
77 | Resources:
78 | +-1 replaced
79 | 3 unchanged
80 |
81 | Duration: 10s
82 |
83 | Permalink: https://app.pulumi.com/myuser/iac-workshop/dev/updates/5
84 | ```
85 |
86 | And you will see the contents added above.
87 |
88 | ## Next Steps
89 |
90 | * [Creating a Second Stack](./06-creating-a-second-stack.md)
91 |
--------------------------------------------------------------------------------
/labs/azure/python/01-iac/01-creating-a-new-project.md:
--------------------------------------------------------------------------------
1 | # Creating a New Project
2 |
3 | Infrastructure in Pulumi is organized into projects. Each project is a single program that, when run, declares the desired infrastructure for Pulumi to manage.
4 |
5 | ## Step 1 — Create a Directory
6 |
7 | Each Pulumi project lives in its own directory. Create one now and change into it:
8 |
9 | ```bash
10 | mkdir iac-workshop
11 | cd iac-workshop
12 | ```
13 |
14 | > Pulumi will use the directory name as your project name by default. To create an independent project, simply name the directory differently.
15 |
16 | ## Step 2 — Initialize Your Project
17 |
18 | A Pulumi project is just a directory with some files in it. It's possible for you to create a new one by hand. The `pulumi new` command, however, automates the process:
19 |
20 | ```bash
21 | pulumi new azure-python -y
22 | ```
23 |
24 | This will print output similar to the following with a bit more information and status as it goes:
25 |
26 | ```
27 | Created project 'iac-workshop'
28 |
29 | Please enter your desired stack name.
30 | Created stack 'dev'
31 |
32 | Saved config
33 |
34 | Your new project is ready to go! ✨
35 | ```
36 |
37 | This command has created all the files we need, initialized a new stack named `dev` (an instance of our project), and written a requirements.txt file with the relevant python dependencies.
38 |
39 | ## Step 3 — Inspect Your New Project
40 |
41 | Our project is comprised of multiple files:
42 |
43 | * **`__main__.py`**: your Pulimi program and stack definition file
44 | * **`Pulumi.yaml`**: your project's metadata, containing its name and language
45 | * **`Pulumi.dev.yaml`**: the Azure configuration for the Pulumi dev stack
46 | * **`requirements.txt`**: the python dependencies required from PyPy
47 |
48 | Open `__main__.py` to see the contents of the template program of your infrastructure stack:
49 |
50 | ```python
51 | import pulumi
52 | from pulumi_azure import core, storage
53 |
54 | # Create an Azure Resource Group
55 | resource_group = core.ResourceGroup('resource_group')
56 |
57 | # Create an Azure resource (Storage Account)
58 | account = storage.Account('storage',
59 | # The location for the storage account will be derived automatically from the resource group.
60 | resource_group_name=resource_group.name,
61 | account_tier='Standard',
62 | account_replication_type='LRS')
63 |
64 | # Export the connection string for the storage account
65 | pulumi.export('connection_string', account.primary_connection_string)
66 |
67 | ```
68 |
69 | Feel free to explore the other files, although we won't be editing any of them by hand.
70 |
71 | # Next Steps
72 |
73 | * [Configuring Azure](./02-configuring-azure.md)
74 |
--------------------------------------------------------------------------------
/labs/azure/python/01-iac/02-configuring-azure.md:
--------------------------------------------------------------------------------
1 | # Configuring Azure
2 |
3 | Now that you have a basic project, let's set up your environemnt, and configure Azure support for it.
4 |
5 | ## Step 1 — Create a virtual environment and install python dependencies
6 | Creation of a virtual environment can vary between operating systems - see the [Azure Quickstart](https://www.pulumi.com/docs/get-started/azure/review-project/) for more information.
7 |
8 | ### Windows
9 | Run the following command to create a virtual environment
10 | ```bash
11 | python -m venv venv
12 | ```
13 |
14 | Activate the environment:
15 | ```bash
16 | venv\Scripts\activate
17 | ```
18 |
19 | Install dependencies:
20 | ```bash
21 | pip3 install -r requirements.txt
22 | ```
23 | ### Mac and Linux
24 | Run the following command to create a virtual environment
25 | ```bash
26 | python3 -m venv venv
27 | ```
28 |
29 | Activate the environment:
30 | ```bash
31 | source venv/bin/activate
32 | ```
33 |
34 | Install dependencies:
35 | ```bash
36 | pip3 install -r requirements.txt
37 | ```
38 |
39 | At this point, dependencies will be installed into your virtual environment. **If you close your terminal at any time**, you may need to re-activate the environment:
40 | ```bash
41 | source venv/bin/activate
42 | ```
43 |
44 | ### Point to note
45 | Going forward, instructions will refer to `python` for consistency, but if you are on mac or linux, use the appropriate `python3` command.
46 |
47 | ## Step 2 — Configure an Azure Region
48 |
49 | The Azure region to deploy to is pre-set to WestUS - but you can modify the region you would like to deploy to:
50 |
51 | ```bash
52 | pulumi config set azure:location westus2
53 | ```
54 |
55 | Feel free to choose any Azure region that supports the services used in these labs ([see this infographic](https://azure.microsoft.com/en-us/global-infrastructure/regions/) for a list of available regions).
56 |
57 | The command updates and persists the value to the local `Pulumi.dev.yaml` file. You can view or edit this file at any time to effect the configuration of the current stack.
58 |
59 | ## Step 3 — Login to Azure
60 |
61 | Simply login to the Azure CLI and Pulumi will automatically use your credentials:
62 |
63 | ```
64 | az login
65 | ...
66 | You have logged in. Now let us find all the subscriptions to which you have access...
67 | ...
68 | ```
69 |
70 | The Azure CLI, and thus Pulumi, will use the Default Subscription by default, however it is possible to override the subscription, by simply setting your subscription ID to the id output from `az account list`’s output:
71 |
72 | ```
73 | $ az account list
74 | ```
75 |
76 | Pick out the `` from the list and run:
77 |
78 | ```
79 | $ az account set --subscription=
80 | ```
81 |
82 | ## Next Steps
83 |
84 | * [Provisioning a Resource Group](./03-provisioning-infrastructure.md)
85 |
--------------------------------------------------------------------------------
/labs/aws/in-person/python/lab-04/code/step3.py:
--------------------------------------------------------------------------------
1 | from pulumi import export, Output
2 | import pulumi_aws as aws
3 | import json, hashlib
4 |
5 | h = hashlib.new('sha1')
6 |
7 | # Create the EKS Service Role and the correct role attachments
8 | service_role = aws.iam.Role("eks-service-role",
9 | assume_role_policy=json.dumps({
10 | "Version": "2012-10-17",
11 | "Statement": [{
12 | "Sid": "",
13 | "Effect": "Allow",
14 | "Principal": {
15 | "Service": "eks.amazonaws.com"
16 | },
17 | "Action": "sts:AssumeRole"
18 | }]
19 | })
20 | )
21 |
22 | service_role_managed_policy_arns = [
23 | "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy",
24 | "arn:aws:iam::aws:policy/AmazonEKSServicePolicy"
25 | ]
26 |
27 | for policy in service_role_managed_policy_arns:
28 | h.update(policy.encode('utf-8'))
29 | role_policy_attachment = aws.iam.RolePolicyAttachment(f"eks-service-role-{h.hexdigest()[0:8]}",
30 | policy_arn=policy,
31 | role=service_role.name
32 | )
33 |
34 | # Create the EKS NodeGroup Role and the correct role attachments
35 | node_group_role = aws.iam.Role("eks-nodegroup-role",
36 | assume_role_policy=json.dumps({
37 | "Version": "2012-10-17",
38 | "Statement": [{
39 | "Sid": "",
40 | "Effect": "Allow",
41 | "Principal": {
42 | "Service": "ec2.amazonaws.com"
43 | },
44 | "Action": "sts:AssumeRole"
45 | }]
46 | })
47 | )
48 |
49 | nodegroup_role_managed_policy_arns = [
50 | "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy",
51 | "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy",
52 | "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
53 | ]
54 |
55 | for policy in nodegroup_role_managed_policy_arns:
56 | h.update(policy.encode('utf-8'))
57 | role_policy_attachment = aws.iam.RolePolicyAttachment(f"eks-nodegroup-role-{h.hexdigest()[0:8]}",
58 | policy_arn=policy,
59 | role=node_group_role.name
60 | )
61 |
62 | # Get the VPC and subnets to launch the EKS cluster into
63 | default_vpc = aws.ec2.get_vpc(default="true")
64 | default_vpc_subnets = aws.ec2.get_subnet_ids(vpc_id=default_vpc.id)
65 |
66 | # Create the Security Group that allows access to the cluster pods
67 | sg = aws.ec2.SecurityGroup("eks-cluster-security-group",
68 | vpc_id=default_vpc.id,
69 | revoke_rules_on_delete="true",
70 | ingress=[{
71 | 'cidr_blocks' : ["0.0.0.0/0"],
72 | 'from_port' : '80',
73 | 'to_port' : '80',
74 | 'protocol' : 'tcp',
75 | }]
76 | )
77 |
78 | sg_rule = aws.ec2.SecurityGroupRule("eks-cluster-security-group-egress-rule",
79 | type="egress",
80 | from_port=0,
81 | to_port=0,
82 | protocol="-1",
83 | cidr_blocks=["0.0.0.0/0"],
84 | security_group_id=sg.id
85 | )
86 |
--------------------------------------------------------------------------------
/labs/aws/pulumi-in-practice/python/lab-04/code/step3.py:
--------------------------------------------------------------------------------
1 | from pulumi import export, ResourceOptions
2 | import pulumi_aws as aws
3 | import json
4 |
5 | cluster = aws.ecs.Cluster("cluster")
6 |
7 | default_vpc = aws.ec2.get_vpc(default="true")
8 | default_vpc_subnets = aws.ec2.get_subnet_ids(vpc_id=default_vpc.id)
9 |
10 | group = aws.ec2.SecurityGroup(
11 | "web-secgrp",
12 | vpc_id=default_vpc.id,
13 | description='Enable HTTP access',
14 | ingress=[
15 | { 'protocol': 'tcp', 'from_port': 80, 'to_port': 80, 'cidr_blocks': ['0.0.0.0/0'] }
16 | ],
17 | egress=[
18 | { 'protocol': "-1", 'from_port': 0, 'to_port': 0, 'cidr_blocks': ['0.0.0.0/0'] }
19 | ])
20 |
21 | alb = aws.lb.LoadBalancer("app-lb",
22 | security_groups=[group.id],
23 | subnets=default_vpc_subnets.ids,
24 | )
25 |
26 | atg = aws.lb.TargetGroup("app-tg",
27 | port=80,
28 | protocol="HTTP",
29 | target_type="ip",
30 | vpc_id=default_vpc.id
31 | )
32 |
33 | wl = aws.lb.Listener("web",
34 | load_balancer_arn=alb.arn,
35 | port=80,
36 | default_actions=[{
37 | "type": "forward",
38 | "target_group_arn": atg.arn
39 | }]
40 | )
41 |
42 | role = aws.iam.Role("task-exec-role",
43 | assume_role_policy=json.dumps({
44 | "Version": "2008-10-17",
45 | "Statement": [{
46 | "Sid": "",
47 | "Effect": "Allow",
48 | "Principal": {
49 | "Service": "ecs-tasks.amazonaws.com"
50 | },
51 | "Action": "sts:AssumeRole"
52 | }]
53 | })
54 | )
55 |
56 | rpa = aws.iam.RolePolicyAttachment("task-exec-policy",
57 | role=role.name,
58 | policy_arn="arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
59 | )
60 |
61 | task_definition = aws.ecs.TaskDefinition("app-task",
62 | family="fargate-task-definition",
63 | cpu="256",
64 | memory="512",
65 | network_mode="awsvpc",
66 | requires_compatibilities=["FARGATE"],
67 | execution_role_arn=role.arn,
68 | container_definitions=json.dumps([{
69 | "name": "my-app",
70 | "image": "nginx",
71 | "portMappings": [{
72 | "containerPort": 80,
73 | "hostPort": 80,
74 | "protocol": "tcp"
75 | }]
76 | }])
77 | )
78 |
79 | service = aws.ecs.Service("app-svc",
80 | cluster=cluster.arn,
81 | desired_count=1,
82 | launch_type="FARGATE",
83 | task_definition=task_definition.arn,
84 | network_configuration={
85 | "assign_public_ip": "true",
86 | "subnets": default_vpc_subnets.ids,
87 | "security_groups": [group.id]
88 | },
89 | load_balancers=[{
90 | "target_group_arn": atg.arn,
91 | "container_name": "my-app",
92 | "container_port": 80
93 | }],
94 | opts=ResourceOptions(depends_on=[wl])
95 | )
96 |
97 | export("url", alb.dns_name)
98 |
--------------------------------------------------------------------------------
/labs/aws/pulumi-in-practice/python/lab-04/code/step5.py:
--------------------------------------------------------------------------------
1 | from pulumi import export, ResourceOptions
2 | import pulumi_aws as aws
3 | import json
4 |
5 | cluster = aws.ecs.Cluster("cluster")
6 |
7 | default_vpc = aws.ec2.get_vpc(default="true")
8 | default_vpc_subnets = aws.ec2.get_subnet_ids(vpc_id=default_vpc.id)
9 |
10 | group = aws.ec2.SecurityGroup(
11 | "web-secgrp",
12 | vpc_id=default_vpc.id,
13 | description='Enable HTTP access',
14 | ingress=[
15 | { 'protocol': 'tcp', 'from_port': 80, 'to_port': 80, 'cidr_blocks': ['0.0.0.0/0'] }
16 | ],
17 | egress=[
18 | { 'protocol': "-1", 'from_port': 0, 'to_port': 0, 'cidr_blocks': ['0.0.0.0/0'] }
19 | ])
20 |
21 | alb = aws.lb.LoadBalancer("app-lb",
22 | security_groups=[group.id],
23 | subnets=default_vpc_subnets.ids,
24 | )
25 |
26 | atg = aws.lb.TargetGroup("app-tg",
27 | port=80,
28 | protocol="HTTP",
29 | target_type="ip",
30 | vpc_id=default_vpc.id
31 | )
32 |
33 | wl = aws.lb.Listener("web",
34 | load_balancer_arn=alb.arn,
35 | port=80,
36 | default_actions=[{
37 | "type": "forward",
38 | "target_group_arn": atg.arn
39 | }]
40 | )
41 |
42 | role = aws.iam.Role("task-exec-role",
43 | assume_role_policy=json.dumps({
44 | "Version": "2008-10-17",
45 | "Statement": [{
46 | "Sid": "",
47 | "Effect": "Allow",
48 | "Principal": {
49 | "Service": "ecs-tasks.amazonaws.com"
50 | },
51 | "Action": "sts:AssumeRole"
52 | }]
53 | })
54 | )
55 |
56 | rpa = aws.iam.RolePolicyAttachment("task-exec-policy",
57 | role=role.name,
58 | policy_arn="arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
59 | )
60 |
61 | task_definition = aws.ecs.TaskDefinition("app-task",
62 | family="fargate-task-definition",
63 | cpu="256",
64 | memory="512",
65 | network_mode="awsvpc",
66 | requires_compatibilities=["FARGATE"],
67 | execution_role_arn=role.arn,
68 | container_definitions=json.dumps([{
69 | "name": "my-app",
70 | "image": "nginx",
71 | "portMappings": [{
72 | "containerPort": 80,
73 | "hostPort": 80,
74 | "protocol": "tcp"
75 | }]
76 | }])
77 | )
78 |
79 | service = aws.ecs.Service("app-svc",
80 | cluster=cluster.arn,
81 | desired_count=3,
82 | launch_type="FARGATE",
83 | task_definition=task_definition.arn,
84 | network_configuration={
85 | "assign_public_ip": "true",
86 | "subnets": default_vpc_subnets.ids,
87 | "security_groups": [group.id]
88 | },
89 | load_balancers=[{
90 | "target_group_arn": atg.arn,
91 | "container_name": "my-app",
92 | "container_port": 80
93 | }],
94 | opts=ResourceOptions(depends_on=[wl])
95 | )
96 |
97 | export("url", alb.dns_name)
98 |
--------------------------------------------------------------------------------
/labs/azure/csharp/00-installing-prerequisites.md:
--------------------------------------------------------------------------------
1 | # Installing Prerequisites
2 |
3 | These hands-on labs will walk you through various cloud infrastructure tasks. The prerequisites listed below are required to successfully complete them.
4 |
5 | Although Pulumi supports many clouds and many languages, you will use Microsoft Azure and C# on .NET Core for these labs. Prerequisites are all available on recent versions of Windows, macOS, and Linux.
6 |
7 | ## Pulumi
8 |
9 | You will use Pulumi to deploy infrastructure changes using code. [Install Pulumi here](https://www.pulumi.com/docs/get-started/install/). After installing the CLI, verify that it is working:
10 |
11 | ```bash
12 | $ pulumi version
13 | v1.10.1
14 | ```
15 |
16 | The Pulumi CLI will ask you to login to your Pulumi account as needed. If you prefer to signup now, [go to the signup page](http://app.pulumi.com/signup). Multiple identity provider options are available — email, GitHub, GitLab, or Atlassian — and each of them will work equally well for these labs.
17 |
18 | ## Azure Subscription
19 |
20 | You need an active Azure subscription to deploy the components of the application. You may use your developer subscription, or create a free Azure subscription [here](https://azure.microsoft.com/free/).
21 |
22 | Be sure to clean up the resources after you complete the workshop, as described at the last step of each lab.
23 |
24 | ## Azure CLI
25 |
26 | You will use the command-line interface (CLI) tool to log in to an Azure subscription. You can install the CLI tool, as described [here](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest).
27 |
28 | After you complete the installation, open a command prompt and type `az`. You should see the welcome message:
29 |
30 | ```
31 | $ az
32 | /\
33 | / \ _____ _ _ ___ _
34 | / /\ \ |_ / | | | \'__/ _\
35 | / ____ \ / /| |_| | | | __/
36 | /_/ \_\/___|\__,_|_| \___|
37 |
38 |
39 | Welcome to the cool new Azure CLI!
40 | ```
41 |
42 | ## .NET Core SDK
43 |
44 | Pulumi will need the `dotnet` executable in order to build and run your Pulumi .NET application.
45 |
46 | Install .NET Core 3.1 SDK from [here](https://dotnet.microsoft.com/download).
47 |
48 | Ensure that the `dotnet` executable can be found on your path after installation.
49 |
50 | ```bash
51 | $ dotnet --version
52 | 3.1.100
53 | ```
54 |
55 | ## Docker (Optional)
56 |
57 | If you will be completing the container labs, [install Docker Community Edition](https://docs.docker.com/install). After doing so, verify that the `docker` CLI is operational:
58 |
59 | ```bash
60 | $ docker --version
61 | Docker version 19.03.1, build 74b1e89
62 | ```
63 |
64 | ## Kubernetes (Optional)
65 |
66 | If you will be completing the Kubernetes labs, [install the kubectl CLI](https://kubernetes.io/docs/tasks/tools/install-kubectl/). It isn't necessary to configure it to speak to a cluster — you will do that during the appropriate labs that require it.
67 |
--------------------------------------------------------------------------------
/labs/aws/in-person/python/lab-03/code/step3.py:
--------------------------------------------------------------------------------
1 | from pulumi import export, ResourceOptions
2 | import pulumi_aws as aws
3 | import json
4 |
5 | cluster = aws.ecs.Cluster("cluster")
6 |
7 | default_vpc = aws.ec2.get_vpc(default="true")
8 | default_vpc_subnets = aws.ec2.get_subnet_ids(vpc_id=default_vpc.id)
9 |
10 | group = aws.ec2.SecurityGroup(
11 | "web-secgrp",
12 | vpc_id=default_vpc.id,
13 | description='Enable HTTP access',
14 | ingress=[
15 | { 'protocol': 'icmp', 'from_port': 8, 'to_port': 0, 'cidr_blocks': ['0.0.0.0/0'] },
16 | { 'protocol': 'tcp', 'from_port': 80, 'to_port': 80, 'cidr_blocks': ['0.0.0.0/0'] }
17 | ],
18 | egress=[
19 | { 'protocol': "-1", 'from_port': 0, 'to_port': 0, 'cidr_blocks': ['0.0.0.0/0'] }
20 | ])
21 |
22 | alb = aws.lb.LoadBalancer("app-lb",
23 | security_groups=[group.id],
24 | subnets=default_vpc_subnets.ids,
25 | )
26 |
27 | atg = aws.lb.TargetGroup("app-tg",
28 | port=80,
29 | protocol="HTTP",
30 | target_type="ip",
31 | vpc_id=default_vpc.id
32 | )
33 |
34 | wl = aws.lb.Listener("web",
35 | load_balancer_arn=alb.arn,
36 | port=80,
37 | default_actions=[{
38 | "type": "forward",
39 | "target_group_arn": atg.arn
40 | }]
41 | )
42 |
43 | role = aws.iam.Role("task-exec-role",
44 | assume_role_policy=json.dumps({
45 | "Version": "2008-10-17",
46 | "Statement": [{
47 | "Sid": "",
48 | "Effect": "Allow",
49 | "Principal": {
50 | "Service": "ecs-tasks.amazonaws.com"
51 | },
52 | "Action": "sts:AssumeRole"
53 | }]
54 | })
55 | )
56 |
57 | rpa = aws.iam.RolePolicyAttachment("task-exec-policy",
58 | role=role.name,
59 | policy_arn="arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
60 | )
61 |
62 | task_definition = aws.ecs.TaskDefinition("app-task",
63 | family="fargate-task-definition",
64 | cpu="256",
65 | memory="512",
66 | network_mode="awsvpc",
67 | requires_compatibilities=["FARGATE"],
68 | execution_role_arn=role.arn,
69 | container_definitions=json.dumps([{
70 | "name": "my-app",
71 | "image": "nginx",
72 | "portMappings": [{
73 | "containerPort": 80,
74 | "hostPort": 80,
75 | "protocol": "tcp"
76 | }]
77 | }])
78 | )
79 |
80 | service = aws.ecs.Service("app-svc",
81 | cluster=cluster.arn,
82 | desired_count=1,
83 | launch_type="FARGATE",
84 | task_definition=task_definition.arn,
85 | network_configuration={
86 | "assign_public_ip": "true",
87 | "subnets": default_vpc_subnets.ids,
88 | "security_groups": [group.id]
89 | },
90 | load_balancers=[{
91 | "target_group_arn": atg.arn,
92 | "container_name": "my-app",
93 | "container_port": 80
94 | }],
95 | opts=ResourceOptions(depends_on=[wl])
96 | )
97 |
98 | export("url", alb.dns_name)
99 |
--------------------------------------------------------------------------------
/labs/aws/in-person/python/lab-03/code/step5.py:
--------------------------------------------------------------------------------
1 | from pulumi import export, ResourceOptions
2 | import pulumi_aws as aws
3 | import json
4 |
5 | cluster = aws.ecs.Cluster("cluster")
6 |
7 | default_vpc = aws.ec2.get_vpc(default="true")
8 | default_vpc_subnets = aws.ec2.get_subnet_ids(vpc_id=default_vpc.id)
9 |
10 | group = aws.ec2.SecurityGroup(
11 | "web-secgrp",
12 | vpc_id=default_vpc.id,
13 | description='Enable HTTP access',
14 | ingress=[
15 | { 'protocol': 'icmp', 'from_port': 8, 'to_port': 0, 'cidr_blocks': ['0.0.0.0/0'] },
16 | { 'protocol': 'tcp', 'from_port': 80, 'to_port': 80, 'cidr_blocks': ['0.0.0.0/0'] }
17 | ],
18 | egress=[
19 | { 'protocol': "-1", 'from_port': 0, 'to_port': 0, 'cidr_blocks': ['0.0.0.0/0'] }
20 | ])
21 |
22 | alb = aws.lb.LoadBalancer("app-lb",
23 | security_groups=[group.id],
24 | subnets=default_vpc_subnets.ids,
25 | )
26 |
27 | atg = aws.lb.TargetGroup("app-tg",
28 | port=80,
29 | protocol="HTTP",
30 | target_type="ip",
31 | vpc_id=default_vpc.id
32 | )
33 |
34 | wl = aws.lb.Listener("web",
35 | load_balancer_arn=alb.arn,
36 | port=80,
37 | default_actions=[{
38 | "type": "forward",
39 | "target_group_arn": atg.arn
40 | }]
41 | )
42 |
43 | role = aws.iam.Role("task-exec-role",
44 | assume_role_policy=json.dumps({
45 | "Version": "2008-10-17",
46 | "Statement": [{
47 | "Sid": "",
48 | "Effect": "Allow",
49 | "Principal": {
50 | "Service": "ecs-tasks.amazonaws.com"
51 | },
52 | "Action": "sts:AssumeRole"
53 | }]
54 | })
55 | )
56 |
57 | rpa = aws.iam.RolePolicyAttachment("task-exec-policy",
58 | role=role.name,
59 | policy_arn="arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
60 | )
61 |
62 | task_definition = aws.ecs.TaskDefinition("app-task",
63 | family="fargate-task-definition",
64 | cpu="256",
65 | memory="512",
66 | network_mode="awsvpc",
67 | requires_compatibilities=["FARGATE"],
68 | execution_role_arn=role.arn,
69 | container_definitions=json.dumps([{
70 | "name": "my-app",
71 | "image": "nginx",
72 | "portMappings": [{
73 | "containerPort": 80,
74 | "hostPort": 80,
75 | "protocol": "tcp"
76 | }]
77 | }])
78 | )
79 |
80 | service = aws.ecs.Service("app-svc",
81 | cluster=cluster.arn,
82 | desired_count=3,
83 | launch_type="FARGATE",
84 | task_definition=task_definition.arn,
85 | network_configuration={
86 | "assign_public_ip": "true",
87 | "subnets": default_vpc_subnets.ids,
88 | "security_groups": [group.id]
89 | },
90 | load_balancers=[{
91 | "target_group_arn": atg.arn,
92 | "container_name": "my-app",
93 | "container_port": 80
94 | }],
95 | opts=ResourceOptions(depends_on=[wl])
96 | )
97 |
98 | export("url", alb.dns_name)
99 |
--------------------------------------------------------------------------------
/labs/aws/in-person/go/lab-03/code/step2.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/pulumi/pulumi-aws/sdk/go/aws/ecs"
5 | "github.com/pulumi/pulumi-aws/sdk/go/aws/ec2"
6 | "github.com/pulumi/pulumi-aws/sdk/go/aws/lb"
7 | "github.com/pulumi/pulumi/sdk/go/pulumi"
8 | )
9 |
10 | func main() {
11 | pulumi.Run(func(ctx *pulumi.Context) error {
12 | // Create an ECS cluster to run a container-based service.
13 | cluster, err := ecs.NewCluster(ctx, "app-cluster", nil)
14 | if err != nil {
15 | return err
16 | }
17 |
18 | t := true
19 | vpc, err := ec2.LookupVpc(ctx, &ec2.LookupVpcArgs{Default: &t})
20 | if err != nil {
21 | return err
22 | }
23 | subnet, err := ec2.GetSubnetIds(ctx, &ec2.GetSubnetIdsArgs{VpcId: vpc.Id})
24 | if err != nil {
25 | return err
26 | }
27 |
28 | // Create a SecurityGroup that permits HTTP ingress and unrestricted egress.
29 | webSg, err := ec2.NewSecurityGroup(ctx, "web-sg", &ec2.SecurityGroupArgs{
30 | VpcId: pulumi.String(vpc.Id),
31 | Egress: ec2.SecurityGroupEgressArray{
32 | ec2.SecurityGroupEgressArgs{
33 | Protocol: pulumi.String("-1"),
34 | FromPort: pulumi.Int(0),
35 | ToPort: pulumi.Int(0),
36 | CidrBlocks: pulumi.StringArray{pulumi.String("0.0.0.0/0")},
37 | },
38 | },
39 | Ingress: ec2.SecurityGroupIngressArray{
40 | ec2.SecurityGroupIngressArgs{
41 | Protocol: pulumi.String("tcp"),
42 | FromPort: pulumi.Int(80),
43 | ToPort: pulumi.Int(80),
44 | CidrBlocks: pulumi.StringArray{pulumi.String("0.0.0.0/0")},
45 | },
46 | },
47 | })
48 | if err != nil {
49 | return err
50 | }
51 |
52 | loadBalancer, err := lb.NewLoadBalancer(ctx, "external-loadbalancer", &lb.LoadBalancerArgs{
53 | Internal: pulumi.Bool(false),
54 | SecurityGroups: pulumi.StringArray{webSg.ID().ToStringOutput()},
55 | Subnets: toPulumiStringArray(subnet.Ids),
56 | LoadBalancerType: pulumi.String("application"),
57 | })
58 | if err != nil {
59 | return err
60 | }
61 |
62 | targetGroup, err := lb.NewTargetGroup(ctx, "target-group", &lb.TargetGroupArgs{
63 | Port: pulumi.Int(80),
64 | Protocol: pulumi.String("HTTP"),
65 | TargetType: pulumi.String("ip"),
66 | VpcId: pulumi.String(vpc.Id),
67 | })
68 | if err != nil {
69 | return err
70 | }
71 |
72 | _, err = lb.NewListener(ctx, "listener", &lb.ListenerArgs{
73 | LoadBalancerArn: loadBalancer.Arn,
74 | Port: pulumi.Int(80),
75 | DefaultActions: lb.ListenerDefaultActionArray{
76 | lb.ListenerDefaultActionArgs{
77 | Type: pulumi.String("forward"),
78 | TargetGroupArn: targetGroup.Arn,
79 | },
80 | },
81 | })
82 | if err != nil {
83 | return err
84 | }
85 |
86 | return nil
87 | })
88 | }
89 |
90 | func toPulumiStringArray(a []string) pulumi.StringArrayInput {
91 | var res []pulumi.StringInput
92 | for _, s := range a {
93 | res = append(res, pulumi.String(s))
94 | }
95 | return pulumi.StringArray(res)
96 | }
97 |
--------------------------------------------------------------------------------
/labs/aws/in-person/python/lab-01/06-creating-a-second-stack.md:
--------------------------------------------------------------------------------
1 | # Creating a Second Stack
2 |
3 | It is easy to create multiple instances of the same project. This is called a stack. This is handy for multiple development or test environments, staging versus production, and scaling a given infrastructure across many regions.
4 |
5 | ## Step 1 — Create and Configure a New Stack
6 |
7 | Create a new stack:
8 |
9 | ```bash
10 | pulumi stack init prod
11 | ```
12 |
13 | Next, configure its two required variables:
14 |
15 | ```bash
16 | pulumi config set aws:region eu-west-1
17 | pulumi config set iac-workshop:siteDir wwwprod
18 | ```
19 |
20 | If you are ever curious to see the list of stacks for your current project, run this command:
21 |
22 | ```bash
23 | pulumi stack ls
24 | ```
25 |
26 | It will print all stacks for this project that are available to you:
27 |
28 | ```
29 | NAME LAST UPDATE RESOURCE COUNT URL
30 | dev 30 minutes ago 5 https://app.pulumi.com/joeduffy/iac-workshop/dev
31 | prod* 3 minutes ago 0 https://app.pulumi.com/joeduffy/iac-workshop/prod
32 | ```
33 |
34 | ## Step 2 — Populate the New Site Directory
35 |
36 | It would have been possible to use the existing `www` directory for the `siteDir`. In this example, you will use a different `wwwprod` directory, to demonstrate the value of having configurability.
37 |
38 | Create this new directory:
39 |
40 | ```bash
41 | mkdir wwwprod
42 | ```
43 |
44 | Add a new `index.html` file to it:
45 |
46 | ```html
47 |
48 |
49 |
Hello Pulumi
50 |
(in production!)
51 |
52 |
53 | ```
54 |
55 | ## Step 3 — Deploy the New Stack
56 |
57 | Now deploy all of the changes:
58 |
59 | ```bash
60 | pulumi up
61 | ```
62 |
63 | This will create an entirely new set of resources from scratch, unrelated to the existing `dev` stack's resources.
64 |
65 | ```
66 | Updating (prod):
67 |
68 | Type Name Status
69 | + pulumi:pulumi:Stack iac-workshop-prod created
70 | + ├─ aws:s3:Bucket my-bucket created
71 | + └─ aws:s3:BucketObject index.html created
72 |
73 | Outputs:
74 | bucket_endpoint: "http://my-bucket-c7318c1.s3-website-eu-west-1.amazonaws.com"
75 | bucket_name : "my-bucket-c7318c1"
76 |
77 | Resources:
78 | + 3 created
79 |
80 | Duration: 28s
81 |
82 | Permalink: https://app.pulumi.com/joeduffy/iac-workshop/prod/updates/1
83 | ```
84 |
85 | Now fetch your new website:
86 |
87 | ```bash
88 | curl $(pulumi stack output bucket_endpoint)
89 | ```
90 |
91 | Notice that it's the new production version of your content:
92 |
93 | ```
94 |
95 |
96 |
Hello Pulumi
97 |
(in production!)
98 |
99 |
100 | ```
101 |
102 | ## Next Steps
103 |
104 | * [Destroying Your Infrastructure](./07-destroying-your-infrastructure.md)
105 |
--------------------------------------------------------------------------------
/labs/aws/in-person/typescript/lab-01/06-creating-a-second-stack.md:
--------------------------------------------------------------------------------
1 | # Creating a Second Stack
2 |
3 | It is easy to create multiple instances of the same project. This is called a stack. This is handy for multiple development or test environments, staging versus production, and scaling a given infrastructure across many regions.
4 |
5 | ## Step 1 — Create and Configure a New Stack
6 |
7 | Create a new stack:
8 |
9 | ```bash
10 | pulumi stack init prod
11 | ```
12 |
13 | Next, configure its two required variables:
14 |
15 | ```bash
16 | pulumi config set aws:region eu-west-1
17 | pulumi config set iac-workshop:siteDir wwwprod
18 | ```
19 |
20 | If you are ever curious to see the list of stacks for your current project, run this command:
21 |
22 | ```bash
23 | pulumi stack ls
24 | ```
25 |
26 | It will print all stacks for this project that are available to you:
27 |
28 | ```
29 | NAME LAST UPDATE RESOURCE COUNT URL
30 | dev 30 minutes ago 5 https://app.pulumi.com/joeduffy/iac-workshop/dev
31 | prod* 3 minutes ago 0 https://app.pulumi.com/joeduffy/iac-workshop/prod
32 | ```
33 |
34 | ## Step 2 — Populate the New Site Directory
35 |
36 | It would have been possible to use the existing `www` directory for the `siteDir`. In this example, you will use a different `wwwprod` directory, to demonstrate the value of having configurability.
37 |
38 | Create this new directory:
39 |
40 | ```bash
41 | mkdir wwwprod
42 | ```
43 |
44 | Add a new `index.html` file to it:
45 |
46 | ```html
47 |
48 |
49 |
Hello Pulumi
50 |
(in production!)
51 |
52 |
53 | ```
54 |
55 | ## Step 3 — Deploy the New Stack
56 |
57 | Now deploy all of the changes:
58 |
59 | ```bash
60 | pulumi up
61 | ```
62 |
63 | This will create an entirely new set of resources from scratch, unrelated to the existing `dev` stack's resources.
64 |
65 | ```
66 | Updating (prod):
67 |
68 | Type Name Status
69 | + pulumi:pulumi:Stack iac-workshop-prod created
70 | + ├─ aws:s3:Bucket my-bucket created
71 | + └─ aws:s3:BucketObject index.html created
72 |
73 | Outputs:
74 | bucketEndpoint: "http://my-bucket-c7318c1.s3-website-eu-west-1.amazonaws.com"
75 | bucketName : "my-bucket-c7318c1"
76 |
77 | Resources:
78 | + 3 created
79 |
80 | Duration: 28s
81 |
82 | Permalink: https://app.pulumi.com/joeduffy/iac-workshop/prod/updates/1
83 | ```
84 |
85 | Now fetch your new website:
86 |
87 | ```bash
88 | curl $(pulumi stack output bucketEndpoint)
89 | ```
90 |
91 | Notice that it's the new production version of your content:
92 |
93 | ```
94 |
95 |
96 |
Hello Pulumi
97 |
(in production!)
98 |
99 |
100 | ```
101 |
102 | ## Next Steps
103 |
104 | * [Destroying Your Infrastructure](./07-destroying-your-infrastructure.md)
105 |
--------------------------------------------------------------------------------
/labs/aws/in-person/go/lab-01/06-creating-a-second-stack.md:
--------------------------------------------------------------------------------
1 | # Creating a Second Stack
2 |
3 | It is easy to create multiple instances of the same project. This is called a stack. This is handy for multiple development
4 | or test environments, staging versus production, and scaling a given infrastructure across many regions.
5 |
6 | ## Step 1 — Create and Configure a New Stack
7 |
8 | Create a new stack:
9 |
10 | ```bash
11 | pulumi stack init prod
12 | ```
13 |
14 | Next, configure its two required variables:
15 |
16 | ```bash
17 | pulumi config set aws:region eu-west-1
18 | pulumi config set iac-workshop:siteDir wwwprod
19 | ```
20 |
21 | If you are ever curious to see the list of stacks for your current project, run this command:
22 |
23 | ```bash
24 | pulumi stack ls
25 | ```
26 |
27 | It will print all stacks for this project that are available to you:
28 |
29 | ```
30 | NAME LAST UPDATE RESOURCE COUNT URL
31 | dev 30 minutes ago 5 https://app.pulumi.com/joeduffy/iac-workshop/dev
32 | prod* 3 minutes ago 0 https://app.pulumi.com/joeduffy/iac-workshop/prod
33 | ```
34 |
35 | ## Step 2 — Populate the New Site Directory
36 |
37 | It would have been possible to use the existing `www` directory for the `siteDir`. In this example, you will use a
38 | different `wwwprod` directory, to demonstrate the value of having configurability.
39 |
40 | Create this new directory:
41 |
42 | ```bash
43 | mkdir wwwprod
44 | ```
45 |
46 | Add a new `index.html` file to it:
47 |
48 | ```html
49 |
50 |
51 |
Hello Pulumi
52 |
(in production!)
53 |
54 |
55 | ```
56 |
57 | ## Step 3 — Deploy the New Stack
58 |
59 | Now deploy all of the changes:
60 |
61 | ```bash
62 | pulumi up
63 | ```
64 |
65 | This will create an entirely new set of resources from scratch, unrelated to the existing `dev` stack's resources.
66 |
67 | ```
68 | Updating (prod):
69 |
70 | Type Name Status
71 | + pulumi:pulumi:Stack iac-workshop-prod created
72 | + ├─ aws:s3:Bucket my-bucket created
73 | + └─ aws:s3:BucketObject index.html created
74 |
75 | Outputs:
76 | bucketEndpoint: "http://my-bucket-c7318c1.s3-website-eu-west-1.amazonaws.com"
77 | bucketName : "my-bucket-c7318c1"
78 |
79 | Resources:
80 | + 3 created
81 |
82 | Duration: 28s
83 |
84 | Permalink: https://app.pulumi.com/joeduffy/iac-workshop/prod/updates/1
85 | ```
86 |
87 | Now fetch your new website:
88 |
89 | ```bash
90 | curl $(pulumi stack output bucket_endpoint)
91 | ```
92 |
93 | Notice that it's the new production version of your content:
94 |
95 | ```
96 |
97 |
98 |
Hello Pulumi
99 |
(in production!)
100 |
101 |
102 | ```
103 |
104 | ## Next Steps
105 |
106 | * [Destroying Your Infrastructure](./07-destroying-your-infrastructure.md)
107 |
--------------------------------------------------------------------------------
/labs/aws/in-person/csharp/lab-01/06-creating-a-second-stack.md:
--------------------------------------------------------------------------------
1 | # Creating a Second Stack
2 |
3 | It is easy to create multiple instances of the same project. This is called a stack. This is handy for multiple development
4 | or test environments, staging versus production, and scaling a given infrastructure across many regions.
5 |
6 | ## Step 1 — Create and Configure a New Stack
7 |
8 | Create a new stack:
9 |
10 | ```bash
11 | pulumi stack init prod
12 | ```
13 |
14 | Next, configure its two required variables:
15 |
16 | ```bash
17 | pulumi config set aws:region eu-west-1
18 | pulumi config set iac-workshop:siteDir wwwprod
19 | ```
20 |
21 | If you are ever curious to see the list of stacks for your current project, run this command:
22 |
23 | ```bash
24 | pulumi stack ls
25 | ```
26 |
27 | It will print all stacks for this project that are available to you:
28 |
29 | ```
30 | NAME LAST UPDATE RESOURCE COUNT URL
31 | dev 30 minutes ago 5 https://app.pulumi.com/joeduffy/iac-workshop/dev
32 | prod* 3 minutes ago 0 https://app.pulumi.com/joeduffy/iac-workshop/prod
33 | ```
34 |
35 | ## Step 2 — Populate the New Site Directory
36 |
37 | It would have been possible to use the existing `www` directory for the `siteDir`. In this example, you will use a
38 | different `wwwprod` directory, to demonstrate the value of having configurability.
39 |
40 | Create this new directory:
41 |
42 | ```bash
43 | mkdir wwwprod
44 | ```
45 |
46 | Add a new `index.html` file to it:
47 |
48 | ```html
49 |
50 |
51 |
Hello Pulumi
52 |
(in production!)
53 |
54 |
55 | ```
56 |
57 | ## Step 3 — Deploy the New Stack
58 |
59 | Now deploy all of the changes:
60 |
61 | ```bash
62 | pulumi up
63 | ```
64 |
65 | This will create an entirely new set of resources from scratch, unrelated to the existing `dev` stack's resources.
66 |
67 | ```
68 | Updating (prod):
69 |
70 | Type Name Status
71 | + pulumi:pulumi:Stack iac-workshop-prod created
72 | + ├─ aws:s3:Bucket my-bucket created
73 | + └─ aws:s3:BucketObject index.html created
74 |
75 | Outputs:
76 | WebsiteEndpoint: "http://my-bucket-c7318c1.s3-website-eu-west-1.amazonaws.com"
77 | BucketName : "my-bucket-c7318c1"
78 |
79 | Resources:
80 | + 3 created
81 |
82 | Duration: 28s
83 |
84 | Permalink: https://app.pulumi.com/joeduffy/iac-workshop/prod/updates/1
85 | ```
86 |
87 | Now fetch your new website:
88 |
89 | ```bash
90 | curl $(pulumi stack output WebsiteEndpoint)
91 | ```
92 |
93 | Notice that it's the new production version of your content:
94 |
95 | ```
96 |
97 |
98 |
Hello Pulumi
99 |
(in production!)
100 |
101 |
102 | ```
103 |
104 | ## Next Steps
105 |
106 | * [Destroying Your Infrastructure](./07-destroying-your-infrastructure.md)
107 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # This repo is being deprecated in favor of https://github.com/pulumi/workshops.
2 | 
3 |
4 | The workshops in this repo have been moved over to that repo and placed in the archive as newer workshops based off these workshops have been generated.
5 |
6 | # Infrastructure as Code Workshops
7 |
8 | This repo contains workshops for getting started with Pulumi through a series of hands-on labs. The workshops are organized by cloud provider and then separated into language specific workshops.
9 |
10 | ## Introductory Workshop
11 |
12 | The [introductory workshop](./labs/intro) is designed to guide you through some Pulumi fundamentals. It has a related GitHub repo with a pre-built development environment [here](https://github.com/pulumi/introduction-to-pulumi).
13 |
14 | ## AWS Workshops
15 |
16 | The AWS workshops are designed to guide you through examples of interacting with AWS using Pulumi. You can find more AWS workshops at the [AWS Workshops](https://pulumi.awsworkshop.io/) page.
17 |
18 | ### Prerequisities
19 |
20 | If you want to follow along at home, you'll need to install some dependencies on your local machine.
21 |
22 | * [Installing Prerequisites](./00-installing-prerequisites.md)
23 |
24 | ## In Person Workshop Outline
25 |
26 | The following is an overview of the in-person workshops and their current status:
27 |
28 | | | TypeScript | Python | Go | C# |
29 | | ------ | ------- | ------- | ------- | ------- |
30 | | AWS | [Get started][1] | [Get started][2] | [Get started][4] | [Get started][5] |
31 | | Azure | Coming soon | [Get started][6] | Coming soon | [Get started][3] |
32 | | GCP | Coming Soon | Coming soon | Coming soon | Coming soon |
33 |
34 | ## Next Steps
35 |
36 | After completing these labs, there are several topics you may want to explore.
37 |
38 | * [Continuous delivery](https://www.pulumi.com/docs/guides/continuous-delivery/)
39 | * [Secrets management](https://www.pulumi.com/blog/managing-secrets-with-pulumi/)
40 | * [Multi-project infrastructure architectures](https://www.pulumi.com/blog/architect-aws-application-infra-with-pulumi-stack-references/)
41 | * [Test-driven infrastructure](https://www.pulumi.com/blog/unit-testing-infrastructure-in-nodejs-and-mocha/)
42 |
43 | Thank you for checking out the Infrastructure as Code Workshop! More labs are on their way. Please [file an issue](https://github.com/pulumi/infrastructure-as-code-workshop/issues/new) if there are topics you'd like to see covered in the future.
44 |
45 | [1]: ./labs/aws/in-person/typescript/README.md
46 | [2]: ./labs/aws/in-person/python/README.md
47 | [3]: ./labs/azure/csharp/README.md
48 | [4]: ./labs/aws/in-person/go/README.md
49 | [5]: ./labs/aws/in-person/csharp/README.md
50 | [6]: ./labs/azure/python/README.md
51 |
--------------------------------------------------------------------------------
/labs/azure/csharp/04-vms/code/step1.cs:
--------------------------------------------------------------------------------
1 | using Pulumi;
2 | using Pulumi.Serialization;
3 |
4 | using Azure = Pulumi.Azure;
5 | using Pulumi.Azure.Compute;
6 | using Pulumi.Azure.Compute.Inputs;
7 | using Pulumi.Azure.Network;
8 | using Pulumi.Azure.Network.Inputs;
9 |
10 | class MyStack : Stack
11 | {
12 | public MyStack()
13 | {
14 | var resourceGroup = new Azure.Core.ResourceGroup("my-group");
15 |
16 | var network = new VirtualNetwork("server-network", new VirtualNetworkArgs
17 | {
18 | ResourceGroupName = resourceGroup.Name,
19 | AddressSpaces = { "10.0.0.0/16" },
20 | Subnets =
21 | {
22 | new VirtualNetworkSubnetsArgs
23 | {
24 | Name = "default",
25 | AddressPrefix = "10.0.1.0/24"
26 | }
27 | },
28 | });
29 |
30 | var publicIp = new PublicIp("server-ip", new PublicIpArgs
31 | {
32 | ResourceGroupName = resourceGroup.Name,
33 | AllocationMethod = "Dynamic",
34 | });
35 |
36 | var networkInterface = new NetworkInterface("server-nic", new NetworkInterfaceArgs
37 | {
38 | ResourceGroupName = resourceGroup.Name,
39 | IpConfigurations =
40 | {
41 | new NetworkInterfaceIpConfigurationsArgs
42 | {
43 | Name = "webserveripcfg",
44 | SubnetId = network.Subnets.Apply(subnets => subnets[0].Id),
45 | PrivateIpAddressAllocation = "Dynamic",
46 | PublicIpAddressId = publicIp.Id,
47 | },
48 | }
49 | });
50 |
51 | var vm = new VirtualMachine("server-vm", new VirtualMachineArgs
52 | {
53 | ResourceGroupName = resourceGroup.Name,
54 | NetworkInterfaceIds = { networkInterface.Id },
55 | VmSize = "Standard_A0",
56 | DeleteDataDisksOnTermination = true,
57 | DeleteOsDiskOnTermination = true,
58 | OsProfile = new VirtualMachineOsProfileArgs
59 | {
60 | ComputerName = "hostname",
61 | AdminUsername = "testadmin",
62 | AdminPassword = "NotARealPassword123!",
63 | CustomData =
64 | @"#!/bin/bash
65 | echo ""Hello, World!"" > index.html
66 | nohup python -m SimpleHTTPServer 80 &",
67 | },
68 | OsProfileLinuxConfig = new VirtualMachineOsProfileLinuxConfigArgs
69 | {
70 | DisablePasswordAuthentication = false,
71 | },
72 | StorageOsDisk = new VirtualMachineStorageOsDiskArgs
73 | {
74 | CreateOption = "FromImage",
75 | Name = "myosdisk1",
76 | },
77 | StorageImageReference = new VirtualMachineStorageImageReferenceArgs
78 | {
79 | Publisher = "canonical",
80 | Offer = "UbuntuServer",
81 | Sku = "16.04-LTS",
82 | Version = "latest",
83 | }
84 | });
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/labs/aws/in-person/typescript/lab-02/code/step4.ts:
--------------------------------------------------------------------------------
1 | import * as awsx from "@pulumi/awsx";
2 | import * as aws from "@pulumi/aws";
3 |
4 | // Variable we will use for naming purpose
5 | const name = "demo";
6 |
7 | // Creating a VPC with a Single Nat Gateway Strategy (To save cost)
8 | const myvpc = new awsx.ec2.Vpc(`${name}-vpc`, {
9 | cidrBlock: "10.0.0.0/24",
10 | numberOfAvailabilityZones: 3,
11 | enableDnsHostnames: true,
12 | natGateways: {
13 | strategy: "Single", // This is mainly to save cost. You do this only in dev
14 | },
15 | });
16 |
17 | // VPC Outputs
18 | export const vpc_id = myvpc.vpcId;
19 | export const vpc_natgateways = myvpc.natGateways[0].id;
20 | export const vpc_public_subnetids = myvpc.publicSubnetIds;
21 | export const vpc_private_subnetids = myvpc.privateSubnetIds;
22 |
23 | // Creating Security Group within VPC
24 | const mysecuritygroup = new aws.ec2.SecurityGroup(`${name}-securitygroup`, {
25 | vpcId:myvpc.vpcId,
26 | ingress: [
27 | { protocol: "tcp",
28 | fromPort: 443,
29 | toPort: 443,
30 | cidrBlocks: ["0.0.0.0/0"],
31 | description: "Allow inbound access via https",
32 | self: true, // Add the securitygroup itself as a source
33 | },
34 | {
35 | protocol: "tcp",
36 | fromPort: 80,
37 | toPort: 80,
38 | cidrBlocks: ["0.0.0.0/0"],
39 | description: "Allow inbound access via http",
40 | self: true, // Add the securitygroup itself as a source
41 | },
42 | ],
43 | egress: [
44 | { protocol: "tcp",
45 | fromPort: 443,
46 | toPort: 443,
47 | cidrBlocks: ["0.0.0.0/0"],
48 | description: "Allow outbound access via https"
49 | },
50 | {
51 | protocol: "tcp",
52 | fromPort: 80,
53 | toPort: 80,
54 | cidrBlocks: ["0.0.0.0/0"],
55 | description: "Allow outbound access via http"
56 | },
57 | ],
58 | tags: {"Name": `${name}-securitygroup`},
59 | }, { parent: myvpc, dependsOn: myvpc });
60 |
61 | // Exporting security group outputs
62 | export const security_group_name = mysecuritygroup.id;
63 | export const security_group_vpc = mysecuritygroup.vpcId;
64 | export const security_group_egress = mysecuritygroup.egress;
65 | export const security_group_ingress = mysecuritygroup.ingress;
66 |
67 | // get Function for AMI
68 | const myami = aws.ec2.getAmi({
69 | filters: [{ name: "name", values: ["amzn2-ami-k*-hvm-*-x86_64-gp2"] }],
70 | owners: [ "amazon" ],
71 | mostRecent: true,
72 | });
73 |
74 | // Exporting AMI_ID First Time
75 | //export const ami_id = myami;
76 |
77 | // Exporting AMI_ID with what we want.
78 | export const ami_id = myami.then(ami=>ami.id);
79 |
80 | // Single ec2 instance
81 | const myserver = new aws.ec2.Instance(`${name}-web-server`, {
82 | ami: ami_id,
83 | instanceType: "t2.nano",
84 | subnetId: vpc_public_subnetids[0],
85 | vpcSecurityGroupIds: [mysecuritygroup.id],
86 | tags: { Name: `${name}-web-server` },
87 | userData:
88 | "#!/bin/bash\n" +
89 | "echo 'Hello, World!' > index.html\n" +
90 | "nohup python -m SimpleHTTPServer 80 &",
91 | });
92 |
93 | export const ip = myserver.publicIp;
94 | export const hostname = myserver.publicDns;
--------------------------------------------------------------------------------