From b061eddac1869786fdcb4b36967e211272d25cb0 Mon Sep 17 00:00:00 2001 From: John Bellone Date: Fri, 24 Jul 2015 23:38:25 -0400 Subject: [PATCH 01/22] Merging in changes from master branch. --- .gitattributes | 7 +- .gitignore | 66 +- .kitchen.yml | 43 +- .rspec | 1 + .rubocop_todo.yml | 51 -- .travis.yml | 1 + Berksfile | 8 +- CHANGELOG.md | 13 +- Gemfile | 48 +- Guardfile | 16 + LICENSE | 5 +- README.md | 576 +----------------- Rakefile | 10 - Thorfile | 12 - Vagrantfile | 19 +- attributes/default.rb | 164 +---- cluster.rb | 39 -- libraries/consul.rb | 60 -- libraries/consul_config.rb | 147 +++++ libraries/consul_definition.rb | 56 ++ libraries/consul_service.rb | 175 ++++++ libraries/consul_ui.rb | 50 -- libraries/consul_watch.rb | 42 ++ libraries/encrypt.rb | 21 - libraries/matchers.rb | 28 +- metadata.rb | 39 +- providers/check_def.rb | 44 -- providers/event_watch_def.rb | 39 -- providers/key_watch_def.rb | 39 -- providers/service_def.rb | 47 -- providers/service_watch_def.rb | 39 -- providers/services_watch_def.rb | 18 - recipes/default.rb | 52 +- recipes/install_binary.rb | 46 -- recipes/install_packages.rb | 32 - recipes/install_source.rb | 45 -- recipes/service.rb | 306 ---------- recipes/ui.rb | 44 -- resources/check_def.rb | 56 -- resources/event_watch_def.rb | 45 -- resources/key_watch_def.rb | 46 -- resources/service_def.rb | 72 --- resources/service_watch_def.rb | 45 -- resources/services_watch_def.rb | 27 - .../cookbooks/consul_spec/metadata.rb | 3 - .../recipes/check_def_with_id_create.rb | 9 - .../recipes/check_def_with_id_delete.rb | 5 - .../recipes/check_def_without_id_create.rb | 7 - .../recipes/check_def_without_id_delete.rb | 4 - .../consul_spec/recipes/event_watch_create.rb | 4 - .../consul_spec/recipes/event_watch_delete.rb | 4 - .../consul_spec/recipes/key_watch_create.rb | 5 - .../consul_spec/recipes/key_watch_delete.rb | 4 - .../consul_spec/recipes/service_def_create.rb | 7 - .../consul_spec/recipes/service_def_delete.rb | 5 - spec/spec_helper.rb | 97 --- spec/support/matchers.rb | 35 -- spec/unit/resources/check_def_spec.rb | 65 -- spec/unit/resources/event_watch_def_spec.rb | 27 - spec/unit/resources/key_watch_def_spec.rb | 27 - spec/unit/resources/service_def_spec.rb | 26 - templates/default/consul-init.erb | 136 ----- templates/default/consul-sysconfig.erb | 1 - templates/default/consul-systemd.erb | 18 - templates/default/consul.conf.erb | 26 - templates/default/sv-consul-log-run.erb | 5 - templates/default/sv-consul-run.erb | 8 - .../{consul_spec.rb => default_spec.rb} | 0 .../default/serverspec/spec_helper.rb | 7 - .../helpers/serverspec/spec_helper.rb | 3 + .../{consul_spec.rb => default_spec.rb} | 0 test/integration/ui/serverspec/spec_helper.rb | 4 - test/spec/libraries/consul_config_spec.rb | 77 +++ test/spec/libraries/consul_service_spec.rb | 73 +++ test/spec/recipes/default_recipe.rb | 16 + test/spec/spec_helper.rb | 40 ++ 76 files changed, 866 insertions(+), 2621 deletions(-) delete mode 100644 .rubocop_todo.yml create mode 100644 Guardfile delete mode 100644 Rakefile delete mode 100644 Thorfile delete mode 100644 cluster.rb delete mode 100644 libraries/consul.rb create mode 100644 libraries/consul_config.rb create mode 100644 libraries/consul_definition.rb create mode 100644 libraries/consul_service.rb delete mode 100644 libraries/consul_ui.rb create mode 100644 libraries/consul_watch.rb delete mode 100644 libraries/encrypt.rb delete mode 100644 providers/check_def.rb delete mode 100644 providers/event_watch_def.rb delete mode 100644 providers/key_watch_def.rb delete mode 100644 providers/service_def.rb delete mode 100644 providers/service_watch_def.rb delete mode 100644 providers/services_watch_def.rb delete mode 100644 recipes/install_binary.rb delete mode 100644 recipes/install_packages.rb delete mode 100644 recipes/install_source.rb delete mode 100644 recipes/service.rb delete mode 100644 recipes/ui.rb delete mode 100644 resources/check_def.rb delete mode 100644 resources/event_watch_def.rb delete mode 100644 resources/key_watch_def.rb delete mode 100644 resources/service_def.rb delete mode 100644 resources/service_watch_def.rb delete mode 100644 resources/services_watch_def.rb delete mode 100644 spec/fixtures/cookbooks/consul_spec/metadata.rb delete mode 100644 spec/fixtures/cookbooks/consul_spec/recipes/check_def_with_id_create.rb delete mode 100644 spec/fixtures/cookbooks/consul_spec/recipes/check_def_with_id_delete.rb delete mode 100644 spec/fixtures/cookbooks/consul_spec/recipes/check_def_without_id_create.rb delete mode 100644 spec/fixtures/cookbooks/consul_spec/recipes/check_def_without_id_delete.rb delete mode 100644 spec/fixtures/cookbooks/consul_spec/recipes/event_watch_create.rb delete mode 100644 spec/fixtures/cookbooks/consul_spec/recipes/event_watch_delete.rb delete mode 100644 spec/fixtures/cookbooks/consul_spec/recipes/key_watch_create.rb delete mode 100644 spec/fixtures/cookbooks/consul_spec/recipes/key_watch_delete.rb delete mode 100644 spec/fixtures/cookbooks/consul_spec/recipes/service_def_create.rb delete mode 100644 spec/fixtures/cookbooks/consul_spec/recipes/service_def_delete.rb delete mode 100644 spec/spec_helper.rb delete mode 100644 spec/support/matchers.rb delete mode 100644 spec/unit/resources/check_def_spec.rb delete mode 100644 spec/unit/resources/event_watch_def_spec.rb delete mode 100644 spec/unit/resources/key_watch_def_spec.rb delete mode 100644 spec/unit/resources/service_def_spec.rb delete mode 100644 templates/default/consul-init.erb delete mode 100644 templates/default/consul-sysconfig.erb delete mode 100644 templates/default/consul-systemd.erb delete mode 100644 templates/default/consul.conf.erb delete mode 100644 templates/default/sv-consul-log-run.erb delete mode 100644 templates/default/sv-consul-run.erb rename test/integration/default/serverspec/localhost/{consul_spec.rb => default_spec.rb} (100%) delete mode 100644 test/integration/default/serverspec/spec_helper.rb create mode 100644 test/integration/helpers/serverspec/spec_helper.rb rename test/integration/ui/serverspec/localhost/{consul_spec.rb => default_spec.rb} (100%) delete mode 100644 test/integration/ui/serverspec/spec_helper.rb create mode 100644 test/spec/libraries/consul_config_spec.rb create mode 100644 test/spec/libraries/consul_service_spec.rb create mode 100644 test/spec/recipes/default_recipe.rb create mode 100644 test/spec/spec_helper.rb diff --git a/.gitattributes b/.gitattributes index f5bf9825..c9a5faed 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,8 @@ +Gemfile export-ignore +Berksfile export-ignore +Vagrantfile export-ignore +Thorfile export-ignore +Guardfile export-ignore +.gitattributes export-ignore .gitignore export-ignore .gitmodules export-ignore -.gitattributes export-ignore diff --git a/.gitignore b/.gitignore index fcaab8d9..78151583 100644 --- a/.gitignore +++ b/.gitignore @@ -1,22 +1,54 @@ +# Ignore docs files +_gh_pages +_site +.ruby-version +.node-version +Gemfile.lock + +# Numerous always-ignore extensions +*.diff +*.err +*.orig +*.log +*.rej +*.swo +*.swp +*.zip +*.vi *~ -*# -.#* -\#*# -.*.sw[a-z] -*.un~ -pkg/ -# Berkshelf -.vagrant -/cookbooks -Berksfile.lock +# OS or Editor folders +.DS_Store +._* +Thumbs.db +.cache +.project +.settings +.tmproj +*.esproj +nbproject +*.sublime-project +*.sublime-workspace +.idea -# Bundler -Gemfile.lock -bin/* -.bundle/* +# Komodo +*.komodoproject +.komodotools + +# grunt-html-validation +validation-status.json +validation-report.json -.kitchen/ -.kitchen.local.yml +# Folders to ignore +bin +node_modules +tmp +vendor +.bundle -coverage/ +# Chef specifics to ignore +.chef +.chefdk +.kitchen +.vagrant +Berksfile.lock diff --git a/.kitchen.yml b/.kitchen.yml index 47f61728..35385b06 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -8,22 +8,11 @@ provisioner: platforms: - name: ubuntu-14.04 - name: ubuntu-12.04 - - name: centos-7.0 - - name: centos-6.5 - - name: windows-2012r2 - driver_config: - network: - - ["forwarded_port", {guest: 5985, host: 5985}] - communicator: winrm - gui: true - box_url: https://wrock.blob.core.windows.net/vhds/vbox2012r2.box - customize: - usbehci: "off" + - name: centos-7.1 + - name: centos-6.6 suites: - name: default - excludes: - - windows-2012r2 run_list: - recipe[consul::default] attributes: @@ -33,8 +22,6 @@ suites: advertise_interface: eth0 encrypt: CGXC2NsXW4AvuB4h5ODYzQ== - name: source - excludes: - - windows-2012r2 run_list: - recipe[consul::default] attributes: @@ -53,10 +40,7 @@ suites: excludes: - centos-7.0 - centos-6.5 - - windows-2012r2 - name: runit - excludes: - - windows-2012r2 run_list: - recipe[consul::default] attributes: @@ -64,8 +48,6 @@ suites: datacenter: FortMeade init_style: runit - name: ui - excludes: - - windows-2012r2 run_list: - recipe[consul::default] - recipe[consul::ui] @@ -74,30 +56,9 @@ suites: serve_ui: true client_interface: eth0 - name: cluster - excludes: - - windows-2012r2 run_list: - recipe[consul::default] attributes: consul: service_mode: cluster bootstrap_expect: 1 - - name: atlas - excludes: - - windows-2012r2 - run_list: - - recipe[consul::default] - attributes: - consul: - atlas_autojoin: true - atlas_cluster: <%= ENV.fetch('ATLAS_CLUSTER', 'example/cluster') %> - atlas_token: <%= ENV.fetch('ATLAS_TOKEN', 'NOT_REAL') %> - - name: windows - includes: - - windows-2012r2 - run_list: - - recipe[consul::default] - attributes: - consul: - install_method: windows - service_user: vagrant diff --git a/.rspec b/.rspec index 83e16f80..2cdc09b7 100644 --- a/.rspec +++ b/.rspec @@ -1,2 +1,3 @@ --color --require spec_helper +--default-path test/spec diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml deleted file mode 100644 index 075130f4..00000000 --- a/.rubocop_todo.yml +++ /dev/null @@ -1,51 +0,0 @@ -# This configuration was generated by `rubocop --auto-gen-config` -# on 2014-07-04 11:27:45 -0400 using RuboCop version 0.24.1. -# The point is for the user to remove these configuration records -# one by one as the offenses are removed from the code base. -# Note that changes in the inspected code, or installation of new -# versions of RuboCop, may require this file to be generated again. - -# Offense count: 2 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -Style/AlignParameters: - Enabled: false - -# Offense count: 1 -Style/CyclomaticComplexity: - Max: 7 - -# Offense count: 4 -# Configuration parameters: MaxLineLength. -Style/IfUnlessModifier: - Enabled: false - -# Offense count: 1 -Style/Lambda: - Enabled: false - -# Offense count: 9 -# Configuration parameters: AllowURI. -Style/LineLength: - Max: 119 - -# Offense count: 1 -# Configuration parameters: EnforcedStyle, SupportedStyles. -Style/Next: - Enabled: false - -# Offense count: 4 -# Configuration parameters: MaxSlashes. -Style/RegexpLiteral: - Enabled: false - -# Offense count: 2 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -Style/StringLiterals: - Enabled: false - -# Offense count: 2 -# Configuration parameters: EnforcedStyleForMultiline, SupportedStyles. -Style/TrailingComma: - Enabled: false diff --git a/.travis.yml b/.travis.yml index 4faed68c..92e95513 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ language: ruby script: bin/rspec rvm: - 2.1 + - 2.2 branches: only: - master diff --git a/Berksfile b/Berksfile index 95238856..9042e42c 100644 --- a/Berksfile +++ b/Berksfile @@ -1,7 +1,3 @@ -source 'https://supermarket.getchef.com' - +source 'https://supermarket.chef.io' +cookbook 'chef-vault', git: 'https://github.com/johnbellone/chef-vault-cookbook' metadata - -group :test do - cookbook "consul_spec", path: "spec/fixtures/cookbooks/consul_spec" -end diff --git a/CHANGELOG.md b/CHANGELOG.md index 1184e28e..0fb3dc94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,4 @@ -# 0.11.1 -Minor fixes and README updates. - -# 0.11 -Minor fixes. (Actually) last release prior to 1.0.0. - -* Enhancements - - Windows support. [@gdavison](https://github.com/gdavison) - -# 0.10.1 -Minor fixes. Last major release prior to 1.0.0. +# 1.0.0 # 0.10 Fixes several bugs, minor enhancements and changes default version of @@ -33,7 +23,6 @@ Consul to 0.5.2. * Lock to Chef 11 compatible version of libarchive cookbook # 0.9.0 - * Enhancements - Adds support for publishing to statsd URL. [@akerekes](https://github.com/akerekes) - Adds support for Arch Linux. ([@logankoester](https://github.com/logankoester)) diff --git a/Gemfile b/Gemfile index 9fb0da36..07f0e559 100644 --- a/Gemfile +++ b/Gemfile @@ -1,16 +1,40 @@ source 'https://rubygems.org' -gem 'berkshelf' -gem 'rake' -gem 'rspec' -gem 'rubocop' -gem 'foodcritic' -gem 'tailor' -gem 'coveralls', require: false -gem 'stove' - -group :test, :integration do +gem 'chef-vault', '~> 2.6' + +group :lint do + gem 'rubocop' +end + +group :kitchen_common do + gem 'test-kitchen', '~> 1.4' +end + +group :kitchen_vagrant do + gem 'kitchen-vagrant', '~> 0.17' +end + +group :kitchen_cloud do + gem 'kitchen-openstack', '~> 1.8' +end + +group :unit do + gem 'berkshelf' gem 'chefspec' - gem 'test-kitchen' - gem 'kitchen-vagrant' +end + +group :integration do gem 'serverspec' end + +group :development do + gem 'guard' + gem 'guard-kitchen' + gem 'guard-rspec' + gem 'guard-rubocop' + gem 'rake' + gem 'stove' +end + +group :doc do + gem 'yard' +end diff --git a/Guardfile b/Guardfile new file mode 100644 index 00000000..2ca644c1 --- /dev/null +++ b/Guardfile @@ -0,0 +1,16 @@ +# More info at https://github.com/guard/guard#readme +guard 'rubocop' do + watch(%r{^attributes/.+\.rb$}) + watch(%r{^providers/.+\.rb$}) + watch(%r{^recipes/.+\.rb$}) + watch(%r{^resources/.+\.rb$}) + watch(%r{^libraries/.+\.rb$}) + watch('metadata.rb') +end + +guard :rspec, :cmd => 'chef exec /opt/chefdk/embedded/bin/rspec', all_on_start: false, notification: false do + watch(%r{^(recipes|libraries|providers|resources)/(.+)\.rb$}) do |m| + "test/spec/#{m[0]}/#{m[1]}_spec.rb" + end + watch('test/spec/spec_helper.rb') { 'test/spec' } +end diff --git a/LICENSE b/LICENSE index ca60bb87..4f55d866 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,4 @@ -Copyright 2014 John Bellone -Copyright 2014 Bloomberg Finance L.P. +Copyright 2014, 2015 Bloomberg Finance L.P. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -11,4 +10,4 @@ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file +limitations under the License. diff --git a/README.md b/README.md index 4e2ec945..f6e9e4c7 100644 --- a/README.md +++ b/README.md @@ -1,555 +1,37 @@ consul-cookbook =============== - [![Join the chat at https://gitter.im/johnbellone/consul-cookbook](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/johnbellone/consul-cookbook?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ![Release](http://img.shields.io/github/release/johnbellone/consul-cookbook.svg) -[![Build Status](http://img.shields.io/travis/johnbellone/consul-cookbook.svg)][5] -[![Code Coverage](http://img.shields.io/coveralls/johnbellone/consul-cookbook.svg)][6] - -Installs and configures [Consul][1] client, server and UI. +[![Build Status](http://img.shields.io/travis/johnbellone/consul-cookbook.svg)](http://travis-ci.org/johnbellone/consul-cookbook) +[![Code Coverage](http://img.shields.io/coveralls/johnbellone/consul-cookbook.svg)](https://coveralls.io/r/johnbellone/consul-cookbook) -## Supported Platforms -- CentOS 6.5, 7.0 -- RHEL 6.5, 7.0 -- Ubuntu 12.04, 14.04 -- Arch Linux -- Windows +[Application cookbook][0] which installs and configures [Consul][1]. ## Attributes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescriptionDefault
['consul']['version']StringVersion to install0.5.0
['consul']['base_url']StringBase URL for binary downloadshttps://dl.bintray.com/mitchellh/consul/
['consul']['encrypt']StringEncryption string for consul cluster.nil
['consul']['install_method']StringMethod to install consul with when using default recipe: 'binary', 'source' or 'windows' - \*nix: binary
- Windows: binary -
['consul']['choco_source']StringSource to use for fetching the chocolatey package. Defaults to the chocolatey public feedhttps://chocolatey.org/api/v2/
['consul']['install_dir']StringDirectory to install binary to. - \*nix: /usr/local/bin
- Windows: {chocolatey_install_dir}\lib\consul.{consul_version} -
['consul']['service_mode']StringMode to run consul as: bootstrap, cluster, server, or clientbootstrap
['consul']['bootstrap_expect']StringWhen bootstrapping a cluster, the number of server nodes to expect.nil
['consul']['data_dir']StringLocation to store consul's data in - \*nix: /var/lib/consul
- Windows: C:\ProgramData\consul\data -
['consul']['config_dir']StringLocation to read service definitions from (directoy will be created) - \*nix: /etc/consul.d
- Windows: C:\ProgramData\consul\config -
['consul']['etc_config_dir']StringMisc. configuration directory that might need to be execute during service start - Debian: /etc/default/consul
- Windows: {chocolatey_install_dir}\lib\consul.{consul_version}\tools
- Other: /etc/sysconfig/consul -
['consul']['servers']Array StringsConsul servers to join[]
['consul']['retry_on_join']BooleanSet to true to wait for servers to be up before try to elect a leaderfalse
['consul']['bind_addr']Stringaddress that should be bound to for internal cluster communications0.0.0.0
['consul']['datacenter']StringName of Datacenterdc1
['consul']['domain']StringDomain for service lookup dns queriesconsul
['consul']['enable_syslog']Booleanenables logging to syslognil
['consul']['log_level']String - The level of logging to show after the Consul agent has started: 'trace', 'debug', 'info', 'warn', or 'err' - info
['consul']['node_name']StringThe name of this node in the clusterhostname of the machine
['consul']['advertise_addr']Stringaddress that we advertise to other nodes in the clusterValue of bind_addr
['consul']['init_style']StringService init mode for running consul as: 'init', 'runit', 'systemd', or 'windows' - \*nix: init
- Windows: windows -
['consul']['service_user']StringFor runit/systemd service: run consul as this user (init uses 'root')consul
['consul']['service_group']StringFor runit/systemd service: run consul as this group (init uses 'root')consul
['consul']['bind_interface']String - Interface to bind to, such as 'eth1'. Sets bind_addr - attribute to the IP of the specified interface if it exists. - nil
['consul']['advertise_interface']String - Interface to advertise, such as 'eth1'. Sets advertise_addr - attribute to the IP of the specified interface if it exists. - nil
['consul']['extra_params']hash - Pass a hash of extra params to the default.json config file - {}
['consul']['encrypt_enabled']Boolean - To enable Consul gossip encryption - false
['consul']['verify_incoming']Boolean - If set to True, Consul requires that all incoming connections make use of TLS. - false
['consul']['verify_outgoing']Boolean - If set to True, Consul requires that all outgoing connections make use of TLS. - false
['consul']['key_file']String - The content of PEM encoded private key - nil
['consul']['key_file_path']String - Path where the private key is stored on the disk - /etc/consul.d/key.pem
['consul']['ca_file']String - The content of PEM encoded ca cert - nil
['consul']['ca_file_path']String - Path where ca is stored on the disk - /etc/consul.d/ca.pem
['consul']['cert_file']String - The content of PEM encoded cert. It should only contain the public key. - nil
['consul']['cert_file_path']String - Path where cert is stored on the disk - /etc/consul.d/cert.pem
['consul']['statsd_addr']StringThis provides the address of a statsd instance (UDP).nil
['consul']['atlas_autojoin']Boolean - Determines whether Consul attempts to auto-join the cluster provided by atlas_cluster using the value of atlas_token - false
['consul']['atlas_cluster']String - Name of Atlas cluster to auto-join - nil
['consul']['atlas_token']String - API token used for Atlas integration - nil
['consul']['startup_sleep']Integer - Delay to return-of-control when invoked via an init.d script. Protects consul from an early HUP. - 3
- -### Databag Attributes (optional) -Following attributes, if exist in the [encrypted databag][7], override the node attributes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyDatabag itemTypeDescription
key_file['consul']['encrypt']StringThe content of PEM encoded private key
key_file_{fqdn}['consul']['encrypt']StringNode's(identified by fqdn) unique PEM encoded private key. If it exists, it will override the databag and node key_file attribute
ca_file['consul']['encrypt']StringThe content of PEM encoded ca cert
encrypt['consul']['encrypt']StringConsul Gossip encryption key
cert_file['consul']['encrypt']StringThe content of PEM encoded cert
cert_file_{fqdn}['consul']['encrypt']StringNode's(identified by fqdn) unique PEM encoded cert. If it exists, it will override the databag and node cert_file attribute
- -### Consul UI Attributes - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescriptionDefault
['consul']['client_addr']StringAddress to bind to0.0.0.0
['consul']['client_interface']String - Interface to advertise, such as 'eth1'. Sets advertise_addr - attribute to the IP of the specified interface if it exists. - nil
['consul']['serve_ui']BooleanDetermines whether the consul service also serve's the UIfalse
- -## Usage -The easiest way to bootstrap a cluster is to use the cluster recipe -and use [Chef provisioning][8] which is a relatively new -extension. This extension allows you to use any driver and easily -stand up a cluster. Once the [Chef Development Kit][9] has been -installed you can run the following command to provision a cluster. - -```ruby -gem install chef-provisioning chef-provisioning-fog -export CHEF_DRIVER=fog:AWS -chef-client -z cluster.rb -``` - -Please follow the [Chef provisioning README][10] which provides more -detailed information about provisioning. You'll need to configure -your credentials prior to provisioning. - -### consul::default -The default recipe will install the Consul agent using the -`consul::install_binary` recipe. It will also configure and -start consul at the machine boot. - -### consul::install_binary -If you only wish to simply install the binary from the official -mirror you simply include `consul::install_binary` in your node's -`run_list`: - -```json -{ - "run_list": [ - "recipe[consul::install_binary]" - ] -} -``` - -### consul::install_source -Instead if you wish to install Consul from source you simply need -to include `consul::install_source` in your node's `run_list`. This -will also configure the Go language framework on the node to build -the application. - -```json -{ - "run_list": [ - "recipe[consul::install_source]" - ] -} -``` - -### consul::ui -Installing the separate Consul UI simply requires you to include -the `consul::ui` recipe in your node's `run_list`. Consul UI is not supported -on Windows platform. - -```json -{ - "run_list": [ - "recipe[consul::ui]" - ] -} -``` - -### LWRP - -##### Adding key watch - consul_key_watch_def 'key-watch-name' do - key "/key/path" - handler "chef-client" - end - - -##### Adding event watch - consul_event_watch_def 'event-name' do - handler "chef-client" - end - -##### Adding services watch - consul_services_watch_def 'services-name' do - handler "chef-client" - end - -##### Adding service watch - consul_service_watch_def 'service-name' do - passingonly true - handler "chef-client" - end - -##### Adding service without check - - consul_service_def 'voice1' do - port 5060 - tags ['_sip._udp'] - notifies :reload, 'service[consul]' - end - -##### Adding services with checks - - consul_service_def 'voice1' do - port 5060 - tags ['_sip._udp'] - check( - interval: '10s', - script: 'echo ok' - ) - notifies :reload, 'service[consul]' - end - - consul_service_def 'server1' do - port 80 - tags ['http'] - check( - interval: '10s', - http: 'http://localhost:80' - ) - notifies :reload, 'service[consul]' - end - -##### Removing service - - consul_service_def 'voice1' do - action :delete - notifies :reload, 'service[consul]' - end - -> Be sure to notify the Consul resource to restart when your service def changes. - -#### Getting Started - -To bootstrap a consul cluster follow the following steps: - 0. Make sure that ports 8300-8302 (by default, if you configured different ones open those) UDP/TCP are all open. - 1. Bootstrap a few (preferablly 3 nodes) to be your consul servers, these will be the KV masters. - 2. Put `node['consul']['servers'] =["Array of the bootstrapped servers ips or dns names"]` in your environment. - 3. Apply the consul cookbook to these nodes with `node['consul']['service_mode'] = 'cluster'` (I put this in this in a CONSUL_MASTER role). - 4. Let these machines converge, once you can run `consul members` and get a list of all of the servers your ready to move on - 5. Apply the consul cookbook to the rest of your nodes with `node['consul']['service_mode'] = 'client'` (I put this in the environment) - 6. Start adding services and checks to your cookbooks. - 7. If you want to get values out of consul to power your chef, curl localhost:8500/v1/kv/key/path?raw in your cookbook. - -## Authors - -Created and maintained by [John Bellone][3] [@johnbellone][2] () and a growing community of [contributors][4]. - +This cookbook provides node attributes which can be used to fine tune +how the recipes install and configure the Consul client, server and +UI. These values are passed into the resource/providers for +validation prior to converging. + +| Key | Type | Description | Default | +|---------|--------|----------------|-----------| +| ['consul']['version'] | String | Installation version | 0.5.1 | +| ['consul']['remote_url'] | String | Remote URL for download. | https://dl.bintray.com/mitchellh/consul | +| ['consul']['service_name'] | String | Name of the service (operating system) | consul | +| ['consul']['service_user'] | String | Name of the service user | consul | +| ['consul']['service_group'] | String | Name of the service group | consul | + +## Resources/Providers +This cookbook provides resource and provider primitives to manage the +Consul client, server and UI. These primitives are what is used in the +recipes, and should be used in your own [wrapper cookbooks][2]. + +### consul_client +### consul_config +### consul_service +### consul_watch +### consul_definition + +[0]: http://blog.vialstudios.com/the-environment-cookbook-pattern/#theapplicationcookbook [1]: http://consul.io -[2]: https://twitter.com/johnbellone -[3]: https://github.com/johnbellone -[4]: https://github.com/johnbellone/consul-cookbook/graphs/contributors -[5]: http://travis-ci.org/johnbellone/consul-cookbook -[6]: https://coveralls.io/r/johnbellone/consul-cookbook -[7]: https://docs.getchef.com/essentials_data_bags.html -[8]: https://github.com/opscode/chef-provisioning -[9]: https://github.com/opscode/chef-dk -[10]: https://github.com/opscode/chef-provisioning/blob/master/README.md +[2]: http://blog.vialstudios.com/the-environment-cookbook-pattern#thewrappercookbook diff --git a/Rakefile b/Rakefile deleted file mode 100644 index a483f66f..00000000 --- a/Rakefile +++ /dev/null @@ -1,10 +0,0 @@ -require 'rspec/core/rake_task' -require 'stove/rake_task' - -Stove::RakeTask.new - -RSpec::Core::RakeTask.new(:test) do |t| - t.pattern = 'spec/**/*_spec.rb' -end - -task default: :spec diff --git a/Thorfile b/Thorfile deleted file mode 100644 index b23ee163..00000000 --- a/Thorfile +++ /dev/null @@ -1,12 +0,0 @@ -# encoding: utf-8 - -require 'bundler' -require 'bundler/setup' -require 'berkshelf/thor' - -begin - require 'kitchen/thor_tasks' - Kitchen::ThorTasks.new -rescue LoadError - puts ">>>>> Kitchen gem not loaded, omitting tasks" unless ENV['CI'] -end diff --git a/Vagrantfile b/Vagrantfile index 13c92636..46b63468 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -1,22 +1,15 @@ Vagrant.configure('2') do |config| - # Set the version of chef to install using the vagrant-omnibus plugin - config.omnibus.chef_version = :latest - - # Enabling the Berkshelf plugin. To enable this globally, add this configuration - # option to your ~/.vagrant.d/Vagrantfile file config.berkshelf.enabled = true + config.omnibus.chef_version = :latest - # Every Vagrant virtual environment requires a box to build off of. - config.vm.box = 'opscode-ubuntu-12.04' - - # The url from where the 'config.vm.box' box will be fetched if it - # doesn't already exist on the user's system. - config.vm.box_url = "https://opscode-vm-bento.s3.amazonaws.com/vagrant/opscode_ubuntu-12.04_provisionerless.box" + config.vm.box = ENV.fetch('VAGRANT_VM_BOX', 'opscode-ubuntu-14.04') + config.vm.box_url = ENV.fetch('VAGRANT_VM_BOX_URL', 'https://opscode-vm-bento.s3.amazonaws.com/vagrant/opscode_ubuntu-14.04_provisionerless.box') config.vm.define :bootstrap, primary: true do |guest| guest.vm.network :private_network, ip: '172.16.38.10' - guest.vm.provision :chef_solo do |chef| - chef.run_list = ['recipe[consul::default]', 'recipe[consul::ui]'] + guest.vm.provision :chef_zero do |chef| + chef.nodes_path = File.expand_path('../.vagrant/chef/nodes', __FILE__) + chef.run_list = %w(recipe[consul::default]) end end end diff --git a/attributes/default.rb b/attributes/default.rb index b242952d..8025c88e 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -1,54 +1,39 @@ # -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. +# Cookbook: consul +# License: Apache 2.0 # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright 2014, 2015 Bloomberg Finance L.P. # -default['consul']['base_url'] = "https://dl.bintray.com/mitchellh/consul/%{version}.zip" -default['consul']['version'] = '0.5.2' -if node['platform_family'] == 'windows' - default['consul']['version'] = '0.5.0' -end -default['consul']['install_method'] = 'binary' -default['consul']['install_dir'] = '/usr/local/bin' -default['consul']['choco_source'] = "https://chocolatey.org/api/v2/" - -default['consul']['checksums'] = { - '0.3.0_darwin_amd64' => '9dfbc70c01ebbc3e7dba0e4b31baeddbdcbd36ef99f5ac87ca6bbcc7405df405', - '0.3.0_linux_386' => '2513496374f8f15bda0da4da33122e93f82ce39f661ee3e668c67a5b7e98fd5f', - '0.3.0_linux_amd64' => 'da1337ab3b236bad19b791a54a8df03a8c2a340500a392000c21608696957b15', - '0.3.0_web_ui' => '0ab215e6aa7c94ccdb2c074732b8706940d37386b88c9421f1e4bc2501065476', - '0.3.0_windows_386' => '5d42e143eeb7c348ed8f7e15c6223e02ce0221dc0e076d15c8e6bdf88c8cd5d2', +default['consul']['service_name'] = 'consul' +default['consul']['service_user'] = 'consul' +default['consul']['service_group'] = 'consul' - '0.3.1_darwin_amd64' => 'e310d54244b207702143f1667d61bf0147d1bd656a29496d8b58eea07078d1dc', - '0.3.1_linux_386' => '9b8340fdf464a99fc9dc108115602c761b703a16277fbd9f4f164123cf2a9f11', - '0.3.1_linux_amd64' => 'c33da8ac24f01eefe8549e8d4d301b4e18a71b61f06ae1377a88ccd6eab2cfbb', - '0.3.1_web_ui' => 'd8982803fffb84d3202260161f6310bd6bddb5b12bf690cf00210cd659a31ddd', - '0.3.1_windows_386' => '102bda6e02b193a9417e80795875bf7d18259fc5daff3d048d274beef690eb26', +default['consul']['bag_name'] = 'secrets' +default['consul']['bag_item'] = 'consul' - '0.4.0_darwin_amd64' => '87a1b0f37e773d92c939ca7dd6a50985acc4fb4aaec31384756ef896aef4035b', - '0.4.0_linux_386' => 'e2d494654cfed1b9248734f5cb9d34dba9f356dffdcc8a09ab0ab85d170dba7c', - '0.4.0_linux_amd64' => '4f8cd1cc5d90be9e1326fee03d3c96289a4f8b9b6ccb062d228125a1adc9ea0c', - '0.4.0_windows_386' => '895387de34352f29e8cb91066b44750a958d4a44a88ac39e164cf9c62b521b08', - '0.4.0_web_ui' => '0ee574e616864b658ba6ecf16db1183b63c5a4a36401880fb0404a2ea18536a6', +default['consul']['config']['data_dir'] = '/var/lib/consul' +default['consul']['config']['ca_file'] = '/etc/ssl/CA/consul.crt' +default['consul']['config']['cert_file'] = '/etc/ssl/certs/consul.crt' +default['consul']['config']['client_addr'] = '0.0.0.0' +default['consul']['config']['key_file'] = '/etc/ssl/private/consul.key' +default['consul']['config']['ports'] = { + 'dns' => 8600, + 'http' => 8500, + 'rpc' => 8400, + 'serf_lan' => 8301, + 'serf_wan' => 8302, + "server" => 8300, +} - '0.4.1_darwin_amd64' => '957fe9ba27bbaf99539cd534db8ac8ec4c9fa1c6b3b4675d0c0eb3a7fbfb646c', - '0.4.1_linux_386' => 'a496d6fd8ff5b460aea50be5d20fbd95cb5d30e9018259a0540273a17fae1c25', - '0.4.1_linux_amd64' => '2cf6e59edf348c3094c721eb77436e8c789afa2c35e6e3123a804edfeb1744ac', - '0.4.1_windows_386' => '61906f5d73a0d991dae5d75a25299f183670efa473cd155c715eefc98ce49cc8', - '0.4.1_web_ui' => 'e02929ed44f5392cadd5513bdc60b7ab7363d1670d59e64d2422123229962fa0', +default['consul']['service']['install_method'] = :binary +default['consul']['service']['config_file'] = '/etc/consul.json' +default['consul']['service']['config_dir'] = '/etc/consul.d' +default['consul']['binary_url'] = "https://dl.bintray.com/mitchellh/consul/%{filename}.zip" +default['consul']['source_url'] = 'https://github.com/hashicorp/consul' +default['consul']['version'] = '0.5.2' +default['consul']['checksums'] = { '0.5.0_darwin_amd64' => '24d9758c873e9124e0ce266f118078f87ba8d8363ab16c2e59a3cd197b77e964', '0.5.0_linux_386' => '4b6147c30596a30361d4753d409f8a1af9518f54f5ed473a4c4ac973738ac0fd', '0.5.0_linux_amd64' => '161f2a8803e31550bd92a00e95a3a517aa949714c19d3124c46e56cfdc97b088', @@ -67,96 +52,3 @@ '0.5.2_windows_386' => '2e866812de16f1a6138a0fd1eebc76143f1314826e3b52597a55ac510ae94be6', '0.5.2_web_ui' => 'ad883aa52e1c0136ab1492bbcedad1210235f26d59719fb6de3ef6464f1ff3b1', } -default['consul']['source_revision'] = 'master' -default['consul']['use_packagecloud_repo'] = true - -# Service attributes -default['consul']['service_mode'] = 'bootstrap' -default['consul']['retry_on_join'] = false - -# In the cluster mode, set the default cluster size to 3 -default['consul']['bootstrap_expect'] = 3 -default['consul']['data_dir'] = '/var/lib/consul' -default['consul']['config_dir'] = '/etc/consul.d' -default['consul']['logfile'] = '/var/log/consul.log' -default['consul']['init_style'] = 'init' # 'init', 'runit', 'systemd' -case node['platform_family'] -when 'windows' - default['consul']['install_method'] = 'windows' - default['consul']['init_style'] = 'windows' - default['consul']['config_dir'] = "#{ENV['SystemDrive']}\\ProgramData\\consul\\config" - default['consul']['data_dir'] = "#{ENV['SystemDrive']}\\ProgramData\\consul\\data" - default['consul']['install_dir'] = "#{ChocolateyHelpers.chocolatey_install}\\lib\\consul.#{node['consul']['version']}" - default['consul']['etc_config_dir'] = "#{ChocolateyHelpers.chocolatey_install}\\lib\\consul.#{node['consul']['version']}\\tools" -when 'debian' - default['consul']['etc_config_dir'] = '/etc/default/consul' -when 'rhel' - default['consul']['etc_config_dir'] = '/etc/sysconfig/consul' -else - default['consul']['etc_config_dir'] = '/etc/sysconfig/consul' -end - -default['consul']['servers'] = [] - -case node['consul']['init_style'] -when 'runit' || 'systemd' - default['consul']['service_user'] = 'consul' - default['consul']['service_group'] = 'consul' -when 'windows' - default['consul']['service_user'] = 'Administrator' - default['consul']['service_group'] = 'Administrators' -else - default['consul']['service_user'] = 'root' - default['consul']['service_group'] = 'root' -end -default['consul']['system_account'] = false - -default['consul']['ports'] = { - 'dns' => 8600, - 'http' => 8500, - 'rpc' => 8400, - 'serf_lan' => 8301, - 'serf_wan' => 8302, - "server" => 8300, -} - -# Ubuntu Upstart Open Files Limit -default['consul']['files_soft_limit'] = 2048 -default['consul']['files_hard_limit'] = 4096 - -# Consul DataBag -default['consul']['data_bag'] = 'consul' -default['consul']['data_bag_encrypt_item'] = 'encrypt' - -# Gossip encryption -default['consul']['encrypt_enabled'] = false -default['consul']['encrypt'] = nil -# TLS support -default['consul']['verify_incoming'] = false -default['consul']['verify_outgoing'] = false -# Cert in pem format -default['consul']['ca_cert'] = nil -default['consul']['ca_path'] = "%{config_dir}/ca.pem" -default['consul']['cert_file'] = nil -default['consul']['cert_path'] = "%{config_dir}/cert.pem" -# Cert in pem format. It can be unique for each host -default['consul']['key_file'] = nil -default['consul']['key_file_path'] = "%{config_dir}/key.pem" - -# Optionally bind to a specific interface -default['consul']['bind_interface'] = nil -default['consul']['advertise_interface'] = nil -default['consul']['client_interface'] = nil - -# UI attributes -default['consul']['client_addr'] = '0.0.0.0' -default['consul']['serve_ui'] = false -default['consul']['extra_params'] = {} - -# Atlas support -default['consul']['atlas_autojoin'] = false -default['consul']['atlas_cluster'] = nil -default['consul']['atlas_token'] = nil - -# Init script startup delay -default['consul']['startup_sleep'] = 3 diff --git a/cluster.rb b/cluster.rb deleted file mode 100644 index 12a515af..00000000 --- a/cluster.rb +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -include_recipe 'chef-provisioning::default' - -num_quorum = ENV.fetch('CONSUL_QUORUM', 3) - -batch = machine_batch do - 1.upto(num_quorum).each do |index| - machine "consul-#{index}" do - recipe 'consul::default' - attributes(consul: { service_mode: 'cluster' }) - end - end -end - -include_recipe 'chef-sugar::default' -node.default['consul']['servers'] = batch.machines.each { |m| best_ip_for(m.node) } - -machine 'consul-ui' do - recipe 'consul::ui' - attributes(consul: { - service_mode: 'client', - servers: node['consul']['servers'] - }) -end diff --git a/libraries/consul.rb b/libraries/consul.rb deleted file mode 100644 index ca59249e..00000000 --- a/libraries/consul.rb +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright 2014-2015 John Bellone -# Copyright 2014-2015 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the 'License'); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an 'AS IS' BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -class Chef - module Consul - class << self - def active_binary(node) - File.join(node['consul']['install_dir'], 'consul') - end - - def cached_archive(node) - File.join(Chef::Config[:file_cache_path], File.basename(remote_url(node))) - end - - def latest_binary(node) - File.join(install_path(node), 'consul') - end - - def remote_checksum(node) - node['consul']['checksums'].fetch(remote_filename(node)) - end - - def remote_filename(node) - [node['consul']['version'], node['os'], arch(node)].join('_') - end - - def remote_url(node) - node['consul']['base_url'] % { version: remote_filename(node) } - end - - def source_binary(node) - File.join(node['go']['gobin'], 'consul') - end - - def install_path(node) - File.join(['/opt', 'consul', node['consul']['version']]) - end - - private - - def arch(node) - node['kernel']['machine'] =~ /x86_64/ ? 'amd64' : '386' - end - end - end -end diff --git a/libraries/consul_config.rb b/libraries/consul_config.rb new file mode 100644 index 00000000..9910362f --- /dev/null +++ b/libraries/consul_config.rb @@ -0,0 +1,147 @@ +# +# Cookbook: consul +# License: Apache 2.0 +# +# Copyright (C) 2014, 2015 Bloomberg Finance L.P. +# +require 'poise' + +class Chef::Resource::ConsulConfig < Chef::Resource + include Poise(fused: true) + provides(:consul_config) + actions(:create, :delete) + + # @!attribute path + # @return [String] + attribute(:path, kind_of: String, name_attribute: true) + + # @!attribute owner + # @return [String] + attribute(:user, kind_of: String, default: 'consul') + + # @!attribute group + # @return [String] + attribute(:group, kind_of: String, default: 'consul') + + # @see: http://www.consul.io/docs/agent/options.html + attribute(:acl_datacenter, kind_of: String) + attribute(:acl_default_policy, kind_of: String) + attribute(:acl_down_policy, kind_of: String) + attribute(:acl_master_token, kind_of: String) + attribute(:acl_token, kind_of: String) + attribute(:acl_ttl, kind_of: String) + attribute(:addresses, kind_of: [Hash, Mash]) + attribute(:advertise_addr, kind_of: String) + attribute(:bind_addr, kind_of: String) + attribute(:bootstrap, equal_to: [true, false], default: false) + attribute(:bootstrap_expect, kind_of: Integer, default: 3) + attribute(:ca_file, kind_of: String) + attribute(:cert_file, kind_of: String) + attribute(:check_update_interval, kind_of: String) + attribute(:client_addr, kind_of: String) + attribute(:data_dir, kind_of: String) + attribute(:datacenter, kind_of: String) + attribute(:disable_anonymous_signature, equal_to: [true, false], default: false) + attribute(:disable_remote_exec, equal_to: [true, false], default: false) + attribute(:disable_update_check, equal_to: [true, false], default: false) + attribute(:dns_config, kind_of: [Hash, Mash]) + attribute(:domain, kind_of: String) + attribute(:enable_debug, equal_to: [true, false], default: false) + attribute(:enable_syslog, equal_to: [true, false], default: false) + attribute(:encrypt, kind_of: String) + attribute(:key_file, kind_of: String) + attribute(:leave_on_terminate, equal_to: [true, false], default: false) + attribute(:log_level, equal_to: %w(INFO DEBUG WARN), default: 'INFO') + attribute(:node_name, kind_of: String) + attribute(:ports, kind_of: [Hash, Mash]) + attribute(:protocol, kind_of: String) + attribute(:recurser, kind_of: String) + attribute(:retry_interval, kind_of: Integer) + attribute(:server, equal_to: [true, false], default: true) + attribute(:server_name, kind_of: String) + attribute(:skip_leave_on_interrupt, equal_to: [true, false], default: false) + attribute(:start_join, kind_of: Array) + attribute(:statsd_addr, kind_of: String) + attribute(:statsite_addr, kind_of: String) + attribute(:syslog_facility, kind_of: String) + attribute(:ui_dir, kind_of: String) + attribute(:verify_incoming, equal_to: [true, false], default: false) + attribute(:verify_outgoing, equal_to: [true, false], default: false) + attribute(:watches, kind_of: [Hash, Mash], default: {}) + + # Transforms the resource into a JSON format which matches the + # Consul service's configuration format. + def to_json + for_keeps = %i{acl_datacenter acl_default_policy acl_down_policy acl_master_token acl_token acl_ttl addresses advertise_addr bind_addr bootstrap bootstrap_expect ca_file cert_file check_update_interval client_addr data_dir datacenter disable_anonymous_signature disable_remote_exec disable_update_check dns_config domain enable_debug enable_syslog encrypt key_file leave_on_terminate log_level node_name ports protocol recurser retry_interval server server_name skip_leave_on_interrupt start_join statsd_addr statsite_addr syslog_facility ui_dir verify_incoming verify_outgoing watches} + config = to_hash.keep_if do |k, v| + for_keeps.include?(k.to_sym) + end + JSON.pretty_generate(config, quirks_mode: true) + end + + def tls? + verify_incoming || verify_outgoing + end + + action(:create) do + notifying_block do + if new_resource.tls? + include_recipe 'chef-vault::default' + + directory ::File.dirname(new_resource.ca_file) do + recursive true + end + + item = chef_vault_item(node['consul']['bag_name'], node['consul']['bag_item']) + file new_resource.ca_file do + content item['ca_certificate'] + mode '0644' + owner new_resource.user + group new_resource.group + end + + directory ::File.dirname(new_resource.cert_file) do + recursive true + end + + file new_resource.cert_file do + content item['certificate'] + mode '0644' + owner new_resource.user + group new_resource.group + end + + directory ::File.dirname(new_resource.key_file) do + recursive true + end + + file new_resource.key_file do + sensitive true + content item['private_key'] + mode '0644' + owner new_resource.user + group new_resource.group + end + end + + directory ::File.dirname(new_resource.path) do + recursive true + end + + file new_resource.path do + owner new_resource.user + group new_resource.group + content new_resource.to_json + mode '0644' + end + end + end + + action(:delete) do + notifying_block do + file new_resource.path do + action :delete + end + end + end +end diff --git a/libraries/consul_definition.rb b/libraries/consul_definition.rb new file mode 100644 index 00000000..97397e37 --- /dev/null +++ b/libraries/consul_definition.rb @@ -0,0 +1,56 @@ +# +# Cookbook: consul +# License: Apache 2.0 +# +# Copyright (C) 2014, 2015 Bloomberg Finance L.P. +# +require 'poise' + +class Chef::Resource::ConsulDefinition < Chef::Resource + include Poise(fused: true) + provides(:consul_definition) + actions(:create, :delete) + + # @!attribute path + # @return [String] + attribute(:path, kind_of: String, name_attribute: true) + + # @!attribute id + # @return [String, NilClass] + attribute(:id, kind_of: String) + + # @!attribute user + # @return [String] + attribute(:user, kind_of: String, default: 'consul') + + # @!attribute group + # @return [String] + attribute(:group, kind_of: String, default: 'consul') + + def to_json + for_keeps = %i{} + config = to_hash.keep_if do |k, v| + for_keeps.include?(k.to_sym) + end + JSON.pretty_generate(config, quirks_mode: true) + end + + action(:create) do + notifying_block do + file new_resource.path do + content new_resource.to_json + user new_resource.user + group new_resource.group + mode '0600' + end + end + end + + action(:delete) do + notifying_block do + file new_resource.path do + action :delete + end + end + end +end diff --git a/libraries/consul_service.rb b/libraries/consul_service.rb new file mode 100644 index 00000000..2a549f1a --- /dev/null +++ b/libraries/consul_service.rb @@ -0,0 +1,175 @@ +# +# Cookbook: consul +# License: Apache 2.0 +# +# Copyright (C) 2014, 2015 Bloomberg Finance L.P. +# +require 'poise_service/service_mixin' + +# Resource for managing the Consul service on an instance. +# @since 1.0.0 +class Chef::Resource::ConsulService < Chef::Resource + provides(:consul_service) + include PoiseService::ServiceMixin + + # @!attribute service_name + # @return [String] + attribute(:service_name, kind_of: String, name_attribute: true) + + # @!attribute version + # @return [String] + attribute(:version, kind_of: String, required: true) + + # @!attribute install_method + # @return [Symbol] + attribute(:install_method, default: :binary, equal_to: %i{source binary package}) + + # @!attribute install_path + # @return [String] + attribute(:install_path, kind_of: String, default: '/srv') + + # @!attribute config_filename + # @return [String] + attribute(:config_file, kind_of: String, default: '/etc/consul.json') + + # @!attribute user + # @return [String] + attribute(:user, kind_of: String, default: 'consul') + + # @!attribute group + # @return [String] + attribute(:group, kind_of: String, default: 'consul') + + # @!attribute environment + # @return [String] + attribute(:environment, kind_of: Hash, default: lazy { default_environment }) + + # @!attribute package_name + # @return [String] + attribute(:package_name, kind_of: String, default: 'consul') + + # @!attribute binary_url + # @return [String] + attribute(:binary_url, kind_of: String) + + # @!attribute source_url + # @return [String] + attribute(:source_url, kind_of: String) + + # @!attribute data_dir + # @return [String] + attribute(:data_dir, kind_of: String, default: '/var/lib/consul') + + # @!attribute config_dir + # @return [String] + attribute(:config_dir, kind_of: String, default: '/etc/consul.d') + + def default_environment + { GOMAXPROCS: [node['cpu']['total'], 2].max, PATH: '/usr/local/bin:/usr/bin:/bin' } + end + + def command + "consul agent -config-file=#{config_file} -config-dir=#{config_dir}" + end + + def binary_checksum + node['consul']['checksums'].fetch(binary_filename) + end + + def binary_filename + arch = node['kernel']['machine'] =~ /x86_64/ ? 'amd64' : '386' + [version, node['os'], arch].join('_') + end +end + +# Provider for managing the Consul service on an instance. +# @since 1.0.0 +class Chef::Provider::ConsulService < Chef::Provider + provides(:consul_service) + include PoiseService::ServiceMixin + + def action_enable + notifying_block do + directory new_resource.data_dir do + recursive true + owner new_resource.user + group new_resource.group + mode '0744' + end + + directory new_resource.config_dir do + recursive true + mode '0644' + end + + package new_resource.package_name do + version new_resource.version unless new_resource.version.nil? + only_if { new_resource.install_method == :package } + end + + if new_resource.install_method == :binary + artifact = libartifact_file "consul-#{new_resource.version}" do + artifact_name 'consul' + artifact_version new_resource.version + install_path new_resource.install_path + remote_url new_resource.binary_url % { filename: new_resource.binary_filename } + remote_checksum new_resource.binary_checksum + end + + link '/usr/local/bin/consul' do + to ::File.join(artifact.current_path, 'consul') + end + end + + if new_resource.install_method == :source + include_recipe 'golang::default' + + source_dir = directory ::File.join(new_resource.install_path, 'consul', 'src') do + recursive true + end + + git ::File.join(source_dir.path, "consul-#{new_resource.version}") do + repository new_resource.source_url + reference new_resource.version + action :checkout + end + + golang_package 'github.com/hashicorp/consul' do + action :install + end + + directory ::File.join(new_resource.install_path, 'bin') + + link ::File.join(new_resource.install_path, 'bin', 'consul') do + to ::File.join(source_dir.path, "consul-#{new_resource.version}", 'consul') + end + end + end + super + end + + def action_disable + notifying_block do + file new_resource.filename do + action :delete + end + + directory new_resource.config_dir do + action :delete + end + + directory new_resource.data_dir do + action :delete + end + end + super + end + + def service_options(service) + service.command(new_resource.command) + service.directory(new_resource.data_dir) + service.user(new_resource.user) + service.environment(new_resource.environment) + service.restart_on_update(true) + end +end diff --git a/libraries/consul_ui.rb b/libraries/consul_ui.rb deleted file mode 100644 index 33194a8e..00000000 --- a/libraries/consul_ui.rb +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2014-2015 John Bellone -# Copyright 2014-2015 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the 'License'); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an 'AS IS' BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -class Chef - module ConsulUI - class << self - def active_path(node) - File.join(node['consul']['data_dir'], 'ui') - end - - def cached_archive(node) - File.join(Chef::Config[:file_cache_path], File.basename(remote_url(node))) - end - - def install_path(node) - File.join(['/opt', 'consul_ui', node['consul']['version']]) - end - - def latest_dist(node) - File.join(install_path(node), 'dist') - end - - def remote_filename(node) - [node['consul']['version'], 'web_ui'].join('_') - end - - def remote_checksum(node) - node['consul']['checksums'].fetch(remote_filename(node)) - end - - def remote_url(node) - node['consul']['base_url'] % { version: remote_filename(node) } - end - end - end -end diff --git a/libraries/consul_watch.rb b/libraries/consul_watch.rb new file mode 100644 index 00000000..6f46aa17 --- /dev/null +++ b/libraries/consul_watch.rb @@ -0,0 +1,42 @@ +# +# Cookbook: consul +# License: Apache 2.0 +# +# Copyright (C) 2014, 2015 Bloomberg Finance L.P. +# +require 'poise' + +class Chef::Resource::ConsulWatch < Chef::Resource + include Poise(fused: true) + provides(:consul_watch) + actions(:create, :delete) + + # @!attribute watch_name + # @return [String] + attribute(:watch_name, kind_of: String, name_attribute: true) + + # @!attribute watch_type + # @return [String] + attribute(:watch_type, equal_to: %w(checks event key keyprefix service)) + + # @!attribute datacenter + # @return [String] + attribute(:datacenter, kind_of: String) + + # @!attribute handler + # @return [String] + attribute(:handler, kind_of: String) + + # @!attribute token + # @return [String] + attribute(:token, kind_of: String) + + action(:create) do + execute new_resource.command do + guard_interpreter :default + end + end + + action(:delete) do + end +end diff --git a/libraries/encrypt.rb b/libraries/encrypt.rb deleted file mode 100644 index 8dd65488..00000000 --- a/libraries/encrypt.rb +++ /dev/null @@ -1,21 +0,0 @@ -class Chef - class Recipe - # Don't throw the error if it doesn't exist - def consul_encrypted_dbi - begin - # loads the secret from /etc/chef/encrypted_data_bag_secret - Chef::EncryptedDataBagItem.load(node['consul']['data_bag'], node['consul']['data_bag_encrypt_item']) - rescue Net::HTTPServerException => e - raise e unless e.response.code == '404' - end - end - - def consul_dbi_key_with_node_default(dbi, key) - value = dbi[key] - Chef::Log.warn "Consul encrypt key=#{key} doesn't exist in the databag. \ -Reading it from node's attributes" if value.nil? - value ||= node['consul'][key] - value - end - end -end diff --git a/libraries/matchers.rb b/libraries/matchers.rb index 1485ac28..1f87917f 100644 --- a/libraries/matchers.rb +++ b/libraries/matchers.rb @@ -1,17 +1,25 @@ if defined?(ChefSpec) - def create_consul_service_def(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:consul_service_def, :create, resource_name) - end + %i{create delete}.each do |action| + define_method(:"#{action}_consul_client") do |resource_name| + ChefSpec::Matchers::ResourceMatcher.new(:consul_client, action, resource_name) + end - def delete_consul_service_def(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:consul_service_def, :delete, resource_name) - end + define_method(:"#{action}_consul_config") do |resource_name| + ChefSpec::Matchers::ResourceMatcher.new(:consul_config, action, resource_name) + end + + define_method(:"#{action}_consul_definition") do |resource_name| + ChefSpec::Matchers::ResourceMatcher.new(:consul_definition, action, resource_name) + end - def create_consul_event_watch_def(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:consul_event_watch_def, :create, resource_name) + define_method(:"#{action}_consul_watch") do |resource_name| + ChefSpec::Matchers::ResourceMatcher.new(:consul_watch, action, resource_name) + end end - def delete_consul_key_watch_def(resource_name) - ChefSpec::Matchers::ResourceMatcher.new(:consul_key_watch_def, :create, resource_name) + %i{enable disable stop start restart reload}.each do |action| + define_method(:"#{action}_consul_service") do |resource_name| + ChefSpec::Matchers::ResourceMatcher.new(:consul_service, action, resource_name) + end end end diff --git a/metadata.rb b/metadata.rb index 10f275de..3871b49e 100644 --- a/metadata.rb +++ b/metadata.rb @@ -1,34 +1,21 @@ name 'consul' maintainer 'John Bellone' maintainer_email 'jbellone@bloomberg.net' -license 'Apache v2.0' -description 'Installs/Configures Consul client, server and UI.' -long_description 'Installs/Configures Consul client, server and UI.' -version '0.11.1' +license 'Apache 2.0' +description 'Application cookbook which installs and configures Consul.' +long_description 'Application cookbook which installs and configures Consul.' +version '1.0.0' -recipe 'consul', 'Installs and starts consul service.' -recipe 'consul::install_binary', 'Installs consul service from binary.' -recipe 'consul::install_source', 'Installs consul service from source.' -recipe 'consul::ui', 'Installs consul ui service.' +recipe 'consul::default', 'Installs, configures and starts the Consul service.' -%w(redhat centos).each do |name| - supports name, '~> 7.0' - supports name, '~> 6.5' -end - -supports 'ubuntu', '= 12.04' -supports 'ubuntu', '= 14.04' +supports 'centos', '>= 6.5' +supports 'redhat', '>= 6.5' +supports 'ubuntu', '>= 12.04' supports 'arch' -supports 'windows' - -recommends 'chef-provisioning' -depends 'libarchive', ">= 0.6.0" +depends 'chef-vault' +depends 'libartifact', '~> 1.2' depends 'golang', '~> 1.4' -depends 'runit' -depends 'yum-repoforge' -depends 'packagecloud' - -# for windows -depends 'windows' -depends "chocolatey" +depends 'poise', '~> 2.0' +depends 'poise-service' +depends 'selinux' diff --git a/providers/check_def.rb b/providers/check_def.rb deleted file mode 100644 index 15f40a2e..00000000 --- a/providers/check_def.rb +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -use_inline_resources - -action :create do - file new_resource.path_with_name do - action :delete - only_if { new_resource.id } - end - - file new_resource.path do - if node['platform'] == 'windows' - rights :full_control, node['consul']['service_user'], :applies_to_children => true - else - user node['consul']['service_user'] - group node['consul']['service_group'] - end - mode 0600 - content new_resource.to_json - - action :create - end -end - -action :delete do - file new_resource.path do - action :delete - end -end diff --git a/providers/event_watch_def.rb b/providers/event_watch_def.rb deleted file mode 100644 index ca87cbc7..00000000 --- a/providers/event_watch_def.rb +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -use_inline_resources - -action :create do - file new_resource.path do - if node['platform'] == 'windows' - rights :full_control, node['consul']['service_user'], :applies_to_children => true - else - user node['consul']['service_user'] - group node['consul']['service_group'] - end - mode 0600 - content new_resource.to_json - - action :create - end -end - -action :delete do - file new_resource.path do - action :delete - end -end diff --git a/providers/key_watch_def.rb b/providers/key_watch_def.rb deleted file mode 100644 index ca87cbc7..00000000 --- a/providers/key_watch_def.rb +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -use_inline_resources - -action :create do - file new_resource.path do - if node['platform'] == 'windows' - rights :full_control, node['consul']['service_user'], :applies_to_children => true - else - user node['consul']['service_user'] - group node['consul']['service_group'] - end - mode 0600 - content new_resource.to_json - - action :create - end -end - -action :delete do - file new_resource.path do - action :delete - end -end diff --git a/providers/service_def.rb b/providers/service_def.rb deleted file mode 100644 index 112991ce..00000000 --- a/providers/service_def.rb +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -use_inline_resources if defined? use_inline_resources - -def set_updated - r = yield - new_resource.updated_by_last_action(r.updated_by_last_action?) -end - -action :create do - set_updated do - file new_resource.path do - if node['platform'] == 'windows' - rights :full_control, node['consul']['service_user'], :applies_to_children => true - else - user node['consul']['service_user'] - group node['consul']['service_group'] - end - mode 0600 - content new_resource.to_json - action :create - end - end -end - -action :delete do - set_updated do - file new_resource.path do - action :delete - end - end -end diff --git a/providers/service_watch_def.rb b/providers/service_watch_def.rb deleted file mode 100644 index ca87cbc7..00000000 --- a/providers/service_watch_def.rb +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -use_inline_resources - -action :create do - file new_resource.path do - if node['platform'] == 'windows' - rights :full_control, node['consul']['service_user'], :applies_to_children => true - else - user node['consul']['service_user'] - group node['consul']['service_group'] - end - mode 0600 - content new_resource.to_json - - action :create - end -end - -action :delete do - file new_resource.path do - action :delete - end -end diff --git a/providers/services_watch_def.rb b/providers/services_watch_def.rb deleted file mode 100644 index 9f9506a6..00000000 --- a/providers/services_watch_def.rb +++ /dev/null @@ -1,18 +0,0 @@ -use_inline_resources - -action :create do - file new_resource.path do - user node['consul']['service_user'] - group node['consul']['service_group'] - mode 0600 - content new_resource.to_json - - action :create - end -end - -action :delete do - file new_resource.path do - action :delete - end -end diff --git a/recipes/default.rb b/recipes/default.rb index 87e6ed87..c20e1715 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -1,31 +1,33 @@ # -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. +# Cookbook Name:: consul +# License:: Apache 2.0 # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright 2014, 2015 Bloomberg Finance L.P. # +include_recipe 'selinux::permissive' -case node['consul']['install_method'] -when 'binary' - include_recipe 'consul::install_binary' -when 'source' - include_recipe 'consul::install_source' -when 'packages' - include_recipe 'consul::install_packages' -when 'windows' - include_recipe 'consul::install_windows' -else - Chef::Application.fatal!("[consul::default] unknown install method, method=#{node['consul']['install_method']}") +poise_service_user node['consul']['service_user'] do + group node['consul']['service_group'] end -include_recipe 'consul::service' +consul_config node['consul']['service']['config_file'] do |resource| + user node['consul']['service_user'] + group node['consul']['service_group'] + + node['consul']['config'].each_pair { |k, v| resource.send(k, v) } + notifies :restart, "consul_service[#{node['consul']['service_name']}]", :delayed +end + +consul_service node['consul']['service_name'] do + user node['consul']['service_user'] + group node['consul']['service_group'] + version node['consul']['version'] + install_method node['consul']['service']['install_method'] + install_path node['consul']['service']['install_path'] + config_dir node['consul']['service']['config_dir'] + config_file node['consul']['service']['config_file'] + + package_name node['consul']['package_name'] + binary_url node['consul']['binary_url'] + source_url node['consul']['source_url'] +end diff --git a/recipes/install_binary.rb b/recipes/install_binary.rb deleted file mode 100644 index 5c244ede..00000000 --- a/recipes/install_binary.rb +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -include_recipe 'libarchive::default' - -archive = remote_file Chef::Consul.cached_archive(node) do - source Chef::Consul.remote_url(node) - checksum Chef::Consul.remote_checksum(node) -end - -libarchive_file 'consul.zip' do - path archive.path - extract_to Chef::Consul.install_path(node) - extract_options :no_overwrite - - action :extract -end - -directory File.basename(Chef::Consul.active_binary(node)) do - recursive true - action :create -end - -# JW TODO: Remove after next major release. -file Chef::Consul.active_binary(node) do - action :delete - not_if "test -L #{Chef::Consul.active_binary(node)}" -end - -link Chef::Consul.active_binary(node) do - to Chef::Consul.latest_binary(node) -end diff --git a/recipes/install_packages.rb b/recipes/install_packages.rb deleted file mode 100644 index 3f5f70fa..00000000 --- a/recipes/install_packages.rb +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# NOTE: This is only supported for Ubuntu 12.04LTS and 14.04LTS. - -if node['consul']['use_packagecloud_repo'] - - packagecloud_repo "darron/consul" do - type "deb" - end - - packagecloud_repo "darron/consul-webui" do - type "deb" - end - -end - -package 'consul' -package 'consul-webui' diff --git a/recipes/install_source.rb b/recipes/install_source.rb deleted file mode 100644 index d0fec1e2..00000000 --- a/recipes/install_source.rb +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -include_recipe 'golang::default' - -directory File.join(node['go']['gopath'], 'src/github.com/hashicorp') do - owner 'root' - group 'root' - mode '00755' - recursive true - action :create -end - -git File.join(node['go']['gopath'], '/src/github.com/hashicorp/consul') do - repository 'https://github.com/hashicorp/consul.git' - reference node['consul']['source_revision'] - action :checkout -end - -golang_package 'github.com/hashicorp/consul' do - action :install -end - -directory File.basename(Chef::Consul.active_binary(node)) do - recursive true - action :create -end - -link Chef::Consul.active_binary(node) do - to Chef::Consul.source_binary(node) -end diff --git a/recipes/service.rb b/recipes/service.rb deleted file mode 100644 index 8dc9d30e..00000000 --- a/recipes/service.rb +++ /dev/null @@ -1,306 +0,0 @@ -# -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require 'json' - -# Configure directories -consul_directories = [] -consul_directories << node['consul']['data_dir'] -consul_directories << node['consul']['config_dir'] - -case node['consul']['init_style'] -when 'runit' - include_recipe 'runit::default' - consul_directories << '/var/log/consul' -when 'windows' - # already added, move along -else - consul_directories << '/var/lib/consul' -end - - -# Select service user & group -consul_user = node['consul']['service_user'] -consul_group = node['consul']['service_group'] - -# Create service user -case node['consul']['init_style'] -when 'windows' - user "consul service user: #{consul_user}" do - not_if { consul_user == 'Administrator' } - username consul_user - comment 'consul service user' - end -else - user "consul service user: #{consul_user}" do - not_if { consul_user == 'root' } - username consul_user - home '/dev/null' - shell '/bin/false' - system node['consul']['system_account'] - comment 'consul service user' - end -end - -# Create service group -group "consul service group: #{consul_group}" do - not_if { consul_group == 'root' && node['platform'] != 'windows'} - not_if { consul_group == 'Administrators' && node['platform'] == 'windows'} - group_name consul_group - members consul_user - system node['consul']['system_account'] - append true -end - -# Create service directories -consul_directories.uniq.each do |dirname| - directory dirname do - if node['platform'] == 'windows' - rights :full_control, node['consul']['service_user'], :applies_to_children => true - recursive true - else - user consul_user - group consul_group - end - mode 0755 - end - - execute "chown -R #{consul_user}:#{consul_group} #{dirname}" do - not_if { node['platform'] == 'windows' } - only_if do - Etc.getpwuid(File.stat(dirname).uid).name != consul_user or - Etc.getgrgid(File.stat(dirname).gid).name != consul_group - end - end -end - -# Determine service params -service_config = JSON.parse(node['consul']['extra_params'].to_json) -service_config['data_dir'] = node['consul']['data_dir'] -num_cluster = node['consul']['bootstrap_expect'].to_i -join_mode = node['consul']['retry_on_join'] ? 'retry_join' : 'start_join' - -case node['consul']['service_mode'] -when 'bootstrap' - service_config['server'] = true - service_config['bootstrap'] = true -when 'cluster' - service_config['server'] = true - if num_cluster > 1 - service_config['bootstrap_expect'] = num_cluster - service_config[join_mode] = node['consul']['servers'] - else - service_config['bootstrap'] = true - end -when 'server' - service_config['server'] = true - service_config[join_mode] = node['consul']['servers'] -when 'client' - service_config[join_mode] = node['consul']['servers'] -else - Chef::Application.fatal! %Q(node['consul']['service_mode'] must be "bootstrap", "cluster", "server", or "client") -end - -iface_addr_map = { - bind_interface: :bind_addr, - advertise_interface: :advertise_addr, - client_interface: :client_addr -} - -iface_addr_map.each_pair do |interface,addr| - next unless node['consul'][interface] - - if node["network"]["interfaces"][node['consul'][interface]] - ip = node["network"]["interfaces"][node['consul'][interface]]["addresses"].detect{|k,v| v[:family] == "inet"}.first - node.default['consul'][addr] = ip - else - Chef::Application.fatal!("Interface specified in node['consul'][#{interface}] does not exist!") - end -end - -if node['consul']['serve_ui'] - service_config['ui_dir'] = Chef::ConsulUI.active_path(node) - service_config['client_addr'] = node['consul']['client_addr'] -end - -additional_options = ['recursor', 'statsd_addr', 'leave_on_terminate', 'rejoin_after_leave', 'disable_remote_exec', 'acl_datacenter', 'acl_token', 'acl_default_policy', 'acl_down_policy', 'acl_master_token'] - -additional_options.each do |option| - if node['consul'][option] - service_config[option] = node['consul'][option] - end -end - -copy_params = [ - :bind_addr, :datacenter, :domain, :log_level, :node_name, :advertise_addr, :ports, :enable_syslog, :statsd_addr -] -copy_params.each do |key| - if node['consul'][key] - if key == :ports - Chef::Application.fatal! 'node[:consul][:ports] must be a Hash' unless node[:consul][key].kind_of?(Hash) - end - - service_config[key] = node['consul'][key] - end -end - -dbi = nil -# Gossip encryption -if node.consul.encrypt_enabled - # Fetch the databag only once, and use empty hash if it doesn't exists - dbi = consul_encrypted_dbi || {} - secret = consul_dbi_key_with_node_default(dbi, 'encrypt') - raise "Consul encrypt key is empty or nil" if secret.nil? or secret.empty? - service_config['encrypt'] = secret -else - # for backward compatibilty - service_config['encrypt'] = node.consul.encrypt unless node.consul.encrypt.nil? -end - -# TLS encryption -if node.consul.verify_incoming || node.consul.verify_outgoing - dbi = consul_encrypted_dbi || {} if dbi.nil? - service_config['verify_outgoing'] = node.consul.verify_outgoing - service_config['verify_incoming'] = node.consul.verify_incoming - - ca_path = node.consul.ca_path % { config_dir: node.consul.config_dir } - service_config['ca_file'] = ca_path - - cert_path = node.consul.cert_path % { config_dir: node.consul.config_dir } - service_config['cert_file'] = cert_path - - key_path = node.consul.key_file_path % { config_dir: node.consul.config_dir } - service_config['key_file'] = key_path - - # Search for key_file_hostname since key and cert file can be unique/host - key_content = dbi['key_file_' + node.fqdn] || consul_dbi_key_with_node_default(dbi, 'key_file') - cert_content = dbi['cert_file_' + node.fqdn] || consul_dbi_key_with_node_default(dbi, 'cert_file') - ca_content = consul_dbi_key_with_node_default(dbi, 'ca_cert') - - # Save the certs if exists - {ca_path => ca_content, key_path => key_content, cert_path => cert_content}.each do |path, content| - unless content.nil? or content.empty? - file path do - user consul_user - group consul_group - mode 0600 - action :create - content content - end - end - end -end - -# Atlas integration -if node['consul']['atlas_autojoin'] or node['consul']['atlas_token'] - cluster = node['consul']['atlas_cluster'] - token = node['consul']['atlas_token'] - raise "atlas_cluster is empty or nil" if cluster.empty? or cluster.nil? - raise "atlas_token is empty or nil" if token.empty? or token.nil? - service_config['atlas_infrastructure'] = cluster - service_config['atlas_join'] = node['consul']['atlas_autojoin'] - service_config['atlas_token'] = token -end - -consul_config_filename = File.join(node['consul']['config_dir'], 'default.json') - -file consul_config_filename do - user consul_user - group consul_group - mode 0600 - action :create - content JSON.pretty_generate(service_config, quirks_mode: true) - # https://github.com/johnbellone/consul-cookbook/issues/72 - notifies :restart, "service[consul]" -end - -case node['consul']['init_style'] -when 'init' - if platform?("ubuntu") - init_file = '/etc/init/consul.conf' - init_tmpl = 'consul.conf.erb' - init_mode = 0644 - else - init_file = '/etc/init.d/consul' - init_tmpl = 'consul-init.erb' - init_mode = 0755 - end - - template node['consul']['etc_config_dir'] do - source 'consul-sysconfig.erb' - mode 0644 - notifies :create, "template[#{init_file}]", :immediately - end - - template init_file do - source init_tmpl - mode init_mode - variables( - consul_logfile: node['consul']['logfile'], - startup_sleep: node['consul']['startup_sleep'], - soft_limit: node['consul']['files_soft_limit'], - hard_limit: node['consul']['files_hard_limit'] - ) - notifies :restart, 'service[consul]', :immediately - end - - service 'consul' do - provider Chef::Provider::Service::Upstart if platform?("ubuntu") - supports status: true, restart: true, reload: true - action [:enable, :start] - subscribes :restart, "file[#{consul_config_filename}]" - subscribes :restart, "link[#{Chef::Consul.active_binary(node)}]" - end -when 'runit' - runit_service 'consul' do - supports status: true, restart: true, reload: true - action [:enable, :start] - subscribes :restart, "file[#{consul_config_filename}]" - subscribes :restart, "link[#{Chef::Consul.active_binary(node)}]" - log true - end - - service 'consul' do - supports status: true, restart: true, reload: true - reload_command "'#{node['runit']['sv_bin']}' hup consul" - end -when 'systemd' - template node['consul']['etc_config_dir'] do - source 'consul-sysconfig.erb' - mode 0644 - notifies :create, "template[/etc/systemd/system/consul.service]", :immediately - end - - template '/etc/systemd/system/consul.service' do - source 'consul-systemd.erb' - mode 0644 - notifies :restart, 'service[consul]', :immediately - end - - service 'consul' do - supports status: true, restart: true, reload: true - action [:enable, :start] - subscribes :restart, "file[#{consul_config_filename}]" - subscribes :restart, "link[#{Chef::Consul.active_binary(node)}]" - end -when 'windows' - # Windows service for consul has been create by Chocolatey and - # config is managed by the chocolatey package - service 'consul' do - subscribes :restart, "file[#{consul_config_filename}]" - end -end diff --git a/recipes/ui.rb b/recipes/ui.rb deleted file mode 100644 index 6133f1a3..00000000 --- a/recipes/ui.rb +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2014 Benny Wong -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -if node['platform'] == 'windows' - Chef::Log.error "UI Installation not supported for Windows" -else - include_recipe 'libarchive::default' - - archive = remote_file Chef::ConsulUI.cached_archive(node) do - source Chef::ConsulUI.remote_url(node) - checksum Chef::ConsulUI.remote_checksum(node) - end - - libarchive_file 'consul_ui.zip' do - path archive.path - extract_to Chef::ConsulUI.install_path(node) - extract_options :no_overwrite - - action :extract - end - - # JW TODO: Remove after next major release. - directory Chef::ConsulUI.active_path(node) do - action :delete - recursive true - not_if "test -L #{Chef::ConsulUI.active_path(node)}" - end - - link Chef::ConsulUI.active_path(node) do - to Chef::ConsulUI.latest_dist(node) - end -end diff --git a/resources/check_def.rb b/resources/check_def.rb deleted file mode 100644 index 1efb45ff..00000000 --- a/resources/check_def.rb +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require 'json' - -actions :create, :delete -default_action :create - -attribute :name, name_attribute: true, required: true, kind_of: String -attribute :id, kind_of: String -attribute :script, kind_of: String -attribute :http, kind_of: String -attribute :ttl, kind_of: String -attribute :interval, kind_of: String -attribute :notes, kind_of: String - -def path - ::File.join(node['consul']['config_dir'], "check-#{id || name}.json") -end - -def path_with_name - ::File.join(node['consul']['config_dir'], "check-#{name}.json") -end - -def to_json - JSON.pretty_generate(to_hash) -end - -def to_hash - hash = { - check: { - name: name - } - } - hash[:check][:id] = id unless id.nil? - hash[:check][:script] = script unless script.nil? - hash[:check][:ttl] = ttl unless ttl.nil? - hash[:check][:http] = http unless http.nil? - hash[:check][:interval] = interval unless interval.nil? - hash[:check][:notes] = notes unless notes.nil? - hash -end diff --git a/resources/event_watch_def.rb b/resources/event_watch_def.rb deleted file mode 100644 index 1772d76f..00000000 --- a/resources/event_watch_def.rb +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require 'json' - -actions :create, :delete -default_action :create - -attribute :name, name_attribute: true, required: true, kind_of: String -attribute :handler, required: true, kind_of: String - -def path - ::File.join(node['consul']['config_dir'], "event-watch-#{name}.json") -end - -def to_json - JSON.pretty_generate(to_hash) -end - -def to_hash - hash = { - watches:[ - { - type: 'event', - name: name, - handler: handler - } - ] - } - hash -end diff --git a/resources/key_watch_def.rb b/resources/key_watch_def.rb deleted file mode 100644 index 4d698fba..00000000 --- a/resources/key_watch_def.rb +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require 'json' - -actions :create, :delete -default_action :create - -attribute :name, name_attribute: true, required: true, kind_of: String -attribute :key, required: true, kind_of: String -attribute :handler, required: true, kind_of: String - -def path - ::File.join(node['consul']['config_dir'], "key-watch-#{name}.json") -end - -def to_json - JSON.pretty_generate(to_hash) -end - -def to_hash - hash = { - watches:[ - { - type: 'key', - key: key, - handler: handler - } - ] - } - hash -end diff --git a/resources/service_def.rb b/resources/service_def.rb deleted file mode 100644 index 33b972d1..00000000 --- a/resources/service_def.rb +++ /dev/null @@ -1,72 +0,0 @@ -# -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require 'json' - -actions :create, :delete -default_action :create - -attribute :name, name_attribute: true, required: true, kind_of: String -attribute :id, kind_of: String -attribute :port, kind_of: Integer -attribute :tags, kind_of: Array, default: nil -attribute :check, kind_of: Hash, default: nil, callbacks: { - 'Checks must be a hash containing either a `:ttl` key/value or a `:script/:http` and `:interval` key/value' => ->(check) do - Chef::Resource::ConsulServiceDef.validate_check(check) - end -} - -def self.validate_check(check) - unless check.is_a?(Hash) - return false - end - - if check.key?(:ttl) && ( [:interval, :script, :http].none?{|key| check.key?(key)} ) - return true - end - - if check.key?(:interval) && check.key?(:script) - return true - end - - if check.key?(:interval) && check.key?(:http) - return true - end - - false -end - -def path - ::File.join(node['consul']['config_dir'], "service-#{id || name}.json") -end - -def to_json - JSON.pretty_generate(to_hash) -end - -def to_hash - hash = { - service: { - name: name - } - } - hash[:service][:id] = id unless id.nil? - hash[:service][:port] = port unless port.nil? - hash[:service][:tags] = tags unless tags.nil? - hash[:service][:check] = check unless check.nil? - hash -end diff --git a/resources/service_watch_def.rb b/resources/service_watch_def.rb deleted file mode 100644 index 4f469aa0..00000000 --- a/resources/service_watch_def.rb +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright 2014 John Bellone -# Copyright 2014 Bloomberg Finance L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require 'json' - -actions :create, :delete -default_action :create - -attribute :service, name_attribute: true, required: true, kind_of: String -attribute :handler, required: true, kind_of: String -attribute :passingonly, required: false, kind_of: [TrueClass, FalseClass] -attribute :tag, required: false, kind_of: String - -def path - ::File.join(node['consul']['config_dir'], "service-watch-#{name}.json") -end - -def to_json - JSON.pretty_generate({'watches'=> [to_hash]}) -end - -def to_hash - hash = { - type: "service" - } - hash[:service] = name - hash[:handler] = handler unless handler.nil? - hash[:tag] = tag unless tag.nil? - hash[:passingonly] = passingonly unless passingonly.nil? - hash -end diff --git a/resources/services_watch_def.rb b/resources/services_watch_def.rb deleted file mode 100644 index d1fdaf19..00000000 --- a/resources/services_watch_def.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'json' - -actions :create, :delete -default_action :create - -attribute :name, name_attribute: true, required: true, kind_of: String -attribute :handler, required: true, kind_of: String - -def path - ::File.join(node['consul']['config_dir'], "watch-services.json") -end - -def to_json - JSON.pretty_generate(to_hash) -end - -def to_hash - hash = { - watches:[ - { - type: 'services', - handler: handler - } - ] - } - hash -end diff --git a/spec/fixtures/cookbooks/consul_spec/metadata.rb b/spec/fixtures/cookbooks/consul_spec/metadata.rb deleted file mode 100644 index a40a72e5..00000000 --- a/spec/fixtures/cookbooks/consul_spec/metadata.rb +++ /dev/null @@ -1,3 +0,0 @@ -name 'consul_spec' - -depends 'consul' diff --git a/spec/fixtures/cookbooks/consul_spec/recipes/check_def_with_id_create.rb b/spec/fixtures/cookbooks/consul_spec/recipes/check_def_with_id_create.rb deleted file mode 100644 index ad49a705..00000000 --- a/spec/fixtures/cookbooks/consul_spec/recipes/check_def_with_id_create.rb +++ /dev/null @@ -1,9 +0,0 @@ -include_recipe "consul" -consul_check_def "dummy name" do - id "uniqueid" - script "curl http://localhost:8888/health" - interval "10s" - ttl "50s" - http "http://localhost:8888/health" - notes "Blahblah" -end diff --git a/spec/fixtures/cookbooks/consul_spec/recipes/check_def_with_id_delete.rb b/spec/fixtures/cookbooks/consul_spec/recipes/check_def_with_id_delete.rb deleted file mode 100644 index 0ebaa855..00000000 --- a/spec/fixtures/cookbooks/consul_spec/recipes/check_def_with_id_delete.rb +++ /dev/null @@ -1,5 +0,0 @@ -include_recipe "consul" -consul_check_def "dummy name" do - id "uniqueid" - action :delete -end diff --git a/spec/fixtures/cookbooks/consul_spec/recipes/check_def_without_id_create.rb b/spec/fixtures/cookbooks/consul_spec/recipes/check_def_without_id_create.rb deleted file mode 100644 index 563686a5..00000000 --- a/spec/fixtures/cookbooks/consul_spec/recipes/check_def_without_id_create.rb +++ /dev/null @@ -1,7 +0,0 @@ -include_recipe "consul" -consul_check_def "dummy name" do - script "curl http://localhost:8888/health" - interval "10s" - ttl "50s" - notes "Blahblah" -end diff --git a/spec/fixtures/cookbooks/consul_spec/recipes/check_def_without_id_delete.rb b/spec/fixtures/cookbooks/consul_spec/recipes/check_def_without_id_delete.rb deleted file mode 100644 index 7d314cec..00000000 --- a/spec/fixtures/cookbooks/consul_spec/recipes/check_def_without_id_delete.rb +++ /dev/null @@ -1,4 +0,0 @@ -include_recipe "consul" -consul_check_def "dummy name" do - action :delete -end diff --git a/spec/fixtures/cookbooks/consul_spec/recipes/event_watch_create.rb b/spec/fixtures/cookbooks/consul_spec/recipes/event_watch_create.rb deleted file mode 100644 index fad2acf5..00000000 --- a/spec/fixtures/cookbooks/consul_spec/recipes/event_watch_create.rb +++ /dev/null @@ -1,4 +0,0 @@ -include_recipe "consul" -consul_event_watch_def "dummy" do - handler "chef-client" -end diff --git a/spec/fixtures/cookbooks/consul_spec/recipes/event_watch_delete.rb b/spec/fixtures/cookbooks/consul_spec/recipes/event_watch_delete.rb deleted file mode 100644 index ff1318c2..00000000 --- a/spec/fixtures/cookbooks/consul_spec/recipes/event_watch_delete.rb +++ /dev/null @@ -1,4 +0,0 @@ -include_recipe "consul" -consul_event_watch_def "dummy" do - action :delete -end diff --git a/spec/fixtures/cookbooks/consul_spec/recipes/key_watch_create.rb b/spec/fixtures/cookbooks/consul_spec/recipes/key_watch_create.rb deleted file mode 100644 index 26c6a9b8..00000000 --- a/spec/fixtures/cookbooks/consul_spec/recipes/key_watch_create.rb +++ /dev/null @@ -1,5 +0,0 @@ -include_recipe "consul" -consul_key_watch_def "dummy" do - key "/key/path" - handler "chef-client" -end diff --git a/spec/fixtures/cookbooks/consul_spec/recipes/key_watch_delete.rb b/spec/fixtures/cookbooks/consul_spec/recipes/key_watch_delete.rb deleted file mode 100644 index 679f115a..00000000 --- a/spec/fixtures/cookbooks/consul_spec/recipes/key_watch_delete.rb +++ /dev/null @@ -1,4 +0,0 @@ -include_recipe "consul" -consul_key_watch_def "dummy" do - action :delete -end diff --git a/spec/fixtures/cookbooks/consul_spec/recipes/service_def_create.rb b/spec/fixtures/cookbooks/consul_spec/recipes/service_def_create.rb deleted file mode 100644 index 6b6be73e..00000000 --- a/spec/fixtures/cookbooks/consul_spec/recipes/service_def_create.rb +++ /dev/null @@ -1,7 +0,0 @@ -include_recipe "consul" -consul_service_def "dummy" do - id "uniqueid" - port 8888 - tags ['releases', 'v1'] - check :interval => "10s", :script => "curl http://localhost:8888/health" -end diff --git a/spec/fixtures/cookbooks/consul_spec/recipes/service_def_delete.rb b/spec/fixtures/cookbooks/consul_spec/recipes/service_def_delete.rb deleted file mode 100644 index 8a78f6a5..00000000 --- a/spec/fixtures/cookbooks/consul_spec/recipes/service_def_delete.rb +++ /dev/null @@ -1,5 +0,0 @@ -include_recipe "consul" -consul_service_def "dummy" do - id "uniqueid" - action :delete -end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb deleted file mode 100644 index ceae4944..00000000 --- a/spec/spec_helper.rb +++ /dev/null @@ -1,97 +0,0 @@ -require 'chefspec' -require 'chefspec/berkshelf' -require 'chefspec/cacher' -require 'chefspec/server' -require 'coveralls' - -require_relative 'support/matchers' - -Coveralls.wear! - -RSpec.configure do |config| - config.color = true - config.alias_example_group_to :describe_recipe, type: :recipe - config.alias_example_group_to :describe_resource, type: :resource - - config.filter_run :focus - config.run_all_when_everything_filtered = true - - Kernel.srand config.seed - config.order = :random - - if config.files_to_run.one? - config.default_formatter = 'doc' - end - - config.expect_with :rspec do |expectations| - expectations.syntax = :expect - end - - config.mock_with :rspec do |mocks| - mocks.syntax = :expect - mocks.verify_partial_doubles = true - end -end - -at_exit { ChefSpec::Coverage.report! } - -RSpec.shared_context 'recipe tests', type: :recipe do - before do - stub_command("test -L /usr/local/bin/consul").and_return(true) - end - - let(:chef_run) { ChefSpec::Runner.new(node_attributes).converge(described_recipe) } - - def node_attributes - { - platform: 'ubuntu', - version: '12.04' - } - end -end - -RSpec.shared_context "resource tests", type: :resource do - before do - stub_command("test -L /usr/local/bin/consul").and_return(true) - end - - let(:chef_run) do - ChefSpec::SoloRunner.new(node_attributes.merge(step_into)).converge(example_recipe) - end - - let(:example_recipe) do - fail %( -Please specify the name of the test recipe that executes your recipe: - - let(:example_recipe) do - "consul_spec::service_def" - end - -) - end - - let(:node) { chef_run.node } - - def node_attributes - { - platform: 'ubuntu', - version: '12.04' - } - end - - let(:step_into) do - { step_into: [cookbook_name] } - end - - def cookbook_recipe_names - described_recipe.split("::", 2) - end - - def cookbook_name - cookbook_recipe_names.first - end - - def recipe_name - cookbook_recipe_names.last - end -end diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb deleted file mode 100644 index 422b8a5f..00000000 --- a/spec/support/matchers.rb +++ /dev/null @@ -1,35 +0,0 @@ -def start_runit_service(name) - ChefSpec::Matchers::ResourceMatcher.new(:runit_service, :start, name) -end - -def stop_runit_service(name) - ChefSpec::Matchers::ResourceMatcher.new(:runit_service, :stop, name) -end - -def enable_runit_service(name) - ChefSpec::Matchers::ResourceMatcher.new(:runit_service, :enable, name) -end - -def disable_runit_service(name) - ChefSpec::Matchers::ResourceMatcher.new(:runit_service, :disable, name) -end - -def install_golang_package(name) - ChefSpec::Matchers::ResourceMatcher.new(:golang_package, :install, name) -end - -def uninstall_golang_package(name) - ChefSpec::Matchers::ResourceMatcher.new(:golang_package, :uninstall, name) -end - -def put_ark(name) - ChefSpec::Matchers::ResourceMatcher.new(:ark, :put, name) -end - -def dump_ark(name) - ChefSpec::Matchers::ResourceMatcher.new(:ark, :dump, name) -end - -def install_ark(name) - ChefSpec::Matchers::ResourceMatcher.new(:ark, :install, name) -end diff --git a/spec/unit/resources/check_def_spec.rb b/spec/unit/resources/check_def_spec.rb deleted file mode 100644 index 0e037421..00000000 --- a/spec/unit/resources/check_def_spec.rb +++ /dev/null @@ -1,65 +0,0 @@ -require 'spec_helper' -require 'chefspec/berkshelf' - -describe_resource "consul_check_def" do - describe "with id" do - let(:check_def_path) { "/etc/consul.d/check-uniqueid.json" } - - describe "create" do - let(:example_recipe) { "consul_spec::check_def_with_id_create" } - - it "removes any check previously registered by name" do - expect(chef_run).to delete_file("/etc/consul.d/check-dummy name.json") - end - - it "register the check" do - ['"name": "dummy name"', - '"id": "uniqueid"', - '"script": "curl http://localhost:8888/health"', - '"http": "http://localhost:8888/health"', - '"interval": "10s"', - '"ttl": "50s"', - '"notes": "Blahblah"'].each do |content| - expect(chef_run).to render_file(check_def_path) - .with_content(content) - end - end - end - - describe "delete" do - let(:example_recipe) { "consul_spec::check_def_with_id_delete" } - - it "de-register the check" do - expect(chef_run).to delete_file(check_def_path) - end - end - end - - describe "without id" do - let(:check_def_path) { "/etc/consul.d/check-dummy name.json" } - - describe "create" do - let(:example_recipe) { "consul_spec::check_def_without_id_create" } - - it "does not remove checks previously registered by name" do - expect(chef_run).not_to delete_file("/etc/consul.d/check-dummy name.json") - end - - it "register the check" do - ['"name": "dummy name"', '"script": "curl http://localhost:8888/health"', - '"interval": "10s"', '"ttl": "50s"', '"notes": "Blahblah"'].each do |content| - expect(chef_run).to render_file(check_def_path) - .with_content(content) - end - end - end - - describe "delete" do - let(:example_recipe) { "consul_spec::check_def_without_id_delete" } - - it "de-register the check" do - expect(chef_run).to delete_file(check_def_path) - end - end - end -end diff --git a/spec/unit/resources/event_watch_def_spec.rb b/spec/unit/resources/event_watch_def_spec.rb deleted file mode 100644 index 040cc377..00000000 --- a/spec/unit/resources/event_watch_def_spec.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'spec_helper' -require 'chefspec/berkshelf' - -describe_resource "consul_event_watch_def" do - let(:service_def_path) { "/etc/consul.d/event-watch-dummy.json" } - - describe "create" do - let(:example_recipe) { "consul_spec::event_watch_create" } - - it "register the service" do - ['"name": "dummy"', '"type": "event"', - '"handler": "chef-client"'].each do |content| - expect(chef_run).to render_file(service_def_path) - .with_content(content) - end - end - end - - describe "delete" do - let(:example_recipe) { "consul_spec::event_watch_delete" } - - it "de-register the service" do - expect(chef_run).to delete_file(service_def_path) - expect(chef_run.file(service_def_path)) - end - end -end diff --git a/spec/unit/resources/key_watch_def_spec.rb b/spec/unit/resources/key_watch_def_spec.rb deleted file mode 100644 index c807fa0c..00000000 --- a/spec/unit/resources/key_watch_def_spec.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'spec_helper' -require 'chefspec/berkshelf' - -describe_resource "consul_key_watch_def" do - let(:service_def_path) { "/etc/consul.d/key-watch-dummy.json" } - - describe "create" do - let(:example_recipe) { "consul_spec::key_watch_create" } - - it "register the service" do - ['"key": "/key/path"', '"type": "key"', - '"handler": "chef-client"'].each do |content| - expect(chef_run).to render_file(service_def_path) - .with_content(content) - end - end - end - - describe "delete" do - let(:example_recipe) { "consul_spec::key_watch_delete" } - - it "de-register the service" do - expect(chef_run).to delete_file(service_def_path) - expect(chef_run.file(service_def_path)) - end - end -end diff --git a/spec/unit/resources/service_def_spec.rb b/spec/unit/resources/service_def_spec.rb deleted file mode 100644 index bc139d98..00000000 --- a/spec/unit/resources/service_def_spec.rb +++ /dev/null @@ -1,26 +0,0 @@ -require 'spec_helper' -require 'chefspec/berkshelf' - -describe_resource "consul_service_def" do - let(:service_def_path) { "/etc/consul.d/service-uniqueid.json" } - - describe "create" do - let(:example_recipe) { "consul_spec::service_def_create" } - - it "register the service" do - ['"name": "dummy"', '"port": 8888', - '"script": "curl http://localhost:8888/health"'].each do |content| - expect(chef_run).to render_file(service_def_path) - .with_content(content) - end - end - end - - describe "delete" do - let(:example_recipe) { "consul_spec::service_def_delete" } - - it "de-register the service" do - expect(chef_run).to delete_file(service_def_path) - end - end -end diff --git a/templates/default/consul-init.erb b/templates/default/consul-init.erb deleted file mode 100644 index 14fc07e7..00000000 --- a/templates/default/consul-init.erb +++ /dev/null @@ -1,136 +0,0 @@ -#!/bin/bash -### BEGIN INIT INFO -# Provides: consul -# Required-Start: $network $remote_fs $syslog -# Required-Stop: $network $remote_fs $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Consul Service Discovery Platform -# Description: Consul is a tool for discovering and configuring services -# in your infrastructure. It provides several key features: -# * Service Discovery -# * Health Checking -# * Key/Valuye Store -# * Multi Datacenter -### END INIT INFO - -if [ -f <%= node['consul']['etc_config_dir'] %> ]; then -. <%= node['consul']['etc_config_dir'] %> -fi - -export GOMAXPROCS=${GOMAXPROCS} - -CMD="<%= Chef::Consul.active_binary(node) %> agent -config-dir <%= node['consul']['config_dir'] %>" -NAME="consul" - -PIDFILE="/var/run/$NAME.pid" -LOGFILE="<%= @consul_logfile %>" - -STARTIMEOUT=5 -STOPTIMEOUT=30 - -get_pid() { - cat "$PIDFILE" -} - -is_running() { - [ -f "$PIDFILE" ] && ps `get_pid` > /dev/null 2>&1 -} - -case "$1" in - start) - if is_running; then - echo "$NAME already running" - else - echo "Starting $NAME" - exec 2> >(while IFS= read -r line; do logger -t consul "$line"; done) - ${CMD[@]} >> "$LOGFILE" & - CONSULPID=$! - echo $CONSULPID > "$PIDFILE" - TIMEOUT="$STARTIMEOUT" - sleep <%= @startup_sleep %> - while [ $TIMEOUT -gt 0 ]; do - if is_running; then - break - sleep 1 - let TIMEOUT=${TIMEOUT}-1 - fi - done - if [ $TIMEOUT -eq 0 ]; then - echo "Unable to start $NAME, see $LOGFILE" - exit 1 - fi - exit 0 - fi - ;; - stop) - if is_running; then - echo -n "Stopping $NAME..." - CONSULPID=`get_pid` - /bin/kill -INT "$CONSULPID" >/dev/null 2>&1 - ret=$? - if [ $ret -eq 0 ]; then - TIMEOUT="$STOPTIMEOUT" - while [ $TIMEOUT -gt 0 ]; do - kill -0 "$CONSULPID" >/dev/null 2>&1 || break - sleep 1 - let TIMEOUT=${TIMEOUT}-1 - done - if is_running; then - echo "$NAME not stopped, sending SIGKILL" - kill -9 $CONSULPID - sleep 1 - fi - if is_running; then - echo "$NAME not stopped; may still be shutting down or shutdown may have failed" - exit 1 - else - echo "$NAME stopped" - if [ -f "$PIDFILE" ]; then - rm "$PIDFILE" - fi - exit 0 - fi - fi - else - echo "$NAME not running" - fi - ;; - restart) - $0 stop - if is_running; then - echo "Unable to stop $NAME, will not attempt to start" - exit 1 - fi - $0 start - ;; - status) - if is_running; then - echo "$NAME is running" - else - echo "$NAME is stopped" - exit 1 - fi - ;; - reload) - if is_running; then - echo -n "Reloading $NAME..." - kill -HUP `get_pid` - sleep 1 - echo - - if ! is_running; then - echo "$NAME has died, see $LOGFILE" - exit 1 - fi - else - echo "$NAME not running" - fi - ;; - *) - echo "Usage: $0 {start|stop|restart|reload|status}" - exit 1 - ;; -esac - -exit 0 diff --git a/templates/default/consul-sysconfig.erb b/templates/default/consul-sysconfig.erb deleted file mode 100644 index 1c8c50c9..00000000 --- a/templates/default/consul-sysconfig.erb +++ /dev/null @@ -1 +0,0 @@ -GOMAXPROCS=<%= [node['cpu']['total'], 2].max %> diff --git a/templates/default/consul-systemd.erb b/templates/default/consul-systemd.erb deleted file mode 100644 index 07d403e7..00000000 --- a/templates/default/consul-systemd.erb +++ /dev/null @@ -1,18 +0,0 @@ -[Unit] -Description=Consul Agent -Wants=basic.target -After=basic.target network.target - -[Service] -User=<%= node['consul']['service_user'] %> -Group=<%= node['consul']['service_group'] %> -EnvironmentFile=-<%= node['consul']['etc_config_dir'] %> -ExecStart=<%= Chef::Consul.active_binary(node) %> agent \ - -config-dir <%= node['consul']['config_dir'] %> -ExecReload=/bin/kill -HUP $MAINPID -KillMode=process -Restart=on-failure -RestartSec=15s - -[Install] -WantedBy=multi-user.target diff --git a/templates/default/consul.conf.erb b/templates/default/consul.conf.erb deleted file mode 100644 index bf8078bf..00000000 --- a/templates/default/consul.conf.erb +++ /dev/null @@ -1,26 +0,0 @@ -description "Consul Service Discovery Platform" - -emits consul-up - -start on runlevel [2345] -stop on runlevel [!2345] - -# set max open files -limit nofile <%= @soft_limit %> <%= @hard_limit %> - -script - if [ -f <%= node['consul']['etc_config_dir'] %> ]; then - . <%= node['consul']['etc_config_dir'] %> - fi - export GOMAXPROCS=${GOMAXPROCS} - CMD="<%= Chef::Consul.active_binary(node) %> agent -config-dir <%= node['consul']['config_dir'] %>" - LOGFILE="<%= @consul_logfile %>" - exec $CMD >> "$LOGFILE" -end script - -post-start exec initctl emit consul-up - -kill signal INT - -respawn -respawn limit 10 10 diff --git a/templates/default/sv-consul-log-run.erb b/templates/default/sv-consul-log-run.erb deleted file mode 100644 index 42cd1197..00000000 --- a/templates/default/sv-consul-log-run.erb +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -exec chpst -u '<%= node[:consul][:service_user] %>':'<%= node[:consul][:service_group] %>' \ - svlogd \ - /var/log/consul \ -# # diff --git a/templates/default/sv-consul-run.erb b/templates/default/sv-consul-run.erb deleted file mode 100644 index eda48517..00000000 --- a/templates/default/sv-consul-run.erb +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -export GOMAXPROCS=<%= [node['cpu']['total'], 2].max %> - -exec 2>&1 -exec <%= node['runit']['chpst_bin'] %> \ - -u <%= node['consul']['service_user'] %>:<%= node['consul']['service_group'] %> \ - <%= Chef::Consul.active_binary(node) %> agent -config-dir <%= node['consul']['config_dir'] %> diff --git a/test/integration/default/serverspec/localhost/consul_spec.rb b/test/integration/default/serverspec/localhost/default_spec.rb similarity index 100% rename from test/integration/default/serverspec/localhost/consul_spec.rb rename to test/integration/default/serverspec/localhost/default_spec.rb diff --git a/test/integration/default/serverspec/spec_helper.rb b/test/integration/default/serverspec/spec_helper.rb deleted file mode 100644 index c0925118..00000000 --- a/test/integration/default/serverspec/spec_helper.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'serverspec' - -set :backend, :exec - -RSpec.configure do |c| - c.path = '/usr/local/bin:/sbin:/bin:/usr/bin' -end diff --git a/test/integration/helpers/serverspec/spec_helper.rb b/test/integration/helpers/serverspec/spec_helper.rb new file mode 100644 index 00000000..37af1b45 --- /dev/null +++ b/test/integration/helpers/serverspec/spec_helper.rb @@ -0,0 +1,3 @@ +require 'serverspec' + +set :backend, :exec diff --git a/test/integration/ui/serverspec/localhost/consul_spec.rb b/test/integration/ui/serverspec/localhost/default_spec.rb similarity index 100% rename from test/integration/ui/serverspec/localhost/consul_spec.rb rename to test/integration/ui/serverspec/localhost/default_spec.rb diff --git a/test/integration/ui/serverspec/spec_helper.rb b/test/integration/ui/serverspec/spec_helper.rb deleted file mode 100644 index 1f1bebea..00000000 --- a/test/integration/ui/serverspec/spec_helper.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'serverspec' - -set :backend, :exec -set :path, '$PATH:/usr/local/bin:/sbin:/bin:/usr/bin' diff --git a/test/spec/libraries/consul_config_spec.rb b/test/spec/libraries/consul_config_spec.rb new file mode 100644 index 00000000..6eed3536 --- /dev/null +++ b/test/spec/libraries/consul_config_spec.rb @@ -0,0 +1,77 @@ +require 'spec_helper' + +describe_recipe 'consul::default' do + context 'with default attributes' do + cached(:chef_run) { ChefSpec::ServerRunner.new(step_into: %w{consul_config}).converge(described_recipe) } + + it { expect(chef_run).not_to include_recipe('chef-vault::default') } + it do + expect(chef_run).to create_file('/etc/consul.d/default.json') + .with(owner: 'consul') + .with(group: 'consul') + .with(mode: '0640') + end + + it 'converges successfully' do + chef_run + end + end + + context 'with verify_incoming & verify_outgoing = true' do + cached(:chef_run) do + ChefSpec::ServerRunner.new(step_into: %w{consul_config}) do |node, server| + server.create_data_bag('secrets', { + 'consul' => { + 'ca_certificate' => 'foo', + 'certificate' => 'bar', + 'private_key' => 'baz' + } + }) + + node.set['consul']['config']['verify_incoming'] = true + node.set['consul']['config']['verify_outgoing'] = true + end.converge(described_recipe) + end + + it { expect(chef_run).to include_recipe('chef-vault::default') } + it { expect(chef_run).to create_directory('/etc/ssl/certs') } + it { expect(chef_run).to create_directory('/etc/ssl/private') } + it { expect(chef_run).to create_directory('/etc/ssl/CA') } + + it do + expect(chef_run).to create_file('/etc/consul.d/default.json') + .with(owner: 'consul') + .with(group: 'consul') + .with(mode: '0640') + end + + it do + expect(chef_run).to create_file('/etc/ssl/CA/consul.crt') + .with(content: 'foo') + .with(owner: 'consul') + .with(group: 'consul') + .with(mode: '0644') + end + + it do + expect(chef_run).to create_file('/etc/ssl/certs/consul.crt') + .with(content: 'bar') + .with(owner: 'consul') + .with(group: 'consul') + .with(mode: '0644') + end + + it do + expect(chef_run).to create_file('/etc/ssl/private/consul.key') + .with(content: 'baz') + .with(sensitive: true) + .with(owner: 'consul') + .with(group: 'consul') + .with(mode: '0640') + end + + it 'converges successfully' do + chef_run + end + end +end diff --git a/test/spec/libraries/consul_service_spec.rb b/test/spec/libraries/consul_service_spec.rb new file mode 100644 index 00000000..11141048 --- /dev/null +++ b/test/spec/libraries/consul_service_spec.rb @@ -0,0 +1,73 @@ +require 'spec_helper' + +describe_recipe 'consul::default' do + context 'with default attributes' do + cached(:chef_run) do + ChefSpec::ServerRunner.new(step_into: %w{consul_service}) do |node, server| + server.create_data_bag('secrets', { + 'consul' => { + 'ca_certificate' => 'foo', + 'certificate' => 'bar', + 'private_key' => 'baz' + } + }) + end.converge(described_recipe) + end + + it { expect(chef_run).to create_libartifact_file('consul-0.5.2') } + it { expect(chef_run).to create_link('/usr/local/bin/consul').with(to: '/srv/consul/0.5.2/consul') } + + it 'converges successfully' do + chef_run + end + end + + context "with node['consul']['service']['install_method'] = :source" do + cached(:chef_run) do + ChefSpec::ServerRunner.new(step_into: %w{consul_service}) do |node, server| + server.create_data_bag('secrets', { + 'consul' => { + 'ca_certificate' => 'foo', + 'certificate' => 'bar', + 'private_key' => 'baz' + } + }) + + node.set['consul']['service']['install_method'] = :source + server.update_node(node) + end.converge(described_recipe) + end + + it { expect(chef_run).to include_recipe('golang::default') } + it { expect(chef_run).to create_directory('/srv/consul/src') } + it { expect(chef_run).to checkout_git('/srv/consul/src/consul-0.5.2') } + it { expect(chef_run).to create_link('/usr/local/bin/consul').with(to: '/srv/consul/0.5.2/consul') } + + it 'converges successfully' do + chef_run + end + end + + context "with node['consul']['service']['install_method'] = :package" do + cached(:chef_run) do + ChefSpec::ServerRunner.new(step_into: %w{consul_service}) do |node, server| + server.create_data_bag('secrets', { + 'consul' => { + 'ca_certificate' => 'foo', + 'certificate' => 'bar', + 'private_key' => 'baz' + } + }) + + node.set['consul']['service']['install_method'] = :package + server.update_node(node) + end.converge(described_recipe) + end + + it { expect(chef_run).to install_package('consul') } + + it 'converges successfully' do + chef_run + end + end +end diff --git a/test/spec/recipes/default_recipe.rb b/test/spec/recipes/default_recipe.rb new file mode 100644 index 00000000..19510f6e --- /dev/null +++ b/test/spec/recipes/default_recipe.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe_recipe 'consul::default' do + cached(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) } + + context 'with default attributes' do + it { expect(chef_run).to include_recipe('selinux::permissive') } + it { expect(chef_run).to create_poise_service_user('consul').with(group: 'consul') } + it { expect(chef_run).to create_consul_config('/etc/consul.json') } + it { expect(chef_run).to enable_consul_service('consul').with(config_file: '/etc/consul.json') } + + it 'converges successfully' do + chef_run + end + end +end diff --git a/test/spec/spec_helper.rb b/test/spec/spec_helper.rb new file mode 100644 index 00000000..12d3ff8e --- /dev/null +++ b/test/spec/spec_helper.rb @@ -0,0 +1,40 @@ +require 'chefspec' +require 'chefspec/berkshelf' +require 'chefspec/cacher' +require 'chef-vault' + +RSpec.configure do |config| + config.platform = 'ubuntu' + config.version = '14.04' + + config.color = true + config.alias_example_group_to :describe_recipe, type: :recipe + + config.filter_run :focus + config.run_all_when_everything_filtered = true + + Kernel.srand config.seed + config.order = :random + + if config.files_to_run.one? + config.default_formatter = 'doc' + end + + config.expect_with :rspec do |expectations| + expectations.syntax = :expect + end + + config.mock_with :rspec do |mocks| + mocks.syntax = :expect + mocks.verify_partial_doubles = true + end +end + +at_exit { ChefSpec::Coverage.report! } + +RSpec.shared_context 'recipe tests', type: :recipe do + before do + stub_command("test -L /usr/local/bin/consul").and_return(true) + stub_command("/usr/local/go/bin/go version | grep \"go1.4 \"").and_return(true) + end +end From c60909eb578756f1f579c3042e4fb56db90afc71 Mon Sep 17 00:00:00 2001 From: John Bellone Date: Sun, 14 Jun 2015 21:47:49 -0400 Subject: [PATCH 02/22] Fixes the permissions on the private key. --- README.md | 17 +++++++++++++++-- attributes/default.rb | 8 ++++---- libraries/consul_config.rb | 2 +- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index f6e9e4c7..1eb8e21e 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,24 @@ This cookbook provides resource and provider primitives to manage the Consul client, server and UI. These primitives are what is used in the recipes, and should be used in your own [wrapper cookbooks][2]. -### consul_client ### consul_config +```ruby +consul_config '/etc/consul.json' do + user 'consul' + group 'consul' +end +``` +### consul_definition ### consul_service +```ruby +consul_service 'consul' do + user 'consul' + group 'consul' + install_method :binary + binary_url node['consul']['binary_url'] +end +``` ### consul_watch -### consul_definition [0]: http://blog.vialstudios.com/the-environment-cookbook-pattern/#theapplicationcookbook [1]: http://consul.io diff --git a/attributes/default.rb b/attributes/default.rb index 8025c88e..e555b2a8 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -1,6 +1,6 @@ # # Cookbook: consul -# License: Apache 2.0 +# License:: Apache 2.0 # # Copyright 2014, 2015 Bloomberg Finance L.P. # @@ -13,10 +13,10 @@ default['consul']['bag_item'] = 'consul' default['consul']['config']['data_dir'] = '/var/lib/consul' -default['consul']['config']['ca_file'] = '/etc/ssl/CA/consul.crt' -default['consul']['config']['cert_file'] = '/etc/ssl/certs/consul.crt' +default['consul']['config']['ca_file'] = '/etc/consul/ca.crt' +default['consul']['config']['cert_file'] = '/etc/consul/consul.crt' default['consul']['config']['client_addr'] = '0.0.0.0' -default['consul']['config']['key_file'] = '/etc/ssl/private/consul.key' +default['consul']['config']['key_file'] = '/etc/consul/consul.key' default['consul']['config']['ports'] = { 'dns' => 8600, 'http' => 8500, diff --git a/libraries/consul_config.rb b/libraries/consul_config.rb index 9910362f..a619b30b 100644 --- a/libraries/consul_config.rb +++ b/libraries/consul_config.rb @@ -118,7 +118,7 @@ def tls? file new_resource.key_file do sensitive true content item['private_key'] - mode '0644' + mode '0640' owner new_resource.user group new_resource.group end From ae2e69204fdbc8706598f05bbbcde7c3e7d9c5bb Mon Sep 17 00:00:00 2001 From: John Bellone Date: Mon, 15 Jun 2015 07:41:46 -0400 Subject: [PATCH 03/22] Adds data bag stub for consul integration testing. --- test/fixtures/data_bags/secrets/consul.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 test/fixtures/data_bags/secrets/consul.json diff --git a/test/fixtures/data_bags/secrets/consul.json b/test/fixtures/data_bags/secrets/consul.json new file mode 100644 index 00000000..98db07f5 --- /dev/null +++ b/test/fixtures/data_bags/secrets/consul.json @@ -0,0 +1,6 @@ +{ + "id": "consul", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDjzCCAnegAwIBAgIBCjANBgkqhkiG9w0BAQUFADB8MQswCQYDVQQGEwJVUzER\nMA8GA1UECBMITmV3IFlvcmsxFjAUBgNVBAcTDU5ldyBZb3JrIENpdHkxHzAdBgNV\nBAoTFkJsb29tYmVyZyBGaW5hbmNlIEwuUC4xITAfBgNVBAsUGFImRCBQbGF0Zm9y\nbSBFbmdpbmVlcmluZzAeFw0xNTA2MTUxMTM1MDhaFw0yNTA2MTIxMTM1MDhaMIGi\nMRUwEwYDVQQDEwxKb2huIEJlbGxvbmUxETAPBgNVBAgTCE5ldyBZb3JrMQswCQYD\nVQQGEwJVUzElMCMGCSqGSIb3DQEJARYWamJlbGxvbmVAYmxvb21iZXJnLm5ldDEf\nMB0GA1UEChMWQmxvb21iZXJnIEZpbmFuY2UgTC5QLjEhMB8GA1UECxQYUiZEIFBs\nYXRmb3JtIEVuZ2luZWVyaW5nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO\nJTDt2WDTCKeB2ubzvBbE5ziCQZwGj1T4/uzlXlrybQ9q5M+oQDD44WRzSANx3Vx+\nI6ao57z6QtA5qOG9cw3csFgsMn6lVLzoegm2wQ7UhvqfcD2SOOWHBBsXp8VmX+ay\nOXpKRT5UOdLx3AczoUTua7aVsXDk/FJ9D4NV8NOF5wIDAQABo3kwdzAJBgNVHRME\nAjAAMB0GA1UdDgQWBBRo/0cnJ6coZaWuE+M7oqSsZ52vBjAfBgNVHSMEGDAWgBS5\nzSJ2wMBbmqDs6IlOdrUynXj8gTALBgNVHQ8EBAMCBaAwHQYDVR0lBBYwFAYIKwYB\nBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4IBAQCzqVLJ+v+yzvA0RFif\nf6j4DMj8MT/bxyaaX6SwYoC4ILIZjJ9Pn/1LwxZUfOkpEXwOQnT4G1epvuJIhXL7\nkILMoewMxseY6laHW4vCo3w4UJsKKlSnGinSkUun+CtI2CpPaIZ4bRnKsYGdqzeN\nShbn7xVc+oVS4tQA72T4g7WltVGTM+At6EKhKCvbEUiZ3OznFHEmvxYzrGZGii18\nyamF6DtSIS4a6E1G5zDGr2ba4THcHBuV9JsZeQhg9UlGdyA30n9zz5M8QJpUr34Z\nfRGmyGq+fIwpH639F/I2sLNIcZKsPbjfVojK+4e6d4t4rQiqo1jv9YZUvgvDIiu8\nWatv\n-----END CERTIFICATE-----\n", + "ca_certificate": "-----BEGIN CERTIFICATE-----\nMIIEXjCCA0agAwIBAgIJAJ4alkWMxGdeMA0GCSqGSIb3DQEBBQUAMHwxCzAJBgNV\nBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazEWMBQGA1UEBxMNTmV3IFlvcmsgQ2l0\neTEfMB0GA1UEChMWQmxvb21iZXJnIEZpbmFuY2UgTC5QLjEhMB8GA1UECxQYUiZE\nIFBsYXRmb3JtIEVuZ2luZWVyaW5nMB4XDTE1MDYxNTExMzEyMVoXDTI1MDYxMjEx\nMzEyMVowfDELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMRYwFAYDVQQH\nEw1OZXcgWW9yayBDaXR5MR8wHQYDVQQKExZCbG9vbWJlcmcgRmluYW5jZSBMLlAu\nMSEwHwYDVQQLFBhSJkQgUGxhdGZvcm0gRW5naW5lZXJpbmcwggEiMA0GCSqGSIb3\nDQEBAQUAA4IBDwAwggEKAoIBAQDnEeVEYXozw1TPU15hyGN89eD07MOLHF4eAU7n\neZXNNHNYuuX4Ub2nbpAbekO7Muq2s9I3x+CzGfMSkKSxSh8aT+S1Fu9xxA91VE8L\nMIFZTy+O4CFWYzYaRXI+hJ5Hf0JF/pHPyfZbYX2gSUIWmxjBDnpUNeCfr/LrWRpn\nXL8GoIeKrINXGwJJas7ZLuW/TmaOIlwFD+mRl6hAlyYbekozSnCLL8PfE+F5iVK2\nRbra1z3WFiHNvMnBRaZIiUdci0JRmccdc3IEM301ZJjD0PbXpoW+4r/bAiJxT3Gw\n6X2rjES6du/MnlApr3yUuGhF46Eb5RrTRZSRRWDiqOqWNSy/AgMBAAGjgeIwgd8w\nHQYDVR0OBBYEFLnNInbAwFuaoOzoiU52tTKdePyBMIGvBgNVHSMEgacwgaSAFLnN\nInbAwFuaoOzoiU52tTKdePyBoYGApH4wfDELMAkGA1UEBhMCVVMxETAPBgNVBAgT\nCE5ldyBZb3JrMRYwFAYDVQQHEw1OZXcgWW9yayBDaXR5MR8wHQYDVQQKExZCbG9v\nbWJlcmcgRmluYW5jZSBMLlAuMSEwHwYDVQQLFBhSJkQgUGxhdGZvcm0gRW5naW5l\nZXJpbmeCCQCeGpZFjMRnXjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IB\nAQBGyM0eOlHYyGFyYs/mPZv+UMifwITnUqnDBpbMZmoWUFBQMqAbc/XRbrBH5bpm\nXuEoV4PqEnkzSsMZN2bHulyor2wrgh5AoO1rEW6QghGlMG0dbwcqtA0D+JPzb13c\nw3TLD6LOo8O+1lymNe18nhdye3xxN+IYzxwAvQwszbupFqQ1f8EiNcTgxTfiVr56\n84ca5/3YRtV12CiFy0RICjw062UeJ03ki15HNp0bLWXnZFcK+MqL7sH9/ZoKBfKq\n3WXH3r45LJlMpNxZJYIAODMKe8WGj8Y61cfyYEed3wszEYqe7u6L+2Hee5XWDSi4\n91WN5l6KnBpBpYOERH1BfEie\n-----END CERTIFICATE-----\n", + "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIICXQIBAAKBgQDOJTDt2WDTCKeB2ubzvBbE5ziCQZwGj1T4/uzlXlrybQ9q5M+o\nQDD44WRzSANx3Vx+I6ao57z6QtA5qOG9cw3csFgsMn6lVLzoegm2wQ7UhvqfcD2S\nOOWHBBsXp8VmX+ayOXpKRT5UOdLx3AczoUTua7aVsXDk/FJ9D4NV8NOF5wIDAQAB\nAoGBAKmI+KaD4hdsxKYM62eERo2FQ3oMj07tzgpBTX6NjOpXOxjEOOu8bwogA8az\ncPHSBWFP3J6Ih2iiTjE9bPmrh7d/feEArjNUAL0ntcM3VFDX3IcZis8ZjgVqQG1J\nwvpn2o1qP37FJE1JSVdzN0MvWzFzgmhewxLqJcnFbUJysbaBAkEA8oW5EEd5beZO\nZ7V71C6EfOQw3HeCo34M5ndhI7rIa4MeLnLMVYBYodIezNdWHsFV7lqSkJamrKH9\nfLzjrsvMYQJBANmZ8d9QmfYJfBlJqZQziUqmEXQ8a7A0zW8WnFWgQrpLojs+eEMm\nx0Xb1IdyQT3Irl9+cE8lVoAiF8RxWd+FN0cCQQCR2IE2nQUVZk74Z1eUfnUGdmQ7\n8VMK5x7y6g/s4MLuhOd9n2Pqd0jV5/rFzSnpTPNUZ/uEIFUTtEcw4Jc74yuBAkBh\n15KmMvvHYWRninOxq6qj4iAe/7v8MwHcXXJWHgVi9vcvZFt29kzL4JijfoBPY5jk\nX1nofIV0f9/n+H/MvX2pAkBtiZ0gtW35QOmWdhqnOqpToOcNdzw6ON8d2bAx2mA1\nQm5P2pmsxEBJ3cSElRvOK+36OMWr0uMjUz5IogI6Fas7\n-----END RSA PRIVATE KEY-----\n" +} From 25eccc8112b9dcba1010501041e3b7bd9e65ba80 Mon Sep 17 00:00:00 2001 From: John Bellone Date: Mon, 15 Jun 2015 09:47:58 -0400 Subject: [PATCH 04/22] Updates the directories and tests for /etc/consul.d/ssl. --- attributes/default.rb | 6 +- .../serverspec/localhost/consul_spec.rb | 55 ------------------- .../packages/serverspec/spec_helper.rb | 7 --- .../ui/serverspec/localhost/default_spec.rb | 11 ---- test/spec/libraries/consul_config_spec.rb | 6 +- 5 files changed, 6 insertions(+), 79 deletions(-) delete mode 100644 test/integration/packages/serverspec/localhost/consul_spec.rb delete mode 100644 test/integration/packages/serverspec/spec_helper.rb delete mode 100644 test/integration/ui/serverspec/localhost/default_spec.rb diff --git a/attributes/default.rb b/attributes/default.rb index e555b2a8..0f6ceed4 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -13,10 +13,10 @@ default['consul']['bag_item'] = 'consul' default['consul']['config']['data_dir'] = '/var/lib/consul' -default['consul']['config']['ca_file'] = '/etc/consul/ca.crt' -default['consul']['config']['cert_file'] = '/etc/consul/consul.crt' +default['consul']['config']['ca_file'] = '/etc/consul.d/ssl/CA/ca.crt' +default['consul']['config']['cert_file'] = '/etc/consul.d/ssl/certs/consul.crt' default['consul']['config']['client_addr'] = '0.0.0.0' -default['consul']['config']['key_file'] = '/etc/consul/consul.key' +default['consul']['config']['key_file'] = '/etc/consul.d/ssl/private/consul.key' default['consul']['config']['ports'] = { 'dns' => 8600, 'http' => 8500, diff --git a/test/integration/packages/serverspec/localhost/consul_spec.rb b/test/integration/packages/serverspec/localhost/consul_spec.rb deleted file mode 100644 index aee11c01..00000000 --- a/test/integration/packages/serverspec/localhost/consul_spec.rb +++ /dev/null @@ -1,55 +0,0 @@ -require 'spec_helper' - -describe command('which consul') do - its(:exit_status) { should eq 0 } - its(:stdout) { should match '/usr/local/bin/consul' } -end - -describe service('consul') do - it { should be_enabled } - it { should be_running } -end - -describe file('/etc/consul.d') do - it { should be_directory } -end - -describe file('/var/lib/consul') do - it { should be_directory } -end - -[8300, 8400, 8500, 8600].each do |p| - describe port(p) do - it { should be_listening } - end -end - -describe command 'consul members -detailed' do - its(:exit_status) { should eq 0 } - its(:stdout) { should match %r{\balive\b} } - its(:stdout) { should match %r{\brole=consul\b} } - its(:stdout) { should match %r{\bbootstrap=1\b} } -end - -describe 'config file attributes' do - context command 'consul members -detailed' do - its(:stdout) { should match %r{\bdc=fortmeade\b} } - end -end - -eth0_ip = command("/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'").stdout.strip -describe command("grep #{eth0_ip} /etc/consul.d/default.json") do - its(:exit_status) { should eq 0 } - # bind_addr should only be in the config if node[:consul][:bind_addr] is set - its(:stdout) { should match %r{"bind_addr":\s"#{eth0_ip}"}} - its(:stdout) { should match %r{"advertise_addr":\s"#{eth0_ip}"}} -end - -describe command('grep encrypt /etc/consul.d/default.json') do - its(:exit_status) { should eq 0 } - its(:stdout) { should match %r{"encrypt":\s"([^\"]*)"} } -end - -describe file('/var/lib/consul/ui/index.html') do - it { should be_file } -end diff --git a/test/integration/packages/serverspec/spec_helper.rb b/test/integration/packages/serverspec/spec_helper.rb deleted file mode 100644 index c0925118..00000000 --- a/test/integration/packages/serverspec/spec_helper.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'serverspec' - -set :backend, :exec - -RSpec.configure do |c| - c.path = '/usr/local/bin:/sbin:/bin:/usr/bin' -end diff --git a/test/integration/ui/serverspec/localhost/default_spec.rb b/test/integration/ui/serverspec/localhost/default_spec.rb deleted file mode 100644 index 69c84958..00000000 --- a/test/integration/ui/serverspec/localhost/default_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'spec_helper' - -describe file('/var/lib/consul/ui/index.html') do - it { should be_file } -end - -eth0_ip = command("/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'").stdout.strip -describe command("wget -q -O- http://#{eth0_ip}:8500/ui/index.html") do - its(:exit_status) { should eq 0 } - its(:stdout) { should eq File.read('/var/lib/consul/ui/index.html') } -end diff --git a/test/spec/libraries/consul_config_spec.rb b/test/spec/libraries/consul_config_spec.rb index 6eed3536..31878f81 100644 --- a/test/spec/libraries/consul_config_spec.rb +++ b/test/spec/libraries/consul_config_spec.rb @@ -46,7 +46,7 @@ end it do - expect(chef_run).to create_file('/etc/ssl/CA/consul.crt') + expect(chef_run).to create_file('/etc/consul.d/ssl/CA/consul.crt') .with(content: 'foo') .with(owner: 'consul') .with(group: 'consul') @@ -54,7 +54,7 @@ end it do - expect(chef_run).to create_file('/etc/ssl/certs/consul.crt') + expect(chef_run).to create_file('/etc/consul.d/ssl/certs/consul.crt') .with(content: 'bar') .with(owner: 'consul') .with(group: 'consul') @@ -62,7 +62,7 @@ end it do - expect(chef_run).to create_file('/etc/ssl/private/consul.key') + expect(chef_run).to create_file('/etc/consul.d/ssl/private/consul.key') .with(content: 'baz') .with(sensitive: true) .with(owner: 'consul') From beda08bc28558d4baaeeaa04811ad5d2ae275c73 Mon Sep 17 00:00:00 2001 From: John Bellone Date: Tue, 16 Jun 2015 06:41:28 -0400 Subject: [PATCH 05/22] Fixes a few bits after a code review. @coderanger pointed out a few things that I could spruce up. --- .kitchen.yml | 48 +++++++--------------- attributes/default.rb | 7 ++-- libraries/consul_service.rb | 9 ++-- recipes/default.rb | 15 +++---- test/spec/libraries/consul_config_spec.rb | 6 +-- test/spec/libraries/consul_service_spec.rb | 10 ++--- 6 files changed, 35 insertions(+), 60 deletions(-) diff --git a/.kitchen.yml b/.kitchen.yml index 35385b06..9db8b4e2 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -17,48 +17,30 @@ suites: - recipe[consul::default] attributes: consul: - datacenter: FortMeade - bind_interface: eth0 - advertise_interface: eth0 - encrypt: CGXC2NsXW4AvuB4h5ODYzQ== + config: + datacenter: FortMeade + bind_interface: eth0 + advertise_interface: eth0 + encrypt: CGXC2NsXW4AvuB4h5ODYzQ== - name: source run_list: - recipe[consul::default] attributes: consul: - install_method: source - - name: packages + service: + install_method: source + - name: package run_list: - recipe[consul::default] attributes: consul: - datacenter: FortMeade - bind_interface: eth0 - advertise_interface: eth0 - encrypt: CGXC2NsXW4AvuB4h5ODYzQ== - install_method: packages + service: + install_method: package + config: + datacenter: FortMeade + bind_interface: eth0 + advertise_interface: eth0 + encrypt: CGXC2NsXW4AvuB4h5ODYzQ== excludes: - centos-7.0 - centos-6.5 - - name: runit - run_list: - - recipe[consul::default] - attributes: - consul: - datacenter: FortMeade - init_style: runit - - name: ui - run_list: - - recipe[consul::default] - - recipe[consul::ui] - attributes: - consul: - serve_ui: true - client_interface: eth0 - - name: cluster - run_list: - - recipe[consul::default] - attributes: - consul: - service_mode: cluster - bootstrap_expect: 1 diff --git a/attributes/default.rb b/attributes/default.rb index 0f6ceed4..a3858722 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -4,7 +4,6 @@ # # Copyright 2014, 2015 Bloomberg Finance L.P. # - default['consul']['service_name'] = 'consul' default['consul']['service_user'] = 'consul' default['consul']['service_group'] = 'consul' @@ -26,12 +25,12 @@ "server" => 8300, } -default['consul']['service']['install_method'] = :binary +default['consul']['service']['install_method'] = 'binary' default['consul']['service']['config_file'] = '/etc/consul.json' default['consul']['service']['config_dir'] = '/etc/consul.d' +default['consul']['service']['binary_url'] = "https://dl.bintray.com/mitchellh/consul/%{filename}.zip" +default['consul']['service']['source_url'] = 'https://github.com/hashicorp/consul' -default['consul']['binary_url'] = "https://dl.bintray.com/mitchellh/consul/%{filename}.zip" -default['consul']['source_url'] = 'https://github.com/hashicorp/consul' default['consul']['version'] = '0.5.2' default['consul']['checksums'] = { '0.5.0_darwin_amd64' => '24d9758c873e9124e0ce266f118078f87ba8d8363ab16c2e59a3cd197b77e964', diff --git a/libraries/consul_service.rb b/libraries/consul_service.rb index 2a549f1a..30a257b3 100644 --- a/libraries/consul_service.rb +++ b/libraries/consul_service.rb @@ -9,6 +9,7 @@ # Resource for managing the Consul service on an instance. # @since 1.0.0 class Chef::Resource::ConsulService < Chef::Resource + include Poise provides(:consul_service) include PoiseService::ServiceMixin @@ -22,7 +23,7 @@ class Chef::Resource::ConsulService < Chef::Resource # @!attribute install_method # @return [Symbol] - attribute(:install_method, default: :binary, equal_to: %i{source binary package}) + attribute(:install_method, default: 'binary', equal_to: %w{source binary package}) # @!attribute install_path # @return [String] @@ -104,10 +105,10 @@ def action_enable package new_resource.package_name do version new_resource.version unless new_resource.version.nil? - only_if { new_resource.install_method == :package } + only_if { new_resource.install_method == 'package' } end - if new_resource.install_method == :binary + if new_resource.install_method == 'binary' artifact = libartifact_file "consul-#{new_resource.version}" do artifact_name 'consul' artifact_version new_resource.version @@ -121,7 +122,7 @@ def action_enable end end - if new_resource.install_method == :source + if new_resource.install_method == 'source' include_recipe 'golang::default' source_dir = directory ::File.join(new_resource.install_path, 'consul', 'src') do diff --git a/recipes/default.rb b/recipes/default.rb index c20e1715..711b6aa8 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -10,24 +10,19 @@ group node['consul']['service_group'] end -consul_config node['consul']['service']['config_file'] do |resource| +consul_config node['consul']['service']['config_file'] do |r| user node['consul']['service_user'] group node['consul']['service_group'] - node['consul']['config'].each_pair { |k, v| resource.send(k, v) } + node['consul']['config'].each_pair { |k, v| r.send(k, v) } notifies :restart, "consul_service[#{node['consul']['service_name']}]", :delayed end -consul_service node['consul']['service_name'] do +consul_service node['consul']['service_name'] do |r| user node['consul']['service_user'] group node['consul']['service_group'] version node['consul']['version'] - install_method node['consul']['service']['install_method'] - install_path node['consul']['service']['install_path'] - config_dir node['consul']['service']['config_dir'] - config_file node['consul']['service']['config_file'] - package_name node['consul']['package_name'] - binary_url node['consul']['binary_url'] - source_url node['consul']['source_url'] + node['consul']['service'].each_pair { |k, v| r.send(k, v) } + action [:enable, :start] end diff --git a/test/spec/libraries/consul_config_spec.rb b/test/spec/libraries/consul_config_spec.rb index 31878f81..312c64b5 100644 --- a/test/spec/libraries/consul_config_spec.rb +++ b/test/spec/libraries/consul_config_spec.rb @@ -34,9 +34,9 @@ end it { expect(chef_run).to include_recipe('chef-vault::default') } - it { expect(chef_run).to create_directory('/etc/ssl/certs') } - it { expect(chef_run).to create_directory('/etc/ssl/private') } - it { expect(chef_run).to create_directory('/etc/ssl/CA') } + it { expect(chef_run).to create_directory('/etc/consul.d/ssl/certs') } + it { expect(chef_run).to create_directory('/etc/consul.d/ssl/private') } + it { expect(chef_run).to create_directory('/etc/consul.d/ssl/CA') } it do expect(chef_run).to create_file('/etc/consul.d/default.json') diff --git a/test/spec/libraries/consul_service_spec.rb b/test/spec/libraries/consul_service_spec.rb index 11141048..61158b6d 100644 --- a/test/spec/libraries/consul_service_spec.rb +++ b/test/spec/libraries/consul_service_spec.rb @@ -22,7 +22,7 @@ end end - context "with node['consul']['service']['install_method'] = :source" do + context "with node['consul']['service']['install_method'] = 'source'" do cached(:chef_run) do ChefSpec::ServerRunner.new(step_into: %w{consul_service}) do |node, server| server.create_data_bag('secrets', { @@ -33,8 +33,7 @@ } }) - node.set['consul']['service']['install_method'] = :source - server.update_node(node) + node.set['consul']['service']['install_method'] = 'source' end.converge(described_recipe) end @@ -48,7 +47,7 @@ end end - context "with node['consul']['service']['install_method'] = :package" do + context "with node['consul']['service']['install_method'] = 'package'" do cached(:chef_run) do ChefSpec::ServerRunner.new(step_into: %w{consul_service}) do |node, server| server.create_data_bag('secrets', { @@ -59,8 +58,7 @@ } }) - node.set['consul']['service']['install_method'] = :package - server.update_node(node) + node.set['consul']['service']['install_method'] = 'package' end.converge(described_recipe) end From faef8cf992d9de29f2a074240a2e7e035fc899a3 Mon Sep 17 00:00:00 2001 From: John Bellone Date: Tue, 16 Jun 2015 06:48:15 -0400 Subject: [PATCH 06/22] Adds support for running Consul under runit provider. It seems that some people really dig runit. I don't get all the hype. But here it is courtesy of @coderanger. --- .kitchen.yml | 16 ++++++++++------ metadata.rb | 1 + recipes/runit.rb | 9 +++++++++ .../runit/serverspec/localhost/default_spec.rb | 6 ++++++ .../{default_recipe.rb => default_spec.rb} | 0 test/spec/recipes/runit_spec.rb | 14 ++++++++++++++ 6 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 recipes/runit.rb create mode 100644 test/integration/runit/serverspec/localhost/default_spec.rb rename test/spec/recipes/{default_recipe.rb => default_spec.rb} (100%) create mode 100644 test/spec/recipes/runit_spec.rb diff --git a/.kitchen.yml b/.kitchen.yml index 9db8b4e2..685c39ed 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -19,8 +19,14 @@ suites: consul: config: datacenter: FortMeade - bind_interface: eth0 - advertise_interface: eth0 + encrypt: CGXC2NsXW4AvuB4h5ODYzQ== + - name: runit + run_list: + - recipe[consul::default] + attributes: + consul: + config: + datacenter: FortMeade encrypt: CGXC2NsXW4AvuB4h5ODYzQ== - name: source run_list: @@ -38,9 +44,7 @@ suites: install_method: package config: datacenter: FortMeade - bind_interface: eth0 - advertise_interface: eth0 encrypt: CGXC2NsXW4AvuB4h5ODYzQ== excludes: - - centos-7.0 - - centos-6.5 + - centos-7.1 + - centos-6.4 diff --git a/metadata.rb b/metadata.rb index 3871b49e..2390a5a0 100644 --- a/metadata.rb +++ b/metadata.rb @@ -18,4 +18,5 @@ depends 'golang', '~> 1.4' depends 'poise', '~> 2.0' depends 'poise-service' +depends 'poise-service-runit' depends 'selinux' diff --git a/recipes/runit.rb b/recipes/runit.rb new file mode 100644 index 00000000..50f16e55 --- /dev/null +++ b/recipes/runit.rb @@ -0,0 +1,9 @@ +# +# Cookbook Name:: consul +# License:: Apache 2.0 +# +# Copyright 2014, 2015 Bloomberg Finance L.P. +# +node.default['poise-service']['provider'] = 'runit' +include_recipe 'runit::default' +include_recipe 'consul::default' diff --git a/test/integration/runit/serverspec/localhost/default_spec.rb b/test/integration/runit/serverspec/localhost/default_spec.rb new file mode 100644 index 00000000..156a0227 --- /dev/null +++ b/test/integration/runit/serverspec/localhost/default_spec.rb @@ -0,0 +1,6 @@ +require 'spec_helper' + +describe service('consul') do + it { should be_running.under('runit') } + it { should be_enabled } +end diff --git a/test/spec/recipes/default_recipe.rb b/test/spec/recipes/default_spec.rb similarity index 100% rename from test/spec/recipes/default_recipe.rb rename to test/spec/recipes/default_spec.rb diff --git a/test/spec/recipes/runit_spec.rb b/test/spec/recipes/runit_spec.rb new file mode 100644 index 00000000..eafd4564 --- /dev/null +++ b/test/spec/recipes/runit_spec.rb @@ -0,0 +1,14 @@ +require 'spec_helper' + +describe_recipe 'consul::runit' do + cached(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) } + + context 'with default attributes' do + it { expect(chef_run).to include_recipe('runit::default') } + it { expect(chef_run).to include_recipe('consul::default') } + + it 'converges successfully' do + chef_run + end + end +end From 07dca120ce3d68179efa09893808af412a35b62f Mon Sep 17 00:00:00 2001 From: John Bellone Date: Tue, 16 Jun 2015 06:59:49 -0400 Subject: [PATCH 07/22] Cleans up the rubocop bits. --- .rubocop.yml | 42 +++++++++++++++++++++++++++++++++++++----- .tailor | 30 ------------------------------ 2 files changed, 37 insertions(+), 35 deletions(-) delete mode 100644 .tailor diff --git a/.rubocop.yml b/.rubocop.yml index d4fdfa73..4e10fefd 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,9 +1,41 @@ --- -inherit_from: .rubocop_todo.yml +AlignParameters: + Enabled: false + +Encoding: + Enabled: false + +ClassLength: + Enabled: false + +MethodLength: + Enabled: false + +LineLength: + Enabled: false + +Documentation: + Enabled: false + +PerceivedComplexity: + Enabled: false + +CyclomaticComplexity: + Enabled: false + +Style/FileName: + Enabled: false + +Style/ClassAndModuleChildren: + Enabled: false + +Metrics/AbcSize: + Enabled: false AllCops: Exclude: - - 'bin/**/*' - - 'vendor/**/*' - - 'test/**/*' - - 'spec/**/*' + - 'Guardfile' + - 'test/**/*_spec.rb' + +Style/GuardClause: + Enabled: false diff --git a/.tailor b/.tailor deleted file mode 100644 index e7b9f312..00000000 --- a/.tailor +++ /dev/null @@ -1,30 +0,0 @@ -# -*- mode: ruby -*- -Tailor.config do |config| - config.formatters "text" - config.file_set 'recipes/**/*.rb' do |style| - style.allow_camel_case_methods false, level: :error - style.allow_conditional_parentheses false, level: :warn - style.allow_hard_tabs false, level: :error - style.allow_screaming_snake_case_classes false, level: :error - style.allow_trailing_line_spaces false, level: :error - style.allow_unnecessary_interpolation false, level: :warn - style.allow_unnecessary_double_quotes false, level: :warn - style.allow_invalid_ruby false, level: :warn - style.indentation_spaces 2, level: :error - style.max_code_lines_in_class 300, level: :error - style.max_code_lines_in_method 30, level: :error - style.max_line_length 80, level: :error - style.spaces_after_comma 1, level: :error - style.spaces_after_conditional 1, level: :error - style.spaces_after_lbrace 1, level: :error - style.spaces_after_lbracket 0, level: :error - style.spaces_after_lparen 0, level: :error - style.spaces_before_comma 0, level: :error - style.spaces_before_lbrace 1, level: :error - style.spaces_before_rbrace 1, level: :error - style.spaces_before_rbracket 0, level: :error - style.spaces_before_rparen 0, level: :error - style.spaces_in_empty_braces 0, level: :error - style.trailing_newlines 1, level: :error - end -end From e41c3d0ae2c6381f20c64f4e41d8b605c8570e62 Mon Sep 17 00:00:00 2001 From: John Bellone Date: Tue, 16 Jun 2015 08:04:08 -0400 Subject: [PATCH 08/22] Fixes a few more issues while test-kitchen converging. --- .kitchen.yml | 2 +- attributes/default.rb | 2 +- libraries/consul_service.rb | 3 ++- recipes/default.rb | 5 +++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.kitchen.yml b/.kitchen.yml index 685c39ed..d5f97c62 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -22,7 +22,7 @@ suites: encrypt: CGXC2NsXW4AvuB4h5ODYzQ== - name: runit run_list: - - recipe[consul::default] + - recipe[consul::runit] attributes: consul: config: diff --git a/attributes/default.rb b/attributes/default.rb index a3858722..a9ecce49 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -11,6 +11,7 @@ default['consul']['bag_name'] = 'secrets' default['consul']['bag_item'] = 'consul' +default['consul']['config']['path'] = '/etc/consul.json' default['consul']['config']['data_dir'] = '/var/lib/consul' default['consul']['config']['ca_file'] = '/etc/consul.d/ssl/CA/ca.crt' default['consul']['config']['cert_file'] = '/etc/consul.d/ssl/certs/consul.crt' @@ -26,7 +27,6 @@ } default['consul']['service']['install_method'] = 'binary' -default['consul']['service']['config_file'] = '/etc/consul.json' default['consul']['service']['config_dir'] = '/etc/consul.d' default['consul']['service']['binary_url'] = "https://dl.bintray.com/mitchellh/consul/%{filename}.zip" default['consul']['service']['source_url'] = 'https://github.com/hashicorp/consul' diff --git a/libraries/consul_service.rb b/libraries/consul_service.rb index 30a257b3..0812768f 100644 --- a/libraries/consul_service.rb +++ b/libraries/consul_service.rb @@ -66,7 +66,7 @@ class Chef::Resource::ConsulService < Chef::Resource attribute(:config_dir, kind_of: String, default: '/etc/consul.d') def default_environment - { GOMAXPROCS: [node['cpu']['total'], 2].max, PATH: '/usr/local/bin:/usr/bin:/bin' } + { GOMAXPROCS: [node['cpu']['total'], 2].max.to_s, PATH: '/usr/local/bin:/usr/bin:/bin' } end def command @@ -86,6 +86,7 @@ def binary_filename # Provider for managing the Consul service on an instance. # @since 1.0.0 class Chef::Provider::ConsulService < Chef::Provider + include Poise provides(:consul_service) include PoiseService::ServiceMixin diff --git a/recipes/default.rb b/recipes/default.rb index 711b6aa8..85228ad9 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -10,19 +10,20 @@ group node['consul']['service_group'] end -consul_config node['consul']['service']['config_file'] do |r| +config = consul_config node['consul']['service_name'] do |r| user node['consul']['service_user'] group node['consul']['service_group'] node['consul']['config'].each_pair { |k, v| r.send(k, v) } - notifies :restart, "consul_service[#{node['consul']['service_name']}]", :delayed end consul_service node['consul']['service_name'] do |r| user node['consul']['service_user'] group node['consul']['service_group'] version node['consul']['version'] + config_file config.path node['consul']['service'].each_pair { |k, v| r.send(k, v) } + subscribes :reload, "consul_config[#{config.name}]" action [:enable, :start] end From 71e8e334f5d43e42acc94dddf4bb84a4e6d47baf Mon Sep 17 00:00:00 2001 From: John Bellone Date: Wed, 17 Jun 2015 05:58:23 -0400 Subject: [PATCH 09/22] Removes the poise-runit cookbook after speaking with @coderanger. The way that this cookbook is intended to work is for it to be included in a [base cookbook][0] or an [environment cookbook][1] so that the whole infrastructure built with poise-service uses runit. [0]: http://blog.vialstudios.com/the-environment-cookbook-pattern/#thebasecookbook [1]: http://blog.vialstudios.com/the-environment-cookbook-pattern/#theenvironmentcookbook --- .kitchen.yml | 19 +++++------------ metadata.rb | 1 - recipes/runit.rb | 9 -------- .../serverspec/localhost/default_spec.rb | 21 ------------------- .../serverspec/localhost/default_spec.rb | 6 ------ test/spec/recipes/runit_spec.rb | 14 ------------- 6 files changed, 5 insertions(+), 65 deletions(-) delete mode 100644 recipes/runit.rb delete mode 100644 test/integration/runit/serverspec/localhost/default_spec.rb delete mode 100644 test/spec/recipes/runit_spec.rb diff --git a/.kitchen.yml b/.kitchen.yml index d5f97c62..218b7269 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -10,22 +10,14 @@ platforms: - name: ubuntu-12.04 - name: centos-7.1 - name: centos-6.6 - + suites: - name: default run_list: - recipe[consul::default] attributes: consul: - config: - datacenter: FortMeade - encrypt: CGXC2NsXW4AvuB4h5ODYzQ== - - name: runit - run_list: - - recipe[consul::runit] - attributes: - consul: - config: + config: &defaut-config datacenter: FortMeade encrypt: CGXC2NsXW4AvuB4h5ODYzQ== - name: source @@ -33,6 +25,7 @@ suites: - recipe[consul::default] attributes: consul: + config: *default-config service: install_method: source - name: package @@ -42,9 +35,7 @@ suites: consul: service: install_method: package - config: - datacenter: FortMeade - encrypt: CGXC2NsXW4AvuB4h5ODYzQ== + config: *default-config excludes: - centos-7.1 - - centos-6.4 + - centos-6.6 diff --git a/metadata.rb b/metadata.rb index 2390a5a0..3871b49e 100644 --- a/metadata.rb +++ b/metadata.rb @@ -18,5 +18,4 @@ depends 'golang', '~> 1.4' depends 'poise', '~> 2.0' depends 'poise-service' -depends 'poise-service-runit' depends 'selinux' diff --git a/recipes/runit.rb b/recipes/runit.rb deleted file mode 100644 index 50f16e55..00000000 --- a/recipes/runit.rb +++ /dev/null @@ -1,9 +0,0 @@ -# -# Cookbook Name:: consul -# License:: Apache 2.0 -# -# Copyright 2014, 2015 Bloomberg Finance L.P. -# -node.default['poise-service']['provider'] = 'runit' -include_recipe 'runit::default' -include_recipe 'consul::default' diff --git a/test/integration/default/serverspec/localhost/default_spec.rb b/test/integration/default/serverspec/localhost/default_spec.rb index 75161787..4256abb6 100644 --- a/test/integration/default/serverspec/localhost/default_spec.rb +++ b/test/integration/default/serverspec/localhost/default_spec.rb @@ -10,14 +10,6 @@ it { should be_running } end -describe file('/etc/consul.d') do - it { should be_directory } -end - -describe file('/var/lib/consul') do - it { should be_directory } -end - [8300, 8400, 8500, 8600].each do |p| describe port(p) do it { should be_listening } @@ -36,16 +28,3 @@ its(:stdout) { should match %r{\bdc=FortMeade\b}i } end end - -eth0_ip = command("/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'").stdout.strip -describe command("grep #{eth0_ip} /etc/consul.d/default.json") do - its(:exit_status) { should eq 0 } - # bind_addr should only be in the config if node[:consul][:bind_addr] is set - its(:stdout) { should match %r{"bind_addr":\s"#{eth0_ip}"}} - its(:stdout) { should match %r{"advertise_addr":\s"#{eth0_ip}"}} -end - -describe command('grep encrypt /etc/consul.d/default.json') do - its(:exit_status) { should eq 0 } - its(:stdout) { should match %r{"encrypt":\s"([^\"]*)"} } -end diff --git a/test/integration/runit/serverspec/localhost/default_spec.rb b/test/integration/runit/serverspec/localhost/default_spec.rb deleted file mode 100644 index 156a0227..00000000 --- a/test/integration/runit/serverspec/localhost/default_spec.rb +++ /dev/null @@ -1,6 +0,0 @@ -require 'spec_helper' - -describe service('consul') do - it { should be_running.under('runit') } - it { should be_enabled } -end diff --git a/test/spec/recipes/runit_spec.rb b/test/spec/recipes/runit_spec.rb deleted file mode 100644 index eafd4564..00000000 --- a/test/spec/recipes/runit_spec.rb +++ /dev/null @@ -1,14 +0,0 @@ -require 'spec_helper' - -describe_recipe 'consul::runit' do - cached(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) } - - context 'with default attributes' do - it { expect(chef_run).to include_recipe('runit::default') } - it { expect(chef_run).to include_recipe('consul::default') } - - it 'converges successfully' do - chef_run - end - end -end From 64a4532c7a80ab62d9598a50bcee64d37b550f4d Mon Sep 17 00:00:00 2001 From: John Bellone Date: Tue, 30 Jun 2015 23:33:53 -0400 Subject: [PATCH 10/22] Fixes integration testing issues with CentOS 6.6 and upstart. In all of RedHat's infinite wisdom it seems that upstart is available on EL6.6. The poise-service library cookbook we use defaults to that so we need to conver that test case in our integration tests. --- recipes/default.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/recipes/default.rb b/recipes/default.rb index 85228ad9..7d62ef5b 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -1,6 +1,6 @@ # -# Cookbook Name:: consul -# License:: Apache 2.0 +# Cookbook: consul +# License: Apache 2.0 # # Copyright 2014, 2015 Bloomberg Finance L.P. # @@ -15,6 +15,7 @@ group node['consul']['service_group'] node['consul']['config'].each_pair { |k, v| r.send(k, v) } + notifies :reload, "consul_service[#{name}]", :delayed end consul_service node['consul']['service_name'] do |r| @@ -24,6 +25,4 @@ config_file config.path node['consul']['service'].each_pair { |k, v| r.send(k, v) } - subscribes :reload, "consul_config[#{config.name}]" - action [:enable, :start] end From b26421c12f18fe7171e7cc9aa29b4e536997c0cc Mon Sep 17 00:00:00 2001 From: John Bellone Date: Tue, 30 Jun 2015 23:57:09 -0400 Subject: [PATCH 11/22] Fixes a bunch of issues with integration test harness. --- .kitchen.yml | 8 +++++--- .travis.yml | 10 ++-------- Vagrantfile | 8 ++++++++ attributes/default.rb | 2 +- libraries/consul_config.rb | 6 ++++-- libraries/consul_definition.rb | 2 +- libraries/consul_service.rb | 5 ++++- libraries/consul_watch.rb | 2 +- recipes/default.rb | 3 ++- .../serverspec/localhost/default_spec.rb | 20 +++++++++---------- test/spec/libraries/consul_config_spec.rb | 15 ++------------ 11 files changed, 40 insertions(+), 41 deletions(-) diff --git a/.kitchen.yml b/.kitchen.yml index 218b7269..ca389e65 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -10,14 +10,16 @@ platforms: - name: ubuntu-12.04 - name: centos-7.1 - name: centos-6.6 - + suites: - name: default run_list: - recipe[consul::default] attributes: consul: - config: &defaut-config + config: &default-config + bootstrap: true + server: true datacenter: FortMeade encrypt: CGXC2NsXW4AvuB4h5ODYzQ== - name: source @@ -33,9 +35,9 @@ suites: - recipe[consul::default] attributes: consul: + config: *default-config service: install_method: package - config: *default-config excludes: - centos-7.1 - centos-6.6 diff --git a/.travis.yml b/.travis.yml index 92e95513..7c6959e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ --- language: ruby +notifications: + slack: blpsi:eHp3Czg42iGzaTgG8sAFeD9v script: bin/rspec rvm: - 2.1 @@ -8,13 +10,5 @@ branches: only: - master builder_args: --jobs 7 -notifications: - irc: - channels: - - 'chat.freenode.net#bloomberg' - use_notice: true - skip_join: true - template: - - "%{message} (%{author}): %{build_url}" matrix: fast_finish: true diff --git a/Vagrantfile b/Vagrantfile index 46b63468..beb4dd3d 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -10,6 +10,14 @@ Vagrant.configure('2') do |config| guest.vm.provision :chef_zero do |chef| chef.nodes_path = File.expand_path('../.vagrant/chef/nodes', __FILE__) chef.run_list = %w(recipe[consul::default]) + chef.json = { + consul: { + config: { + bootstrap: true, + server: true + } + } + } end end end diff --git a/attributes/default.rb b/attributes/default.rb index a9ecce49..a55fc7cf 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -1,6 +1,6 @@ # # Cookbook: consul -# License:: Apache 2.0 +# License: Apache 2.0 # # Copyright 2014, 2015 Bloomberg Finance L.P. # diff --git a/libraries/consul_config.rb b/libraries/consul_config.rb index a619b30b..26400d46 100644 --- a/libraries/consul_config.rb +++ b/libraries/consul_config.rb @@ -9,7 +9,7 @@ class Chef::Resource::ConsulConfig < Chef::Resource include Poise(fused: true) provides(:consul_config) - actions(:create, :delete) + default_action(:create) # @!attribute path # @return [String] @@ -67,12 +67,14 @@ class Chef::Resource::ConsulConfig < Chef::Resource attribute(:ui_dir, kind_of: String) attribute(:verify_incoming, equal_to: [true, false], default: false) attribute(:verify_outgoing, equal_to: [true, false], default: false) + attribute(:verify_server_hostname, equal_to: [true, false], default: false) attribute(:watches, kind_of: [Hash, Mash], default: {}) # Transforms the resource into a JSON format which matches the # Consul service's configuration format. def to_json - for_keeps = %i{acl_datacenter acl_default_policy acl_down_policy acl_master_token acl_token acl_ttl addresses advertise_addr bind_addr bootstrap bootstrap_expect ca_file cert_file check_update_interval client_addr data_dir datacenter disable_anonymous_signature disable_remote_exec disable_update_check dns_config domain enable_debug enable_syslog encrypt key_file leave_on_terminate log_level node_name ports protocol recurser retry_interval server server_name skip_leave_on_interrupt start_join statsd_addr statsite_addr syslog_facility ui_dir verify_incoming verify_outgoing watches} + for_keeps = %i{acl_datacenter acl_default_policy acl_down_policy acl_master_token acl_token acl_ttl addresses advertise_addr bind_addr bootstrap bootstrap_expect check_update_interval client_addr data_dir datacenter disable_anonymous_signature disable_remote_exec disable_update_check dns_config domain enable_debug enable_syslog encrypt leave_on_terminate log_level node_name ports protocol recurser retry_interval server server_name skip_leave_on_interrupt start_join statsd_addr statsite_addr syslog_facility ui_dir verify_incoming verify_outgoing verify_server_hostname watches} + for_keeps << %i{ca_file cert_file key_file} if tls? config = to_hash.keep_if do |k, v| for_keeps.include?(k.to_sym) end diff --git a/libraries/consul_definition.rb b/libraries/consul_definition.rb index 97397e37..bcc4f5b2 100644 --- a/libraries/consul_definition.rb +++ b/libraries/consul_definition.rb @@ -9,7 +9,7 @@ class Chef::Resource::ConsulDefinition < Chef::Resource include Poise(fused: true) provides(:consul_definition) - actions(:create, :delete) + default_action(:create) # @!attribute path # @return [String] diff --git a/libraries/consul_service.rb b/libraries/consul_service.rb index 0812768f..d2367456 100644 --- a/libraries/consul_service.rb +++ b/libraries/consul_service.rb @@ -12,6 +12,7 @@ class Chef::Resource::ConsulService < Chef::Resource include Poise provides(:consul_service) include PoiseService::ServiceMixin + default_action(:enable) # @!attribute service_name # @return [String] @@ -70,7 +71,7 @@ def default_environment end def command - "consul agent -config-file=#{config_file} -config-dir=#{config_dir}" + "/usr/bin/env consul agent -config-file=#{config_file} -config-dir=#{config_dir}" end def binary_checksum @@ -106,6 +107,7 @@ def action_enable package new_resource.package_name do version new_resource.version unless new_resource.version.nil? + action :upgrade only_if { new_resource.install_method == 'package' } end @@ -116,6 +118,7 @@ def action_enable install_path new_resource.install_path remote_url new_resource.binary_url % { filename: new_resource.binary_filename } remote_checksum new_resource.binary_checksum + action :create end link '/usr/local/bin/consul' do diff --git a/libraries/consul_watch.rb b/libraries/consul_watch.rb index 6f46aa17..086f167c 100644 --- a/libraries/consul_watch.rb +++ b/libraries/consul_watch.rb @@ -9,7 +9,7 @@ class Chef::Resource::ConsulWatch < Chef::Resource include Poise(fused: true) provides(:consul_watch) - actions(:create, :delete) + default_action(:create) # @!attribute watch_name # @return [String] diff --git a/recipes/default.rb b/recipes/default.rb index 7d62ef5b..5fe6b1be 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -8,6 +8,7 @@ poise_service_user node['consul']['service_user'] do group node['consul']['service_group'] + action :create end config = consul_config node['consul']['service_name'] do |r| @@ -15,7 +16,6 @@ group node['consul']['service_group'] node['consul']['config'].each_pair { |k, v| r.send(k, v) } - notifies :reload, "consul_service[#{name}]", :delayed end consul_service node['consul']['service_name'] do |r| @@ -25,4 +25,5 @@ config_file config.path node['consul']['service'].each_pair { |k, v| r.send(k, v) } + subscribes :restart, "consul_config[#{config.name}]", :delayed end diff --git a/test/integration/default/serverspec/localhost/default_spec.rb b/test/integration/default/serverspec/localhost/default_spec.rb index 4256abb6..c561f14a 100644 --- a/test/integration/default/serverspec/localhost/default_spec.rb +++ b/test/integration/default/serverspec/localhost/default_spec.rb @@ -1,8 +1,13 @@ require 'spec_helper' -describe command('which consul') do - its(:exit_status) { should eq 0 } - its(:stdout) { should match '/usr/local/bin/consul' } +describe file('/srv/consul/current/consul') do + it { should be_file } + it { should be_executable } +end + +describe file('/usr/local/bin/consul') do + it { should be_symlink } + it { should be_linked_to '/srv/consul/current/consul' } end describe service('consul') do @@ -16,15 +21,10 @@ end end -describe command 'consul members -detailed' do +describe command('/usr/local/bin/consul members -detailed') do its(:exit_status) { should eq 0 } its(:stdout) { should match %r{\balive\b} } its(:stdout) { should match %r{\brole=consul\b} } its(:stdout) { should match %r{\bbootstrap=1\b} } -end - -describe 'config file attributes' do - context command 'consul members -detailed' do - its(:stdout) { should match %r{\bdc=FortMeade\b}i } - end + its(:stdout) { should match %r{\bdc=fortmeade\b} } end diff --git a/test/spec/libraries/consul_config_spec.rb b/test/spec/libraries/consul_config_spec.rb index 312c64b5..e1344f8b 100644 --- a/test/spec/libraries/consul_config_spec.rb +++ b/test/spec/libraries/consul_config_spec.rb @@ -5,12 +5,7 @@ cached(:chef_run) { ChefSpec::ServerRunner.new(step_into: %w{consul_config}).converge(described_recipe) } it { expect(chef_run).not_to include_recipe('chef-vault::default') } - it do - expect(chef_run).to create_file('/etc/consul.d/default.json') - .with(owner: 'consul') - .with(group: 'consul') - .with(mode: '0640') - end + it { expect(chef_run).to create_file('/etc/consul.json').with(owner: 'consul', group: 'consul') } it 'converges successfully' do chef_run @@ -38,19 +33,13 @@ it { expect(chef_run).to create_directory('/etc/consul.d/ssl/private') } it { expect(chef_run).to create_directory('/etc/consul.d/ssl/CA') } - it do - expect(chef_run).to create_file('/etc/consul.d/default.json') - .with(owner: 'consul') - .with(group: 'consul') - .with(mode: '0640') - end + it { expect(chef_run).to create_file('/etc/consul.json').with(owner: 'consul', group: 'consul') } it do expect(chef_run).to create_file('/etc/consul.d/ssl/CA/consul.crt') .with(content: 'foo') .with(owner: 'consul') .with(group: 'consul') - .with(mode: '0644') end it do From 56eddd347575bc3c113bf87e24ab40322ee5a2a8 Mon Sep 17 00:00:00 2001 From: John Bellone Date: Fri, 3 Jul 2015 21:14:45 -0400 Subject: [PATCH 12/22] Adds support for creating consul service but not enabling. --- libraries/consul_service.rb | 34 +++++++++++++++++++--------------- recipes/default.rb | 1 + 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/libraries/consul_service.rb b/libraries/consul_service.rb index d2367456..ce2e99a0 100644 --- a/libraries/consul_service.rb +++ b/libraries/consul_service.rb @@ -12,7 +12,8 @@ class Chef::Resource::ConsulService < Chef::Resource include Poise provides(:consul_service) include PoiseService::ServiceMixin - default_action(:enable) + actions(:create) + default_action(:create) # @!attribute service_name # @return [String] @@ -91,20 +92,8 @@ class Chef::Provider::ConsulService < Chef::Provider provides(:consul_service) include PoiseService::ServiceMixin - def action_enable + def action_create notifying_block do - directory new_resource.data_dir do - recursive true - owner new_resource.user - group new_resource.group - mode '0744' - end - - directory new_resource.config_dir do - recursive true - mode '0644' - end - package new_resource.package_name do version new_resource.version unless new_resource.version.nil? action :upgrade @@ -118,7 +107,6 @@ def action_enable install_path new_resource.install_path remote_url new_resource.binary_url % { filename: new_resource.binary_filename } remote_checksum new_resource.binary_checksum - action :create end link '/usr/local/bin/consul' do @@ -150,6 +138,22 @@ def action_enable end end end + end + + def action_enable + notifying_block do + directory new_resource.data_dir do + recursive true + owner new_resource.user + group new_resource.group + mode '0744' + end + + directory new_resource.config_dir do + recursive true + mode '0644' + end + end super end diff --git a/recipes/default.rb b/recipes/default.rb index 5fe6b1be..452f31c0 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -26,4 +26,5 @@ node['consul']['service'].each_pair { |k, v| r.send(k, v) } subscribes :restart, "consul_config[#{config.name}]", :delayed + action [:create, :enable] end From fc18d6c9b9c8d720246d6d7cd10cbe147196ea67 Mon Sep 17 00:00:00 2001 From: John Bellone Date: Fri, 3 Jul 2015 21:30:41 -0400 Subject: [PATCH 13/22] Fixes issues with unit tests failing. --- .gitignore | 1 + .rspec | 1 - Gemfile | 3 + libraries/consul_config.rb | 21 +++++- libraries/consul_service.rb | 5 -- test/spec/libraries/consul_config_spec.rb | 76 ++++++---------------- test/spec/libraries/consul_service_spec.rb | 6 +- test/spec/recipes/default_spec.rb | 3 +- test/spec/spec_helper.rb | 6 +- 9 files changed, 53 insertions(+), 69 deletions(-) diff --git a/.gitignore b/.gitignore index 78151583..0360a014 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,4 @@ vendor .kitchen .vagrant Berksfile.lock +coverage/ diff --git a/.rspec b/.rspec index 2cdc09b7..4b0b8f98 100644 --- a/.rspec +++ b/.rspec @@ -1,3 +1,2 @@ --color ---require spec_helper --default-path test/spec diff --git a/Gemfile b/Gemfile index 07f0e559..548e8a69 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,7 @@ source 'https://rubygems.org' gem 'chef-vault', '~> 2.6' +gem 'poise', '~> 2.0' +gem 'poise-boiler' group :lint do gem 'rubocop' @@ -27,6 +29,7 @@ group :integration do end group :development do + gem 'awesome_print' gem 'guard' gem 'guard-kitchen' gem 'guard-rspec' diff --git a/libraries/consul_config.rb b/libraries/consul_config.rb index 26400d46..ba9a0e1f 100644 --- a/libraries/consul_config.rb +++ b/libraries/consul_config.rb @@ -9,7 +9,6 @@ class Chef::Resource::ConsulConfig < Chef::Resource include Poise(fused: true) provides(:consul_config) - default_action(:create) # @!attribute path # @return [String] @@ -23,6 +22,14 @@ class Chef::Resource::ConsulConfig < Chef::Resource # @return [String] attribute(:group, kind_of: String, default: 'consul') + # @!attribute bag_name + # @return [String] + attribute(:bag_name, kind_of: String, default: 'consul') + + # @!attribute bag_item + # @return [String] + attribute(:bag_item, kind_of: String, default: 'secrets') + # @see: http://www.consul.io/docs/agent/options.html attribute(:acl_datacenter, kind_of: String) attribute(:acl_default_policy, kind_of: String) @@ -94,7 +101,7 @@ def tls? recursive true end - item = chef_vault_item(node['consul']['bag_name'], node['consul']['bag_item']) + item = chef_vault_item(new_resource.bag_name, new_resource.bag_item) file new_resource.ca_file do content item['ca_certificate'] mode '0644' @@ -141,6 +148,16 @@ def tls? action(:delete) do notifying_block do + if new_resource.tls? + file new_resource.cert_file do + action :delete + end + + file new_resource.key_file do + action :delete + end + end + file new_resource.path do action :delete end diff --git a/libraries/consul_service.rb b/libraries/consul_service.rb index ce2e99a0..d96532b4 100644 --- a/libraries/consul_service.rb +++ b/libraries/consul_service.rb @@ -15,10 +15,6 @@ class Chef::Resource::ConsulService < Chef::Resource actions(:create) default_action(:create) - # @!attribute service_name - # @return [String] - attribute(:service_name, kind_of: String, name_attribute: true) - # @!attribute version # @return [String] attribute(:version, kind_of: String, required: true) @@ -96,7 +92,6 @@ def action_create notifying_block do package new_resource.package_name do version new_resource.version unless new_resource.version.nil? - action :upgrade only_if { new_resource.install_method == 'package' } end diff --git a/test/spec/libraries/consul_config_spec.rb b/test/spec/libraries/consul_config_spec.rb index e1344f8b..5ac77c2b 100644 --- a/test/spec/libraries/consul_config_spec.rb +++ b/test/spec/libraries/consul_config_spec.rb @@ -1,66 +1,30 @@ -require 'spec_helper' +require 'poise_boiler/spec_helper' +require 'poise' -describe_recipe 'consul::default' do - context 'with default attributes' do - cached(:chef_run) { ChefSpec::ServerRunner.new(step_into: %w{consul_config}).converge(described_recipe) } - - it { expect(chef_run).not_to include_recipe('chef-vault::default') } - it { expect(chef_run).to create_file('/etc/consul.json').with(owner: 'consul', group: 'consul') } - - it 'converges successfully' do - chef_run - end - end - - context 'with verify_incoming & verify_outgoing = true' do - cached(:chef_run) do - ChefSpec::ServerRunner.new(step_into: %w{consul_config}) do |node, server| - server.create_data_bag('secrets', { - 'consul' => { - 'ca_certificate' => 'foo', - 'certificate' => 'bar', - 'private_key' => 'baz' - } - }) - - node.set['consul']['config']['verify_incoming'] = true - node.set['consul']['config']['verify_outgoing'] = true - end.converge(described_recipe) - end +RSpec.configure do |config| + config.include Halite::SpecHelper +end - it { expect(chef_run).to include_recipe('chef-vault::default') } - it { expect(chef_run).to create_directory('/etc/consul.d/ssl/certs') } - it { expect(chef_run).to create_directory('/etc/consul.d/ssl/private') } - it { expect(chef_run).to create_directory('/etc/consul.d/ssl/CA') } +require_relative '../../../libraries/consul_config' - it { expect(chef_run).to create_file('/etc/consul.json').with(owner: 'consul', group: 'consul') } +describe Chef::Resource::ConsulConfig do + step_into(:consul_config) - it do - expect(chef_run).to create_file('/etc/consul.d/ssl/CA/consul.crt') - .with(content: 'foo') - .with(owner: 'consul') - .with(group: 'consul') + context 'with defaults' do + recipe do + consul_config '/etc/consul/default.json' do + bag_name 'secrets' + bag_item 'vault' + end end - it do - expect(chef_run).to create_file('/etc/consul.d/ssl/certs/consul.crt') - .with(content: 'bar') - .with(owner: 'consul') - .with(group: 'consul') - .with(mode: '0644') + before do + recipe = double("Chef::Recipe") + allow_any_instance_of(Chef::RunContext).to receive(:include_recipe).and_return([recipe]) end - it do - expect(chef_run).to create_file('/etc/consul.d/ssl/private/consul.key') - .with(content: 'baz') - .with(sensitive: true) - .with(owner: 'consul') - .with(group: 'consul') - .with(mode: '0640') - end - - it 'converges successfully' do - chef_run - end + it { is_expected.to create_directory('/etc/consul') } + it { is_expected.to create_file('/etc/consul/default.json') } + it { run_chef } end end diff --git a/test/spec/libraries/consul_service_spec.rb b/test/spec/libraries/consul_service_spec.rb index 61158b6d..a177d24d 100644 --- a/test/spec/libraries/consul_service_spec.rb +++ b/test/spec/libraries/consul_service_spec.rb @@ -3,7 +3,7 @@ describe_recipe 'consul::default' do context 'with default attributes' do cached(:chef_run) do - ChefSpec::ServerRunner.new(step_into: %w{consul_service}) do |node, server| + ChefSpec::ServerRunner.new(step_into: %i{consul_service}) do |node, server| server.create_data_bag('secrets', { 'consul' => { 'ca_certificate' => 'foo', @@ -24,7 +24,7 @@ context "with node['consul']['service']['install_method'] = 'source'" do cached(:chef_run) do - ChefSpec::ServerRunner.new(step_into: %w{consul_service}) do |node, server| + ChefSpec::ServerRunner.new(step_into: %i{consul_service}) do |node, server| server.create_data_bag('secrets', { 'consul' => { 'ca_certificate' => 'foo', @@ -49,7 +49,7 @@ context "with node['consul']['service']['install_method'] = 'package'" do cached(:chef_run) do - ChefSpec::ServerRunner.new(step_into: %w{consul_service}) do |node, server| + ChefSpec::ServerRunner.new(step_into: %i{consul_service}) do |node, server| server.create_data_bag('secrets', { 'consul' => { 'ca_certificate' => 'foo', diff --git a/test/spec/recipes/default_spec.rb b/test/spec/recipes/default_spec.rb index 19510f6e..a25e4dbe 100644 --- a/test/spec/recipes/default_spec.rb +++ b/test/spec/recipes/default_spec.rb @@ -6,7 +6,8 @@ context 'with default attributes' do it { expect(chef_run).to include_recipe('selinux::permissive') } it { expect(chef_run).to create_poise_service_user('consul').with(group: 'consul') } - it { expect(chef_run).to create_consul_config('/etc/consul.json') } + it { expect(chef_run).to create_consul_config('consul').with(path: '/etc/consul.json') } + it { expect(chef_run).to create_consul_service('consul').with(config_file: '/etc/consul.json') } it { expect(chef_run).to enable_consul_service('consul').with(config_file: '/etc/consul.json') } it 'converges successfully' do diff --git a/test/spec/spec_helper.rb b/test/spec/spec_helper.rb index 12d3ff8e..e726d2eb 100644 --- a/test/spec/spec_helper.rb +++ b/test/spec/spec_helper.rb @@ -2,6 +2,7 @@ require 'chefspec/berkshelf' require 'chefspec/cacher' require 'chef-vault' +require 'poise_boiler/spec_helper' RSpec.configure do |config| config.platform = 'ubuntu' @@ -9,6 +10,7 @@ config.color = true config.alias_example_group_to :describe_recipe, type: :recipe + config.alias_example_group_to :describe_resource, type: :resource config.filter_run :focus config.run_all_when_everything_filtered = true @@ -30,7 +32,9 @@ end end -at_exit { ChefSpec::Coverage.report! } +RSpec.shared_context 'resource tests', type: :resource do + +end RSpec.shared_context 'recipe tests', type: :recipe do before do From 275877e7a0e78173fbb894cf598fcd7e98d9040e Mon Sep 17 00:00:00 2001 From: John Bellone Date: Thu, 9 Jul 2015 21:52:13 -0400 Subject: [PATCH 14/22] Fixes permissions for key and certificate. --- libraries/consul_config.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/consul_config.rb b/libraries/consul_config.rb index ba9a0e1f..c37eb3ca 100644 --- a/libraries/consul_config.rb +++ b/libraries/consul_config.rb @@ -115,7 +115,7 @@ def tls? file new_resource.cert_file do content item['certificate'] - mode '0644' + mode '0640' owner new_resource.user group new_resource.group end @@ -141,7 +141,7 @@ def tls? owner new_resource.user group new_resource.group content new_resource.to_json - mode '0644' + mode '0640' end end end From 6cc4c6cc1cdf83457b3835ace94d5d26bd2aafb9 Mon Sep 17 00:00:00 2001 From: John Bellone Date: Thu, 9 Jul 2015 22:06:16 -0400 Subject: [PATCH 15/22] Adds more test converage to Consul configuration. --- attributes/default.rb | 8 +-- libraries/consul_config.rb | 2 +- test/spec/libraries/consul_config_spec.rb | 59 ++++++++++++++++++++--- test/spec/spec_helper.rb | 2 + 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/attributes/default.rb b/attributes/default.rb index a55fc7cf..8d95a105 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -13,10 +13,10 @@ default['consul']['config']['path'] = '/etc/consul.json' default['consul']['config']['data_dir'] = '/var/lib/consul' -default['consul']['config']['ca_file'] = '/etc/consul.d/ssl/CA/ca.crt' -default['consul']['config']['cert_file'] = '/etc/consul.d/ssl/certs/consul.crt' +default['consul']['config']['ca_file'] = '/etc/consul/ssl/CA/ca.crt' +default['consul']['config']['cert_file'] = '/etc/consul/ssl/certs/consul.crt' default['consul']['config']['client_addr'] = '0.0.0.0' -default['consul']['config']['key_file'] = '/etc/consul.d/ssl/private/consul.key' +default['consul']['config']['key_file'] = '/etc/consul/ssl/private/consul.key' default['consul']['config']['ports'] = { 'dns' => 8600, 'http' => 8500, @@ -27,7 +27,7 @@ } default['consul']['service']['install_method'] = 'binary' -default['consul']['service']['config_dir'] = '/etc/consul.d' +default['consul']['service']['config_dir'] = '/etc/consul' default['consul']['service']['binary_url'] = "https://dl.bintray.com/mitchellh/consul/%{filename}.zip" default['consul']['service']['source_url'] = 'https://github.com/hashicorp/consul' diff --git a/libraries/consul_config.rb b/libraries/consul_config.rb index c37eb3ca..4b807119 100644 --- a/libraries/consul_config.rb +++ b/libraries/consul_config.rb @@ -115,7 +115,7 @@ def tls? file new_resource.cert_file do content item['certificate'] - mode '0640' + mode '0644' owner new_resource.user group new_resource.group end diff --git a/test/spec/libraries/consul_config_spec.rb b/test/spec/libraries/consul_config_spec.rb index 5ac77c2b..9dc87fac 100644 --- a/test/spec/libraries/consul_config_spec.rb +++ b/test/spec/libraries/consul_config_spec.rb @@ -5,26 +5,71 @@ config.include Halite::SpecHelper end + require_relative '../../../libraries/consul_config' describe Chef::Resource::ConsulConfig do step_into(:consul_config) + before do + recipe = double('Chef::Recipe') + allow_any_instance_of(Chef::RunContext).to receive(:include_recipe).and_return([recipe]) + end + context 'with defaults' do + recipe { consul_config '/etc/consul/default.json' } + + it { is_expected.to create_directory('/etc/consul') } + it { is_expected.to create_file('/etc/consul/default.json') } + it { run_chef } + end + + context 'with tls enabled' do + before do + allow_any_instance_of(Chef::DSL::Recipe).to receive(:chef_vault_item).and_return( + { 'ca_certificate' => 'foo', 'certificate' => 'bar', 'private_key' => 'baz' } + ) + end + recipe do consul_config '/etc/consul/default.json' do - bag_name 'secrets' - bag_item 'vault' + key_file '/etc/consul/ssl/private/consul.key' + ca_file '/etc/consul/ssl/CA/ca.crt' + cert_file '/etc/consul/ssl/certs/consul.crt' + verify_incoming true + verify_outgoing true end end - before do - recipe = double("Chef::Recipe") - allow_any_instance_of(Chef::RunContext).to receive(:include_recipe).and_return([recipe]) + it { is_expected.to create_directory('/etc/consul/ssl/CA') } + it { is_expected.to create_directory('/etc/consul/ssl/certs') } + it { is_expected.to create_directory('/etc/consul/ssl/private') } + + it do + is_expected.to create_file('/etc/consul/ssl/CA/ca.crt') + .with(content: 'foo') + .with(owner: 'consul') + .with(group: 'consul') + .with(mode: '0644') + end + + it do + is_expected.to create_file('/etc/consul/ssl/certs/consul.crt') + .with(content: 'bar') + .with(owner: 'consul') + .with(group: 'consul') + .with(mode: '0644') + end + + it do + is_expected.to create_file('/etc/consul/ssl/private/consul.key') + .with(content: 'baz') + .with(sensitive: true) + .with(owner: 'consul') + .with(group: 'consul') + .with(mode: '0640') end - it { is_expected.to create_directory('/etc/consul') } - it { is_expected.to create_file('/etc/consul/default.json') } it { run_chef } end end diff --git a/test/spec/spec_helper.rb b/test/spec/spec_helper.rb index e726d2eb..3bb1ed45 100644 --- a/test/spec/spec_helper.rb +++ b/test/spec/spec_helper.rb @@ -5,6 +5,8 @@ require 'poise_boiler/spec_helper' RSpec.configure do |config| + config.include Halite::SpecHelper + config.platform = 'ubuntu' config.version = '14.04' From fa8ac56a1e9140f324a51a0bd38ed96141576bd7 Mon Sep 17 00:00:00 2001 From: John Bellone Date: Fri, 10 Jul 2015 07:13:14 -0400 Subject: [PATCH 16/22] Adds more unit tests for resources. --- libraries/consul_watch.rb | 6 +- test/spec/libraries/consul_config_spec.rb | 32 ++++---- test/spec/libraries/consul_definition_spec.rb | 40 ++++++++++ test/spec/libraries/consul_service_spec.rb | 79 +++++-------------- test/spec/libraries/consul_watch_spec.rb | 48 +++++++++++ test/spec/spec_helper.rb | 5 -- 6 files changed, 127 insertions(+), 83 deletions(-) create mode 100644 test/spec/libraries/consul_definition_spec.rb create mode 100644 test/spec/libraries/consul_watch_spec.rb diff --git a/libraries/consul_watch.rb b/libraries/consul_watch.rb index 086f167c..fc6edcfb 100644 --- a/libraries/consul_watch.rb +++ b/libraries/consul_watch.rb @@ -32,8 +32,10 @@ class Chef::Resource::ConsulWatch < Chef::Resource attribute(:token, kind_of: String) action(:create) do - execute new_resource.command do - guard_interpreter :default + notifying_block do + execute new_resource.command do + guard_interpreter :default + end end end diff --git a/test/spec/libraries/consul_config_spec.rb b/test/spec/libraries/consul_config_spec.rb index 9dc87fac..e0213c46 100644 --- a/test/spec/libraries/consul_config_spec.rb +++ b/test/spec/libraries/consul_config_spec.rb @@ -5,27 +5,15 @@ config.include Halite::SpecHelper end - require_relative '../../../libraries/consul_config' describe Chef::Resource::ConsulConfig do step_into(:consul_config) - before do - recipe = double('Chef::Recipe') - allow_any_instance_of(Chef::RunContext).to receive(:include_recipe).and_return([recipe]) - end - - context 'with defaults' do - recipe { consul_config '/etc/consul/default.json' } - - it { is_expected.to create_directory('/etc/consul') } - it { is_expected.to create_file('/etc/consul/default.json') } - it { run_chef } - end - - context 'with tls enabled' do + context '#action_create' do before do + recipe = double('Chef::Recipe') + allow_any_instance_of(Chef::RunContext).to receive(:include_recipe).and_return([recipe]) allow_any_instance_of(Chef::DSL::Recipe).to receive(:chef_vault_item).and_return( { 'ca_certificate' => 'foo', 'certificate' => 'bar', 'private_key' => 'baz' } ) @@ -70,6 +58,20 @@ .with(mode: '0640') end + it { is_expected.to create_directory('/etc/consul') } + it { is_expected.to create_file('/etc/consul/default.json') } + it { run_chef } end + + context '#action_delete' do + recipe do + consul_config '/etc/consul/default.json' do + action :delete + end + + it { is_expected.to delete_file('/etc/consul/default.json') } + it { run_chef } + end + end end diff --git a/test/spec/libraries/consul_definition_spec.rb b/test/spec/libraries/consul_definition_spec.rb new file mode 100644 index 00000000..1c032dc3 --- /dev/null +++ b/test/spec/libraries/consul_definition_spec.rb @@ -0,0 +1,40 @@ +require 'poise_boiler/spec_helper' +require 'poise' + +RSpec.configure do |config| + config.include Halite::SpecHelper +end + +require_relative '../../../libraries/consul_definition' + +describe Chef::Resource::ConsulDefinition do + step_into(:consul_definition) + + context '#action_create' do + recipe do + consul_definition '/etc/consul/default.json' do + end + end + + it do + is_expected.to create_file() + end + + it { run_chef } + end + + context '#action_create' do + recipe do + consul_definition '/etc/consul/default.json' do + action :delete + end + end + + it do + is_expected.to delete_file() + end + + it { run_chef } + end + +end diff --git a/test/spec/libraries/consul_service_spec.rb b/test/spec/libraries/consul_service_spec.rb index a177d24d..94102541 100644 --- a/test/spec/libraries/consul_service_spec.rb +++ b/test/spec/libraries/consul_service_spec.rb @@ -1,71 +1,28 @@ -require 'spec_helper' +require 'poise_boiler/spec_helper' +require 'poise' -describe_recipe 'consul::default' do - context 'with default attributes' do - cached(:chef_run) do - ChefSpec::ServerRunner.new(step_into: %i{consul_service}) do |node, server| - server.create_data_bag('secrets', { - 'consul' => { - 'ca_certificate' => 'foo', - 'certificate' => 'bar', - 'private_key' => 'baz' - } - }) - end.converge(described_recipe) - end - - it { expect(chef_run).to create_libartifact_file('consul-0.5.2') } - it { expect(chef_run).to create_link('/usr/local/bin/consul').with(to: '/srv/consul/0.5.2/consul') } - - it 'converges successfully' do - chef_run - end - end - - context "with node['consul']['service']['install_method'] = 'source'" do - cached(:chef_run) do - ChefSpec::ServerRunner.new(step_into: %i{consul_service}) do |node, server| - server.create_data_bag('secrets', { - 'consul' => { - 'ca_certificate' => 'foo', - 'certificate' => 'bar', - 'private_key' => 'baz' - } - }) +RSpec.configure do |config| + config.include Halite::SpecHelper +end - node.set['consul']['service']['install_method'] = 'source' - end.converge(described_recipe) - end +require_relative '../../../libraries/consul_service' - it { expect(chef_run).to include_recipe('golang::default') } - it { expect(chef_run).to create_directory('/srv/consul/src') } - it { expect(chef_run).to checkout_git('/srv/consul/src/consul-0.5.2') } - it { expect(chef_run).to create_link('/usr/local/bin/consul').with(to: '/srv/consul/0.5.2/consul') } +describe Chef::Resource::ConsulService do + step_into(:consul_service) - it 'converges successfully' do - chef_run - end + context '#action_create' do + it { run_chef } end - context "with node['consul']['service']['install_method'] = 'package'" do - cached(:chef_run) do - ChefSpec::ServerRunner.new(step_into: %i{consul_service}) do |node, server| - server.create_data_bag('secrets', { - 'consul' => { - 'ca_certificate' => 'foo', - 'certificate' => 'bar', - 'private_key' => 'baz' - } - }) - - node.set['consul']['service']['install_method'] = 'package' - end.converge(described_recipe) - end + context '#action_enable' do + it { run_chef } + end - it { expect(chef_run).to install_package('consul') } + context '#action_disable' do + it { run_chef } + end - it 'converges successfully' do - chef_run - end + context '#action_delete' do + it { run_chef } end end diff --git a/test/spec/libraries/consul_watch_spec.rb b/test/spec/libraries/consul_watch_spec.rb new file mode 100644 index 00000000..feea5c13 --- /dev/null +++ b/test/spec/libraries/consul_watch_spec.rb @@ -0,0 +1,48 @@ +require 'poise_boiler/spec_helper' +require 'poise' + +RSpec.configure do |config| + config.include Halite::SpecHelper +end + +require_relative '../../../libraries/consul_watch' + +describe Chef::Resource::ConsulWatch do + step_into(:consul_watch) + + context '#action_create' do + before do + # TODO: (jbellone) Stub out the execute bits. + end + + recipe do + consul_watch 'foobar' do + + end + end + + it do + is_expected.to run_execute() + end + + it { run_chef } + end + + context '#action_delete' do + before do + # TODO: (jbellone) Stub out the execute bits. + end + + recipe do + consul_watch 'foobar' do + action :delete + end + end + + it do + is_expected.to run_execute() + end + + it { run_chef } + end +end diff --git a/test/spec/spec_helper.rb b/test/spec/spec_helper.rb index 3bb1ed45..8bea8b88 100644 --- a/test/spec/spec_helper.rb +++ b/test/spec/spec_helper.rb @@ -12,7 +12,6 @@ config.color = true config.alias_example_group_to :describe_recipe, type: :recipe - config.alias_example_group_to :describe_resource, type: :resource config.filter_run :focus config.run_all_when_everything_filtered = true @@ -34,10 +33,6 @@ end end -RSpec.shared_context 'resource tests', type: :resource do - -end - RSpec.shared_context 'recipe tests', type: :recipe do before do stub_command("test -L /usr/local/bin/consul").and_return(true) From ea9c597479c38087f3469b9c5680c5bad65dcb00 Mon Sep 17 00:00:00 2001 From: John Bellone Date: Fri, 10 Jul 2015 07:35:22 -0400 Subject: [PATCH 17/22] Modifies the watch resource to write out as a file. This ensures that we can check for idempotence by simply using the normal Chef means. Its actually a hell of a lot better than querying Consul and doing some insane magic in the background. --- README.md | 27 +++++++++++++++ libraries/consul_watch.rb | 42 ++++++++++++++++------- test/spec/libraries/consul_watch_spec.rb | 43 +++++++++--------------- 3 files changed, 71 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 1eb8e21e..b0516a3b 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,33 @@ consul_service 'consul' do end ``` ### consul_watch +```ruby +consul_watch '/etc/consul/foobarbaz.json' do + type 'key' + parameters(key: 'foo/bar/baz', handler: '/bin/false') +end +``` + +```ruby +consul_watch '/etc/consul/foobarbaz.json' do + type 'keyprefix' + parameters(prefix: 'foo/', handler: '/bin/false') +end +``` + +```ruby +consul_watch '/etc/consul/foobarbaz.json' do + type 'service' + parameters(service: 'redis', handler: '/bin/false') +end +``` + +```ruby +consul_watch '/etc/consul/foobarbaz.json' do + type 'event' + parameters(event: 'web-deploy', handler: '/bin/false') +end +``` [0]: http://blog.vialstudios.com/the-environment-cookbook-pattern/#theapplicationcookbook [1]: http://consul.io diff --git a/libraries/consul_watch.rb b/libraries/consul_watch.rb index fc6edcfb..9037fba8 100644 --- a/libraries/consul_watch.rb +++ b/libraries/consul_watch.rb @@ -11,34 +11,50 @@ class Chef::Resource::ConsulWatch < Chef::Resource provides(:consul_watch) default_action(:create) - # @!attribute watch_name + # @!attribute path # @return [String] - attribute(:watch_name, kind_of: String, name_attribute: true) + attribute(:path, kind_of: String, name_attribute: true) - # @!attribute watch_type + # @!attribute user # @return [String] - attribute(:watch_type, equal_to: %w(checks event key keyprefix service)) + attribute(:user, kind_of: String, default: 'consul') - # @!attribute datacenter + # @!attribute group # @return [String] - attribute(:datacenter, kind_of: String) + attribute(:group, kind_of: String, default: 'consul') - # @!attribute handler + # @!attribute type # @return [String] - attribute(:handler, kind_of: String) + attribute(:type, equal_to: %w{checks event key keyprefix service}) - # @!attribute token - # @return [String] - attribute(:token, kind_of: String) + # @!attribute parameters + # @return [Hash] + attribute(:parameters, option_collector: true, default: {}) + + def to_json + JSON.pretty_generate({ type: type }.merge(parameters), quicks_mode: true) + end action(:create) do notifying_block do - execute new_resource.command do - guard_interpreter :default + directory ::File.dirname(new_resource.path) do + recursive true + end + + file new_resource.path do + owner new_resource.user + group new_resource.group + content new_resource.to_json + mode '0640' end end end action(:delete) do + notifying_block do + file new_resource.path do + action :delete + end + end end end diff --git a/test/spec/libraries/consul_watch_spec.rb b/test/spec/libraries/consul_watch_spec.rb index feea5c13..ecce1458 100644 --- a/test/spec/libraries/consul_watch_spec.rb +++ b/test/spec/libraries/consul_watch_spec.rb @@ -10,39 +10,26 @@ describe Chef::Resource::ConsulWatch do step_into(:consul_watch) - context '#action_create' do - before do - # TODO: (jbellone) Stub out the execute bits. - end - + context 'defines key watch' do recipe do - consul_watch 'foobar' do - + consul_watch '/etc/consul/watches/foo.json' do + type 'key' + parameters(key: 'foo/bar/baz', handler: '/bin/false') end end + it { is_expected.to create_directory('/etc/consul/watches') } it do - is_expected.to run_execute() - end - - it { run_chef } - end - - context '#action_delete' do - before do - # TODO: (jbellone) Stub out the execute bits. + is_expected.to create_file('/etc/consul/watches/foo.json') + .with(user: 'consul', group: 'consul', mode: '0640') + .with(content: JSON.pretty_generate( + { + type: 'key', + key: 'foo/bar/baz', + handler: '/bin/false' + }, + quicks_mode: true + )) end - - recipe do - consul_watch 'foobar' do - action :delete - end - end - - it do - is_expected.to run_execute() - end - - it { run_chef } end end From ccc0c3f4990ec55a55d49012208d4bceeda3bc8a Mon Sep 17 00:00:00 2001 From: John Bellone Date: Fri, 10 Jul 2015 08:02:40 -0400 Subject: [PATCH 18/22] Updates the README and defaults for various HWRP. --- README.md | 35 ++++++++++++++++++++++++++++------ libraries/consul_definition.rb | 19 +++++++----------- libraries/consul_service.rb | 2 +- 3 files changed, 37 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index b0516a3b..ff4e7f31 100644 --- a/README.md +++ b/README.md @@ -27,14 +27,32 @@ Consul client, server and UI. These primitives are what is used in the recipes, and should be used in your own [wrapper cookbooks][2]. ### consul_config +| Parameter | Type | Description | Default | +| --------- | ---- | ----------- | ------- | +| path | String | File system path to write configuration. | name | +| user | String | System username for configuration ownership. | consul | +| group | String | System groupname for configuration ownership. | consul | +| bag_name | String | Name of the chef-vault data bag for TLS configuration. | secrets | +| bag_item | String | Item of the chef-vault data bag for TLS configuration. | consul | + ```ruby consul_config '/etc/consul.json' do - user 'consul' - group 'consul' + user 'jbellone' + group 'staff' end ``` -### consul_definition ### consul_service +| Parameter | Type | Description | Default | +| --------- | ---- | ----------- | ------- | +| user | String | System username for configuration ownership. | consul | +| group | String | System groupname for configuration ownership. | consul | +| install_method | String | Determines method of installing Consul agent on node. | source, binary, package | +| install_path | String | Absolute path to where Consul agent is unpacked. | /srv | +| version | String | The version of Consul agent to install. | nil | +| config_file | String | Absolute path to the Consul agent's configuration file. | /etc/consul.json | +| config_dir | String | Absolute path to configuration directory (for definitions, watches). | /etc/consul | +| data_dir | String | Absolute path to the Consul agent's data directory. | /var/lib/consul | + ```ruby consul_service 'consul' do user 'consul' @@ -44,27 +62,32 @@ consul_service 'consul' do end ``` ### consul_watch +| Parameter | Type | Description | Default | +| --------- | ---- | ----------- | ------- | +| path | String | File system path to write configuration. | name | +| user | String | System username for configuration ownership. | consul | +| group | String | System groupname for configuration ownership. | consul | +| type | String | Type of the Consul watch to configure. | key, keyprefix, service, event | +| parameters | Hash | Parameters to configure; depends on type of watch. | {} | + ```ruby consul_watch '/etc/consul/foobarbaz.json' do type 'key' parameters(key: 'foo/bar/baz', handler: '/bin/false') end ``` - ```ruby consul_watch '/etc/consul/foobarbaz.json' do type 'keyprefix' parameters(prefix: 'foo/', handler: '/bin/false') end ``` - ```ruby consul_watch '/etc/consul/foobarbaz.json' do type 'service' parameters(service: 'redis', handler: '/bin/false') end ``` - ```ruby consul_watch '/etc/consul/foobarbaz.json' do type 'event' diff --git a/libraries/consul_definition.rb b/libraries/consul_definition.rb index bcc4f5b2..d651d2d4 100644 --- a/libraries/consul_definition.rb +++ b/libraries/consul_definition.rb @@ -15,10 +15,6 @@ class Chef::Resource::ConsulDefinition < Chef::Resource # @return [String] attribute(:path, kind_of: String, name_attribute: true) - # @!attribute id - # @return [String, NilClass] - attribute(:id, kind_of: String) - # @!attribute user # @return [String] attribute(:user, kind_of: String, default: 'consul') @@ -28,20 +24,19 @@ class Chef::Resource::ConsulDefinition < Chef::Resource attribute(:group, kind_of: String, default: 'consul') def to_json - for_keeps = %i{} - config = to_hash.keep_if do |k, v| - for_keeps.include?(k.to_sym) - end - JSON.pretty_generate(config, quirks_mode: true) end action(:create) do notifying_block do + directory ::File.dirname(new_resource.path) do + recursive true + end + file new_resource.path do - content new_resource.to_json - user new_resource.user + owner new_resource.user group new_resource.group - mode '0600' + content new_resource.to_json + mode '0640' end end end diff --git a/libraries/consul_service.rb b/libraries/consul_service.rb index d96532b4..10bec896 100644 --- a/libraries/consul_service.rb +++ b/libraries/consul_service.rb @@ -61,7 +61,7 @@ class Chef::Resource::ConsulService < Chef::Resource # @!attribute config_dir # @return [String] - attribute(:config_dir, kind_of: String, default: '/etc/consul.d') + attribute(:config_dir, kind_of: String, default: '/etc/consul') def default_environment { GOMAXPROCS: [node['cpu']['total'], 2].max.to_s, PATH: '/usr/local/bin:/usr/bin:/bin' } From a74c9b26a4c1097e8954e6274938a8018d817c3e Mon Sep 17 00:00:00 2001 From: John Bellone Date: Thu, 23 Jul 2015 07:47:51 -0400 Subject: [PATCH 19/22] Adds test-kitchen support for Windows platform. --- .kitchen.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.kitchen.yml b/.kitchen.yml index ca389e65..c88cd5cc 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -10,6 +10,7 @@ platforms: - name: ubuntu-12.04 - name: centos-7.1 - name: centos-6.6 + - name: windows-2012r2 suites: - name: default @@ -22,6 +23,8 @@ suites: server: true datacenter: FortMeade encrypt: CGXC2NsXW4AvuB4h5ODYzQ== + excludes: + - windows-2012r2 - name: source run_list: - recipe[consul::default] @@ -30,6 +33,8 @@ suites: config: *default-config service: install_method: source + excludes: + - windows-2012r2 - name: package run_list: - recipe[consul::default] From 8ad3ad2eb149fc6d14f92e130c6ad320f6a001b3 Mon Sep 17 00:00:00 2001 From: John Bellone Date: Thu, 23 Jul 2015 07:49:38 -0400 Subject: [PATCH 20/22] Bumps version of libartifact-cookbook ~> 1.3. --- metadata.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadata.rb b/metadata.rb index 3871b49e..ead34a8a 100644 --- a/metadata.rb +++ b/metadata.rb @@ -14,7 +14,7 @@ supports 'arch' depends 'chef-vault' -depends 'libartifact', '~> 1.2' +depends 'libartifact', '~> 1.3' depends 'golang', '~> 1.4' depends 'poise', '~> 2.0' depends 'poise-service' From 2267367b1626a0545cea8ec87a72716c5bc87fd6 Mon Sep 17 00:00:00 2001 From: John Bellone Date: Thu, 23 Jul 2015 08:20:29 -0400 Subject: [PATCH 21/22] Implements the Consul definition HWRP. --- README.md | 13 +++++++++++++ libraries/consul_definition.rb | 9 +++++++++ 2 files changed, 22 insertions(+) diff --git a/README.md b/README.md index ff4e7f31..a29eae3b 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,19 @@ consul_watch '/etc/consul/foobarbaz.json' do parameters(event: 'web-deploy', handler: '/bin/false') end ``` +### consul_definition +| Parameter | Type | Description | Default | +| --------- | ---- | ----------- | ------- | +| path | String | File system path to write configuration. | name | +| user | String | System username for configuration ownership. | consul | +| group | String | System groupname for configuration ownership. | consul | +| type | String | Type of definition | service, check | +```ruby +consul_definition '/etc/consul/redis.json' do + type 'service' + parameters(tags: %w{master}, address: '127.0.0.1', port: 6379) +end +``` [0]: http://blog.vialstudios.com/the-environment-cookbook-pattern/#theapplicationcookbook [1]: http://consul.io diff --git a/libraries/consul_definition.rb b/libraries/consul_definition.rb index d651d2d4..4de78106 100644 --- a/libraries/consul_definition.rb +++ b/libraries/consul_definition.rb @@ -23,7 +23,16 @@ class Chef::Resource::ConsulDefinition < Chef::Resource # @return [String] attribute(:group, kind_of: String, default: 'consul') + # @!attribute type + # @return [String] + attribute(:type, equal_to: %w{check service}) + + # @!attribute parameters + # @return [Hash] + attribute(:parameters, option_collector: true, default: {}) + def to_json + JSON.pretty_generate(type => parameters, quicks_mode: true) end action(:create) do From 6371cd3a564cc57c50cab0aaeb9e3daaa75ca9a5 Mon Sep 17 00:00:00 2001 From: John Bellone Date: Fri, 24 Jul 2015 23:41:55 -0400 Subject: [PATCH 22/22] Fixes a few issues during the merge/rebase. --- recipes/install_windows.rb | 26 ---------------- .../atlas/serverspec/localhost/atlas_spec.rb | 22 -------------- .../atlas/serverspec/spec_helper.rb | 7 ----- .../serverspec/localhost/consul_spec.rb | 30 ------------------- .../windows/serverspec/spec_helper.rb | 5 ---- 5 files changed, 90 deletions(-) delete mode 100644 recipes/install_windows.rb delete mode 100644 test/integration/atlas/serverspec/localhost/atlas_spec.rb delete mode 100644 test/integration/atlas/serverspec/spec_helper.rb delete mode 100644 test/integration/windows/serverspec/localhost/consul_spec.rb delete mode 100644 test/integration/windows/serverspec/spec_helper.rb diff --git a/recipes/install_windows.rb b/recipes/install_windows.rb deleted file mode 100644 index ba83397d..00000000 --- a/recipes/install_windows.rb +++ /dev/null @@ -1,26 +0,0 @@ -# -# Copyright 2015 Rohit Amarnath -# Copyright 2015 Full 360 Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -if node['platform'] == 'windows' - - include_recipe 'chocolatey::default' - - chocolatey 'consul' do - version node['consul']['version'] - source node['consul']['choco_source'] - end -end diff --git a/test/integration/atlas/serverspec/localhost/atlas_spec.rb b/test/integration/atlas/serverspec/localhost/atlas_spec.rb deleted file mode 100644 index 0da40b2b..00000000 --- a/test/integration/atlas/serverspec/localhost/atlas_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -require 'spec_helper' - -describe command('which consul') do - its(:exit_status) { should eq 0 } - its(:stdout) { should match '/usr/local/bin/consul' } -end - -describe service('consul') do - it { should be_enabled } - it { should be_running } -end - -describe file('/etc/consul.d') do - it { should be_directory } -end - -describe command('grep atlas /etc/consul.d/default.json') do - its(:exit_status) { should eq 0 } - its(:stdout) { should match %r{"atlas_infrastructure":\s"([^"]*)"} } - its(:stdout) { should match %r{"atlas_join":\s(true|false)} } - its(:stdout) { should match %r{"atlas_token":\s"([^"]*)"} } -end diff --git a/test/integration/atlas/serverspec/spec_helper.rb b/test/integration/atlas/serverspec/spec_helper.rb deleted file mode 100644 index c0925118..00000000 --- a/test/integration/atlas/serverspec/spec_helper.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'serverspec' - -set :backend, :exec - -RSpec.configure do |c| - c.path = '/usr/local/bin:/sbin:/bin:/usr/bin' -end diff --git a/test/integration/windows/serverspec/localhost/consul_spec.rb b/test/integration/windows/serverspec/localhost/consul_spec.rb deleted file mode 100644 index 7e7f92cb..00000000 --- a/test/integration/windows/serverspec/localhost/consul_spec.rb +++ /dev/null @@ -1,30 +0,0 @@ -require 'spec_helper' - -describe command('where.exe /R C:\ProgramData\chocolatey\bin consul') do - its(:exit_status) { should eq 0 } - its(:stdout) { should match "C:\\ProgramData\\chocolatey\\bin\\consul.exe\n" } -end - -describe service('consul') do - it { should be_enabled } - it { should be_running } -end - -describe file('C:\ProgramData\consul\config') do - it { should be_directory } -end - -describe file('C:\ProgramData\consul\data') do - it { should be_directory } -end - -describe port(8300) do - it { should be_listening } -end - -# For some reason, the check can't find the port -#[8400, 8500, 8600].each do |p| -# describe port(p) do -# it { should be_listening.on('127.0.0.1') } -# end -#end diff --git a/test/integration/windows/serverspec/spec_helper.rb b/test/integration/windows/serverspec/spec_helper.rb deleted file mode 100644 index ede13c0e..00000000 --- a/test/integration/windows/serverspec/spec_helper.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'serverspec' - -set :backend, :cmd -set :os, :family => 'windows' -set :architecture, :x86_64