Skip to content

Commit

Permalink
Merge pull request #1893 from carolynvs/sync
Browse files Browse the repository at this point in the history
Sync release/v1 branch with main
  • Loading branch information
carolynvs authored Feb 8, 2022
2 parents f7767d0 + 5d045c5 commit 6783074
Show file tree
Hide file tree
Showing 18 changed files with 383 additions and 18 deletions.
13 changes: 8 additions & 5 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ _If there is not an existing issue, please make sure we have context on why this
_Put any questions or notes for the reviewer here._

# Checklist
- [ ] Unit Tests
- [ ] Documentation
- [ ] Schema (porter.yaml)
- [ ] Did you write tests?
- [ ] Did you write documentation?
- [ ] Did you change porter.yaml or a storage document record? Update the corresponding schema file.
- [ ] If this is your first pull request, please add your name to the bottom of our [Contributors][contributors] list. Thank you for making Porter better! 🙇‍♀️

If this is your first pull request, please add your name to the bottom of our [Contributors][contributors] list. Thank you for making Porter better! 🙇‍♀️
# Reviewer Checklist
* Comment with /azp run test-porter-release if a magefile or build script was modified
* Comment with /azp run porter-integration if it's a non-trivial PR

[contributors]: https://porter.sh/src/CONTRIBUTORS.md
[contributors]: https://porter.sh/src/CONTRIBUTORS.md
2 changes: 2 additions & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ and we will add you. **All** contributors belong here. 💯
* [Ritesh Yadav](https://github.com/DARK-art108)
* [Jérémy Audiger](https://github.com/jaudiger)
* [Om More](https://github.com/thisisommore)
* [Avinash Upadhyaya](https://github.com/avinashupadhya99)
* [Mike Barkas](https://github.com/mikebarkas)
* [Joshua Bezaleel Abednego](https://github.com/joshuabezaleel)
* [Avinash Upadhyaya](https://github.com/avinashupadhya99)
* [Mahendra Bishnoi](https://github.com/mahendrabishnoi2)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<img align="right" src="docs/static/images/porter-docs-header.svg" width="300px" />

[![Build Status](https://dev.azure.com/getporter/porter/_apis/build/status/porter-release?branchName=main)](https://dev.azure.com/getporter/porter/_build/latest?definitionId=2&branchName=main)
[![Build Status](https://dev.azure.com/getporter/porter/_apis/build/status/porter-canary?branchName=main)](https://dev.azure.com/getporter/porter/_build/latest?definitionId=26&branchName=main)

# Porter

Expand Down
36 changes: 36 additions & 0 deletions cmd/porter/completion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package main

import (
"get.porter.sh/porter/pkg/porter"
"github.com/spf13/cobra"
)

func buildCompletionCommand(p *porter.Porter) *cobra.Command {

cmd := &cobra.Command{
Use: "completion [bash|zsh|fish|powershell]",
Short: "Generate completion script",
Long: `Save the output of this command to a file and load the file into your shell.
For additional details see: https://porter.sh/install#command-completion`,
Example: "porter completion bash > /usr/local/etc/bash_completions.d/porter",
DisableFlagsInUseLine: true,
ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
Args: cobra.ExactValidArgs(1),
Run: func(cmd *cobra.Command, args []string) {
switch args[0] {
case "bash":
cmd.Root().GenBashCompletion(p.Out)
case "zsh":
cmd.Root().GenZshCompletion(p.Out)
case "fish":
cmd.Root().GenFishCompletion(p.Out, true)
case "powershell":
cmd.Root().GenPowerShellCompletionWithDesc(p.Out)
}
},
}
cmd.Annotations = map[string]string{
"group": "meta",
}
return cmd
}
29 changes: 29 additions & 0 deletions cmd/porter/completion_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package main

import (
"bytes"
"os"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestCompletion(t *testing.T) {

t.Run("completion", func(t *testing.T) {
p := buildRootCommand()

// Capture the output of the command.
var out bytes.Buffer
p.SetOut(&out)

// Run the initial completion command with a bash example.
os.Args = []string{"porter", "completion", "bash"}

err := p.Execute()
require.NoError(t, err)
// Test the output of the command contains a specific string for bash.
assert.Contains(t, out.String(), "bash completion for porter")
})
}
1 change: 1 addition & 0 deletions cmd/porter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ Try our QuickStart https://porter.sh/quickstart to learn how to use Porter.
cmd.AddCommand(buildPluginsCommands(p))
cmd.AddCommand(buildCredentialsCommands(p))
cmd.AddCommand(buildParametersCommands(p))
cmd.AddCommand(buildCompletionCommand(p))

for _, alias := range buildAliasCommands(p) {
cmd.AddCommand(alias)
Expand Down
131 changes: 131 additions & 0 deletions docs/content/blog/ignoring-errors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
---
title: "Ignoring Mixin Errors and Idempotent Actions"
description: "Porter now supports ignoring the errors from a mixin. The az mixin takes advantage of this new feature to manage resource groups."
date: "2022-01-25"
authorname: "Carolyn Van Slyck"
author: "@carolynvs"
authorlink: "https://twitter.com/carolynvs"
authorimage: "https://github.com/carolynvs.png"
tags: ["mixins"]
summary: |
Porter now supports ignoring the errors from a mixin. The az mixin takes advantage of this new feature to manage resource groups.
---

Previously, if you needed to handle an error in a bundle, you had to switch from Porter's declarative mixin syntax to a bash script.
But not anymore! The exec mixin has just added support for determining if the error returned by a command is fatal, and should stop the bundle, or if the error can be ignored.

A common scenario for ignoring errors is during the install action.
When an install fails halfway through, the user will try again by repeating the install command.
If a resource was created during the first install, repeating a command that creates a resource could result in an error because the resource already exists.
Some command-line tools handle this gracefully, while others return an error.
The exec mixin now lets you decide if that error is fatal based on the command's return code or output.

Let's take a look at a few different ways that you can handle errors from the exec mixin.

## Ignore All Errors

You can ignore all errors that are returned by a command, and continue executing the next step in the action.
This can be useful in a couple scenarios such as debugging while writing a bundle, when a command always returns a non-zero exit code, or when you want to try calling a command and keep going regardless of whether it worked.

```yaml
install:
- exec:
description: "This may not work but such is life"
command: ./buy-me-coffee.sh
ignoreError:
all: true # Ignore any errors from this command
```
## Ignore Exit Codes
Sometimes you get lucky, and the command that you are using has well-defined exit codes.
For the following example, the behavior of thing responds with the exit code [2] when the resource already exists.
```yaml
install:
- exec:
description: "Ensure thing exists"
command: thing
arguments:
- create
ignoreError:
exitCodes: [2]
```
In this example, since you don't care about the implied error as the desired outcome is the existence of resource, you configure porter to ignore the [2] exit code.
You can ignore multiple exit codes, and if any match, then the command's error is ignored.
## Ignore Output Containing a String
Usually we aren't so lucky, and we have to scrape the contents of standard error to figure out what went wrong.
Continuing our efforts to create idempotent resources, we can ignore the error when it contains "thing already exits".
```yaml
install:
- exec:
description: "Ensure thing exists"
command: thing
arguments:
- create
ignoreError:
output:
contains: ["thing already exists"]
```
## Ignore Output Matching a Regular Expression
Finally, there are times when the error message is a bit more difficult to parse, so we fall back to our favorite hammer: regular expressions.
In the example below, when we delete a thing that has already been deleted, "thing NAME not found" is printed to standard error.
Regular expressions being the tricky devils they are, I recommend using [regex101.com](https://regex101.com/) to quickly test and iterate on your regular expression.
```yaml
uninstall:
- exec:
description: "Make the thing go away"
command: thing
arguments:
- remove
ignoreError:
output:
regex: "thing (.*) not found"
```
## Create Custom Idempotent Mixin Commands
Whenever possible, I encourage you to avoid the exec mixin and use a custom mixin for the tooling that you are automating.
For example, if you are automating terraform, use the [terraform mixin](https://porter.sh/mixins/terraform/).
Mixins are meant to adapt a tool to work well inside a bundle.
I used the new ignore errors capability of the exec mixin's library to create a custom command for the [az mixin](https://porter.sh/mixins/az/).
The **group** command allows you to declare a resource group, and the mixin will handle creating it if it doesn't exist, and cleaning it up when the bundle is uninstalled.
```yaml
install:
- az:
description: "Ensure my resource group exists"
group:
name: mygroup
location: eastus2

uninstall:
- az:
description: "Remove my resource group"
group:
name: mygroup
```
These mixin commands are idempotent and handle errors automatically for you.
This lets you focus on the resources you need, and spend less time figuring out how to automate a command-line tool to work in a way it wasn't designed for.
## Try it out
Bundle authors, try moving some of that custom error handling logic out of bash scripts and into your exec mixin calls.
Mixin authors, take a look at how the [Skeletor] mixin template source [uses the get.porter.sh/porter/pkg/exec/builder package to include error handling](https://github.com/getporter/skeletor/blob/6261f95d7583d581a778d755612827d7d979e40e/pkg/skeletor/action.go#L112-L115).
You can quickly add the same error handling behavior to your mixin, or create a custom command that handles errors automatically by looking at the [source for the az group command](https://github.com/getporter/az-mixin/blob/v0.6.0/pkg/az/group.go).
Give it a try and let us know how it works for you!
If there is a mixin that you would like to use this new error handling with, let us know, and we can help make that happen more quickly.
[Skeletor]: https://github.com/getporter/skeletor
73 changes: 73 additions & 0 deletions docs/content/blog/secret-free-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
title: "Get those secrets out of your config"
description: "Learn how to keep your Porter config file secret-free"
date: "2022-02-01"
authorname: "Carolyn Van Slyck"
author: "@carolynvs"
authorlink: "https://twitter.com/carolynvs"
authorimage: "https://github.com/carolynvs.png"
tags: ["best-practices"]
summary: |
Keep sensitive data out of your Porter config files with the new variables ${env.NAME} and ${secret.KEY}
---

As part of the v1 hardening process, we have been hard at work securing Porter.
Keeping sensitive data off your machine, and safely in a secret store or vault where it belongs is a big part of that.
Now Porter's config file is getting the same white glove treatment that bundle credentials always have!
We have [added templating support to Porter's config file][cfg-docs] so that you can use environment variables and secrets without hard-coding sensitive data in the file.

[cfg-docs]: https://release-v1.porter.sh/configuration/#config-file

Porter has plugins for retrieving secrets from a secret store, and for storing its data in a Mongo database.
Configuring the plugins with credentials to connect to those resources is how sensitive data sneaks into the config file.
Let's walk through what your config file may look like today and how to take advantage of templating to keep your config file secret-free.

```toml
# ~/.porter/config.toml
default-storage = "mydb"

[[storage]]
name = "mydb"
plugin = "mongodb"

[[storage.config]]
url = "a top secret mongodb connection string"

[[secrets]]
name = "mysecrets"
plugin = "azure.keyvault"

[[secrets.config]]
vault = "myvault"
subscription-id = "my azure subscription id"
```

In the example above we have two bits of sensitive data in the config file: a mongodb connection string, and our Azure subscription id.
We can replace those hard-coded values with templates, using `${env.NAME}` to insert an environment variable and `${secret.KEY}` to resolve a secret from your default secret store. Below is the final, secret-free version of the same config file:

```toml
# ~/.porter/config.toml
default-storage = "mydb"

[[storage]]
name = "mydb"
plugin = "mongodb"

[[storage.config]]
url = "${secret.porter-connection-string}"

[[secrets]]
name = "mysecrets"
plugin = "azure.keyvault"

[[secrets.config]]
vault = "myvault"
subscription-id = "${env.AZURE_SUBSCRIPTION_ID}"
```

Porter takes two passes over the configuration file: first replacing environment variables, and then resolving any secrets used in the config file with the secrets plugin.

You may have noticed that this is a different template syntax than what is used in porter.yaml.
In an upcoming release, Porter's template syntax will get a similar refresh, so that the templating language is the same for both Porter's manifest and its configuration file.

Install the [latest v1 prerelease](https://github.com/getporter/porter/releases?q=v1.0.0) and make your config files secret-free! 🕊
40 changes: 40 additions & 0 deletions docs/content/cli/completion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
title: "porter completion"
slug: porter_completion
url: /cli/porter_completion/
---
## porter completion

Generate completion script

### Synopsis

Capture the output of the completion command to a file for your shell environment.

```
porter completion [bash|zsh|fish|powershell]
```

### Examples

```
porter completion bash > /usr/local/etc/bash_completions.d/porter
```

### Options

```
-h, --help help for completion
```

### Options inherited from parent commands

```
--debug Enable debug logging
--debug-plugins Enable plugin debug logging
```

### SEE ALSO

* [porter](/cli/porter/) - I am porter 👩🏽‍✈️, the friendly neighborhood CNAB authoring tool

1 change: 1 addition & 0 deletions docs/content/cli/porter.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ porter [flags]
* [porter archive](/cli/porter_archive/) - Archive a bundle from a reference
* [porter build](/cli/porter_build/) - Build a bundle
* [porter bundles](/cli/porter_bundles/) - Bundle commands
* [porter completion](/cli/porter_completion/) - Generate completion script
* [porter copy](/cli/porter_copy/) - Copy a bundle
* [porter create](/cli/porter_create/) - Create a bundle
* [porter credentials](/cli/porter_credentials/) - Credentials commands
Expand Down
2 changes: 1 addition & 1 deletion docs/content/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: All the magic of Porter explained

Porter is an open source project that lets you package your application artifact, client tools, configuration and deployment logic together as a versioned bundle that you can distribute, and then install with a single command.

> 🚧 This is documentation for the Porter v1 prerelease. Go to our [stable docs](https://porter.sh/docs/), if you are using a stable release of Porter (v0.38).
> This is documentation for the Porter v1 prerelease. Go to our [stable docs](https://porter.sh/docs/), if you are using a stable release of Porter (v0.38).
## Explore documentation

Expand Down
Loading

0 comments on commit 6783074

Please sign in to comment.