Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Programming model reorganization #4707

Merged
merged 14 commits into from Feb 3, 2021
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Expand Up @@ -17,14 +17,14 @@ We generally use Hugo's [`relref` shortcode](https://gohugo.io/content-managemen

```markdown
[Install]({{< relref "/docs/get-started/install" >}})
[Outputs]({{< relref "/docs/intro/concepts/programming-model#stack-outputs" >}})
[Outputs]({{< relref "/docs/intro/concepts/stack#outputs" >}})
```

Which, on a page inside the `./content/reference` directory, will generate:

```html
<a href="/docs/install/">Install</a>
<a href="/docs/intro/concepts/programming-model/#stack-outputs">Outputs</a>
<a href="/docs/intro/concepts/stack/#stack-outputs">Outputs</a>
```

### Hugo tips
Expand Down
Expand Up @@ -36,7 +36,7 @@ We'll review referencing existing resources, and then dive deeper into how you c
For referencing existing resources, Pulumi offers several tools.

* The `.get` methods available on every resource let you [get all the details for a resource]({{< relref "/docs/reference/pkg/aws/ec2/vpc#look-up" >}}) from the cloud provider based just on its `id`.
* The `StackReference` resource lets you reference outputs of another stack for use as inputs to a stack, which is very useful for [organizing projects and stacks]({{< relref "/docs/intro/concepts/organizing-stacks-projects" >}}).
* The `StackReference` resource lets you reference outputs of another stack for use as inputs to a stack, which is very useful for [organizing projects and stacks]({{< relref "/docs/guides/organizing-projects-stacks" >}}).
* [`terraform.state.RemoteStateReference()`]({{< relref "/blog/using-terraform-remote-state-with-pulumi" >}}), [`aws.cloudformation.getStack()`]({{< relref "/docs/reference/pkg/aws/cloudformation/getstack" >}}) and [`azure.core.TemplateDeployment.get()`]({{< relref "/docs/reference/pkg/azure/core/templatedeployment#look-up" >}}) let you reference outputs from existing Terraform, CloudFormation and ARM deployments respectively.

Together, these make it easy to reference existing infrastructure regardless of how it was provisioned.
Expand Down
2 changes: 1 addition & 1 deletion content/blog/advanced-typescript-type-ftw/index.md
Expand Up @@ -13,7 +13,7 @@ how this works for infrastructure as code can be fascinating!
<!--more-->

A core part of the Pulumi [programming model]({{< relref "/docs/reference" >}}) is that we allow people to express complex
[dependency data]({{< relref "/docs/intro/concepts/programming-model#outputs" >}}) that may _eventually_ be available.
[dependency data]({{< relref "/docs/intro/concepts/inputs-outputs" >}}) that may _eventually_ be available.
Traditional JavaScript programming might expose that as a Promise<T>, but we’ve taken that one step further by introducing
a type we call:

Expand Down
2 changes: 1 addition & 1 deletion content/blog/amazon-eks-distro/index.md
Expand Up @@ -30,7 +30,7 @@ If you're already a user of Amazon EKS, you're already getting all of the benefi

Installing an Amazon EKS Distro cluster involves bootstrapping a Kubernetes cluster but with the images provided by the Amazon EKS team. The simplest way to provision a Kubernetes cluster is using [kops](https://kops.sigs.k8s.io/) and the Amazon EKS Distro team provides instructions on how to replace the default Kubernetes components with the Amazon EKS Distro built parts.

It's possible to get all of the benefits of provisioning a Kubernetes cluster with kops while also taking part in the Pulumi resource lifecycle. Pulumi offers support for running arbitrary commands using [dynamic providers](https://www.pulumi.com/docs/intro/concepts/programming-model/#dynamicproviders) (available in the JavaScript, Typescript and Python SDKs) and you can register the kops commands used to create and destroy clusters as dynamic provider callbacks. Once your Kubernetes cluster has been created, you can provision Kubernetes resources using Pulumi's Kubernetes provider, using the Pulumi resource model to set dependencies on the created cluster.
It's possible to get all of the benefits of provisioning a Kubernetes cluster with kops while also taking part in the Pulumi resource lifecycle. Pulumi offers support for running arbitrary commands using [dynamic providers]({{< relref "/docs/intro/concepts/resources#dynamicproviders" >}}) (available in the JavaScript, Typescript and Python SDKs) and you can register the kops commands used to create and destroy clusters as dynamic provider callbacks. Once your Kubernetes cluster has been created, you can provision Kubernetes resources using Pulumi's Kubernetes provider, using the Pulumi resource model to set dependencies on the created cluster.

### Creating an Amazon EKS Distro cluster with Pulumi

Expand Down
Expand Up @@ -37,7 +37,7 @@ $ tree -d -L 1
```

This means all of the work required for the networking components can be in the network project. We can use
[Stack References]({{< relref "/docs/intro/concepts/organizing-stacks-projects#inter-stack-dependencies" >}}) in Pulumi
[Stack References]({{< relref "/docs/intro/concepts/stack#stackreferences" >}}) in Pulumi
to expose any required information from the networking layer, to the database and application layers.

Let's create the networking project.
Expand Down
2 changes: 1 addition & 1 deletion content/blog/architecture-as-code-kubernetes/index.md
Expand Up @@ -99,6 +99,6 @@ Using this example, you can quickly build any of the Kubernetes architectural pa

## Conclusion

Deploying modern applications is complex. Anyone of the architectures we’ve examined -- virtual machines, microservices, serverless and Kubernetes -- require deploying and configuring multiple resources. For many reasons, including security, compliance, and cost management, we want to reuse resources consistently. In a sense, architecture as code is the logical progression of the DevOps principle of ["cattle not pets"](https://medium.com/@Joachim8675309/devops-concepts-pets-vs-cattle-2380b5aab313). Infrastructure as code is the tool that enables this by bringing standard development practices, such as code review, CI/CD, and testing to infrastructure. Learn how to build reusable infrastructure components with Pulumi’s [programming model]({{< relref "/docs/intro/concepts/programming-model" >}}), [API reference for cloud service providers]({{< relref "/docs/reference/pkg" >}}), and [examples](https://github.com/pulumi/examples).
Deploying modern applications is complex. Any one of the architectures we’ve examined -- virtual machines, microservices, serverless and Kubernetes -- require deploying and configuring multiple resources. For many reasons, including security, compliance, and cost management, we want to reuse resources consistently. In a sense, architecture as code is the logical progression of the DevOps principle of ["cattle not pets"](https://medium.com/@Joachim8675309/devops-concepts-pets-vs-cattle-2380b5aab313). Infrastructure as code is the tool that enables this by bringing standard development practices, such as code review, CI/CD, and testing to infrastructure. Learn how to build reusable infrastructure components with Pulumi’s [programming model]({{< relref "/docs/intro/concepts" >}}), [API reference for cloud service providers]({{< relref "/docs/reference/pkg" >}}), and [examples](https://github.com/pulumi/examples).

Want to know more? Listen to the [New Stack Context podcast](https://thenewstack.io/pulumi-program-the-infrastructure-with-an-actual-programming-language/) on the Pulumi 2.0 release and Architecture as Code.
4 changes: 2 additions & 2 deletions content/blog/architecture-as-code-microservices/index.md
Expand Up @@ -27,15 +27,15 @@ Pulumi is organized around [Projects]({{< relref "/docs/intro/concepts/project"

Monolithic stacks are a common way to structure a project. A single project defines the infrastructure and resources for an entire service. However, Pulumi also supports deploying microservices as individual stacks within a project. Because microservices represent a specific business capability, having stacks for each service allows teams to work independently of each other. Separate stacks can enforce security policies through Role-Based Access Control, and each service can be built and deployed independently of other components.

Microservices deployed as stacks communicate with each other through the [StackReference]({{< relref "/docs/intro/concepts/organizing-stacks-projects#inter-stack-dependencies" >}}) resource, which makes stack exports such as networking, environmental variables, and even Kubernetes configuration available to stacks in the project. The `StackReference` constructor takes as input a string of the form `<organization>/<project>/<stack>`, and lets services access the outputs of that stack. The following section walks through a microservices example that deploys a database on AWS RDS, a REST application in AWS Fargate, and an AWS Application Load Balancer.
Microservices deployed as stacks communicate with each other through the [StackReference]({{< relref "/docs/intro/concepts/stack#stackreferences" >}}) resource, which makes stack exports such as networking, environmental variables, and even Kubernetes configuration available to stacks in the project. The `StackReference` constructor takes as input a string of the form `<organization>/<project>/<stack>`, and lets services access the outputs of that stack. The following section walks through a microservices example that deploys a database on AWS RDS, a REST application in AWS Fargate, and an AWS Application Load Balancer.

## A Microservices Application Infrastructure

We'll use the [AWS Stack Reference example](https://github.com/pulumi/examples/tree/master/aws-stackreference-architecture) to illustrate how Pulumi uses Architecture as Code to create reusable components and deployment frameworks. We’ve previously [blogged]({{< relref "/blog/architect-aws-application-infra-with-pulumi-stack-references" >}}) about this example and covered the code in some detail.

Let's examine how it creates reusable components for building out resources. First up is the [VPC class](https://github.com/pulumi/examples/blob/master/aws-stackreference-architecture/networking/src/vpc.ts) in the [networking stack](https://github.com/pulumi/examples/tree/master/aws-stackreference-architecture/networking).

In the networking service, [`vpc.ts`](https://github.com/pulumi/examples/blob/master/aws-stackreference-architecture/networking/src/vpc.ts) creates a TypeScript class that extends Pulumi [ComponentResource]({{< relref "/docs/intro/concepts/programming-model#resources" >}}). A ComponentResource abstracts one or more children that do not require custom create, read, update, and delete operations for provisioning. We can add the related resources to the correct parent to build out the class.
In the networking service, [`vpc.ts`](https://github.com/pulumi/examples/blob/master/aws-stackreference-architecture/networking/src/vpc.ts) creates a TypeScript class that extends Pulumi [ComponentResource]({{< relref "/docs/intro/concepts/resources" >}}). A ComponentResource abstracts one or more children that do not require custom create, read, update, and delete operations for provisioning. We can add the related resources to the correct parent to build out the class.

```ts
export class Vpc extends ComponentResource {
Expand Down
2 changes: 1 addition & 1 deletion content/blog/architecture-as-code-serverless/index.md
Expand Up @@ -100,7 +100,7 @@ rpa = aws.iam.RolePolicyAttachment('task-exec-policy',
)
```

To learn more about creating [reusable components]({{< relref "/docs/intro/concepts/programming-model#components" >}}), read about Pulumi's programming model, which shows how to author components.
To learn more about creating [reusable components]({{< relref "/docs/intro/concepts/resources#components" >}}), read about Pulumi's programming model, which shows how to author components.

## Polyglot applications

Expand Down
2 changes: 1 addition & 1 deletion content/blog/architecture-as-code-vm/index.md
Expand Up @@ -113,7 +113,7 @@ Now we have a virtual machine that can receive HTTP and HTTPS requests and allow

Provisioning a VM when it's created by running user-supplied scripts is relatively straightforward. For example, AWS EC2 instances have a userData parameter that allows you to specify an inline script that runs when the instance starts. But what if you need to copy and execute scripts on the virtual machine without replacing the instance?

This where you can use Pulumi’s [dynamic provider]({{< relref "/docs/intro/concepts/programming-model#dynamicproviders" >}}) to provision existing instances. Dynamic providers enable creating custom resource types, such as provisioners, within the source code of your Pulumi program. They let you execute arbitrary code during the deployment process. Dynamic provisioners run during resource provisioning, and enable adding custom logic to a deployment workflow during the create, read, update, or delete steps of a Pulumi program.
This where you can use Pulumi’s [dynamic provider]({{< relref "/docs/intro/concepts/resources#dynamicproviders" >}}) to provision existing instances. Dynamic providers enable creating custom resource types, such as provisioners, within the source code of your Pulumi program. They let you execute arbitrary code during the deployment process. Dynamic provisioners run during resource provisioning, and enable adding custom logic to a deployment workflow during the create, read, update, or delete steps of a Pulumi program.

Let's look at the code which creates a dynamic provisioner. In the code below, if Pulumi doesn't find the resource, it creates the resource. However, if you run `pulumi up` again and the resource is already running, Pulumi uses the diff method to replace the resource.

Expand Down
2 changes: 1 addition & 1 deletion content/blog/automation-api-as-platform/index.md
Expand Up @@ -24,7 +24,7 @@ This example demonstrates how to create infrastructure with Automation API and t

### Infrastructure as a function

We use an `inline` Pulumi program that doesn't require a separate package with `index.ts` and `Pulumi.yaml` files, although they can be authored in an `index.ts` file or imported from another package. The example deploys an AWS S3 website with the context and deployment automation defined in a function. Functions can be [components]({{< relref "/docs/intro/concepts/programming-model#components" >}}), in this case, a static S3 website. However, they can be more complex, such as a Kubernetes cluster with accompanying containers and AWS resources.
We use an `inline` Pulumi program that doesn't require a separate package with `index.ts` and `Pulumi.yaml` files, although they can be authored in an `index.ts` file or imported from another package. The example deploys an AWS S3 website with the context and deployment automation defined in a function. Functions can be [components]({{< relref "/docs/intro/concepts/resources#components" >}}), in this case, a static S3 website. However, they can be more complex, such as a Kubernetes cluster with accompanying containers and AWS resources.

```typescript
const projectName = "pulumi_over_http";
Expand Down
2 changes: 1 addition & 1 deletion content/blog/automation-api-workflow/index.md
Expand Up @@ -96,7 +96,7 @@ Let's break down the infrastructure piece by piece, starting with setting up con
$ aws secretsmanager create-secret --name dbpass --secret-string hellosql
```
We retrieve the secret with a function that retrieves it as a Pulumi [output]({{< relref "/docs/intro/concepts/programming-model#outputs" >}}) and returns it as a string type, which is the type that Aurora MySQL requires for the `masterpassword` property. This is a little complicated because we use the secret name to retrieve the secret properties with [`getSecret`]({{< relref "/docs/reference/pkg/aws/secretsmanager" >}}), which returns the secret ARN. Then, we use the ARN to retrieve the password with [`getSecretVersion`]({{< relref "/docs/reference/pkg/aws/secretsmanager/secretversion" >}}). Note that the function is wrapped in [`async/await`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) because we will need the password before creating the database.
We retrieve the secret with a function that retrieves it as a Pulumi [output]({{< relref "/docs/intro/concepts/inputs-outputs" >}}) and returns it as a string type, which is the type that Aurora MySQL requires for the `masterpassword` property. This is a little complicated because we use the secret name to retrieve the secret properties with [`getSecret`]({{< relref "/docs/reference/pkg/aws/secretsmanager" >}}), which returns the secret ARN. Then, we use the ARN to retrieve the password with [`getSecretVersion`]({{< relref "/docs/reference/pkg/aws/secretsmanager/secretversion" >}}). Note that the function is wrapped in [`async/await`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) because we will need the password before creating the database.
```typescript
async function getSecret(name: string) {
Expand Down
2 changes: 1 addition & 1 deletion content/blog/build-publish-containers-iac/index.md
Expand Up @@ -1873,7 +1873,7 @@ Also note the base and versioned image URLs are exported as stack outputs. These

1. As we see here, the CLI will print them after each deployment.
2. The CLI can fetch them on-demand, e.g., 'pulumi stack output fullImageName', making it easy to script access to these container images.
3. The [Pulumi `StackReference` component]({{< relref "/docs/intro/concepts/organizing-stacks-projects#inter-stack-dependencies" >}}) can be used to depend on this stack from another, allowing us to build higher levels of infrastructure that consume these images.
3. The [Pulumi `StackReference` component]({{< relref "/docs/intro/concepts/stack#stackreferences" >}}) can be used to depend on this stack from another, allowing us to build higher levels of infrastructure that consume these images.

As an example of (2) in action, let's run the image locally using the exported image name:

Expand Down
Expand Up @@ -55,7 +55,7 @@ suited in a production setup giving users more flexibility and
boundaries between their teams. We will use this structure in our
example below. For more information on Pulumi projects and stacks,
please refer to our documentation
[here]({{< relref "/docs/intro/concepts/organizing-stacks-projects" >}}).
[here]({{< relref "/docs/guides/organizing-projects-stacks" >}}).

### Use Tags to group Pulumi Stacks as Environments:

Expand Down
Expand Up @@ -309,7 +309,7 @@ You can continue adding new segments to the cleanup lambda to help cleanup your
## Deploying To Multiple Regions

We want to ensure that all of our regions are cleaned up; therefore, we need to change the structure of the code. We can
take advantage of [explicit provider configuration]({{< relref "/docs/intro/concepts/programming-model#explicit-provider-configuration" >}})
take advantage of [explicit provider configuration]({{< relref "/docs/intro/concepts/resources#explicit-provider-configuration" >}})
to allow us to target the deployment of a resource to a specific region.

Let's assume we want to deploy our application to `us-east-1`, `us-east-2`, `eu-west-1`, `eu-west-2` and `us-west-2`. We can
Expand Down
2 changes: 1 addition & 1 deletion content/blog/crossguard-2-0/index.md
Expand Up @@ -42,7 +42,7 @@ By default, the `enable` and `disable` commands use an organization's default Po

Policies now have access to more information about the resources under review. With access to the options, parent, and dependencies of a resource, you can now write even more thorough policies.

You may access a [resource's options]({{< relref "/docs/intro/concepts/programming-model#resourceoptions" >}}) via the `ResourceValidationArgs` parameter. In the below example, we enforce that all DynamoDB tables be `protected` to prevent data loss.
You may access a [resource's options]({{< relref "/docs/intro/concepts/resources#options" >}}) via the `ResourceValidationArgs` parameter. In the below example, we enforce that all DynamoDB tables be `protected` to prevent data loss.

```typescript
new PolicyPack("aws-policies", {
Expand Down