MonkeyKing
Monkey king is a tool which is initially designed for generating deployment manifests for a bosh deployment based on an existing deployment, and it could also be used for other purposes like performing functions on keys/values in yaml files based on yaml tags.
Here is some scenarios about how it works, some of these examples are in the ./fixtures/ directory:
Using secret generation
The !MK:secret(<password_length>) directive generates a random secret using [a-Z,0-9] with the length specified in the parameter.
Before:
---
meta:
secret: !MK:secret(12) replace_me
another_secret: !MK:secret replace_me
not_secret: not_secret
After:
---
meta:
secret: !MK:secret(12) SomeRandomPass
another_secret: !MK:secret() AnotherRandomPass
not_secret: not_secret
Using environment variables
The !MK:env(<variable_name>) directive pulls values from environment variables and replaces the tagged keys/values
Given:
export id1=id1_from_env
export id2=id2_from_env
Before:
---
meta1:
not_secret: not_secret
layer1:
- id1: !MK:env(id1) id1_before
- layer2:
- id2: !MK:env(id2) id2_before
- !MK:env(id1) id3: !MK:env:id1 id1_before
After:
---
meta1:
not_secret: not_secret
layer1:
- id1: !MK:env(id1) id1_from_env
- layer2:
- id2: !MK:env(id2) id2_from_env
- !MK:env(id1) id1_from_env: !MK:env:id1 id1_from_env
Using Read and Write
The !MK:read(<variable_name>) and !MK:write(<variable_name>,<value>) directive is used to save the generated value and use it later.
NOTE: at this time, reads must be ordered after writes in the YAML document until we implement a dependency graph.
Before:
---
meta:
secret: !MK:write(nat_secret,secret(12)) replace_me
same_secret_again: !MK:read(nat_secret) replace_me
After:
---
meta:
secret: !MK:write(nat_secret,secret(12)) SAME_PASSWORD_HERE
same_secret_again: !MK:read(nat_secret) SAME_PASSWORD_HERE
Using string format
The !MK:format(<variable_1>,<variable_2>,...,<string>) directive can be used to format the string given in the yaml field. This is usally used with write_value directive which store the template to a variable.
NOTE: The string literal must be defined outside of the YAML tag, as there is a limited set of allowed characters in YAML tags. See usage of nat_template in example below
Given:
export NAT_HOST=10.10.0.6
Before:
---
nat_template: write_value(TEMPLATE) https://%s
meta:
nat_url: !MK:format(env(NAT_HOST),read(TEMPLATE)) replaceme
After:
---
nat_template: write_value(TEMPLATE) https://%s
meta:
nat_url: !MK:format(env(NAT_HOST),read(TEMPLATE)) https://10.10.0.6
Combine them all
You can combine the directive in a LISP-like syntax to create more poweful usages:
Example:
Given:
export NATS_USER=nats_user
export NATS_HOST=10.10.0.6
Before:
nat_template_1: !MK:write_value(NAT_TEMPLATE_1) https://%s:%s@%s
nat_template_2: !MK:write_value(NAT_TEMPLATE_2) '%s/info'
meta1:
not_secret: not_secret
layer1:
- nat_user: !MK:write(NATS_USER,env(NATS_USER)) replaceme
- nat_host: !MK:write(NATS_HOST,env(NATS_HOST)) replaceme
- nat_password: !MK:write(NATS_PASSWORD,secret(12)) replaceme
layer2:
- nat_connection: !MK:write(NATS_STRING,format(read(NATS_USER),read(NATS_PASSWORD),read(NATS_HOST),read(NAT_TEMPLATE_1)))
- info_endpoint: !MK:format(read(NATS_STRING),read(NAT_TEMPLATE_2))
After:
---
nat_template_1: !MK:write_value(NAT_TEMPLATE_1) https://%s:%s@%s
nat_template_2: !MK:write_value(NAT_TEMPLATE_2) '%s/info'
meta1:
not_secret: not_secret
layer1:
- nat_user: !MK:write(NATS_USER,env(NATS_USER)) nats_user
- nat_host: !MK:write(NATS_HOST,env(NATS_HOST)) 10.10.0.6
- nat_password: !MK:write(NATS_PASSWORD,secret(12)) WxhUE4RoJXYF
layer2:
- nat_connection: !MK:write(NATS_STRING,format(read(NATS_USER),read(NATS_PASSWORD),read(NATS_HOST),read(NAT_TEMPLATE_1))) https://nats_user:[email protected]
- info_endpoint: !MK:format(read(NATS_STRING),read(NAT_TEMPLATE_2)) https://nats_user:[email protected]/info
Installation
Add this line to your application's Gemfile:
gem 'monkey_king'
And then execute:
$ bundle
Or install it yourself as:
$ gem install monkey_king
Or if you want the cutting edge
git clone https://github.com/pivotal-cloudops/monkey_king.git
cd monkey_king
bundle exec mk
Try it Out:
You can create a yaml file (example: demo.yml in ~/tmp) with the 'MK' yaml tags as described earlier.
Then run:
cd monkey_king
bundle exec mk demo ~/tmp/demo.yml
Full Usage
$ mk
Commands:
help [COMMAND] Help!
clone REPO DIR use MK to clone github repo and transform
replace GLOBS... Do MK transform for existing directory(ies)
demo FILE Demo MK transform for one file```
$ mk help clone
Clone the repo and replace secret and env annotation
Usage: clone REPO DIR...
Options:
--dir DIR
--repo REPO
$ mk help replace
Replace secret and env annotation for existing directory
Usage: replace GLOBS...
Options:
--globs GLOBS
Example 1: clone the repo and replace all the manifest under bosh-init directory.
$ mk clone --repo git@github.com:[USERNAME]/[DEPLOYMENT].git bosh-init
Cloning into '[DEPLOYMENT]'...
remote: Counting objects: 346, done.
remote: Total 346 (delta 0), reused 0 (delta 0), pack-reused 346
Receiving objects: 100% (346/346), 179.86 KiB | 0 bytes/s, done.
Resolving deltas: 100% (157/157), done.
Checking connectivity... done.
Transforming [DEPLOYMENT]/bosh-init/bosh-init.yml...
Done.
Example 2: replace all the manifest under bosh-init directory.
$ mk replace deployment0/bosh-init/*.yml
Transforming deployment0/bosh-init/bosh-init.yml...
Done.
Development
After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/monkey_king. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
License
The gem is available as open source under the terms of the MIT License.