Skip to content

Commit

Permalink
Merge pull request #9 from mdb/improvements
Browse files Browse the repository at this point in the history
Improvements
  • Loading branch information
mdb committed Oct 17, 2019
2 parents 22b380c + 45acbf0 commit fb3d542
Show file tree
Hide file tree
Showing 14 changed files with 289 additions and 132 deletions.
38 changes: 32 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
[![Docker Automated build](https://img.shields.io/docker/automated/clapclapexcitement/concourse-consul-kv-resource.svg?style=flat)](https://hub.docker.com/r/clapclapexcitement/concourse-consul-kv-resource/)
[![Build Status](https://travis-ci.org/mdb/concourse-consul-kv-resource.svg?branch=master)](https://travis-ci.org/mdb/concourse-consul-kv-resource)


# concourse-consul-kv-resource

A [Concourse](http://concourse.ci/) resource for interacting with [Consul's KV store](https://www.consul.io/api/kv.html).

`concourse-consul-kv-resource` can be used to get or set a key in Consul's KV store.
`concourse-consul-kv-resource` can be used to get or set a key/value in Consul's KV store.

## Source configuration

* `key`: _Required_. The Consul key to interact with. Note that all URL path parts following `/v1/kv` are required. For example, if your key is `my-consul:8500/v1/kv/my/key`, then `key` should be "my/key".
* `host`: _Required_. The Consul host.
* `token`: _Required_. A Consul ACL token.
* `tls_cert`: _Required_. A TLS cert for the Consul.
* `token`: _Optional_. A Consul ACL token.
* `tls_cert`: _Optional_. A TLS cert for the Consul.
* `tls_key`: _Required_. A TLS cert key for the Consul.
* `port`: _Optional_. The port on which the Consul API is hosted. Defaults to `8500`.
* `protocol`: _Optional_. The protocol to use in calling the Consul API. Defaults to `https`.
Expand All @@ -23,7 +22,30 @@ A [Concourse](http://concourse.ci/) resource for interacting with [Consul's KV s

### `in`: Get a Consul KV key's value

Gets the value of the Consul KV key configured in the source.
Gets the value of the Consul KV key configured in the source. The key's plain text value is written to a `<resource-get>/<key-name>` file.

For example, the following pipeline's `get-my-consul-key` job writes the `foo` key's value to a `my-consul-key/my/key` file:

```yaml
...

resources:

- name: my-consul-key
type: consul-kv
source:
token: my-acl-token
host: my-consul.com
tls_cert: my-cert-string
tls_key: my-cert-key-string
key: my/key

jobs:

- name: get-my-consul-key
plan:
- get: my-consul-key
```
### `out`: Set a Consul KV key's value

Expand All @@ -38,7 +60,7 @@ Sets the Consul KV key configured in the source to the value specified in the pa

## Example pipeline

```
```yaml
resources:
- name: my-consul-key
Expand All @@ -60,6 +82,10 @@ resource_types:
jobs:
- name: get-my-consul-key
plan:
- get: my-consul-key
- name: set-my-consul-key
plan:
- put: my-consul-key
Expand Down
7 changes: 4 additions & 3 deletions assets/check.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#!/usr/bin/env node

'use strict';

const checkAction = require('./lib/check');
const handlers = require('./lib/handlers');

checkAction()
.then((result) => {
.then(result => {
handlers.success(result);
})
.catch(problem => {
handlers.fail(problem);
});
5 changes: 3 additions & 2 deletions assets/in.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#!/usr/bin/env node

'use strict';

const inAction = require('./lib/in');
const handlers = require('./lib/handlers');

inAction(process.argv[2])
.then(result => {
handlers.success(result);
})
.catch(problem => {
handlers.fail(problem);
});
32 changes: 21 additions & 11 deletions assets/lib/check.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
'use strict';

const Client = require('./client');
const handlers = require('./handlers');

function checkAction() {
return new Promise(resolve => {
return new Promise((resolve, reject) => {
process.stdin.on('data', stdin => {
let data = JSON.parse(stdin);
let source = data.source || {};
let client = new Client(source);
const data = JSON.parse(stdin);
const source = data.source || {};
const client = new Client(source);
const previousVersion = data.version && data.version.value ? data.version.value : undefined;

client.get(source.key)
.then(value => {
resolve([{
value: value.value
}]);
if (!value.value) {
reject(new Error(`${source.key} has no value`));

return;
}

if (!previousVersion || previousVersion !== value.value) {
resolve([{
value: value.value
}]);

return;
}

resolve([]);
}, rejected => {
handlers.fail(rejected);
reject(rejected);
});
});
});
Expand Down
2 changes: 0 additions & 2 deletions assets/lib/client.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use strict';

const Consul = require('consul-kv');

class Client {
Expand Down
2 changes: 0 additions & 2 deletions assets/lib/handlers.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use strict';

module.exports = {
fail: function(err) {
if (err) {
Expand Down
41 changes: 24 additions & 17 deletions assets/lib/in.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,42 @@
'use strict';

const fs = require('fs-extra');
const Client = require('./client');
const handlers = require('./handlers');

function inAction(destDir) {
return new Promise(resolve => {
return new Promise((resolve, reject) => {
process.stdin.on('data', stdin => {
let data = JSON.parse(stdin);
let source = data.source || {};
let client = new Client(source);
let file = `${destDir}/${source.key}`;
const data = JSON.parse(stdin);
const source = data.source || {};
const client = new Client(source);
const file = `${destDir}/${source.key}`;

client.get(source.key).then(value => {
fs.ensureFile(file, (err) => {
if (err) handlers.fail(err);
fs.ensureFile(file, err => {
if (err) {
reject(err);

return;
}

fs.writeFile(file, value.value, err => {
if (err) {
reject(err);

fs.writeFile(file, value.value, (err) => {
if (err) handlers.fail(err);
return;
}

resolve({
version: {
value: value.value,
// timestamp in milliseconds:
ref: Date.now().toString()
}
value: value.value
},
metadata: [{
name: 'value',
value: value.value
}]
});
});
});
}, rejected => {
handlers.fail(rejected);
reject(rejected);
});
});
});
Expand Down
36 changes: 21 additions & 15 deletions assets/lib/out.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,54 @@
'use strict';

const Client = require('./client');
const handlers = require('./handlers');
const fs = require('fs');

function getValue(params, sourceDir) {
return new Promise(resolve => {
return new Promise((resolve, reject) => {
if (params.value && params.file) {
handlers.fail(new Error('Both `file` and `value` present in params'));
reject(new Error('Both `file` and `value` present in params'));
}

if (params.file) {
fs.readFile(`${sourceDir}/${params.file}`, (err, val) => {
if (err) handlers.fail(err);
if (err) {
reject(err);

return;
}

resolve(val.toString().replace(/\n$/, ''));
});
} else {
resolve(params.value);

return;
}

resolve(params.value);
});
}

function outAction(sourceDir) {
return new Promise(resolve => {
return new Promise((resolve, reject) => {
process.stdin.on('data', stdin => {
let data = JSON.parse(stdin);
let source = data.source || {};
let client = new Client(source);
const data = JSON.parse(stdin);
const source = data.source || {};
const client = new Client(source);

getValue(data.params, sourceDir).then(value => {
client.set(source.key, value).then(() => {
resolve({
version: {
// timestamp in milliseconds:
ref: Date.now().toString()
value: value
},
metadata: [{
name: 'timestamp',
// timestamp in milliseconds:
value: Date.now().toString()
}, {
name: 'value',
value: value
}]
});
}, rejected => {
handlers.fail(rejected);
reject(rejected);
});
});
});
Expand Down
5 changes: 3 additions & 2 deletions assets/out.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#!/usr/bin/env node

'use strict';

const outAction = require('./lib/out');
const handlers = require('./lib/handlers');

outAction(process.argv[2])
.then(result => {
handlers.success(result);
})
.catch(problem => {
handlers.fail(problem);
});
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "consul-kv-resource",
"version": "0.0.8",
"version": "0.9.0",
"description": "Get and update Consul K/V from Concourse pipelines",
"author": "Mike Ball",
"scripts": {
Expand Down
Loading

0 comments on commit fb3d542

Please sign in to comment.