Skip to content

Commit

Permalink
Blog: IgnoreErrors and Az group command
Browse files Browse the repository at this point in the history
* Explain the new ignoreError feature in the exec mixin
* Show how developers can use this functionality to create custom
commands for this mixin.

Signed-off-by: Carolyn Van Slyck <[email protected]>
  • Loading branch information
carolynvs committed Jan 6, 2022
1 parent 1342c0c commit 2800c7c
Showing 1 changed file with 131 additions and 0 deletions.
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-10"
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.
---

When is an error not really an error?
Questions like this come up regularly when automating deployments with tooling that was designed without state in mind.
What most of us are after is to declare a resource and having our tools ensure that it exists when we need it, and to clean it up when we are done.
However, a lot of command-line tools weren't designed that way.
Calling create twice for the same resource may result in an error because it already exists.
Conversely, deleting a resource twice can trigger an error if the resource doesn't exist anymore.

This is something that mixins can help with!
The exec mixin now lets you handle errors without having to fall back to using bash.

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

## Ignore All Errors

Sometimes you want to run a command but don't really care if it fails.
Now I won't tell you what to do in production, but when debugging a bundle, this can be handy.

The snippet below will run a command, and Porter will ignore any errors returned by the command, and continue executing the next step in the action.

```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.
In the example below, the made-up thing command returns 2 when the resource already exists.
We can check for that and ignore an error when we try to create a thing that already exists.
You can ignore multiple exit codes, and if any match, then the command's error is ignored.
```yaml
install:
- exec:
description: "Ensure thing exists"
command: thing
arguments:
- create
ignoreError:
exitCodes: [2]
```
## 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.
We can use a Go regular expression to match the error message.
I recommend using [regex101.com](https://regex101.com/) to test out your regular expression with the Golang syntax enabled.
```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 new 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 out moving some of that custom error handling logic out of bash scripts and move it into your exec mixin calls.
Mixin authors, take a look at how the az mixin uses the exec mixin library to add error handling.
You can quickly add the same functionality from the exec mixin to yours, or create a custom command that manages the error handling automatically.
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.

0 comments on commit 2800c7c

Please sign in to comment.