Skip to content
This repository has been archived by the owner on Jan 14, 2020. It is now read-only.

Commit

Permalink
updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ojkelly committed Jun 29, 2018
1 parent c452586 commit d1e7147
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 44 deletions.
81 changes: 81 additions & 0 deletions documentation/content/api/plugin.md
@@ -0,0 +1,81 @@
+++
title = "Plugin API"
description = "Plugin API Specification"
date = "2018-06-14T00:00:00+10:00"
weight = 20
draft = false
bref = ""
toc = true
layout = "docs"
+++


## `pkg/plugins/api`

### func RegisterMapping

```go
func RegisterMapping(
mapping func(
name string,
data string,
) (cf types.TemplateObject),
) func(
name string,
data string,
) []byte
```

RegisterMapping for your plugin

### func RegisterOutput

```go
func RegisterOutput(
output func(
name string,
data string,
) (cf types.TemplateObject),
) func(
name string,
data string,
) []byte
```

RegisterOutput for your plugin

### func RegisterPlugin

```go
func RegisterPlugin(config apiTypes.Config) []byte
```

RegisterPlugin to provide the name, prefix and version, and requiresAWSSession

### func RegisterResource

```go
func RegisterResource(
resource func(
name string,
data string,
) (cf types.TemplateObject),
) func(
name string,
data string,
) []byte
```

RegisterResource for your plugin

__Usage__

```go
var Resources = map[string]func(
name string,
data string,
) []byte{
// resources.ParseLambdaFunction is explained in the next section
"Function": api.RegisterResource(resources.ParseLambdaFunction),
}
```
9 changes: 0 additions & 9 deletions documentation/content/api/plugins.md

This file was deleted.

53 changes: 53 additions & 0 deletions documentation/content/concepts/plugins.md
Expand Up @@ -6,4 +6,57 @@ weight = 20
draft = false
bref = ""
toc = true
layout = "docs"
+++

## How a plugin works

Kombustion's implementation of plugins builds upon the Go [Plugin package](https://golang.org/pkg/plugin/).

Plugins are loaded according to the `kombustion.lock` file (which is genrated from `kombustion.yaml`).

If a template uses a resource registered to a plugin, the relevant parser function is called. The
plugins parser function receives the name of the resource, and the template object as a string. It's
then up to the parser function to transform those inputs into one or more Cloudformation template objects, and
return them.

Due to the nature of Go's Plugin package, however it's not quite that simple. We need to serialise
(marshall) the input into binary before sending it to the plugin, and unserialise (unmarshall) it
on the other side. We also to the same to return the output back to `kombustion` from the plugin.

The reason for this is by design:
> A plugin cannot access the symbols of a host program.
What this means, is a plugin and it's host program must function mostly as two seperate programs. The
only information that can be transimitted between them, are types from the standard library (byte, string, func, bool).

If we try to pass a struct from the plugin to the host, the program will crash.

To get around this, `kombustion` uses an interface that abstracts all the binary marshalling away,
removing the need to write this boilerplate code in your plugin. When you call `api.RegisterResource` you're
calling a helper function, that returns another function that handles the binary marshalling.


### Cloudformation Definitions

Because plugins are compiled the version of Cloudformation definitions is frozen in time for that plugin.
This means, if a new parameter is added to a resource the plugin uses, it will be inaccessible until
the plugin is updated.

This issue is localised to the plugin, and plugins can operate with different definitions of Cloudformation
resources. This will only become problematic if Cloudformation has a breaking change, which happen rarely.

## Best Practices

To build a reliable, safe and secure plugin we have a few best practices.

### Plugins Should Be Pure

A plugin's parser functions should all be pure; they should generate the same output for the same input, and produce no side effects.

### Accessing AWS Resources in a plugin

If your plugin needs to access AWS resources during create or update, the only method you should
use are [Custom Resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html).

An example of when you may want to do this, is to get the latest AMI for a set of tags. AWS has a [walkthrough for this use case](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/walkthrough-custom-resources-lambda-lookup-amiids.html).
30 changes: 0 additions & 30 deletions documentation/content/concepts/states.md

This file was deleted.

8 changes: 4 additions & 4 deletions documentation/content/docs/getting-started.md
Expand Up @@ -30,7 +30,7 @@ You can run `kombustion -v` to confirm you have the correct version installed.
In the root directory of your repository containing your Cloudformation templates run the following to create the `kombustion.yaml` file:

```bash
// Create a new kombustion.yaml file in the current directory
# Create a new kombustion.yaml file in the current directory
$ kombustion init
```

Expand All @@ -43,7 +43,7 @@ To use a plugin you first need to add it to your project
Kombustion is fully backwards compatible with native CloudFormation templates. You can use any of your existing templates to get started, otherwise here's one to help you get started:

```yaml
// example.yaml
# example.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: "A simple SNS topic"
Resources:
Expand All @@ -58,7 +58,7 @@ Resources:
Kombustion will use the AWS CLI provided credentials location. If you already have the AWS CLI installed and have run an `aws configure`, you're good to go. If not, we can craft this file ourselves without the need to install the AWS CLI tooling. The default file location is ~/.aws/credentials and looks like the following:

```
// ~/.aws/credentials
# ~/.aws/credentials
[default]
aws_access_key_id = AKIAXXXXXXXXXXXXXX
aws_secret_access_key = xxxxxxxxxxxxxxxxxxxxxxxxxx
Expand All @@ -69,5 +69,5 @@ aws_secret_access_key = xxxxxxxxxxxxxxxxxxxxxxxxxx
The following will upsert the stack you have created when you specify the filename of the stack:

```bash
kombustion cf upsert example.yaml --stackName example-stack
kombustion upsert example.yaml
```
16 changes: 15 additions & 1 deletion documentation/content/guides/project.md
@@ -1,5 +1,5 @@
+++
title = "Projects"
title = "Project"
description = "How to setup a project"
date = "2018-06-14T00:00:00+10:00"
weight = 20
Expand All @@ -9,3 +9,17 @@ toc = true
layout = "docs"
+++

## Best Practices

A project should be a version controlled folder, with `kombustion.yaml`, `kombustion.lock` and `.kombution` all committed to version control.

When using a plugin, a template cannot be created without the plugin - to ensure you can always update your stacks, you must commit your download plugins to version control.

## Create your project

In the root directory of your repository containing your Cloudformation templates run the following to create the `kombustion.yaml` file:

```bash
# Create a new kombustion.yaml file in the current directory
$ kombustion init
```

0 comments on commit d1e7147

Please sign in to comment.