diff --git a/.kitchen.yml b/.kitchen.yml index d9a97eec..c2182dc6 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -7,11 +7,26 @@ provisioner: platforms: - name: ubuntu-14.04 + run_list: + - recipe[apt::default] - name: ubuntu-12.04 + run_list: + - recipe[apt::default] - name: centos-7.2 + run_list: + - recipe[yum::default] - name: centos-6.7 + run_list: + - recipe[yum::default] - name: centos-5.11 + run_list: + - recipe[yum::default] + - name: freebsd-10.2 + run_list: + - recipe[freebsd::default] - name: windows-2012r2 + run_list: + - recipe[windows::default] suites: - name: default @@ -24,30 +39,27 @@ suites: server: true datacenter: FortMeade encrypt: CGXC2NsXW4AvuB4h5ODYzQ== - excludes: - - windows-2012r2 - - name: source + - name: git run_list: - recipe[consul::default] attributes: consul: config: *default-config - service: - install_method: source + installation: + provider: git excludes: - windows-2012r2 - - name: package + - name: webui run_list: - recipe[consul::default] attributes: consul: - config: *default-config - service: - install_method: package - excludes: - - centos-7.2 - - centos-6.7 - - centos-5.11 + config: + bootstrap: true + server: true + ui: true + datacenter: FortMeade + encrypt: CGXC2NsXW4AvuB4h5ODYzQ== - name: acl run_list: - recipe[consul::default] @@ -67,30 +79,3 @@ suites: - centos-7.2 - centos-6.7 - centos-5.11 - - name: windefault - includes: - - windows-2012r2 - run_list: - - recipe[consul::default] - attributes: - consul: - service_user: vagrant - config: *default-config - service: - nssm_params: - AppStdout: C:\foo\bar\out.log - AppStderr: C:\foo\bar\err.log - # - name: atlas - # excludes: - # - windows-2012r2 - # run_list: - # - recipe[consul::default] - # attributes: - # consul: - # config: - # bootstrap: true - # server: true - # datacenter: fortmeade - # atlas_join: true - # atlas_infrastructure: <%= ENV.fetch('ATLAS_INFRASTRUCTURE', 'example/cluster') %> - # atlas_token: <%= ENV.fetch('ATLAS_TOKEN', 'NOT_REAL') %> diff --git a/Berksfile b/Berksfile index eba2a958..d051b0ec 100644 --- a/Berksfile +++ b/Berksfile @@ -4,4 +4,7 @@ metadata group :test, :integration do cookbook 'consul_spec', path: 'test/cookbooks/consul_spec' cookbook 'apt' + cookbook 'freebsd' + cookbook 'windows' + cookbook 'yum' end diff --git a/TODO.md b/TODO.md index 7a11ccc1..9ddfec63 100644 --- a/TODO.md +++ b/TODO.md @@ -1,4 +1,3 @@ # TODO - Fix the helpers and clean up the where it injects into DSL. -- Add custom resource (and multiple providers) for maintaining the Consul client. - Use the InSpec instead of ServerSpec. diff --git a/attributes/default.rb b/attributes/default.rb index 7704770f..912c3b3a 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -5,7 +5,6 @@ # Copyright 2014-2016, Bloomberg Finance L.P. # -# Only used on Linux default['consul']['service_name'] = 'consul' default['consul']['service_user'] = 'consul' default['consul']['service_group'] = 'consul' @@ -33,12 +32,6 @@ default['consul']['service']['config_dir'] = join_path config_prefix_path, 'conf.d' -default['consul']['service']['install_path'] = windows? ? config_prefix_path : '/srv' -default['consul']['service']['install_method'] = 'binary' -default['consul']['service']['binary_url'] = "https://releases.hashicorp.com/consul/%{version}/%{filename}.zip" # rubocop:disable Style/StringLiterals - -default['consul']['service']['source_url'] = 'https://github.com/hashicorp/consul' - default['consul']['version'] = '0.6.3' # Windows only @@ -50,73 +43,3 @@ 'AppRotateOnline' => 1, 'AppRotateBytes' => 20_000_000 } - -default['consul']['checksums'] = { - 'consul_0.5.0_darwin_amd64' => '24d9758c873e9124e0ce266f118078f87ba8d8363ab16c2e59a3cd197b77e964', - 'consul_0.5.0_linux_386' => '4b6147c30596a30361d4753d409f8a1af9518f54f5ed473a4c4ac973738ac0fd', - 'consul_0.5.0_linux_amd64' => '161f2a8803e31550bd92a00e95a3a517aa949714c19d3124c46e56cfdc97b088', - 'consul_0.5.0_windows_386' => '7fd760ee8a5c2756391cacc1e924ae602b16cdad838db068e564f798383ad714', - 'consul_0.5.0_web_ui' => '0081d08be9c0b1172939e92af5a7cf9ba4f90e54fae24a353299503b24bb8be9', - - 'consul_0.5.1_darwin_amd64' => '06fef2ffc5a8ad8883213227efae5d1e0aa4192ccb772ec6086103a7a08fadf8', - 'consul_0.5.1_linux_386' => 'dad93a02c01de885daee191bcc5a05ca2bf106200da61db33694a658432d8399', - 'consul_0.5.1_linux_amd64' => '967ad75865b950698833eaf26415ba48d8a22befb5d4e8c77630ad70f251b100', - 'consul_0.5.1_windows_386' => 'bb9e1753cf793ad6f9db34bd6e18fb0fa5b0696a8a51a7f1c61484386dfe6682', - 'consul_0.5.1_web_ui' => 'ad883aa52e1c0136ab1492bbcedad1210235f26d59719fb6de3ef6464f1ff3b1', - - 'consul_0.5.2_darwin_amd64' => '87be515d7dbab760a61a359626a734f738d46ece367f68422b7dec9197d9eeea', - 'consul_0.5.2_linux_386' => '29306ce398109f954ceeea3af79878be4fb0d949f8af3a27c95ccef2101e8f60', - 'consul_0.5.2_linux_amd64' => '171cf4074bfca3b1e46112105738985783f19c47f4408377241b868affa9d445', - 'consul_0.5.2_windows_386' => '2e866812de16f1a6138a0fd1eebc76143f1314826e3b52597a55ac510ae94be6', - 'consul_0.5.2_web_ui' => 'ad883aa52e1c0136ab1492bbcedad1210235f26d59719fb6de3ef6464f1ff3b1', - - 'consul_0.6.0_darwin_386' => '95d57bfcc287bc344ec3ae8372cf735651af1158c5b1345e6f30cd9a9c811815', - 'consul_0.6.0_darwin_amd64' => '29ddff01368458048731afa586cec5426c8033a914b43fc83d6442e0a522c114', - 'consul_0.6.0_freebsd_386' => 'c5eb9f5c211612148e1e1cd101670fd08fd1abf9b2e541ac2936ab9637626249', - 'consul_0.6.0_freebsd_amd64' => 'd7be5c95b971f48ccbd2c53c342dced9a3d0a5bc58f57b4f2e75672d96929923', - 'consul_0.6.0_freebsd_arm' => '92f29ad00f8f44d3be43b3b038a904c332757eb2a6848a7d6754583c2791e18b', - 'consul_0.6.0_linux_386' => 'f58f3f03a8b48d89bb8be94a6d1767393ad2a410c920b064066e01c7fa24f06c', - 'consul_0.6.0_linux_amd64' => '307fa26ae32cb8732aed2b3320ed8daf02c28b50d952cbaae8faf67c79f78847', - 'consul_0.6.0_linux_arm' => '425e7332789deb446a486ac25f7143aba5f16453ac46ede39b71ab6a361d8726', - 'consul_0.6.0_windows_386' => '8379afd07668933c120880bba8228277e380abb14e07a6c45b94562ac19b37bd', - 'consul_0.6.0_windows_amd64' => '182beea0d8d346a9bfd70679621a5542aeeeea1f35be81fa3d3aeec2479bac3d', - 'consul_0.6.0_web_ui' => '73c5e7ee50bb4a2efe56331d330e6d7dbf46335599c028344ccc4031c0c32eb0', - - 'consul_0.6.1_darwin_386' => '41dfcc0aefe0a60bdde413eaa8a4a0c98e396d6b438494f1cf29b32d07759b8e', - 'consul_0.6.1_darwin_amd64' => '358654900772b3477497f4a5b5a841f2763dc3062bf29212606a97f5a7a675f3', - 'consul_0.6.1_freebsd_386' => '87d8c56c0c02e2fcde5192614dff9c491af93f7186fd55caae3fbe2c4d6ca80c', - 'consul_0.6.1_freebsd_amd64' => '04688dfabedf6ded7f3d548110c7d9ffc8d6d3a091062593e421702bc42b465d', - 'consul_0.6.1_freebsd_arm' => '7b907fbd4377671de1be2dc0c19f955e1b37cd862c1af8251e9bf6d668b0d3a8', - 'consul_0.6.1_linux_386' => '34b8d4a2a9ec85082b6e93c6785ba9c54663fec414062e45dd4386db46a533c4', - 'consul_0.6.1_linux_amd64' => 'dbb3c348fdb7cdfc03e5617956b243c594a399733afee323e69ef664cdadb1ac', - 'consul_0.6.1_linux_arm' => '5b61e9ed10e02990aa8a2a0116c398c61608bc7f5051cb5a13750ffd47a54d51', - 'consul_0.6.1_windows_386' => '10197d1f7be0d0087414c9965008ddd88e9fcd9ac9d5bd02d72d65eda36f5834', - 'consul_0.6.1_windows_amd64' => '2be6b0f0fdebff00aea202e9846131af570676f52e2936728cbf29ffbb02f57f', - 'consul_0.6.1_web_ui' => 'afccdd540b166b778c7c0483becc5e282bbbb1ee52335bfe94bf757df8c55efc', - - 'consul_0.6.2_darwin_386' => '973105816261c8001fcfa76c9fb707fa56325460476fb0daa97b9ece0602a918', - 'consul_0.6.2_darwin_amd64' => '3089f77fcdb922894456ea6d0bc78a2fb60984d1d3687fa9d8f604b266c83446', - 'consul_0.6.2_freebsd_386' => 'fc87f2ddd2090031e79136954d9e3f85db480d5ed9eba6ae627bf460e4c95e6e', - 'consul_0.6.2_freebsd_amd64' => '1ccf96cb58c6fa927ee21c24d9be368ebe91559ed32626a89a715a3781659e3f', - 'consul_0.6.2_freebsd_arm' => '30d8d09dd88cdd8d5256cea445fd0fed787d73cc6585e2eef7212161f29c8053', - 'consul_0.6.2_linux_386' => '500ac8c75768b7f2d63521d2501ff8cc5fb7f9ddf6c550e9449364810c96f419', - 'consul_0.6.2_linux_amd64' => '7234eba9a6d1ce169ff8d7af91733e63d8fc82193d52d1b10979d8be5c959095', - 'consul_0.6.2_linux_arm' => 'b6b4f66f6dd8b1d4ebbd0339f4ed78c4853c7bd0d42fd15af70179b5bc65482e', - 'consul_0.6.2_solaris_amd64' => 'f5655f0b173e5d51c5b92327d1fc7f24ac0939897a1966da09146e4eb75af9d1', - 'consul_0.6.2_windows_386' => 'f072d89c098dde143897e653d5adaf23125b58062344ef4be4029d635f959654', - 'consul_0.6.2_windows_amd64' => 'df3234fb7def7138b7cb8c73fe7c05942ec1e485925701a7b38fc7e2396a212f', - 'consul_0.6.2_web_ui' => 'f144377b8078df5a3f05918d167a52123089fc47b12fc978e6fb375ae93afc90', - - 'consul_0.6.3_darwin_386' => '7fb30756504cd9559c9b23e5d0d8d73a847ee62ed85d39955b5906c2f59a5bc1', - 'consul_0.6.3_darwin_amd64' => '6dff4ffc61d66aacd627a176737b8725624718a9e68cc81460a3df9b241c7932', - 'consul_0.6.3_freebsd_386' => '4a1aa8f570852eb238b7406172c097f5b32f41a3f01186111e576faa7506248c', - 'consul_0.6.3_freebsd_amd64' => '8bdf2da41e6118af18af9aba0a127d4abb3453a20a9064e1bd1206f5c11ac2c8', - 'consul_0.6.3_freebsd_arm' => '5452d29f1cf0720c4ae0e0ec1cc5e44b0068a0340a6b61ab5ec245fa0f3447ad', - 'consul_0.6.3_linux_386' => '2afb65383ab913344daaa9af827c1e8576c7cae16e93798048122929b6e4cc92', - 'consul_0.6.3_linux_amd64' => 'b0532c61fec4a4f6d130c893fd8954ec007a6ad93effbe283a39224ed237e250', - 'consul_0.6.3_linux_arm' => 'c5fd5278be2757d2468bc7e263af15bc9a9e80fc5108fec658755804ea9bca56', - 'consul_0.6.3_solaris_amd64' => 'e6a286ff17a2345b8800732850eadb858b3dba9486355e1164a774ccec2f0e98', - 'consul_0.6.3_windows_386' => '55733a730c5055d0ed1dc2656b2b6a27b21c7c361a907919cfae90aab2dff870', - 'consul_0.6.3_windows_amd64' => '04cd1fdc9cd3a27ffc64e312e40142db7af0d240608f8080ec6d238294b20652', - 'consul_0.6.3_web_ui' => '93bbb300cacfe8de90fb3bd5ede7d37ae6ce014898edc520b9c96a676b2bbb72' -} diff --git a/attributes/firewall.rb b/attributes/firewall.rb new file mode 100644 index 00000000..02977ced --- /dev/null +++ b/attributes/firewall.rb @@ -0,0 +1,8 @@ +# +# Cookbook: consul +# License: Apache 2.0 +# +# Copyright 2014-2016, Bloomberg Finance L.P. +# + +default['firewall']['allow_consul'] = false diff --git a/libraries/consul_config.rb b/libraries/consul_config.rb index a8b393e8..081ac53f 100644 --- a/libraries/consul_config.rb +++ b/libraries/consul_config.rb @@ -9,7 +9,7 @@ module ConsulCookbook module Resource - # @since 1.0.0 + # @since 1.0 class ConsulConfig < Chef::Resource include Poise(fused: true) include ConsulCookbook::Helpers @@ -18,23 +18,18 @@ class ConsulConfig < Chef::Resource # @!attribute path # @return [String] attribute(:path, kind_of: String, name_attribute: true) - # @!attribute owner # @return [String] attribute(:owner, kind_of: String, default: 'consul') - # @!attribute group # @return [String] attribute(:group, kind_of: String, default: 'consul') - # @!attribute bag_name # @return [String] attribute(:bag_name, kind_of: String, default: 'secrets') - # @!attribute bag_item # @return [String] attribute(:bag_item, kind_of: String, default: 'consul') - # @!attribute options # @return [Hash] attribute(:options, option_collector: true) @@ -118,50 +113,6 @@ def tls? action(:create) do notifying_block do - if new_resource.tls? - include_recipe 'chef-vault::default' - - [new_resource.ca_file, new_resource.cert_file, new_resource.key_file].each do |filename| - directory ::File.dirname(filename) do - recursive true - if node['os'].eql? 'linux' - owner new_resource.owner - group new_resource.group - mode '0755' - end - end - end - - item = chef_vault_item(new_resource.bag_name, new_resource.bag_item) - file new_resource.ca_file do - content item['ca_certificate'] - if node['os'].eql? 'linux' - owner new_resource.owner - group new_resource.group - mode '0644' - end - end - - file new_resource.cert_file do - content item['certificate'] - if node['os'].eql? 'linux' - owner new_resource.owner - group new_resource.group - mode '0644' - end - end - - file new_resource.key_file do - sensitive true - content item['private_key'] - if node['os'].eql? 'linux' - owner new_resource.owner - group new_resource.group - mode '0640' - end - end - end - directory ::File.dirname(new_resource.path) do recursive true if node['os'].eql? 'linux' @@ -185,16 +136,6 @@ 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_installation.rb b/libraries/consul_installation.rb new file mode 100644 index 00000000..b231a120 --- /dev/null +++ b/libraries/consul_installation.rb @@ -0,0 +1,31 @@ +# +# Cookbook: consul +# License: Apache 2.0 +# +# Copyright 2014-2016, Bloomberg Finance L.P. +# +require 'poise' + +module ConsulCookbook + module Resource + # A `consul_installation` resource which manages the Consul installation. + # @action create + # @action remove + # @since 2.0 + class ConsulInstallation < Chef::Resource + include Poise(inversion: true) + provides(:consul_installation) + actions(:create, :remove) + default_action(:create) + + # @!attribute version + # The version of Consul to install. + # @return [String] + attribute(:version, kind_of: String, name_attribute: true) + + def consul_program + @program ||= provider_for_action(:consul_program).consul_program + end + end + end +end diff --git a/libraries/consul_installation_binary.rb b/libraries/consul_installation_binary.rb new file mode 100644 index 00000000..c41a3ca5 --- /dev/null +++ b/libraries/consul_installation_binary.rb @@ -0,0 +1,183 @@ +# +# Cookbook: consul +# License: Apache 2.0 +# +# Copyright 2014-2016, Bloomberg Finance L.P. +# +require 'poise' + +module ConsulCookbook + module Provider + # A `consul_installation` provider which manages Consul binary + # installation from remote source URL. + # @action create + # @action remove + # @provides consul_installation + # @example + # consul_installation '0.5.0' + # @since 2.0 + class ConsulInstallationBinary < Chef::Provider + include Poise(inversion: :consul_installation) + provides(:binary) + inversion_attribute('consul') + + # @api private + def self.provides_auto?(_node, _resource) + true + end + + # Set the default inversion options. + # @return [Hash] + # @api private + def self.default_inversion_options(node, resource) + archive_basename = binary_basename(node, resource) + super.merge( + version: resource.version, + archive_url: default_archive_url % { version: resource.version, basename: archive_basename }, + archive_basename: archive_basename, + archive_checksum: binary_checksum(node, resource), + extract_to: '/opt/consul' + ) + end + + def action_create + archive_url = options[:archive_url] % { + version: options[:version], + basename: options[:archive_basename] + } + + notifying_block do + directory ::File.join(options[:extract_to], new_resource.version) do + recursive true + end + + zipfile options[:archive_basename] do + path ::File.join(options[:extract_to], new_resource.version) + source archive_url + checksum options[:archive_checksum] + not_if { ::File.exist?(consul_program) } + end + end + end + + def action_remove + notifying_block do + directory ::File.join(options[:extract_to], new_resource.version) do + recursive true + action :delete + end + end + end + + def consul_program + @program ||= ::File.join(options[:extract_to], new_resource.version, 'consul') + return @program unless node.platform?('windows') + @program + '.exe' + end + + def self.default_archive_url + "https://releases.hashicorp.com/consul/%{version}/%{basename}" # rubocop:disable Style/StringLiterals + end + + def self.binary_basename(node, resource) + case node['kernel']['machine'] + when 'x86_64' then ['consul', resource.version, node['os'], 'amd64'].join('_') + when 'i386' then ['consul', resource.version, node['os'], '386'].join('_') + else ['consul', resource.version, node['os'], node['kernel']['machine']].join('_') + end.concat('.zip') + end + + def self.binary_checksum(node, resource) + case [node['os'], node['kernel']['machine']].join('-') + when 'darwin-x86_64' + case resource.version + when '0.5.0' then '24d9758c873e9124e0ce266f118078f87ba8d8363ab16c2e59a3cd197b77e964' + when '0.5.1' then '161f2a8803e31550bd92a00e95a3a517aa949714c19d3124c46e56cfdc97b088' + when '0.5.2' then '87be515d7dbab760a61a359626a734f738d46ece367f68422b7dec9197d9eeea' + when '0.6.0' then '29ddff01368458048731afa586cec5426c8033a914b43fc83d6442e0a522c114' + when '0.6.1' then '358654900772b3477497f4a5b5a841f2763dc3062bf29212606a97f5a7a675f3' + when '0.6.2' then '3089f77fcdb922894456ea6d0bc78a2fb60984d1d3687fa9d8f604b266c83446' + when '0.6.3' then '6dff4ffc61d66aacd627a176737b8725624718a9e68cc81460a3df9b241c7932' + end + when 'darwin-i386' + case resource.version + when '0.6.0' then '95d57bfcc287bc344ec3ae8372cf735651af1158c5b1345e6f30cd9a9c811815' + when '0.6.1' then '41dfcc0aefe0a60bdde413eaa8a4a0c98e396d6b438494f1cf29b32d07759b8e' + when '0.6.2' then '973105816261c8001fcfa76c9fb707fa56325460476fb0daa97b9ece0602a918' + when '0.6.3' then '7fb30756504cd9559c9b23e5d0d8d73a847ee62ed85d39955b5906c2f59a5bc1' + end + when 'solaris-x86_64' + case resource.version + when '0.6.2' then 'f5655f0b173e5d51c5b92327d1fc7f24ac0939897a1966da09146e4eb75af9d1' + when '0.6.3' then 'e6a286ff17a2345b8800732850eadb858b3dba9486355e1164a774ccec2f0e98' + end + when 'windows-x86_64' + case resource.version + when '0.6.0' then '182beea0d8d346a9bfd70679621a5542aeeeea1f35be81fa3d3aeec2479bac3d' + when '0.6.1' then '2be6b0f0fdebff00aea202e9846131af570676f52e2936728cbf29ffbb02f57f' + when '0.6.2' then 'df3234fb7def7138b7cb8c73fe7c05942ec1e485925701a7b38fc7e2396a212f' + when '0.6.3' then '04cd1fdc9cd3a27ffc64e312e40142db7af0d240608f8080ec6d238294b20652' + end + when 'windows-i386' + case resource.version + when '0.5.0' then '7fd760ee8a5c2756391cacc1e924ae602b16cdad838db068e564f798383ad714' + when '0.5.1' then 'bb9e1753cf793ad6f9db34bd6e18fb0fa5b0696a8a51a7f1c61484386dfe6682' + when '0.5.2' then '2e866812de16f1a6138a0fd1eebc76143f1314826e3b52597a55ac510ae94be6' + when '0.6.0' then '8379afd07668933c120880bba8228277e380abb14e07a6c45b94562ac19b37bd' + when '0.6.1' then '10197d1f7be0d0087414c9965008ddd88e9fcd9ac9d5bd02d72d65eda36f5834' + when '0.6.2' then 'f072d89c098dde143897e653d5adaf23125b58062344ef4be4029d635f959654' + when '0.6.3' then '55733a730c5055d0ed1dc2656b2b6a27b21c7c361a907919cfae90aab2dff870' + end + when 'linux-x86_64' + case resource.version + when '0.5.0' then '161f2a8803e31550bd92a00e95a3a517aa949714c19d3124c46e56cfdc97b088' + when '0.5.1' then '967ad75865b950698833eaf26415ba48d8a22befb5d4e8c77630ad70f251b100' + when '0.5.2' then '171cf4074bfca3b1e46112105738985783f19c47f4408377241b868affa9d445' + when '0.6.0' then '307fa26ae32cb8732aed2b3320ed8daf02c28b50d952cbaae8faf67c79f78847' + when '0.6.1' then 'dbb3c348fdb7cdfc03e5617956b243c594a399733afee323e69ef664cdadb1ac' + when '0.6.2' then '7234eba9a6d1ce169ff8d7af91733e63d8fc82193d52d1b10979d8be5c959095' + when '0.6.3' then 'b0532c61fec4a4f6d130c893fd8954ec007a6ad93effbe283a39224ed237e250' + end + when 'linux-i386' + case resource.version + when '0.5.0' then '4b6147c30596a30361d4753d409f8a1af9518f54f5ed473a4c4ac973738ac0fd' + when '0.5.1' then 'dad93a02c01de885daee191bcc5a05ca2bf106200da61db33694a658432d8399' + when '0.5.2' then '29306ce398109f954ceeea3af79878be4fb0d949f8af3a27c95ccef2101e8f60' + when '0.6.0' then 'f58f3f03a8b48d89bb8be94a6d1767393ad2a410c920b064066e01c7fa24f06c' + when '0.6.1' then '34b8d4a2a9ec85082b6e93c6785ba9c54663fec414062e45dd4386db46a533c4' + when '0.6.2' then '500ac8c75768b7f2d63521d2501ff8cc5fb7f9ddf6c550e9449364810c96f419' + when '0.6.3' then '2afb65383ab913344daaa9af827c1e8576c7cae16e93798048122929b6e4cc92' + end + when 'linux-arm' + case resource.version + when '0.6.0' then '425e7332789deb446a486ac25f7143aba5f16453ac46ede39b71ab6a361d8726' + when '0.6.1' then '5b61e9ed10e02990aa8a2a0116c398c61608bc7f5051cb5a13750ffd47a54d51' + when '0.6.2' then 'b6b4f66f6dd8b1d4ebbd0339f4ed78c4853c7bd0d42fd15af70179b5bc65482e' + when '0.6.3' then 'c5fd5278be2757d2468bc7e263af15bc9a9e80fc5108fec658755804ea9bca56' + end + when 'freebsd-x86_64' + case resource.version + when '0.6.0' then 'd7be5c95b971f48ccbd2c53c342dced9a3d0a5bc58f57b4f2e75672d96929923' + when '0.6.1' then '04688dfabedf6ded7f3d548110c7d9ffc8d6d3a091062593e421702bc42b465d' + when '0.6.2' then '1ccf96cb58c6fa927ee21c24d9be368ebe91559ed32626a89a715a3781659e3f' + when '0.6.3' then '8bdf2da41e6118af18af9aba0a127d4abb3453a20a9064e1bd1206f5c11ac2c8' + end + when 'freebsd-i386' + case resource.version + when '0.6.0' then 'c5eb9f5c211612148e1e1cd101670fd08fd1abf9b2e541ac2936ab9637626249' + when '0.6.1' then '87d8c56c0c02e2fcde5192614dff9c491af93f7186fd55caae3fbe2c4d6ca80c' + when '0.6.2' then 'fc87f2ddd2090031e79136954d9e3f85db480d5ed9eba6ae627bf460e4c95e6e' + when '0.6.3' then '4a1aa8f570852eb238b7406172c097f5b32f41a3f01186111e576faa7506248c' + end + when 'freebsd-arm' + case resource.version + when '0.6.0' then '92f29ad00f8f44d3be43b3b038a904c332757eb2a6848a7d6754583c2791e18b' + when '0.6.1' then '7b907fbd4377671de1be2dc0c19f955e1b37cd862c1af8251e9bf6d668b0d3a8' + when '0.6.2' then '30d8d09dd88cdd8d5256cea445fd0fed787d73cc6585e2eef7212161f29c8053' + when '0.6.3' then '5452d29f1cf0720c4ae0e0ec1cc5e44b0068a0340a6b61ab5ec245fa0f3447ad' + end + end + end + end + end +end diff --git a/libraries/consul_installation_git.rb b/libraries/consul_installation_git.rb new file mode 100644 index 00000000..95eb805c --- /dev/null +++ b/libraries/consul_installation_git.rb @@ -0,0 +1,71 @@ +# +# Cookbook: consul +# License: Apache 2.0 +# +# Copyright 2014-2016, Bloomberg Finance L.P. +# +require 'poise' + +module ConsulCookbook + module Provider + # A `consul_installation` provider which manages Consul installation + # from the Go source builds. + # @action create + # @action remove + # @provides consul_installation + # @example + # consul_installation '0.5.0' do + # provider 'git' + # end + # @since 2.0 + class ConsulInstallationGit < Chef::Provider + include Poise(inversion: :consul_installation) + provides(:git) + inversion_attribute('consul') + + # Set the default inversion options. + # @return [Hash] + # @api private + def self.default_inversion_options(node, resource) + super.merge( + version: resource.version, + git_url: 'https://github.com/hashicorp/consul', + git_path: '/usr/local/src/consul' + ) + end + + def action_create + notifying_block do + include_recipe 'golang::default', 'build-essential::default' + golang_package 'github.com/mitchellh/gox' + golang_package 'github.com/tools/godep' + + git options[:git_path] do + repository options[:git_url] + reference options.fetch(:git_ref, "v#{new_resource.version}") + action :checkout + end + + execute 'make' do + cwd options[:git_path] + environment(PATH: "#{node['go']['install_dir']}/go/bin:#{node['go']['gobin']}:/usr/bin:/bin", + GOPATH: node['go']['gopath']) + end + end + end + + def action_remove + notifying_block do + directory options[:git_path] do + recursive true + action :delete + end + end + end + + def consul_program + ::File.join(options[:git_path], 'bin', 'consul') + end + end + end +end diff --git a/libraries/consul_installation_package.rb b/libraries/consul_installation_package.rb new file mode 100644 index 00000000..d27bd868 --- /dev/null +++ b/libraries/consul_installation_package.rb @@ -0,0 +1,63 @@ +# +# Cookbook: consul +# License: Apache 2.0 +# +# Copyright 2014-2016, Bloomberg Finance L.P. +# +require 'poise' + +module ConsulCookbook + module Provider + # A `consul_installation` provider which installs Consul from + # package source. + # @action create + # @action remove + # @provides consul_installation + # @example + # consul_installation '0.5.0' do + # provider 'package' + # end + # @since 2.0 + class ConsulInstallationPackage < Chef::Provider + include Poise(inversion: :consul_installation) + provides(:package) + inversion_attribute 'consul' + + # Set the default inversion options. + # @return [Hash] + # @api private + def self.default_inversion_options(node, resource) + super.merge( + version: resource.version, + package_name: 'consul' + ) + end + + def action_create + notifying_block do + package options[:package_name] do + source options[:package_source] + checksum options[:package_checksum] + version options[:version] + action :upgrade + end + end + end + + def action_remove + notifying_block do + package options[:package_name] do + source options[:package_source] + checksum options[:package_checksum] + version options[:version] + action :uninstall + end + end + end + + def consul_program + options.fetch(:consul_program, '/usr/local/bin/consul') + end + end + end +end diff --git a/libraries/consul_service.rb b/libraries/consul_service.rb index 963ecce1..38766b63 100644 --- a/libraries/consul_service.rb +++ b/libraries/consul_service.rb @@ -9,128 +9,67 @@ module ConsulCookbook module Resource - # A resource for managing the Consul service. - # @since 1.0.0 + # A `consul_service` resource for use with `poise_service`. This + # resource manages the Consul service. + # @since 1.0 class ConsulService < Chef::Resource include Poise provides(:consul_service) include PoiseService::ServiceMixin include ConsulCookbook::Helpers - # @!attribute version - # @return [String] - attribute(:version, kind_of: String, required: true) - - # @!attribute install_method - # @return [Symbol] - attribute(:install_method, default: 'binary', equal_to: %w{source binary package}) - - # @!attribute install_path - # @return [String] - attribute(:install_path, kind_of: String, default: lazy { node['consul']['service']['install_path'] }) - # @!attribute config_file # @return [String] attribute(:config_file, kind_of: String, default: lazy { node['consul']['config']['path'] }) - # @!attribute user + # The service user the Consul process runs as. # @return [String] attribute(:user, kind_of: String, default: 'consul') - # @!attribute group + # The service group the Consul process runs as. # @return [String] attribute(:group, kind_of: String, default: 'consul') - # @!attribute environment + # The environment that the Consul process starts with. # @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: lazy { node['consul']['config']['data_dir'] }) - # @!attribute config_dir # @return [String] attribute(:config_dir, kind_of: String, default: lazy { node['consul']['config']['config_dir'] }) - # @!attribute nssm_params # @return [String] attribute(:nssm_params, kind_of: Hash, default: lazy { node['consul']['service']['nssm_params'] }) + # @!attribute program + # The location of the Consul executable. + # @return [String] + attribute(:program, kind_of: String, default: '/usr/local/bin/consul') + + def command + "#{program} agent -config-file=#{config_file} -config-dir=#{config_dir}" + end + + def default_environment + { + 'GOMAXPROCS' => [node['cpu']['total'], 2].max.to_s, + 'PATH' => '/usr/local/bin:/usr/bin:/bin' + } + end end end module Provider # A provider for managing the Consul service. - # @since 1.0.0 + # @since 1.0 class ConsulService < Chef::Provider include Poise provides(:consul_service) include PoiseService::ServiceMixin - include ConsulCookbook::Helpers def action_enable notifying_block do - case new_resource.install_method - when 'package' - package new_resource.package_name do - version new_resource.version unless new_resource.version.nil? - end - when '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 % { version: new_resource.version, filename: new_resource.binary_filename('binary') } - remote_checksum new_resource.binary_checksum 'binary' - end - - link '/usr/local/bin/consul' do - to join_path(artifact.current_path, 'consul') - end - when 'source' - include_recipe 'golang::default' - - source_dir = directory join_path(new_resource.install_path, 'consul', 'src') do - recursive true - owner new_resource.user - group new_resource.group - mode '0755' - end - - git join_path(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 join_path(new_resource.install_path, 'bin') do - recursive true - owner new_resource.user - group new_resource.group - mode '0755' - end - - link join_path(new_resource.install_path, 'bin', 'consul') do - to join_path(source_dir.path, "consul-#{new_resource.version}", 'consul') - end - end - [new_resource.data_dir, new_resource.config_dir].each do |dirname| directory dirname do recursive true @@ -143,17 +82,8 @@ def action_enable super end - def action_disable - notifying_block do - file new_resource.config_file do - action :delete - end - end - super - end - def service_options(service) - service.command(new_resource.command(new_resource.config_file, new_resource.config_dir)) + service.command(new_resource.command) service.directory(new_resource.data_dir) service.user(new_resource.user) service.environment(new_resource.environment) diff --git a/libraries/consul_service_windows.rb b/libraries/consul_service_windows.rb index 1b646574..31d17dd6 100644 --- a/libraries/consul_service_windows.rb +++ b/libraries/consul_service_windows.rb @@ -19,44 +19,25 @@ class ConsulServiceWindows < Chef::Provider def action_enable notifying_block do - case new_resource.install_method - when 'binary' - windows_zipfile "consul-#{new_resource.version}" do - action :unzip - path new_resource.install_path - source new_resource.binary_url % { version: new_resource.version, filename: new_resource.binary_filename('binary') } - not_if { correct_version?(join_path(new_resource.install_path, 'consul.exe'), new_resource.version) } - end - else - Chef::Application.fatal!('The Consul Service provider for Windows only supports the binary install_method at this time') - end - directories = %W{#{new_resource.data_dir} #{new_resource.config_dir} #{::File.dirname(new_resource.nssm_params['AppStdout'])} #{::File.dirname(new_resource.nssm_params['AppStderr'])}}.uniq.compact - - # ::File.dirname '' == '.' directories.delete_if { |i| i.eql? '.' }.each do |dirname| directory dirname do recursive true - # owner new_resource.user - # group new_resource.group - # mode '0755' end end nssm 'consul' do action :install - program join_path(new_resource.install_path, 'consul.exe') - # Don't try and set empty parameters + program new_resource.program params new_resource.nssm_params.select { |_k, v| v != '' } args command(new_resource.config_file, new_resource.config_dir) not_if { nssm_service_installed? } end if nssm_service_installed? - # The nssm resource does not check param values after they've been set mismatch_params = check_nssm_params unless mismatch_params.empty? mismatch_params.each do |k, v| diff --git a/libraries/consul_ui.rb b/libraries/consul_ui.rb deleted file mode 100644 index 54e02777..00000000 --- a/libraries/consul_ui.rb +++ /dev/null @@ -1,77 +0,0 @@ -# -# Cookbook: consul -# License: Apache 2.0 -# -# Copyright 2014-2016, Bloomberg Finance L.P. -# -require 'poise' -require_relative 'helpers' - -module ConsulCookbook - module Resource - # Resource for managing the Consul web UI installation. - class ConsulUI < Chef::Resource - include Poise - include ConsulCookbook::Helpers - provides(:consul_ui) - default_action(:install) - - # @!attribute version - # @return [String] - attribute(:version, kind_of: String, required: true) - - # @!attribute install_path - # @return [String] - attribute(:install_path, kind_of: String, default: '/srv') - - # @!attribute owner - # @return [String] - attribute(:owner, kind_of: String, default: 'consul') - - # @!attribute group - # @return [String] - attribute(:group, kind_of: String, default: 'consul') - - # @!attribute binary_url - # @return [String] - attribute(:binary_url, kind_of: String, default: 'https://releases.hashicorp.com/consul/%{version}/%{filename}.zip') - - # @!attribute source_url - # @return [String] - attribute(:source_url, kind_of: String) - end - end - - module Provider - # Provider for managing the Consul web UI installation. - class ConsulUI < Chef::Provider - include Poise - provides(:consul_ui) - - def action_install - notifying_block do - libartifact_file "#{new_resource.name}-#{new_resource.version}" do - artifact_name new_resource.name - artifact_version new_resource.version - owner new_resource.owner - group new_resource.group - install_path new_resource.install_path - remote_url new_resource.binary_url % { version: new_resource.version, filename: new_resource.binary_filename('web_ui') } - remote_checksum new_resource.binary_checksum 'web_ui' - end - end - end - - def action_uninstall - notifying_block do - libartifact_file "#{new_resource.name}-#{new_resource.version}" do - action :delete - artifact_name new_resource.name - artifact_version new_resource.version - install_path new_resource.install_path - end - end - end - end - end -end diff --git a/libraries/helpers.rb b/libraries/helpers.rb index 2b4a44eb..5de5151e 100644 --- a/libraries/helpers.rb +++ b/libraries/helpers.rb @@ -75,13 +75,6 @@ def nssm_exe "#{node['nssm']['install_location']}\\nssm.exe" end - def default_environment - { - 'GOMAXPROCS' => [node['cpu']['total'], 2].max.to_s, - 'PATH' => '/usr/local/bin:/usr/bin:/bin' - } - end - def nssm_params %w{Application AppParameters diff --git a/metadata.rb b/metadata.rb index 08eade9d..f3df939c 100644 --- a/metadata.rb +++ b/metadata.rb @@ -4,23 +4,29 @@ license 'Apache 2.0' description 'Application cookbook which installs and configures Consul.' long_description 'Application cookbook which installs and configures Consul.' -version '1.5.0' +version '2.0.0' -recipe 'consul::default', 'Installs, configures and starts the Consul service.' +recipe 'consul::default', 'Installs and configures the Consul service.' +recipe 'consul::web_ui', 'Installs and configures the Consul Web UI.' +recipe 'consul::client_gem', 'Installs the Consul Ruby client as a gem.' supports 'centos', '>= 6.4' supports 'redhat', '>= 6.4' supports 'ubuntu', '>= 12.04' +supports 'solaris2' +supports 'freebsd' supports 'arch' supports 'windows' +depends 'build-essential' +depends 'chef-sugar' depends 'chef-vault', '~> 1.3' depends 'nssm' depends 'golang' depends 'firewall', '~> 2.0' -depends 'libartifact', '~> 1.3' depends 'poise', '~> 2.2' depends 'poise-service', '~> 1.0' +depends 'rubyzip', '~> 1.0' depends 'yum-epel' source_url 'https://github.com/johnbellone/consul-cookbook' if respond_to?(:source_url) diff --git a/recipes/default.rb b/recipes/default.rb index 827d7f0d..77793323 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -4,7 +4,9 @@ # # Copyright 2014-2016, Bloomberg Finance L.P. # -if platform_family?('rhel') +include_recipe 'chef-sugar::default' + +if rhel? include_recipe 'yum-epel::default' if node['platform_version'].to_i == 5 end @@ -31,7 +33,7 @@ end end -unless platform?('windows') +unless windows? group node['consul']['service_group'] user node['consul']['service_user'] do shell '/bin/bash' @@ -39,21 +41,33 @@ end end -config = consul_config node['consul']['service_name'] do |r| - unless platform?('windows') +service_name = node['consul']['service_name'] +config = consul_config service_name do |r| + unless windows? owner node['consul']['service_user'] group node['consul']['service_group'] end node['consul']['config'].each_pair { |k, v| r.send(k, v) } + notifies :restart, "consul_service[#{service_name}]", :delayed end -consul_service node['consul']['service_name'] do |r| - unless platform?('windows') - user node['consul']['service_user'] - group node['consul']['service_group'] +install = consul_installation node['consul']['version'] do |r| + if node['consul']['installation'] + node['consul']['installation'].each_pair { |k, v| r.send(k, v) } end + notifies :restart, "consul_service[#{service_name}]", :delayed +end + +consul_service service_name do |r| version node['consul']['version'] config_file config.path - node['consul']['service'].each_pair { |k, v| r.send(k, v) } - subscribes :restart, "consul_config[#{config.name}]", :delayed + program install.consul_program + + unless windows? + user node['consul']['service_user'] + group node['consul']['service_group'] + end + if node['consul']['service'] + node['consul']['service'].each_pair { |k, v| r.send(k, v) } + end end diff --git a/test/cookbooks/consul_spec/recipes/consul_ui.rb b/test/cookbooks/consul_spec/recipes/consul_ui.rb deleted file mode 100644 index a52abf4b..00000000 --- a/test/cookbooks/consul_spec/recipes/consul_ui.rb +++ /dev/null @@ -1,6 +0,0 @@ - consul_ui 'myconsul-ui' do - owner 'myconsul' - group 'myconsul' - version '0.5.1' - install_path '/opt' - end diff --git a/test/integration/acl/serverspec/localhost/default_spec.rb b/test/integration/acl/serverspec/default_spec.rb similarity index 100% rename from test/integration/acl/serverspec/localhost/default_spec.rb rename to test/integration/acl/serverspec/default_spec.rb diff --git a/test/integration/default/serverspec/localhost/default_spec.rb b/test/integration/default/serverspec/default_spec.rb similarity index 84% rename from test/integration/default/serverspec/localhost/default_spec.rb rename to test/integration/default/serverspec/default_spec.rb index 42b771c5..e5818519 100644 --- a/test/integration/default/serverspec/localhost/default_spec.rb +++ b/test/integration/default/serverspec/default_spec.rb @@ -1,15 +1,10 @@ require 'spec_helper' -describe file('/srv/consul/current/consul') do +describe file('/opt/consul/0.6.3/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 group('consul') do it { should exist } end @@ -31,7 +26,7 @@ end end -describe command('/usr/local/bin/consul members -detailed') do +describe command('/opt/consul/0.6.3/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} } @@ -47,7 +42,7 @@ it { should be_file } it { should be_owned_by 'consul' } it { should be_grouped_into 'consul' } - + it { should be_mode 640 } end @@ -55,7 +50,7 @@ it { should be_directory } it { should be_owned_by 'consul' } it { should be_grouped_into 'consul' } - + it { should be_mode 755 } end @@ -63,6 +58,6 @@ it { should be_directory } it { should be_owned_by 'consul' } it { should be_grouped_into 'consul' } - + it { should be_mode 755 } end diff --git a/test/integration/windefault/serverspec/localhost/logging_spec.rb b/test/integration/windefault/serverspec/localhost/logging_spec.rb deleted file mode 100644 index 203a0045..00000000 --- a/test/integration/windefault/serverspec/localhost/logging_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'spec_helper' - -context 'logging' do - describe file('C:\foo\bar\out.log') do - it { should be_file } - end - - describe file('C:\foo\bar\err.log') do - it { should be_file } - end -end \ No newline at end of file diff --git a/test/integration/windefault/serverspec/localhost/default_spec.rb b/test/integration/zip/serverspec/default_spec.rb similarity index 75% rename from test/integration/windefault/serverspec/localhost/default_spec.rb rename to test/integration/zip/serverspec/default_spec.rb index 6f76cf45..a5dc125e 100644 --- a/test/integration/windefault/serverspec/localhost/default_spec.rb +++ b/test/integration/zip/serverspec/default_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe file('C:\Program Files\consul\consul.exe') do +describe file('C:\opt\consul\0.6.3\consul.exe') do it { should be_file } end @@ -15,7 +15,7 @@ end end -describe command('& "C:\Program Files\consul\consul.exe" members -detailed') do +describe command('& "C:\opt\consul\0.6.3\consul.exe" members -detailed') do its(:exit_status) { should eq 0 } its(:stdout) { should match %r{\balive\b} } its(:stdout) { should match %r{\brole=consul\b} } @@ -38,3 +38,11 @@ describe file(data_dir) do it { should be_directory } end + +describe file('C:\foo\bar\out.log') do + it { should be_file } +end + +describe file('C:\foo\bar\err.log') do + it { should be_file } +end diff --git a/test/spec/libraries/consul_config_spec.rb b/test/spec/libraries/consul_config_spec.rb index a5454f83..017e0428 100644 --- a/test/spec/libraries/consul_config_spec.rb +++ b/test/spec/libraries/consul_config_spec.rb @@ -8,7 +8,6 @@ before do recipe = double('Chef::Recipe') allow_any_instance_of(Chef::RunContext).to receive(:include_recipe).and_return([recipe]) - allow_any_instance_of(Chef::Provider).to receive(:chef_vault_item) { { 'ca_certificate' => 'foo', 'certificate' => 'bar', 'private_key' => 'baz' } } end context 'sets options directly' do @@ -29,50 +28,6 @@ EOH end - context 'manages certificates' do - recipe do - consul_config '/etc/consul/default.json' do - 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 - - 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') } - end - context 'deletes configuration' do recipe do consul_config '/etc/consul/default.json' do