Skip to content

Commit

Permalink
feat(lib): helm construct (#346)
Browse files Browse the repository at this point in the history
Closes #65

This introduces a new construct that can be used to include an existing Helm chart into your constructs.
  • Loading branch information
mbonig authored Oct 19, 2020
1 parent 5413b3b commit 6ee449f
Show file tree
Hide file tree
Showing 22 changed files with 1,030 additions and 27 deletions.
4 changes: 1 addition & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: installing dependencies
run: |
pip3 install pipenv
yarn install
run: tools/install-workflow-deps.sh
- name: compile
run: |
tools/align-version.sh
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/release-next.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: installing dependencies
run: |
pip3 install pipenv
yarn install
run: tools/install-workflow-deps.sh
- run: tools/align-version.sh "-pre.${{ github.sha }}"
- run: yarn build
- run: yarn test
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: installing dependencies
run: |
pip3 install pipenv
yarn install
run: tools/install-workflow-deps.sh
- name: compile
run: |
tools/align-version.sh
Expand Down
65 changes: 65 additions & 0 deletions packages/cdk8s/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Name|Description
[Chart](#cdk8s-chart)|*No description*
[DependencyGraph](#cdk8s-dependencygraph)|Represents the dependency graph for a given Node.
[DependencyVertex](#cdk8s-dependencyvertex)|Represents a vertex in the graph.
[Helm](#cdk8s-helm)|Represents a Helm deployment.
[Include](#cdk8s-include)|Reads a YAML manifest from a file or a URL and defines all resources as API objects within the defined scope.
[Lazy](#cdk8s-lazy)|*No description*
[Names](#cdk8s-names)|Utilities for generating unique and stable names.
Expand All @@ -25,6 +26,7 @@ Name|Description
[ApiObjectOptions](#cdk8s-apiobjectoptions)|Options for defining API objects.
[AppOptions](#cdk8s-appoptions)|*No description*
[ChartOptions](#cdk8s-chartoptions)|*No description*
[HelmOptions](#cdk8s-helmoptions)|Options for `Helm`.
[IncludeOptions](#cdk8s-includeoptions)|*No description*


Expand Down Expand Up @@ -469,6 +471,44 @@ __Returns__:



## class Helm 🔹 <a id="cdk8s-helm"></a>

Represents a Helm deployment.

Use this construct to import an existing Helm chart and incorporate it into your constructs.

__Implements__: [IConstruct](#constructs-iconstruct)
__Extends__: [Include](#cdk8s-include)

### Initializer




```ts
new Helm(scope: Construct, id: string, opts: HelmOptions)
```

* **scope** (<code>[Construct](#constructs-construct)</code>) *No description*
* **id** (<code>string</code>) *No description*
* **opts** (<code>[HelmOptions](#cdk8s-helmoptions)</code>) *No description*
* **chart** (<code>string</code>) The chart name to use. It can be a chart from a helm repository or a local directory.
* **helmExecutable** (<code>string</code>) The local helm executable to use in order to create the manifest the chart. __*Default*__: "helm"
* **helmFlags** (<code>Array<string></code>) Additional flags to add to the `helm` execution. __*Default*__: []
* **releaseName** (<code>string</code>) The release name. __*Default*__: if unspecified, a name will be allocated based on the construct path
* **values** (<code>Map<string, any></code>) Values to pass to the chart. __*Default*__: If no values are specified, chart will use the defaults.



### Properties


Name | Type | Description
-----|------|-------------
**releaseName**🔹 | <code>string</code> | The helm release name.



## class Include 🔹 <a id="cdk8s-include"></a>

Reads a YAML manifest from a file or a URL and defines all resources as API objects within the defined scope.
Expand All @@ -495,6 +535,14 @@ new Include(scope: Construct, name: string, options: IncludeOptions)



### Properties


Name | Type | Description
-----|------|-------------
**apiObjects**🔹 | <code>Array<[ApiObject](#cdk8s-apiobject)></code> | Returns all the included API objects.



## class Lazy 🔹 <a id="cdk8s-lazy"></a>

Expand Down Expand Up @@ -758,6 +806,23 @@ Name | Type | Description



## struct HelmOptions 🔹 <a id="cdk8s-helmoptions"></a>


Options for `Helm`.



Name | Type | Description
-----|------|-------------
**chart**🔹 | <code>string</code> | The chart name to use. It can be a chart from a helm repository or a local directory.
**helmExecutable**?🔹 | <code>string</code> | The local helm executable to use in order to create the manifest the chart.<br/>__*Default*__: "helm"
**helmFlags**?🔹 | <code>Array<string></code> | Additional flags to add to the `helm` execution.<br/>__*Default*__: []
**releaseName**?🔹 | <code>string</code> | The release name.<br/>__*Default*__: if unspecified, a name will be allocated based on the construct path
**values**?🔹 | <code>Map<string, any></code> | Values to pass to the chart.<br/>__*Default*__: If no values are specified, chart will use the defaults.



## interface IAnyProducer 🔹 <a id="cdk8s-ianyproducer"></a>


Expand Down
83 changes: 66 additions & 17 deletions packages/cdk8s/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,9 @@ emit a single YAML manifest that includes all these objects.

## ApiObject

An `ApiObject` is a construct that represents an entry in a Kubernetes manifest.
An `ApiObject` is a construct that represents an entry in a Kubernetes manifest (level 0).
In most cases, you won't use `ApiObject` directly but rather use classes that
are generated by the cdk8s CLI and extend this base class.

are imported through `cdk8s import` and which extend this base class.

## Include

Expand All @@ -60,27 +59,25 @@ class MyChart extends Chart {
```

All API objects defined in the included manifest will be added as children
`ApiObject`s under the `Include` construct's scope. This implies that you can
use `Node.of(include).children` to inspect them.
`ApiObject`s under the `Include` construct's scope and can be accessed
through the `apiObject` property:

The following example queries for all the `Deployment` resources in the
dashboard:

```ts
const deps = Node.of(dashboard)
.children
.filter((c: ApiObject) => c.kind === 'Deployment');
const deploymentApiObject = dashboard.apiObjects.find(c => c.kind === 'Deployment);
```
NOTE: names of included objects (`metadata.name`) are preserved. This means that
if you try to include the same manifest twice into the same chart, your manifest
will have duplicate definitions of the same objects.
### Dependencies
## Dependencies
You can declare dependencies between various `cdk8s` constructs by using the built-in support of the underlying `constructs` model.
You can declare dependencies between any two cdk8s constructs using the `addDependency()` method.
#### ApiObjects
### ApiObjects
For example, you can force kubernetes to first apply a `Namespace` before applying the `Service` in the scope of that namespace:
Expand Down Expand Up @@ -108,7 +105,7 @@ metadata:
namespace: chart-backend-a59d2e47
```
#### Charts
### Charts
You can also specify dependencies between charts, in exactly the same manner. For example, if we have a chart that provisions our `namespace`, we need that chart to be applied first:
Expand All @@ -120,7 +117,7 @@ const applicationChart = new ApplicationChart(app, 'application');
applicationChart.addDependency(namespaceChart);
```
Running `cdk8s synth` will produce the following dist directory:
Running `cdk8s synth` will produce the following `dist` directory:
```console
> cdk8s synth
Expand All @@ -131,7 +128,7 @@ dist/0001-application.k8s.yaml
Notice that the `namespace` chart appears first with the `0000` prefix. This will ensure that a subsequent execution of `kubectl apply -f dist/` will apply the `namespace` first, and the `application` second.
#### Custom Constructs
### Custom Constructs
The behavior above applies in the same way to custom constructs that you create or use.
Expand Down Expand Up @@ -182,7 +179,7 @@ metadata:
You can see that all `ApiObject`s of the `Database` construct, appear before the `Service` object.
#### Things just got cool
### Things just got cool
If you simply declare a dependency between two `ApiObject`s (or `Constructs`), that belong to two different `Chart`s, `cdk8s` will create the chart dependency automatically for you.
Expand All @@ -208,15 +205,67 @@ dist/0001-application.k8s.yaml
This means you need not be bothered with managing chart dependencies, simply work with the `ApiObject`s you create, and let `cdk8s` infer the chart dependencies.
### Testing
## Helm Support
You can use the `Helm` construct in order to include [Helm](https://helm.sh)
charts.
In order to use this construct, you must have `helm` installed on your system.
See [Installing Helm](https://helm.sh/docs/intro/install/) in the Helm
documentation for details.
The following example adds the
[bitnami/redis](https://github.com/bitnami/charts/tree/master/bitnami/redis)
Helm chart with sentinel containers enabled:
> The Bitnami helm repo needs to be added through: `helm repo add bitnami https://charts.bitnami.com/bitnami`

```ts
class MyChart extends cdk8s.Chart {
constructor(scope: Construct, id: string) {
super(scope, id);
const redis = new Helm(this, 'redis', {
chart: 'bitnami/redis',
values: {
sentinel: {
enabled: true
}
}
});
}
}
```

The `Helm` construct will render the manifest from the specified chart by
executing `helm template`. If `values` is specified, these values will override
the default values included with the chart.

The `name` option can be used to specify the chart's [release name](https://helm.sh/docs/intro/using_helm/#three-big-concepts).
If not specified, a valid and unique release name will be allocated
based on the construct path.

The `Helm` construct extends `Include` and inherits it's API. For example, you
can use the `apiObjects` property to find and interact with included API
objects.

The following example shows how to add an annotation to the Redis master
deployment:

```ts
const master = redis.apiObjects.find(o => o.name === 'foo-redis-master);
master.metadata.addAnnotation('my.annotation', 'hey-there');
```

## Testing

cdk8s bundles a set of test utilities under the `Testing` class:

* `Testing.app()` returns an `App` object bound to a temporary output directory.
* `Testing.chart()` returns a `Chart` object bound to a testing app.
* `Testing.synth(chart)` returns the Kubernetes manifest synthesized from a
chart.


## License

This project is distributed under the [Apache License, Version 2.0](./LICENSE).
Expand Down
Loading

0 comments on commit 6ee449f

Please sign in to comment.