Skip to content

Commit

Permalink
Incorporated remaining feedback, renamed and refactored content, upda…
Browse files Browse the repository at this point in the history
…ted links
  • Loading branch information
David Wrede committed Jan 20, 2021
1 parent afe29c5 commit 8bb8dc2
Show file tree
Hide file tree
Showing 14 changed files with 86 additions and 131 deletions.
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. 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" >}}), [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.
Expand Up @@ -145,7 +145,7 @@ resources to check out:
[Azure AKS](https://github.com/pulumi/examples/tree/master/azure-ts-aks-mean)
- Tutorial: [Operate and deploy to a Kubernetes cluster]({{< relref "/docs/tutorials/kubernetes/exposed-deployment" >}})
- Docs: [Pulumi docs]({{< relref "/docs/reference" >}}), including an
[overview of the programming model]({{< relref "/docs/intro/concepts/programming-model" >}})
[overview of the programming model]({{< relref "/docs/intro/concepts" >}})
- Video: In February, we were honored to have Joe Beda
[show where Pulumi fits in on his TGIK livestream](https://www.youtube.com/watch?v=ILMK65YVSKw),
highlighting how to use your favorite language and consistent workflows to create,
Expand Down
Expand Up @@ -122,7 +122,7 @@ resources to check out:
[Azure AKS](https://github.com/pulumi/examples/tree/master/azure-ts-aks-mean)
- Tutorial: [Operate and deploy to a Kubernetes cluster]({{< relref "/docs/tutorials/kubernetes/exposed-deployment" >}})
- Docs: [Pulumi docs]({{< relref "/docs/reference" >}}), including an
[overview of the programming model]({{< relref "/docs/intro/concepts/programming-model" >}})
[overview of the programming model]({{< relref "/docs/intro/concepts" >}})
- Video: [Watch Joe Beda take Pulumi for a spin in last week's TGIK](https://www.youtube.com/watch?v=ILMK65YVSKw)

As always, you can check out our code
Expand Down
2 changes: 1 addition & 1 deletion content/blog/intro-to-step-functions/index.md
Expand Up @@ -134,7 +134,7 @@ nice_fn = lambda_.Function('niceFunction',
)
```

Finally, we need to update the state machine with a new workflow that includes our new function. The state machine takes three arguments, a name, an IAM role, and the workflow as a JSON document. The code to get the ARN names is Pulumi specific and requires an explanation if you are not familiar with the [Pulumi programming model]({{< relref "/docs/intro/concepts/programming-model" >}}).
Finally, we need to update the state machine with a new workflow that includes our new function. The state machine takes three arguments, a name, an IAM role, and the workflow as a JSON document. The code to get the ARN names is Pulumi specific and requires an explanation if you are not familiar with the [Pulumi programming model]({{< relref "/docs/intro/concepts" >}}).

Instance properties of a resource are called outputs, which behave much like [promises](https://en.wikipedia.org/wiki/Futures_and_promises). This method is necessary because outputs may not be fully available until a resource is fully provisioned. To get the value of a resource, Pulumi has the `apply` method, which has a call back that receives the raw value and computes a new output. `Apply` is how we get the lambda ARN names in the workflow document. The [Output.all]({{< relref "/docs/intro/concepts/inputs-outputs" >}}) method joins a list of Outputs that we can apply to a Python lambda.

Expand Down
Expand Up @@ -63,6 +63,6 @@ Check out [Pulumi: A Better Way to Kubernetes][better-way-to-k8s] for details!
[pulumi-k8s]: https://github.com/pulumi/pulumi-kubernetes
[better-way-to-k8s]: {{< relref "pulumi-a-better-way-to-kubernetes" >}}
[create-before-replace]: {{< relref "/docs/intro/concepts/resources#autonaming" >}}
[programming-model]: {{< relref "/docs/intro/concepts/programming-model" >}}
[programming-model]: {{< relref "/docs/intro/concepts" >}}
[cluster-management]: {{< relref "/docs/tutorials/kubernetes#clusters" >}}
<!-- markdownlint-enable url -->
167 changes: 62 additions & 105 deletions content/docs/intro/concepts/_index.md
Expand Up @@ -21,34 +21,40 @@ This diagram illustrates the structure and major components of Pulumi.

![Pulumi programming model diagram.](/images/docs/pulumi-programming-model-diagram.svg)

*Programs* use existing [programming languages]({{< relref "/docs/intro/languages" >}}) to define how your cloud infrastructure should be deployed. After writing a program, you run the [Pulumi CLI]({{< relref "/docs/reference/cli" >}}) command `pulumi up`, which executes the program and determines the desired infrastructure state for all resources declared.
Pulumi *programs*, written in general-purpose [programming languages]({{< relref "/docs/intro/languages" >}}), define how your cloud infrastructure should be deployed. To declare new infrastructure in your program, you allocate *resource* objects whose properties correspond to the desired state of your infrastructure. These properties are also used between resources to handle any necessary dependencies and can be exported outside of the stack, if needed.

*Resources* represent a type of infrastructure that you declare in your program. Resources have properties that correspond to the desired state of your infrastructure and can be used as *inputs and outputs* that represent dependencies between resources.
Programs reside in a *project*, which is a directory that contains source code for the program and metadata on how to run the program. After writing your program, you run the [Pulumi CLI]({{< relref "/docs/reference/cli" >}}) command `pulumi up` from within your project directory. This command creates an isolated and configurable instance of your program, known as a *stack*. Stacks are similar to different deployment environments that you use when testing and rolling out application updates. For instance, you can have distinct development, staging, and production stacks that you create and test against.

_Stacks_ are isolated, configurable instances of a Pulumi program. Because of their isolated nature, you can think of stacks are similar to deployment environments where your Pulumi program runs.
### Example

The program, stacks, and other metadata reside in a *Project* directory.
To illustrate these concepts, the following program shows how to create an AWS EC2 security group named `web-sg` with a single ingress rule and a `t2.micro`-sized EC2 instance using that security group.

To illustrate these concepts, the following program shows how to create an AWS EC2 security group and an EC2 instance that uses it:
To use the security group, the EC2 resource requires the security group's ID. Pulumi enables this through the output property `name` on the security group resource. Pulumi understands dependencies between resources and uses the relationships between resources to maximize parallelism and ensures correct ordering when a stack is instantiated.

Finally, the server's resulting IP address and DNS name are exported as stack outputs so that their values can be accessed through either a CLI command or by another stack.

{{< chooser language "javascript,typescript,python,go,csharp" >}}

{{% choosable language javascript %}}

```javascript
let pulumi = require("@pulumi/pulumi");
let aws = require("@pulumi/aws");
"user strict";
const pulumi = require("@pulumi/pulumi");
const aws = require("@pulumi/aws");

let group = new aws.ec2.SecurityGroup("web-sg", {
const group = new aws.ec2.SecurityGroup("web-sg", {
description: "Enable HTTP access",
ingress: [{ protocol: "tcp", fromPort: 80, toPort: 80, cidrBlocks: ["0.0.0.0/0"] }],
});

let server = new aws.ec2.Instance("web-server", {
const server = new aws.ec2.Instance("web-server", {
ami: "ami-6869aa05",
instanceType: "t2.micro",
securityGroups: [ group.name ], // reference the security group resource above
vpcSecurityGroupIds: [ group.name ], // reference the security group resource above
});

export const publicIp = server.publicIp;
export const publicDns = server.publicDns;
```

{{% /choosable %}}
Expand All @@ -58,16 +64,19 @@ let server = new aws.ec2.Instance("web-server", {
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

let group = new aws.ec2.SecurityGroup("web-sg", {
const group = new aws.ec2.SecurityGroup("web-sg", {
description: "Enable HTTP access",
ingress: [{ protocol: "tcp", fromPort: 80, toPort: 80, cidrBlocks: ["0.0.0.0/0"] }],
});

let server = new aws.ec2.Instance("web-server", {
const server = new aws.ec2.Instance("web-server", {
ami: "ami-6869aa05",
instanceType: "t2.micro",
securityGroups: [ group.name ], // reference the security group resource above
vpcSecurityGroupIds: [ group.name ], // reference the security group resource above
});

export const publicIp = server.publicIp;
export const publicDns = server.publicDns;
```

{{% /choosable %}}
Expand All @@ -86,7 +95,11 @@ group = aws.ec2.SecurityGroup('web-sg',
server = aws.ec2.Instance('web-server',
ami='ami-6869aa05',
instance_type='t2.micro',
security_groups=[group.name]) # reference the security group resource above
vpc_security_group_ids=[group.name] # reference the security group resource above
)

pulumi.export('public_ip', server.public_ip)
pulumi.export('public_dns', server.public_dns)
```

{{% /choosable %}}
Expand All @@ -96,36 +109,39 @@ server = aws.ec2.Instance('web-server',
package main

import (
"github.com/pulumi/pulumi-aws/sdk/v4/go/aws/ec2"
"github.com/pulumi/pulumi/sdk/go/pulumi"
"github.com/pulumi/pulumi-aws/sdk/v3/go/aws/ec2"
"github.com/pulumi/pulumi/sdk/v2/go/pulumi"
)

func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
group, err := ec2.NewSecurityGroup(ctx, "web-sg", &ec2.SecurityGroupArgs{
Description: pulumi.String("Enable HTTP access"),
Ingress: ec2.SecurityGroupIngressArray{
ec2.SecurityGroupIngressArgs{
Protocol: pulumi.String("tcp"),
FromPort: pulumi.Int(80),
ToPort: pulumi.Int(80),
CidrBlocks: pulumi.StringArray{pulumi.String("0.0.0.0/0")},
},
},
})
if err != nil {
return err
pulumi.Run(func(ctx *pulumi.Context) error {
group, err := ec2.NewSecurityGroup(ctx, "web-sg", &ec2.SecurityGroupArgs{
Description: pulumi.String("Enable HTTP access"),
Ingress: ec2.SecurityGroupIngressArray{
ec2.SecurityGroupIngressArgs{
Protocol: pulumi.String("tcp"),
FromPort: pulumi.Int(80),
ToPort: pulumi.Int(80),
CidrBlocks: pulumi.StringArray{pulumi.String("0.0.0.0/0")},
},
},
})
if err != nil {
return err
}
server, err := ec2.NewInstance(ctx, "web-server", &ec2.InstanceArgs{
Ami: pulumi.String("ami-6869aa05"),
InstanceType: pulumi.String("t2.micro"),
VpcSecurityGroupIds: pulumi.StringArray{group.Name},
})
if err != nil {
return err
}
server, err := ec2.NewInstance(ctx, "web-server", &ec2.InstanceArgs{
Ami: pulumi.String("ami-6869aa05"),
InstanceType: pulumi.String("t2.micro"),
SecurityGroups: pulumi.StringArray{group.Name},
})
if err != nil {
return err
}
return nil
})

ctx.Export("publicIp", server.PublicIp)
ctx.Export("publicHostName", server.PublicDns)
return nil
})
}
```

Expand All @@ -143,7 +159,6 @@ class Program
static Task<int> Main() => Deployment.RunAsync<MyStack>();
}


class MyStack : Stack
{
public MyStack()
Expand All @@ -162,75 +177,17 @@ class MyStack : Stack
var server = new Instance("web-server", new InstanceArgs {
Ami = "ami-6869aa05",
InstanceType = "t2.micro",
SecurityGroups = { group.Name }
VpcSecurityGroupIds = { group.Name }
});
}
}
```

{{% /choosable %}}

{{< /chooser >}}

The two resource objects, and their properties, are used by Pulumi to perform the appropriate actions on your infrastructure. For example, Pulumi understands that you would like an EC2 security group named `web-sg`, with a single ingress rule and a `t2.micro`-sized EC2 instance running AMI `ami-8689aa05` using that security group. And because of the output properties, Pulumi also understands the dependencies between resources, which maximizes parallelism and ensures correct ordering.

When you update your cloud project with Pulumi, Pulumi will compute the desired state, compare it to the current infrastructure you already have (if any), show you the delta, and let you confirm and carry out the changes.

If needed, you can also export resulting infrastructure values to access outside your application. For example, adding the following code to the example above exports the server's resulting IP address and DNS name to either stdout or for use by another stack:

{{< chooser language "javascript,typescript,python,go,csharp" >}}

{{% choosable language javascript %}}

```javascript
// ...
module.exports = {
publicIp: server.publicIp,
publicDns: server.publicDns,
};
```

{{% /choosable %}}
{{% choosable language typescript %}}

```typescript
// ...
export let publicIp = server.publicIp;
export let publicDns = server.publicDns;
```

{{% /choosable %}}
{{% choosable language python %}}

```python
# ...
pulumi.export('public_ip', server.public_ip)
pulumi.export('public_dns', server.public_dns)
```

{{% /choosable %}}
{{% choosable language go %}}

```go
// ...
ctx.Export("publicIp", server.PublicIp)
ctx.Export("publicHostName", server.PublicDns)
return nil
})
}
```

{{% /choosable %}}
{{% choosable language csharp %}}

```csharp
// ...
this.PublicIp = server.PublicIp;
this.PublicDns = server.PublicDns;
}

[Output] Output<string> PublicIp { get; set; }
[Output] Output<string> PublicDns { get; set; }
[Output]
public Output<string> PublicIp { get; set; }

[Output]
public Output<string> PublicDns { get; set; }
}
```

Expand Down
2 changes: 1 addition & 1 deletion content/docs/intro/concepts/config.md
Expand Up @@ -11,7 +11,7 @@ aliases: ["/docs/reference/config/"]

In many cases, different stacks for a single project will need differing values. For instance, you may want to use a different size for your AWS EC2 instance, or a different number of servers for your Kubernetes cluster between your development and production stacks.

Pulumi offers a configuration system for managing such differences. Instead of hard-coding the differences, you can store and retrieve configuration values using a combination of the [CLI]({{< relref "/docs/reference/cli" >}}) and the [programming model]({{< relref "/docs/intro/concepts#programmingmodel" >}}).
Pulumi offers a configuration system for managing such differences. Instead of hard-coding the differences, you can store and retrieve configuration values using a combination of the [CLI]({{< relref "/docs/reference/cli" >}}) and the programming model.

The key-value pairs for any given stack are stored in [your project's stack settings file]({{< relref "/docs/intro/concepts/project#stack-settings-file" >}}), which is automatically named `Pulumi.<stack-name>.yaml`. You can typically ignore this file, although you may want to check it in and version it with your project source code.

Expand Down
8 changes: 6 additions & 2 deletions content/docs/intro/concepts/stack.md
Expand Up @@ -9,7 +9,7 @@ menu:
aliases: ["/docs/reference/stack/"]
---

Every Pulumi program is deployed to a **stack**. A stack is an isolated, independently [configurable]({{< relref "config" >}})
Every Pulumi program is deployed to a **stack**. A stack is an isolated, independently [configurable]({{< relref "/docs/intro/concepts/config" >}})
instance of a Pulumi program. Stacks are commonly used to denote different phases of development (such as **development**, **staging** and **production**) or feature branches (such as **feature-x-dev**, **jane-feature-x-dev**).

A project can have as many stacks as you need. By default, Pulumi creates a stack for you when you start a new project. The stack recognizes the current directory as the default name for your program.
Expand All @@ -32,7 +32,11 @@ $ pulumi stack init broomllc/staging

Fully qualified stack names also include the project name, in the form `orgName/projectName/stackName`, and this fully-qualified format is required in some contexts. In most contexts, the shorthands `orgName/stackName` or `stackName` are valid and use the default organization and the current project context.

Note that while stacks with applied configuration settings will often be accompanied by `Pulumi.<stack-name>.yaml` files, these files are not created by `pulumi stack init`. They are created and managed [with `pulumi config`]({{< relref "/docs/reference/cli/pulumi_config" >}}).
{{% notes "info" %}}
Note that while stacks with applied configuration settings will often be accompanied by `Pulumi.<stack-name>.yaml` files, these files are not created by `pulumi stack init`. They are created and managed with [`pulumi config`]({{< relref "/docs/reference/cli/pulumi_config" >}}).

For information on how to populate your stack configuration files, see [Configuration]({{< relref "/docs/intro/concepts/config" >}}).
{{% /notes %}}

## Listing stacks

Expand Down
1 change: 1 addition & 0 deletions content/docs/reference/_index.md
Expand Up @@ -13,3 +13,4 @@ This section includes all reference documentation for Pulumi.

* [API Reference]({{< relref "/docs/reference/pkg" >}}): detailed package documentation for all cloud packages and APIs
* [Pulumi CLI]({{< relref "cli" >}}): most commonly used commands, in addition to full command and flag documentation
* [Pulumi SDK Helper Functions]({{< relref "/docs/reference/sdk-helper-functions" >}}): useful helper functions in the Pulumi SDK
2 changes: 1 addition & 1 deletion content/docs/reference/cli/_index.md
Expand Up @@ -4,7 +4,7 @@ meta_desc: An overview of the Pulumi CLI and common commands used to deploy clou
menu:
reference:
identifier: cli
weight: 3
weight: 2

aliases: [/docs/reference/commands/]
---
Expand Down
2 changes: 1 addition & 1 deletion content/docs/reference/glossary.md
Expand Up @@ -3,7 +3,7 @@ title: Glossary
meta_desc: A list of common terms and their definitions relating to the Pulumi CLI and Cloud Services.
menu:
reference:
weight: 4
weight: 5
---

{{< glossary >}}

0 comments on commit 8bb8dc2

Please sign in to comment.