1. Tutorials
  2. Creating Resources on Google Cloud

Creating Resources on Google Cloud

In Pulumi, resources represent the fundamental units that make up your infrastructure, such as virtual machines, networks, storage, and databases. A resource is used to define and manage an infrastructure object in your Pulumi configuration. In this tutorial, you will create a simple static website hosted on an Google Cloud virtual instance. You will then refer to documentation in the Pulumi Registry to configure the storage account as a website.

In this tutorial, you'll learn:

  • How to create a new resource
  • How to reference resource definitions in the Pulumi documentation

Create a new project

To start, login to the Pulumi CLI and ensure it is configured to use your Google Cloud account. Next, create a new project and stack.

# Example using Python
$ mkdir pulumi-tutorial-gcp
$ cd pulumi-tutorial-gcp
$ pulumi new gcp-python

Then use the following code snippet to scaffold your project with the required imports and overall program structure that you will fill in as you go along, making sure to replace the value of project with the name/ID of your own Google Cloud project:

"use strict";
const pulumi = require("@pulumi/pulumi");
const gcp = require("@pulumi/gcp");

const region = "us-central1";
const zone = "us-central1-a";
const project = "pulumi-devrel"; // REPLACE

const startupScript = `#!/bin/bash
echo "Hello, World!" > index.html
nohup python -m SimpleHTTPServer 80 &`;

// Create a VPC network.
const vpcNetwork = new gcp.compute.Network("vpc-network", {
    project: project,
    autoCreateSubnetworks: true,
});

// Create an IP address.
const ipAddress = new gcp.compute.Address("ip-address", {
    project: project,
    region: region,
});

// Steps:
// [1] Create a compute instance.
// [2] Create and configure a firewall.

const instanceUrl = ipAddress.address.apply(address => `http://${address}`);

// Export the URL of the server
exports.instanceURL = instanceUrl;
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const region = "us-central1";
const zone = "us-central1-a";
const project = "pulumi-devrel"; // REPLACE

const startupScript = `#!/bin/bash
echo "Hello, World!" > index.html
nohup python -m SimpleHTTPServer 80 &`;

// Create a VPC network.
const vpcNetwork = new gcp.compute.Network("vpc-network", {
    project: project,
    autoCreateSubnetworks: true,
});

// Create an IP address.
const ipAddress = new gcp.compute.Address("ip-address", {
    project: project,
    region: region,
});

// Steps:
// [1] Create a compute instance.
// [2] Create and configure a firewall.

const instanceUrl = ipAddress.address.apply(address => `http://${address}`);

// Export the DNS name of the bucket
export const instanceURL = instanceUrl;
import pulumi
from pulumi_gcp import compute

region = "us-central1"
zone = "us-central1-a"
project = "pulumi-devrel" # REPLACE

startup_script = """#!/bin/bash
echo "Hello, World!" > index.html
nohup python -m SimpleHTTPServer 80 &"""

# Create a VPC network.
vpc_network = compute.Network("vpc-network",
    project=project,
    auto_create_subnetworks=True
)

# Create an IP Address
ip_address = compute.address.Address("ip-address",
    project=project,
    region=region
)

#### Steps:
# [1] Create a compute instance.
# [2] Create and configure a firewall.

# Export the URL of the server
instance_url = ip_address.address.apply(
    lambda address: "http://" + address
)

pulumi.export("instanceURL", instance_url)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v8/go/gcp/compute"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {

		region := "us-central1"
		zone := "us-central1-a"
		project := "pulumi-devrel" // REPLACE

		startupScript := `#!/bin/bash
		echo "Hello, World!" > index.html
		nohup python -m SimpleHTTPServer 80 &`

		// Create a VPC network.
		vpcNetwork, err := compute.NewNetwork(ctx, "vpc-network", &compute.NetworkArgs{
			Project: pulumi.String(project),
			AutoCreateSubnetworks: pulumi.Bool(true),
		})
		if err != nil {
			return err
		}

		// Create an IP address.
		ipAddress, err := compute.NewAddress(ctx, "ip-address", &compute.AddressArgs{
			Project: pulumi.String(project),
			Region: pulumi.String(region),
		})
		if err != nil {
			return err
		}

		// Steps:
		// [1] Create a compute instance.
		// [2] Create and configure a firewall.

        instanceUrl := ipAddress.Address.ApplyT(func(address string) string {
			return "http://" + address
		}).(pulumi.StringOutput)

		// Export the URL of the server
		ctx.Export("instanceURL", instanceUrl)
		return nil
	})
}
using Pulumi;
using Gcp = Pulumi.Gcp;
using System.Linq;
using System.Collections.Generic;

return await Deployment.RunAsync(() =>
{
    var region = "us-central1";
    var zone = "us-central1-a";
    var project = "pulumi-devrel"; // REPLACE
    var startupScript = @"#!/bin/bash
    echo ""Hello, World!"" > index.html
    nohup python -m SimpleHTTPServer 80 &";
    // Create a VPC network.
    var vpcNetwork = new Gcp.Compute.Network("vpc-network", new()
    {
        Project = project,
        AutoCreateSubnetworks = true,
    });
    var ipAddress = new Gcp.Compute.Address("ip-address", new()
    {
        Project = project,
        Region = region,
    });
    // Steps:
    // [1] Create a compute instance.
    // [2] Create and configure a firewall.
    // [1] Create a compute instance.
    var computeInstance = new Gcp.Compute.Instance("webserver-instance", new()
    {
        MachineType ="f1-micro",
        Project = project,
name: gcp-simple-webserver-yaml
runtime: yaml
description: An example that deploys the configuration for a simple web server on Google Cloud.

config:
  gcp:region: us-central1
  gcp:zone: us-central1-a
  gcp:project: pulumi-devrel # REPLACE

resources:
  # Create a VPC network.
  vpcNetwork:
    type: gcp:compute:Network
    name: vpcNetwork
    properties:
      autoCreateSubnetworks: true

  # Create an IP address.
  ipAddress:
    type: gcp:compute:Address
    properties:
      name: ipaddress

  #### Steps:
  # [1] Create a compute instance.
  # [2] Create and configure a firewall.

# Export the URL of the server
outputs:
  instanceURL:
    value: "http://${ipAddress.address}"

The above code creates the following on your behalf:

  • A VPC network
  • An IP address
  • An output of the web server’s URL

Create a virtual machine

The first resource you will create will be virtual machine that will host the web server. The specific details of how to create your virtual machine differ by cloud provider. In the case of Google Cloud, you will be creating a virtual machine instance. The Pulumi Registry provides the documentation for all of the Pulumi providers and their associated resources. Open the gcp.compute.Instance documentation page to view a description of this resource, example usage, the resource definition, and supported properties. You will now define your instance resource as shown below:

"use strict";
const pulumi = require("@pulumi/pulumi");
const gcp = require("@pulumi/gcp");

const region = "us-central1";
const zone = "us-central1-a";
const project = "pulumi-devrel"; // REPLACE

const startupScript = `#!/bin/bash
echo "Hello, World!" > index.html
nohup python -m SimpleHTTPServer 80 &`;

// Create a VPC network.
const vpcNetwork = new gcp.compute.Network("vpc-network", {
    project: project,
    autoCreateSubnetworks: true,
});

// Create an IP address.
const ipAddress = new gcp.compute.Address("ip-address", {
    project: project,
    region: region,
});

// [1] Create a compute instance.
const computeInstance = new gcp.compute.Instance("webserver-instance", {
    machineType: "f1-micro",
    project: project,
    zone: zone,
    metadataStartupScript: startupScript,
    bootDisk: {
        initializeParams: {
            image: "debian-cloud/debian-9-stretch-v20181210",
        },
    },
    networkInterfaces: [
        {
            accessConfigs: [
                {
                    natIp: ipAddress.address,
                },
            ],
            network: vpcNetwork.id,
        },
    ],
    serviceAccount: {
        scopes: ["https://www.googleapis.com/auth/cloud-platform"],
    },
});

// [2] Create and configure a firewall.
// TO-DO

const instanceUrl = ipAddress.address.apply(address => `http://${address}`);

// Export the URL of the server
exports.instanceURL = instanceUrl;
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const region = "us-central1";
const zone = "us-central1-a";
const project = "pulumi-devrel"; // REPLACE

const startupScript = `#!/bin/bash
echo "Hello, World!" > index.html
nohup python -m SimpleHTTPServer 80 &`;

// Create a VPC network.
const vpcNetwork = new gcp.compute.Network("vpc-network", {
    project: project,
    autoCreateSubnetworks: true,
});

// Create an IP address.
const ipAddress = new gcp.compute.Address("ip-address", {
    project: project,
    region: region,
});

// [1] Create a compute instance.
const computeInstance = new gcp.compute.Instance("webserver-instance", {
    machineType: "f1-micro",
    project: project,
    zone: zone,
    metadataStartupScript: startupScript,
    bootDisk: {
        initializeParams: {
            image: "debian-cloud/debian-9-stretch-v20181210",
        },
    },
    networkInterfaces: [
        {
            accessConfigs: [
                {
                    natIp: ipAddress.address,
                },
            ],
            network: vpcNetwork.id,
        },
    ],
    serviceAccount: {
        scopes: ["https://www.googleapis.com/auth/cloud-platform"],
    },
});

// [2] Create and configure a firewall.
// TO- DO

const instanceUrl = ipAddress.address.apply(address => `http://${address}`);

// Export the DNS name of the bucket
export const instanceURL = instanceUrl;
import pulumi
from pulumi_gcp import compute

region = "us-central1"
zone = "us-central1-a"
project = "pulumi-devrel" # REPLACE

startup_script = """#!/bin/bash
echo "Hello, World!" > index.html
nohup python -m SimpleHTTPServer 80 &"""

# Create a VPC network.
vpc_network = compute.Network("vpc-network",
    project=project,
    auto_create_subnetworks=True
)

# Create an IP Address
ip_address = compute.address.Address("ip-address",
    project=project,
    region=region
)

# [1] Create a compute instance.
compute_instance = compute.Instance(
    "webserver-instance",
    machine_type="f1-micro",
    project=project,
    zone=zone,
    metadata_startup_script=startup_script,
    boot_disk=compute.InstanceBootDiskArgs(
        initialize_params=compute.InstanceBootDiskInitializeParamsArgs(
            image="debian-cloud/debian-9-stretch-v20181210"
        )
    ),
    network_interfaces=[compute.InstanceNetworkInterfaceArgs(
            network=vpc_network.id,
            access_configs=[compute.InstanceNetworkInterfaceAccessConfigArgs(
                nat_ip=ip_address.address
            )],
    )],
    service_account=compute.InstanceServiceAccountArgs(
        scopes=["https://www.googleapis.com/auth/cloud-platform"],
    )
)

# [2] Create and configure a firewall.
# TO-DO

# Export the URL of the server
instance_url = ip_address.address.apply(
    lambda address: "http://" + address
)

pulumi.export("instanceURL", instance_url)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v8/go/gcp/compute"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {

		region := "us-central1"
		zone := "us-central1-a"
		project := "pulumi-devrel" // REPLACE

		startupScript := `#!/bin/bash
		echo "Hello, World!" > index.html
		nohup python -m SimpleHTTPServer 80 &`

		// Create a VPC network.
		vpcNetwork, err := compute.NewNetwork(ctx, "vpc-network", &compute.NetworkArgs{
			Project: pulumi.String(project),
			AutoCreateSubnetworks: pulumi.Bool(true),
		})
		if err != nil {
			return err
		}

		// Create an IP address.
		ipAddress, err := compute.NewAddress(ctx, "ip-address", &compute.AddressArgs{
			Project: pulumi.String(project),
			Region: pulumi.String(region),
		})
		if err != nil {
			return err
		}

		// [1] Create a compute instance.
		_, err = compute.NewInstance(ctx, "webserver-instance", &compute.InstanceArgs{
			Project: pulumi.String(project),
			Zone: pulumi.String(zone),
			MachineType: pulumi.String("f1-micro"),
			MetadataStartupScript: pulumi.String(startupScript),
			BootDisk: &compute.InstanceBootDiskArgs{
				InitializeParams: &compute.InstanceBootDiskInitializeParamsArgs{
					Image: pulumi.String("debian-cloud/debian-9-stretch-v20181210"),
				},
			},
			NetworkInterfaces: compute.InstanceNetworkInterfaceArray{
				&compute.InstanceNetworkInterfaceArgs{
					AccessConfigs: &compute.InstanceNetworkInterfaceAccessConfigArray{
						&compute.InstanceNetworkInterfaceAccessConfigArgs{
							NatIp: ipAddress.Address,
						},
					},
					Network: vpcNetwork.ID(),
				},
			},
			ServiceAccount: &compute.InstanceServiceAccountArgs{
				Scopes: pulumi.StringArray{
					pulumi.String("https://www.googleapis.com/auth/cloud-platform"),
				},
			},
		})
		if err != nil {
			return err
		}

		// [2] Create and configure a firewall.
        // TO-DO

        instanceUrl := ipAddress.Address.ApplyT(func(address string) string {
			return "http://" + address
		}).(pulumi.StringOutput)

		// Export the URL of the server
		ctx.Export("instanceURL", instanceUrl)
		return nil
	})
}
using Pulumi;
using Gcp = Pulumi.Gcp;
using System.Linq;
using System.Collections.Generic;

return await Deployment.RunAsync(() =>
{
    var region = "us-central1";
    var zone = "us-central1-a";
    var project = "pulumi-devrel"; // REPLACE
    var startupScript = @"#!/bin/bash
    echo ""Hello, World!"" > index.html
    nohup python -m SimpleHTTPServer 80 &";
    // Create a VPC network.
    var vpcNetwork = new Gcp.Compute.Network("vpc-network", new()
    {
        Project = project,
        AutoCreateSubnetworks = true,
    });
    var ipAddress = new Gcp.Compute.Address("ip-address", new()
    {
        Project = project,
        Region = region,
    });
    // Steps:
    // [1] Create a compute instance.
    // [2] Create and configure a firewall.
    // [1] Create a compute instance.

        MetadataStartupScript=startupScript,
        BootDisk= new Gcp.Compute.Inputs.InstanceBootDiskArgs
        {
            InitializeParams = new Gcp.Compute.Inputs.InstanceBootDiskInitializeParamsArgs
            {
                Image="debian-cloud/debian-9-stretch-v20181210"
            }
        },
        NetworkInterfaces= new[]
        {
            new Gcp.Compute.Inputs.InstanceNetworkInterfaceArgs
            {
                AccessConfigs = new[]
                {
                    new Gcp.Compute.Inputs.InstanceNetworkInterfaceAccessConfigArgs
                    {
                        NatIp = ipAddress.IPAddress
                    }
                },
                Network = vpcNetwork.Id
            }
        },
        ServiceAccount = new Gcp.Compute.Inputs.InstanceServiceAccountArgs
        {
            Scopes = new[] 
            {
                "https://www.googleapis.com/auth/cloud-platform"
            },
        }
    });
    // [2] Create and configure a firewall.
    var computeFirewall = new Gcp.Compute.Firewall("firewall", new()
    {
        Project = project,
        Network = vpcNetwork.SelfLink,
        Allows = new[]
        {
            new Gcp.Compute.Inputs.FirewallAllowArgs
    // TO-DO
name: gcp-simple-webserver-yaml
runtime: yaml
description: An example that deploys the configuration for a simple web server on Google Cloud.

config:
  gcp:region: us-central1
  gcp:zone: us-central1-a
  gcp:project: pulumi-devrel # REPLACE

resources:
  # Create a VPC network.
  vpcNetwork:
    type: gcp:compute:Network
    name: vpcNetwork
    properties:
      autoCreateSubnetworks: true

  # Create an IP address.
  ipAddress:
    type: gcp:compute:Address
    properties:
      name: ipaddress

  # [1] Create a compute instance.
  computeInstance:
    type: gcp:compute:Instance
    name: webserverInstance
    properties:
      machineType: f1-micro
      metadataStartupScript: |
        #!/bin/bash
        echo "Hello, World!" > index.html
        nohup python -m SimpleHTTPServer 80 &        
      bootDisk:
        initializeParams:
          image: debian-cloud/debian-9-stretch-v20181210
      networkInterfaces:
        - accessConfigs:
            - natIp: ${ipAddress.address}
          network: ${vpcNetwork.id}
      serviceAccount:
        scopes:
          - https://www.googleapis.com/auth/cloud-platform

  # [2] Create and configure a firewall.
  # TO-DO

# Export the URL of the server
outputs:
  instanceURL:
    value: "http://${ipAddress.address}"

All resources have a required name argument. Each resource has both a logical name and a physical name. The logical name is how the resource is known inside Pulumi. This is the value provided to the required name argument. The physical name is the name used for the resource in the cloud provider that a Pulumi program is deploying to. It is a combination of the logical name plus a random suffix which helps to prevent resource naming collisions.

In the above example, the logical name for our instance resource is “website-server”, and the physical name might typically look something like “website-server-d7c2fa0”.

In addition to names, resources have properties and options.

Properties are used to specify what type of resource to create. Properties are often resource-specific, and they can be required or optional depending on the specifications of the provider.

Some of the properties inside of your gcp.compute.Instance resource include:

PropertyDescription
machine typetells the Google Cloud provider what type of machine to create
boot disktells the provider the configuration for the instance’s boot disk
network interfacestells the provider what networks to attach to the instance

Options let you control certain aspects of a resource (such as showing explicit dependencies or importing existing infrastructure). You do not have any options defined for this resource, but you can learn more about how it works in the Resource options documentation.

Deploy your resources

Now run the pulumi up command to preview and deploy the resouces you’ve just defined in your project.

$ pulumi up -y

Previewing update (web-server)

     Type                     Name                Plan
 +   pulumi:pulumi:Stack      gcp-web-server      create
 +   ├─ gcp:compute:Network   vpc-network         create
 +   ├─ gcp:compute:Address   ip-address          create
 +   └─ gcp:compute:Instance  webserver-instance  create

Outputs:
    instanceURL: output<string>

Resources:
    + 4 to create

Updating (web-server)

     Type                     Name                Status
 +   pulumi:pulumi:Stack      gcp-web-server      created (73s)
 +   ├─ gcp:compute:Address   ip-address          created (3s)
 +   ├─ gcp:compute:Network   vpc-network         created (53s)
 +   └─ gcp:compute:Instance  webserver-instance  created (15s)

Outputs:
    instanceURL: "http://34.171.149.220"

Resources:
    + 4 created

Duration: 1m15s

The public IP address of your instance has been provided for you as an output, and you can use this to access your web server. However, if you try to visit this address, your request will eventually time out. This is because you have not yet configured web traffic access for your instance. You will do this by creating your firewall resource.

Create a firewall

In this section, you will use Pulumi documentation to configure the firewall on your own. The firewall must allow web traffic on port 80 in order for you to access your web server. Use the following steps as a guide for adding the firewall resource:

  • Navigate to the Google Cloud Registry documentation page
  • Search for the gcp.compute.Firewall resource
  • Define the firewall resource in your project code
  • Configure the firewall to allow traffic on port 80
  • Preview and deploy your updated project code

Once you have completed these steps, navigate to your instance IP address again. You should now be greeted with a “Hello world!” home page message that indicates your web server is running and publically accessible.

View complete solution

You can view the complete project code below:

"use strict";
const pulumi = require("@pulumi/pulumi");
const gcp = require("@pulumi/gcp");

const region = "us-central1";
const zone = "us-central1-a";
const project = "pulumi-devrel"; // REPLACE

const startupScript = `#!/bin/bash
echo "Hello, World!" > index.html
nohup python -m SimpleHTTPServer 80 &`;

// Create a VPC network.
const vpcNetwork = new gcp.compute.Network("vpc-network", {
    project: project,
    autoCreateSubnetworks: true,
});

// Create an IP address.
const ipAddress = new gcp.compute.Address("ip-address", {
    project: project,
    region: region,
});

// [1] Create a compute instance.
const computeInstance = new gcp.compute.Instance("webserver-instance", {
    machineType: "f1-micro",
    project: project,
    zone: zone,
    metadataStartupScript: startupScript,
    bootDisk: {
        initializeParams: {
            image: "debian-cloud/debian-9-stretch-v20181210",
        },
    },
    networkInterfaces: [
        {
            accessConfigs: [
                {
                    natIp: ipAddress.address,
                },
            ],
            network: vpcNetwork.id,
        },
    ],
    serviceAccount: {
        scopes: ["https://www.googleapis.com/auth/cloud-platform"],
    },
});

// [2] Create and configure a firewall.
const firewall = new gcp.compute.Firewall("firewall", {
    project: project,
    network: vpcNetwork.selfLink,
    allows: [
        {
            protocol: "tcp",
            ports: ["80"],
        },
    ],
    sourceRanges: ["0.0.0.0/0"],
});

const instanceUrl = ipAddress.address.apply(address => `http://${address}`);

// Export the URL of the server
exports.instanceURL = instanceUrl;
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const region = "us-central1";
const zone = "us-central1-a";
const project = "pulumi-devrel"; // REPLACE

const startupScript = `#!/bin/bash
echo "Hello, World!" > index.html
nohup python -m SimpleHTTPServer 80 &`;

// Create a VPC network.
const vpcNetwork = new gcp.compute.Network("vpc-network", {
    project: project,
    autoCreateSubnetworks: true,
});

// Create an IP address.
const ipAddress = new gcp.compute.Address("ip-address", {
    project: project,
    region: region,
});

// [1] Create a compute instance.
const computeInstance = new gcp.compute.Instance("webserver-instance", {
    machineType: "f1-micro",
    project: project,
    zone: zone,
    metadataStartupScript: startupScript,
    bootDisk: {
        initializeParams: {
            image: "debian-cloud/debian-9-stretch-v20181210",
        },
    },
    networkInterfaces: [
        {
            accessConfigs: [
                {
                    natIp: ipAddress.address,
                },
            ],
            network: vpcNetwork.id,
        },
    ],
    serviceAccount: {
        scopes: ["https://www.googleapis.com/auth/cloud-platform"],
    },
});

// [2] Create and configure a firewall.
const firewall = new gcp.compute.Firewall("firewall", {
    project: project,
    network: vpcNetwork.selfLink,
    allows: [
        {
            protocol: "tcp",
            ports: ["80"],
        },
    ],
    sourceRanges: ["0.0.0.0/0"],
});

const instanceUrl = ipAddress.address.apply(address => `http://${address}`);

// Export the DNS name of the bucket
export const instanceURL = instanceUrl;
import pulumi
from pulumi_gcp import compute

region = "us-central1"
zone = "us-central1-a"
project = "pulumi-devrel" # REPLACE

startup_script = """#!/bin/bash
echo "Hello, World!" > index.html
nohup python -m SimpleHTTPServer 80 &"""

# Create a VPC network.
vpc_network = compute.Network("vpc-network",
    project=project,
    auto_create_subnetworks=True
)

# Create an IP Address
ip_address = compute.address.Address("ip-address",
    project=project,
    region=region
)

# [1] Create a compute instance.
compute_instance = compute.Instance(
    "webserver-instance",
    machine_type="f1-micro",
    project=project,
    zone=zone,
    metadata_startup_script=startup_script,
    boot_disk=compute.InstanceBootDiskArgs(
        initialize_params=compute.InstanceBootDiskInitializeParamsArgs(
            image="debian-cloud/debian-9-stretch-v20181210"
        )
    ),
    network_interfaces=[compute.InstanceNetworkInterfaceArgs(
            network=vpc_network.id,
            access_configs=[compute.InstanceNetworkInterfaceAccessConfigArgs(
                nat_ip=ip_address.address
            )],
    )],
    service_account=compute.InstanceServiceAccountArgs(
        scopes=["https://www.googleapis.com/auth/cloud-platform"],
    )
)

# [2] Create and configure a firewall.
compute_firewall = compute.Firewall(
    "firewall",
    project=project,
    network=vpc_network.self_link,
    allows=[compute.FirewallAllowArgs(
        protocol="tcp",
        ports=["80"],
    )],
    source_ranges=["0.0.0.0/0"]
)

# Export the URL of the server
instance_url = ip_address.address.apply(
    lambda address: "http://" + address
)

pulumi.export("instanceURL", instance_url)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v8/go/gcp/compute"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {

		region := "us-central1"
		zone := "us-central1-a"
		project := "pulumi-devrel" // REPLACE

		startupScript := `#!/bin/bash
		echo "Hello, World!" > index.html
		nohup python -m SimpleHTTPServer 80 &`

		// Create a VPC network.
		vpcNetwork, err := compute.NewNetwork(ctx, "vpc-network", &compute.NetworkArgs{
			Project: pulumi.String(project),
			AutoCreateSubnetworks: pulumi.Bool(true),
		})
		if err != nil {
			return err
		}

		// Create an IP address.
		ipAddress, err := compute.NewAddress(ctx, "ip-address", &compute.AddressArgs{
			Project: pulumi.String(project),
			Region: pulumi.String(region),
		})
		if err != nil {
			return err
		}

		// [1] Create a compute instance.
		_, err = compute.NewInstance(ctx, "webserver-instance", &compute.InstanceArgs{
			Project: pulumi.String(project),
			Zone: pulumi.String(zone),
			MachineType: pulumi.String("f1-micro"),
			MetadataStartupScript: pulumi.String(startupScript),
			BootDisk: &compute.InstanceBootDiskArgs{
				InitializeParams: &compute.InstanceBootDiskInitializeParamsArgs{
					Image: pulumi.String("debian-cloud/debian-9-stretch-v20181210"),
				},
			},
			NetworkInterfaces: compute.InstanceNetworkInterfaceArray{
				&compute.InstanceNetworkInterfaceArgs{
					AccessConfigs: &compute.InstanceNetworkInterfaceAccessConfigArray{
						&compute.InstanceNetworkInterfaceAccessConfigArgs{
							NatIp: ipAddress.Address,
						},
					},
					Network: vpcNetwork.ID(),
				},
			},
			ServiceAccount: &compute.InstanceServiceAccountArgs{
				Scopes: pulumi.StringArray{
					pulumi.String("https://www.googleapis.com/auth/cloud-platform"),
				},
			},
		})
		if err != nil {
			return err
		}

		// [2] Create and configure a firewall.
		_, err = compute.NewFirewall(ctx, "firewall", &compute.FirewallArgs{
			Project: pulumi.String(project),
			Network: vpcNetwork.SelfLink,
			Allows: compute.FirewallAllowArray{
				&compute.FirewallAllowArgs{
					Protocol: pulumi.String("tcp"),
					Ports: pulumi.StringArray{
						pulumi.String("80"),
					},
				},
			},
			SourceRanges: pulumi.StringArray{
				pulumi.String("0.0.0.0/0"),
			},
		})
		if err != nil {
			return err
		}

        instanceUrl := ipAddress.Address.ApplyT(func(address string) string {
			return "http://" + address
		}).(pulumi.StringOutput)

		// Export the URL of the server
		ctx.Export("instanceURL", instanceUrl)
		return nil
	})
}
using Pulumi;
using Gcp = Pulumi.Gcp;
using System.Linq;
using System.Collections.Generic;

return await Deployment.RunAsync(() =>
{
    var region = "us-central1";
    var zone = "us-central1-a";
    var project = "pulumi-devrel"; // REPLACE
    var startupScript = @"#!/bin/bash
    echo ""Hello, World!"" > index.html
    nohup python -m SimpleHTTPServer 80 &";
    // Create a VPC network.
    var vpcNetwork = new Gcp.Compute.Network("vpc-network", new()
    {
        Project = project,
        AutoCreateSubnetworks = true,
    });
    var ipAddress = new Gcp.Compute.Address("ip-address", new()
    {
        Project = project,
        Region = region,
    });
    // Steps:
    // [1] Create a compute instance.
    // [2] Create and configure a firewall.
    // [1] Create a compute instance.

        MetadataStartupScript=startupScript,
        BootDisk= new Gcp.Compute.Inputs.InstanceBootDiskArgs
        {
            InitializeParams = new Gcp.Compute.Inputs.InstanceBootDiskInitializeParamsArgs
            {
                Image="debian-cloud/debian-9-stretch-v20181210"
            }
        },
        NetworkInterfaces= new[]
        {
            new Gcp.Compute.Inputs.InstanceNetworkInterfaceArgs
            {
                AccessConfigs = new[]
                {
                    new Gcp.Compute.Inputs.InstanceNetworkInterfaceAccessConfigArgs
                    {
                        NatIp = ipAddress.IPAddress
                    }
                },
                Network = vpcNetwork.Id
            }
        },
        ServiceAccount = new Gcp.Compute.Inputs.InstanceServiceAccountArgs
        {
            Scopes = new[] 
            {
                "https://www.googleapis.com/auth/cloud-platform"
            },
        }
    });
    // [2] Create and configure a firewall.
    var computeFirewall = new Gcp.Compute.Firewall("firewall", new()
    {
        Project = project,
        Network = vpcNetwork.SelfLink,
        Allows = new[]
        {
            new Gcp.Compute.Inputs.FirewallAllowArgs
            {
                Protocol = "tcp",
                Ports = new[]
                {
                    "80",
                },
            },
        },
        SourceRanges = new[]
        {
            "0.0.0.0/0",
        },
    });
    var instanceUrl = ipAddress.IPAddress.Apply(ipAddress => $"http://{ipAddress}");
    // Export the URL of the server
    return new Dictionary<string, object?>
    {
        ["instanceURL"] = instanceUrl
    };
});
name: gcp-simple-webserver-yaml
runtime: yaml
description: An example that deploys the configuration for a simple web server on Google Cloud.

config:
  gcp:region: us-central1
  gcp:zone: us-central1-a
  gcp:project: pulumi-devrel # REPLACE

resources:
  # Create a VPC network.
  vpcNetwork:
    type: gcp:compute:Network
    name: vpcNetwork
    properties:
      autoCreateSubnetworks: true

  # Create an IP address.
  ipAddress:
    type: gcp:compute:Address
    properties:
      name: ipaddress

  # [1] Create a compute instance.
  computeInstance:
    type: gcp:compute:Instance
    name: webserverInstance
    properties:
      machineType: f1-micro
      metadataStartupScript: |
        #!/bin/bash
        echo "Hello, World!" > index.html
        nohup python -m SimpleHTTPServer 80 &        
      bootDisk:
        initializeParams:
          image: debian-cloud/debian-9-stretch-v20181210
      networkInterfaces:
        - accessConfigs:
            - natIp: ${ipAddress.address}
          network: ${vpcNetwork.id}
      serviceAccount:
        scopes:
          - https://www.googleapis.com/auth/cloud-platform

  # [2] Create and configure a firewall.
  firewall:
    type: gcp:compute:Firewall
    properties:
      network: ${vpcNetwork.selfLink}
      allows:
        - protocol: tcp
          ports: ["80"]
      sourceRanges: ["0.0.0.0/0"]

# Export the URL of the server
outputs:
  instanceURL:
    value: "http://${ipAddress.address}"

Clean up

Before moving on, tear down the resources that are part of your stack to avoid incurring any charges.

  1. Run pulumi destroy to tear down all resources. You'll be prompted to make sure you really want to delete these resources. A destroy operation may take some time, since Pulumi waits for the resources to finish shutting down before it considers the destroy operation to be complete.
  2. To delete the stack itself, run pulumi stack rm. Note that this command deletes all deployment history from the Pulumi Service.

Next steps

In this tutorial, you create a virtual machine instance configured as a web server, and you created a firewall resource configured for public web access by referencing the Pulumi Registry. You also reviewed resource properties and example usage of various resources.

To learn more about creating resources in Pulumi, take a look at the following resources: