From 1103561918038c9815496abe3085fb929e05580e Mon Sep 17 00:00:00 2001 From: Aaron Gallagher Date: Thu, 8 Dec 2016 22:06:40 -0800 Subject: [PATCH 1/5] Print current vbox version if less than minimum version --- build_win2008.sh | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/build_win2008.sh b/build_win2008.sh index 8925909..f29308a 100755 --- a/build_win2008.sh +++ b/build_win2008.sh @@ -47,10 +47,19 @@ elif [ $(uname) = "Linux" ]; then fi fi -if compare_versions $(VBoxManage -v | sed -e 's/r.*//g' -e 's/_.*//g') $min_vbox_ver false; then - echo "Compatible version of VirtualBox found." +if [ -x "$(which VBoxManage)" ] ; then + current_vbox_ver=$(VBoxManage -v | sed -e 's/r.*//g' -e 's/_.*//g') + if compare_versions $current_vbox_ver $min_vbox_ver false; then + echo "Compatible version of VirtualBox found." + else + echo "A compatible version of VirtualBox was not found." + echo "Current Version=[$current_vbox_ver], Minimum Version=[$min_vbox_ver]" + echo "Please download and install it from https://www.virtualbox.org/" + exit 1 + fi else - echo "A compatible version of VirtualBox was not found. Please download and install it from https://www.virtualbox.org/" + echo "VirtualBox is not installed (or not added to the path)." + echo "Please download and install it from https://www.virtualbox.org/" exit 1 fi From 448dbb007cbaae39b3fa32e3db13043be7611347 Mon Sep 17 00:00:00 2001 From: Arturo Garcia Date: Sun, 5 Mar 2017 08:45:08 -0600 Subject: [PATCH 2/5] Updated the initial startup time for Elasticsearch from 5 seconds to 30 seconds. --- scripts/installs/install_elasticsearch.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/installs/install_elasticsearch.bat b/scripts/installs/install_elasticsearch.bat index dfda300..4ee97bd 100644 --- a/scripts/installs/install_elasticsearch.bat +++ b/scripts/installs/install_elasticsearch.bat @@ -3,7 +3,7 @@ cmd /c ""C:\Program Files\7-Zip\7z.exe" x "C:\Windows\Temp\elasticsearch-1.1.1.z cmd /c ""C:\Program Files\elasticsearch-1.1.1\bin\service.bat" install" sc config "elasticsearch-service-x64" start= auto cmd /c ""C:\Program Files\elasticsearch-1.1.1\bin\service.bat" start" -powershell -Command "Start-Sleep -s 5" +powershell -Command "Start-Sleep -s 30" powershell -Command "$req = [System.Net.HttpWebRequest]::Create('http://localhost:9200/metasploitable3/'); $req.method = 'PUT'; $req.GetResponse()" powershell -Command "$body = [System.Text.Encoding]::ASCII.GetBytes('{\"user\":\"kimchy\", \"post_date\": \"2009-11-15T14:12:12\", \"message\": \"Elasticsearch\" }'); $req = [System.Net.HttpWebRequest]::Create('http://localhost:9200/metasploitable3/message/1'); $req.method = 'PUT'; $req.ContentType = 'application/x-www-form-urlencoded'; $stream = $req.GetRequestStream(); $stream.Write($body, 0, $body.Length); $stream.close(); $req.GetResponse()" From 106631792212a03d4a23d783134c61ad5e8c3fc2 Mon Sep 17 00:00:00 2001 From: James Barnett Date: Mon, 6 Mar 2017 17:05:28 -0600 Subject: [PATCH 3/5] Update URL for WAMP download. Fixes #91 --- scripts/installs/install_wamp.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/installs/install_wamp.bat b/scripts/installs/install_wamp.bat index 9074382..0cf53a3 100644 --- a/scripts/installs/install_wamp.bat +++ b/scripts/installs/install_wamp.bat @@ -1,4 +1,4 @@ -powershell -Command "(New-Object System.Net.WebClient).DownloadFile('http://sourceforge.mirrorservice.org/w/wa/wampserver/WampServer 2/WampServer 2.2/wampserver2.2d-x64.exe', 'C:\Windows\Temp\wampserver2.2.d-x64.exe')" Date: Wed, 15 Mar 2017 23:59:51 +0100 Subject: [PATCH 4/5] linux: add docker_daemon_privilege_escalation Install docker from the community cookbook and add some users in the docker group from attributes. I created the `attributes/default.rb` attribute file to configure which users are added in the `docker` group. I suggest to put all configurable values here, such as users, passwords etc.. --- Vagrantfile | 5 +++++ .../metasploitable/attributes/default.rb | 9 +++++++++ chef/cookbooks/metasploitable/metadata.rb | 1 + chef/cookbooks/metasploitable/recipes/docker.rb | 15 +++++++++++++++ 4 files changed, 30 insertions(+) create mode 100644 chef/cookbooks/metasploitable/attributes/default.rb create mode 100644 chef/cookbooks/metasploitable/recipes/docker.rb diff --git a/Vagrantfile b/Vagrantfile index 3c89824..8f53ed2 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -149,6 +149,10 @@ Vagrant.configure("2") do |config| config.vm.provision :chef_solo do |chef| chef.cookbooks_path = [ 'chef/cookbooks' ] + chef.json = { 'metasploitable' => { + # Customizations here + } + } chef.add_recipe "metasploitable::mysql" chef.add_recipe "metasploitable::apache_continuum" @@ -157,6 +161,7 @@ Vagrant.configure("2") do |config| chef.add_recipe "metasploitable::phpmyadmin" chef.add_recipe "metasploitable::proftpd" chef.add_recipe "metasploitable::users" + chef.add_recipe "metasploitable::docker" end end end diff --git a/chef/cookbooks/metasploitable/attributes/default.rb b/chef/cookbooks/metasploitable/attributes/default.rb new file mode 100644 index 0000000..7bea78e --- /dev/null +++ b/chef/cookbooks/metasploitable/attributes/default.rb @@ -0,0 +1,9 @@ +# +# Cookbook:: metasploitable +# Attributes:: default +# + +default['metasploitable']['docker_users'] = ['boba_fett', + 'jabba_hutt', + 'greedo', + 'chewbacca',] diff --git a/chef/cookbooks/metasploitable/metadata.rb b/chef/cookbooks/metasploitable/metadata.rb index 0ee32db..804b8bf 100644 --- a/chef/cookbooks/metasploitable/metadata.rb +++ b/chef/cookbooks/metasploitable/metadata.rb @@ -18,4 +18,5 @@ version '0.1.0' # # source_url 'https://github.com//metasploitable3' if respond_to?(:source_url) +depends 'docker' depends 'mysql' diff --git a/chef/cookbooks/metasploitable/recipes/docker.rb b/chef/cookbooks/metasploitable/recipes/docker.rb new file mode 100644 index 0000000..423494b --- /dev/null +++ b/chef/cookbooks/metasploitable/recipes/docker.rb @@ -0,0 +1,15 @@ +# +# Cookbook:: metasploitable +# Recipe:: docker +# + +docker_service 'default' do + action [:create, :start] + group 'docker' +end + +group 'docker' do + action [:create, :modify] + append true + members node['metasploitable']['docker_users'] +end From 9f20618e2a8ada18fc40acb9c15239aca1dd0915 Mon Sep 17 00:00:00 2001 From: James Barnett Date: Thu, 30 Mar 2017 15:26:04 -0500 Subject: [PATCH 5/5] Add docker and compat_resource cookbooks. --- chef/cookbooks/compat_resource/CHANGELOG.md | 48 + .../cookbooks/compat_resource/CONTRIBUTING.md | 2 + chef/cookbooks/compat_resource/MAINTAINERS.md | 16 + chef/cookbooks/compat_resource/README.md | 60 + .../files/lib/chef_compat/copied_from_chef.rb | 29 + .../copied_from_chef/chef/constants.rb | 47 + .../chef/delayed_evaluator.rb | 40 + .../copied_from_chef/chef/dsl/core.rb | 73 + .../chef/dsl/declare_resource.rb | 315 ++++ .../chef/dsl/platform_introspection.rb | 292 +++ .../copied_from_chef/chef/dsl/recipe.rb | 37 + .../copied_from_chef/chef/dsl/universal.rb | 70 + .../chef/mixin/lazy_module_include.rb | 98 + .../chef/mixin/notifying_block.rb | 74 + .../chef/mixin/params_validate.rb | 510 +++++ .../chef/mixin/powershell_out.rb | 117 ++ .../copied_from_chef/chef/mixin/properties.rb | 328 ++++ .../copied_from_chef/chef/property.rb | 713 +++++++ .../copied_from_chef/chef/provider.rb | 164 ++ .../chef/provider/apt_repository.rb | 269 +++ .../chef/provider/apt_update.rb | 105 ++ .../copied_from_chef/chef/provider/noop.rb | 56 + .../chef/provider/support/yum_repo.erb | 125 ++ .../chef/provider/systemd_unit.rb | 253 +++ .../chef/provider/yum_repository.rb | 137 ++ .../copied_from_chef/chef/resource.rb | 214 +++ .../chef/resource/action_class.rb | 114 ++ .../chef/resource/apt_repository.rb | 66 + .../chef/resource/apt_update.rb | 52 + .../chef/resource/systemd_unit.rb | 81 + .../chef/resource/yum_repository.rb | 98 + .../copied_from_chef/chef/resource_builder.rb | 174 ++ .../files/lib/chef_compat/mixin/properties.rb | 8 + .../files/lib/chef_compat/monkeypatches.rb | 41 + .../lib/chef_compat/monkeypatches/chef.rb | 33 + .../monkeypatches/chef/exceptions.rb | 10 + .../lib/chef_compat/monkeypatches/chef/log.rb | 30 + .../chef/mixin/params_validate.rb | 17 + .../chef_compat/monkeypatches/chef/node.rb | 9 + .../monkeypatches/chef/property.rb | 15 + .../monkeypatches/chef/provider.rb | 65 + .../chef_compat/monkeypatches/chef/recipe.rb | 118 ++ .../monkeypatches/chef/recipe_hook.rb | 20 + .../monkeypatches/chef/resource.rb | 156 ++ .../monkeypatches/chef/resource/lwrp_base.rb | 60 + .../monkeypatches/chef/resource_builder.rb | 167 ++ .../monkeypatches/chef/resource_collection.rb | 103 + .../chef/resource_collection/resource_list.rb | 49 + .../chef/resource_collection/resource_set.rb | 49 + .../monkeypatches/chef/run_context.rb | 691 +++++++ .../chef_compat/monkeypatches/chef/runner.rb | 153 ++ .../files/lib/chef_compat/property.rb | 6 + .../files/lib/chef_compat/recipe.rb | 8 + .../files/lib/chef_compat/resource.rb | 56 + .../lib/chef_compat/resource/lwrp_base.rb | 44 + .../files/lib/chef_upstream_version.rb | 3 + .../files/lib/compat_resource.rb | 35 + .../compat_resource/libraries/autoload.rb | 31 + chef/cookbooks/compat_resource/metadata.json | 1 + chef/cookbooks/docker/.foodcritic | 1 + chef/cookbooks/docker/CHANGELOG.md | 1676 +++++++++++++++++ chef/cookbooks/docker/CONTRIBUTING.md | 2 + chef/cookbooks/docker/MAINTAINERS.md | 20 + chef/cookbooks/docker/README.md | 1417 ++++++++++++++ .../vendor/cache/docker-api-1.33.2.gem | Bin 0 -> 27648 bytes .../default/vendor/cache/excon-0.54.0.gem | Bin 0 -> 236032 bytes .../files/default/vendor/cache/json-2.0.3.gem | Bin 0 -> 138752 bytes .../vendor/gems/excon-0.54.0/Gemfile.lock | 301 +++ .../vendor/gems/json-2.0.3/ext/json/Makefile | 196 ++ .../ext/json/ext/generator/Makefile | 262 +++ .../ext/json/ext/generator/generator.bundle | Bin 0 -> 49508 bytes .../ext/json/ext/generator/generator.o | Bin 0 -> 114500 bytes .../json-2.0.3/ext/json/ext/parser/Makefile | 262 +++ .../ext/json/ext/parser/parser.bundle | Bin 0 -> 32908 bytes .../json-2.0.3/ext/json/ext/parser/parser.o | Bin 0 -> 54384 bytes .../json-2.0.3/lib/json/ext/generator.bundle | Bin 0 -> 49508 bytes .../json-2.0.3/lib/json/ext/parser.bundle | Bin 0 -> 32908 bytes chef/cookbooks/docker/libraries/_autoload.rb | 13 + .../cookbooks/docker/libraries/docker_base.rb | 90 + .../docker/libraries/docker_container.rb | 437 +++++ .../cookbooks/docker/libraries/docker_exec.rb | 21 + .../docker/libraries/docker_image.rb | 94 + .../libraries/docker_installation_binary.rb | 40 + .../libraries/docker_installation_package.rb | 32 + .../libraries/docker_installation_script.rb | 51 + .../libraries/docker_installation_tarball.rb | 47 + .../docker/libraries/docker_network.rb | 127 ++ .../docker/libraries/docker_registry.rb | 38 + .../docker/libraries/docker_service.rb | 129 ++ .../docker/libraries/docker_service_base.rb | 123 ++ .../docker_service_manager_execute.rb | 56 + .../docker_service_manager_systemd.rb | 116 ++ .../docker_service_manager_sysvinit_debian.rb | 87 + .../docker_service_manager_sysvinit_rhel.rb | 81 + .../docker_service_manager_upstart.rb | 63 + chef/cookbooks/docker/libraries/docker_tag.rb | 27 + .../docker/libraries/docker_volume.rb | 33 + .../docker/libraries/helpers_auth.rb | 10 + .../docker/libraries/helpers_base.rb | 110 ++ .../docker/libraries/helpers_container.rb | 236 +++ .../docker/libraries/helpers_image.rb | 104 + .../libraries/helpers_installation_binary.rb | 66 + .../libraries/helpers_installation_package.rb | 105 ++ .../libraries/helpers_installation_tarball.rb | 50 + .../docker/libraries/helpers_network.rb | 118 ++ .../docker/libraries/helpers_service.rb | 223 +++ chef/cookbooks/docker/libraries/matchers.rb | 339 ++++ chef/cookbooks/docker/metadata.json | 1 + .../default/default/docker-wait-ready.erb | 10 + .../templates/default/default/docker.erb | 24 + .../templates/default/sysconfig/docker.erb | 19 + .../systemd/docker.service-override.erb | 36 + .../default/systemd/docker.service.erb | 18 + .../systemd/docker.socket-override.erb | 12 + .../default/systemd/docker.socket.erb | 12 + .../default/systemd/tmpfiles.d.conf.erb | 1 + .../default/sysvinit/docker-debian.erb | 149 ++ .../default/sysvinit/docker-rhel.erb | 133 ++ .../templates/default/upstart/docker.conf.erb | 57 + 119 files changed, 14430 insertions(+) create mode 100644 chef/cookbooks/compat_resource/CHANGELOG.md create mode 100644 chef/cookbooks/compat_resource/CONTRIBUTING.md create mode 100644 chef/cookbooks/compat_resource/MAINTAINERS.md create mode 100644 chef/cookbooks/compat_resource/README.md create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/constants.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/delayed_evaluator.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/core.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/declare_resource.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/platform_introspection.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/recipe.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/universal.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/lazy_module_include.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/notifying_block.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/params_validate.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/powershell_out.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/properties.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/property.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/apt_repository.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/apt_update.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/noop.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/support/yum_repo.erb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/systemd_unit.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/yum_repository.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/action_class.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/apt_repository.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/apt_update.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/systemd_unit.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/yum_repository.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource_builder.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/mixin/properties.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/exceptions.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/log.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/mixin/params_validate.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/node.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/property.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/provider.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/recipe.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/recipe_hook.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource/lwrp_base.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_builder.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection/resource_list.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection/resource_set.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/run_context.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/runner.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/property.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/recipe.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/resource.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_compat/resource/lwrp_base.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/chef_upstream_version.rb create mode 100644 chef/cookbooks/compat_resource/files/lib/compat_resource.rb create mode 100644 chef/cookbooks/compat_resource/libraries/autoload.rb create mode 100644 chef/cookbooks/compat_resource/metadata.json create mode 100644 chef/cookbooks/docker/.foodcritic create mode 100644 chef/cookbooks/docker/CHANGELOG.md create mode 100644 chef/cookbooks/docker/CONTRIBUTING.md create mode 100644 chef/cookbooks/docker/MAINTAINERS.md create mode 100644 chef/cookbooks/docker/README.md create mode 100644 chef/cookbooks/docker/files/default/vendor/cache/docker-api-1.33.2.gem create mode 100644 chef/cookbooks/docker/files/default/vendor/cache/excon-0.54.0.gem create mode 100644 chef/cookbooks/docker/files/default/vendor/cache/json-2.0.3.gem create mode 100644 chef/cookbooks/docker/files/default/vendor/gems/excon-0.54.0/Gemfile.lock create mode 100644 chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/Makefile create mode 100644 chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/generator/Makefile create mode 100755 chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/generator/generator.bundle create mode 100644 chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/generator/generator.o create mode 100644 chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/parser/Makefile create mode 100755 chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/parser/parser.bundle create mode 100644 chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/parser/parser.o create mode 100755 chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/lib/json/ext/generator.bundle create mode 100755 chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/lib/json/ext/parser.bundle create mode 100644 chef/cookbooks/docker/libraries/_autoload.rb create mode 100644 chef/cookbooks/docker/libraries/docker_base.rb create mode 100644 chef/cookbooks/docker/libraries/docker_container.rb create mode 100644 chef/cookbooks/docker/libraries/docker_exec.rb create mode 100644 chef/cookbooks/docker/libraries/docker_image.rb create mode 100644 chef/cookbooks/docker/libraries/docker_installation_binary.rb create mode 100644 chef/cookbooks/docker/libraries/docker_installation_package.rb create mode 100644 chef/cookbooks/docker/libraries/docker_installation_script.rb create mode 100644 chef/cookbooks/docker/libraries/docker_installation_tarball.rb create mode 100644 chef/cookbooks/docker/libraries/docker_network.rb create mode 100644 chef/cookbooks/docker/libraries/docker_registry.rb create mode 100644 chef/cookbooks/docker/libraries/docker_service.rb create mode 100644 chef/cookbooks/docker/libraries/docker_service_base.rb create mode 100644 chef/cookbooks/docker/libraries/docker_service_manager_execute.rb create mode 100644 chef/cookbooks/docker/libraries/docker_service_manager_systemd.rb create mode 100644 chef/cookbooks/docker/libraries/docker_service_manager_sysvinit_debian.rb create mode 100644 chef/cookbooks/docker/libraries/docker_service_manager_sysvinit_rhel.rb create mode 100644 chef/cookbooks/docker/libraries/docker_service_manager_upstart.rb create mode 100644 chef/cookbooks/docker/libraries/docker_tag.rb create mode 100644 chef/cookbooks/docker/libraries/docker_volume.rb create mode 100644 chef/cookbooks/docker/libraries/helpers_auth.rb create mode 100644 chef/cookbooks/docker/libraries/helpers_base.rb create mode 100644 chef/cookbooks/docker/libraries/helpers_container.rb create mode 100644 chef/cookbooks/docker/libraries/helpers_image.rb create mode 100644 chef/cookbooks/docker/libraries/helpers_installation_binary.rb create mode 100644 chef/cookbooks/docker/libraries/helpers_installation_package.rb create mode 100644 chef/cookbooks/docker/libraries/helpers_installation_tarball.rb create mode 100644 chef/cookbooks/docker/libraries/helpers_network.rb create mode 100644 chef/cookbooks/docker/libraries/helpers_service.rb create mode 100644 chef/cookbooks/docker/libraries/matchers.rb create mode 100644 chef/cookbooks/docker/metadata.json create mode 100644 chef/cookbooks/docker/templates/default/default/docker-wait-ready.erb create mode 100644 chef/cookbooks/docker/templates/default/default/docker.erb create mode 100755 chef/cookbooks/docker/templates/default/sysconfig/docker.erb create mode 100644 chef/cookbooks/docker/templates/default/systemd/docker.service-override.erb create mode 100644 chef/cookbooks/docker/templates/default/systemd/docker.service.erb create mode 100644 chef/cookbooks/docker/templates/default/systemd/docker.socket-override.erb create mode 100644 chef/cookbooks/docker/templates/default/systemd/docker.socket.erb create mode 100644 chef/cookbooks/docker/templates/default/systemd/tmpfiles.d.conf.erb create mode 100644 chef/cookbooks/docker/templates/default/sysvinit/docker-debian.erb create mode 100644 chef/cookbooks/docker/templates/default/sysvinit/docker-rhel.erb create mode 100644 chef/cookbooks/docker/templates/default/upstart/docker.conf.erb diff --git a/chef/cookbooks/compat_resource/CHANGELOG.md b/chef/cookbooks/compat_resource/CHANGELOG.md new file mode 100644 index 0000000..592b3b8 --- /dev/null +++ b/chef/cookbooks/compat_resource/CHANGELOG.md @@ -0,0 +1,48 @@ +# compat_resource Cookbook CHANGELOG + +This file is used to list changes made in each version of the compat_resource cookbook. + +## 12.16.2 (2016-11-09) + +- Sync chef-client changes from Chef 12.16.42 + +## 12.16.1 (2016-10-20) + +- add delayed_action helper + +## 12.16.0 (2016-10-19) + +- Sync chef-client changes from Chef 12.16.14 + +## 12.14.7 (2016-09-26) + +- Update to 12.14.89 Chef +- Fix autoload by applying fix from #106 + +## 12.14.6 (2016-09-20) + +- Update backported codebase to Chef 12.14.77 which brings in yum_repository updates and why-run enabled by default in custom resources + +## 12.14.5 (2016-09-19) + +- Prevent spamming messages in Chefspec runs for cookbooks that depend on compat_resource + +## 12.14.4 (2016-09-19) + +- Fix delayed notifications cloning + +## 12.14.3 (2016-09-12) + +- Fix subscribes notifications + +## 12.14.2 (2016-09-09) + +- Improve documentation +- keep ChefCompat::Resource defined even if we don't load + +## 12.14.1 (2016-09-07) + +- add yum_repository resource from Chef 12.14 +- Update the minimum chef version in the metadata to 12.1 +- Added maintainers files +- suppress constant redef warnings when running chefspec diff --git a/chef/cookbooks/compat_resource/CONTRIBUTING.md b/chef/cookbooks/compat_resource/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/chef/cookbooks/compat_resource/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/chef/cookbooks/compat_resource/MAINTAINERS.md b/chef/cookbooks/compat_resource/MAINTAINERS.md new file mode 100644 index 0000000..5ae0806 --- /dev/null +++ b/chef/cookbooks/compat_resource/MAINTAINERS.md @@ -0,0 +1,16 @@ + + +# Maintainers + +This file lists how this cookbook project is maintained. When making changes to the system, this file tells you who needs to review your patch - you need a review from an existing maintainer for the cookbook to provide a :+1: on your pull request. Additionally, you need to not receive a veto from a Lieutenant or the Project Lead. + +Check out [How Cookbooks are Maintained](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD) for details on the process and how to become a maintainer or the project lead. + +# Project Maintainer +* [Lamont Granquist](https://github.com/lamont-granquist) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) +* [Lamont Granquist](https://github.com/lamont-granquist) diff --git a/chef/cookbooks/compat_resource/README.md b/chef/cookbooks/compat_resource/README.md new file mode 100644 index 0000000..f5c17e5 --- /dev/null +++ b/chef/cookbooks/compat_resource/README.md @@ -0,0 +1,60 @@ +# compat_resource cookbook + +[![Build Status](https://travis-ci.org/chef-cookbooks/compat_resource.svg?branch=master)](https://travis-ci.org/chef-cookbooks/compat_resource) [![Cookbook Version](https://img.shields.io/cookbook/v/compat_resource.svg)](https://supermarket.chef.io/cookbooks/compat_resource) + +This cookbook backports functionality introduced in the latest chef-client releases to any chef-client from 12.1 onwards. This includes [Custom Resource](https://docs.chef.io/custom_resources.html) functionality, notification improvements, as well as new resources added to core chef. It allows for the usage of these new resources in cookbooks without requiring the very latest Chef client release. + +## Backported functionality + +- [Custom Resources](https://docs.chef.io/custom_resources.html) +- [apt_repository](https://docs.chef.io/resource_apt_repository.html) +- [apt_update](https://docs.chef.io/resource_apt_update.html) +- [systemd_unit](https://docs.chef.io/resource_systemd_unit.html) +- [yum_repository](https://docs.chef.io/resource_yum_repository.html) +- [:before notifications](https://docs.chef.io/resources.html#timers) + +## Requirements + +### Platforms + +- All platforms supported by Chef + +### Chef + +- Chef 12.1+ + +### Cookbooks + +- none + +## Usage + +To use this cookbook, put `depends 'compat_resource'` in the metadata.rb of your cookbook. Once this is done, you can use all the new custom resource features to define resources. It Just Works. + +## Custom Resources? + +Curious about how to use custom resources? + +- Docs: +- Slides: + +## License & Authors + +- Author:: Lamont Granquist ([lamont@chef.io](mailto:lamont@chef.io)) +- Author:: John Keiser ([jkeiser@chef.io](mailto:jkeiser@chef.io)) + +```text +Copyright:: 2015-2016 Chef Software, 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. +``` diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef.rb new file mode 100644 index 0000000..219b05b --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef.rb @@ -0,0 +1,29 @@ +module ChefCompat + module CopiedFromChef + def self.extend_chef_module(chef_module, target) + target.instance_eval do + include chef_module + @chef_module = chef_module + def self.method_missing(name, *args, &block) + @chef_module.send(name, *args, &block) + end + def self.const_missing(name) + @chef_module.const_get(name) + end + end + end + + # This patch to CopiedFromChef's ActionClass is necessary for the include to work + require 'chef/resource' + class Chef < ::Chef + class Resource < ::Chef::Resource + module ActionClass + def self.use_inline_resources + end + def self.include_resource_dsl(include_resource_dsl) + end + end + end + end + end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/constants.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/constants.rb new file mode 100644 index 0000000..4acd742 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/constants.rb @@ -0,0 +1,47 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/constants' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: John Keiser +# Copyright:: Copyright 2015-2016, Chef Software Inc. +# License:: Apache License, Version 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. + +class Chef < (defined?(::Chef) ? ::Chef : Object) + NOT_PASSED = Object.new + def NOT_PASSED.to_s + "NOT_PASSED" + end + + def NOT_PASSED.inspect + to_s + end + NOT_PASSED.freeze +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/delayed_evaluator.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/delayed_evaluator.rb new file mode 100644 index 0000000..4fb687e --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/delayed_evaluator.rb @@ -0,0 +1,40 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/delayed_evaluator' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: John Keiser +# Copyright:: Copyright 2015-2016, Chef Software Inc. +# License:: Apache License, Version 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. + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class DelayedEvaluator < (defined?(::Chef::DelayedEvaluator) ? ::Chef::DelayedEvaluator : Proc) + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/core.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/core.rb new file mode 100644 index 0000000..8e30d30 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/core.rb @@ -0,0 +1,73 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/dsl/core' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +#-- +# Author:: Adam Jacob () +# Author:: Christopher Walters () +# Copyright:: Copyright 2008-2016 Chef Software, Inc. +# License:: Apache License, Version 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. +# + +require "chef_compat/copied_from_chef/chef/dsl/declare_resource" +require "chef_compat/copied_from_chef/chef/dsl/universal" +require "chef_compat/copied_from_chef/chef/mixin/notifying_block" +require "chef_compat/copied_from_chef/chef/mixin/lazy_module_include" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module DSL + CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL) + # Part of a family of DSL mixins. + # + # Chef::DSL::Recipe mixes into Recipes and LWRP Providers. + # - this does not target core chef resources and providers. + # - this is restricted to recipe/resource/provider context where a resource collection exists. + # - cookbook authors should typically include modules into here. + # + # Chef::DSL::Core mixes into Recipes, LWRP Providers and Core Providers + # - this adds cores providers on top of the Recipe DSL. + # - this is restricted to recipe/resource/provider context where a resource collection exists. + # - core chef authors should typically include modules into here. + # + # Chef::DSL::Universal mixes into Recipes, LWRP Resources+Providers, Core Resources+Providers, and Attributes files. + # - this adds resources and attributes files. + # - do not add helpers which manipulate the resource collection. + # - this is for general-purpose stuff that is useful nearly everywhere. + # - it also pollutes the namespace of nearly every context, watch out. + # + module Core + CopiedFromChef.extend_chef_module(::Chef::DSL::Core, self) if defined?(::Chef::DSL::Core) + include Chef::DSL::Universal + include Chef::DSL::DeclareResource + include Chef::Mixin::NotifyingBlock + extend Chef::Mixin::LazyModuleInclude + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/declare_resource.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/declare_resource.rb new file mode 100644 index 0000000..45e69dc --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/declare_resource.rb @@ -0,0 +1,315 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/dsl/declare_resource' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +#-- +# Author:: Adam Jacob () +# Author:: Christopher Walters +# Copyright:: Copyright 2008-2016 Chef Software, Inc. +# License:: Apache License, Version 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. +# + + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module DSL + CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL) + module DeclareResource + CopiedFromChef.extend_chef_module(::Chef::DSL::DeclareResource, self) if defined?(::Chef::DSL::DeclareResource) + + # Helper for switching run_contexts. Allows for using :parent or :root in place of + # passing the run_context. Executes the block in the run_context. Returns the return + # value of the passed block. + # + # @param rc [Chef::RunContext,Symbol] Either :root, :parent or a Chef::RunContext + # + # @return return value of the block + # + # @example + # # creates/returns a 'service[foo]' resource in the root run_context + # resource = with_run_context(:root) + # edit_resource(:service, "foo") do + # action :nothing + # end + # end + # + def with_run_context(rc) + raise ArgumentError, "with_run_context is useless without a block" unless block_given? + old_run_context = @run_context + @run_context = + case rc + when Chef::RunContext + rc + when :root + run_context.root_run_context + when :parent + run_context.parent_run_context + else + raise ArgumentError, "bad argument to run_context helper, must be :root, :parent, or a Chef::RunContext" + end + yield + ensure + @run_context = old_run_context + end + + # Lookup a resource in the resource collection by name and delete it. This + # will raise Chef::Exceptions::ResourceNotFound if the resource is not found. + # + # @param type [Symbol] The type of resource (e.g. `:file` or `:package`) + # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2') + # @param run_context [Chef::RunContext] the run_context of the resource collection to operate on + # + # @return [Chef::Resource] The resource + # + # @example + # delete_resource!(:template, '/x/y.txy') + # + def delete_resource!(type, name, run_context: self.run_context) + run_context.resource_collection.delete("#{type}[#{name}]").tap do |resource| + # Purge any pending notifications too. This will not raise an exception + # if there are no notifications. + if resource + run_context.before_notification_collection.delete(resource.declared_key) + run_context.immediate_notification_collection.delete(resource.declared_key) + run_context.delayed_notification_collection.delete(resource.declared_key) + end + end + end + + # Lookup a resource in the resource collection by name and delete it. Returns + # nil if the resource is not found and should not fail. + # + # @param type [Symbol] The type of resource (e.g. `:file` or `:package`) + # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2') + # @param run_context [Chef::RunContext] the run_context of the resource collection to operate on + # + # @return [Chef::Resource] The resource + # + # @example + # delete_resource(:template, '/x/y.txy') + # + def delete_resource(type, name, run_context: self.run_context) + delete_resource!(type, name, run_context: run_context) + rescue Chef::Exceptions::ResourceNotFound + nil + end + + # Lookup a resource in the resource collection by name and edit the resource. If the resource is not + # found this will raise Chef::Exceptions::ResourceNotFound. This is the correct API to use for + # "chef_rewind" functionality. + # + # @param type [Symbol] The type of resource (e.g. `:file` or `:package`) + # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2') + # @param run_context [Chef::RunContext] the run_context of the resource collection to operate on + # @param resource_attrs_block A block that lets you set attributes of the + # resource (it is instance_eval'd on the resource instance). + # + # @return [Chef::Resource] The updated resource + # + # @example + # edit_resource!(:template, '/x/y.txy') do + # cookbook_name: cookbook_name + # end + # + def edit_resource!(type, name, created_at = nil, run_context: self.run_context, &resource_attrs_block) + resource = find_resource!(type, name, run_context: run_context) + if resource_attrs_block + if defined?(new_resource) + resource.instance_exec(new_resource, &resource_attrs_block) + else + resource.instance_exec(&resource_attrs_block) + end + end + resource + end + + # Lookup a resource in the resource collection by name. If it exists, + # return it. If it does not exist, create it. This is a useful function + # for accumulator patterns. In CRUD terminology this is an "upsert" operation and is + # used to assert that the resource must exist with the specified properties. + # + # @param type [Symbol] The type of resource (e.g. `:file` or `:package`) + # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2') + # @param created_at [String] The caller of the resource. Use `caller[0]` + # to get the caller of your function. Defaults to the caller of this + # function. + # @param run_context [Chef::RunContext] the run_context of the resource collection to operate on + # @param resource_attrs_block A block that lets you set attributes of the + # resource (it is instance_eval'd on the resource instance). + # + # @return [Chef::Resource] The updated or created resource + # + # @example + # resource = edit_resource(:template, '/x/y.txy') do + # source "y.txy.erb" + # variables {} + # end + # resource.variables.merge!({ home: "/home/klowns" }) + # + def edit_resource(type, name, created_at = nil, run_context: self.run_context, &resource_attrs_block) + edit_resource!(type, name, created_at, run_context: run_context, &resource_attrs_block) + rescue Chef::Exceptions::ResourceNotFound + declare_resource(type, name, created_at, run_context: run_context, &resource_attrs_block) + end + + # Lookup a resource in the resource collection by name. If the resource is not + # found this will raise Chef::Exceptions::ResourceNotFound. This API is identical to the + # resources() call and while it is a synonym it is not intended to deprecate that call. + # + # @param type [Symbol] The type of resource (e.g. `:file` or `:package`) + # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2') + # @param run_context [Chef::RunContext] the run_context of the resource collection to operate on + # + # @return [Chef::Resource] The updated resource + # + # @example + # resource = find_resource!(:template, '/x/y.txy') + # + def find_resource!(type, name, run_context: self.run_context) + raise ArgumentError, "find_resource! does not take a block" if block_given? + run_context.resource_collection.find(type => name) + end + + # Lookup a resource in the resource collection by name. If the resource is not found + # the will be no exception raised and the call will return nil. If a block is given and + # no resource is found it will create the resource using the block, if the resource is + # found then the block will not be applied. The block version is similar to create_if_missing + # + # @param type [Symbol] The type of resource (e.g. `:file` or `:package`) + # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2') + # @param run_context [Chef::RunContext] the run_context of the resource collection to operate on + # + # @return [Chef::Resource] The updated resource + # + # @example + # if ( find_resource(:template, '/x/y.txy') ) + # # do something + # else + # # don't worry about the error + # end + # + # @example + # # this API can be used to return a resource from an outer run context, and will only create + # # an action :nothing service if one does not already exist. + # resource = with_run_context(:root) do + # find_resource(:service, 'whatever') do + # action :nothing + # end + # end + # + def find_resource(type, name, created_at: nil, run_context: self.run_context, &resource_attrs_block) + find_resource!(type, name, run_context: run_context) + rescue Chef::Exceptions::ResourceNotFound + if resource_attrs_block + declare_resource(type, name, created_at, run_context: run_context, &resource_attrs_block) + end # returns nil otherwise + end + + # Instantiates a resource (via #build_resource), then adds it to the + # resource collection. Note that resource classes are looked up directly, + # so this will create the resource you intended even if the method name + # corresponding to that resource has been overridden. + # + # @param type [Symbol] The type of resource (e.g. `:file` or `:package`) + # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2') + # @param created_at [String] The caller of the resource. Use `caller[0]` + # to get the caller of your function. Defaults to the caller of this + # function. + # @param run_context [Chef::RunContext] the run_context of the resource collection to operate on + # @param resource_attrs_block A block that lets you set attributes of the + # resource (it is instance_eval'd on the resource instance). + # + # @return [Chef::Resource] The new resource. + # + # @example + # declare_resource(:file, '/x/y.txy', caller[0]) do + # action :delete + # end + # # Equivalent to + # file '/x/y.txt' do + # action :delete + # end + # + def declare_resource(type, name, created_at = nil, run_context: self.run_context, create_if_missing: false, &resource_attrs_block) + created_at ||= caller[0] + + if create_if_missing + Chef::Log.deprecation "build_resource with a create_if_missing flag is deprecated, use edit_resource instead" + # midly goofy since we call edit_resource only to re-call ourselves, but that's why its deprecated... + return edit_resource(type, name, created_at, run_context: run_context, &resource_attrs_block) + end + + resource = build_resource(type, name, created_at, &resource_attrs_block) + + run_context.resource_collection.insert(resource, resource_type: type, instance_name: name) + resource + end + + # Instantiate a resource of the given +type+ with the given +name+ and + # attributes as given in the +resource_attrs_block+. + # + # The resource is NOT added to the resource collection. + # + # @param type [Symbol] The type of resource (e.g. `:file` or `:package`) + # @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2') + # @param created_at [String] The caller of the resource. Use `caller[0]` + # to get the caller of your function. Defaults to the caller of this + # function. + # @param run_context [Chef::RunContext] the run_context of the resource collection to operate on + # @param resource_attrs_block A block that lets you set attributes of the + # resource (it is instance_eval'd on the resource instance). + # + # @return [Chef::Resource] The new resource. + # + # @example + # build_resource(:file, '/x/y.txy', caller[0]) do + # action :delete + # end + # + def build_resource(type, name, created_at = nil, run_context: self.run_context, &resource_attrs_block) + created_at ||= caller[0] + + # this needs to be lazy in order to avoid circular dependencies since ResourceBuilder + # will requires the entire provider+resolver universe + require "chef_compat/copied_from_chef/chef/resource_builder" unless defined?(Chef::ResourceBuilder) + + Chef::ResourceBuilder.new( + type: type, + name: name, + created_at: created_at, + params: @params, + run_context: run_context, + cookbook_name: cookbook_name, + recipe_name: recipe_name, + enclosing_provider: self.is_a?(Chef::Provider) ? self : nil + ).build(&resource_attrs_block) + end + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/platform_introspection.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/platform_introspection.rb new file mode 100644 index 0000000..7886000 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/platform_introspection.rb @@ -0,0 +1,292 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/dsl/platform_introspection' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Adam Jacob () +# Copyright:: Copyright 2008-2016, Chef Software Inc. +# License:: Apache License, Version 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. +# + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module DSL + CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL) + + # == Chef::DSL::PlatformIntrospection + # Provides the DSL for platform-dependent switch logic, such as + # #value_for_platform. + module PlatformIntrospection + CopiedFromChef.extend_chef_module(::Chef::DSL::PlatformIntrospection, self) if defined?(::Chef::DSL::PlatformIntrospection) + + # Implementation class for determining platform dependent values + class PlatformDependentValue < (defined?(::Chef::DSL::PlatformIntrospection::PlatformDependentValue) ? ::Chef::DSL::PlatformIntrospection::PlatformDependentValue : Object) + + # Create a platform dependent value object. + # === Arguments + # platform_hash (Hash) a hash of the same structure as Chef::Platform, + # like this: + # { + # :debian => {:default => 'the value for all debian'} + # [:centos, :redhat, :fedora] => {:default => "value for all EL variants"} + # :ubuntu => { :default => "default for ubuntu", '10.04' => "value for 10.04 only"}, + # :default => "the default when nothing else matches" + # } + # * platforms can be specified as Symbols or Strings + # * multiple platforms can be grouped by using an Array as the key + # * values for platforms need to be Hashes of the form: + # {platform_version => value_for_that_version} + # * the exception to the above is the default value, which is given as + # :default => default_value + def initialize(platform_hash) +super if defined?(::Chef::DSL::PlatformIntrospection::PlatformDependentValue) + @values = {} + platform_hash.each { |platforms, value| set(platforms, value) } + end + + def value_for_node(node) + platform, version = node[:platform].to_s, node[:platform_version].to_s + # Check if we match a version constraint via Chef::VersionConstraint::Platform and Chef::Version::Platform + matched_value = match_versions(node) + if @values.key?(platform) && @values[platform].key?(version) + @values[platform][version] + elsif matched_value + matched_value + elsif @values.key?(platform) && @values[platform].key?("default") + @values[platform]["default"] + elsif @values.key?("default") + @values["default"] + else + nil + end + end + + private + + def match_versions(node) + begin + platform, version = node[:platform].to_s, node[:platform_version].to_s + return nil unless @values.key?(platform) + node_version = Chef::Version::Platform.new(version) + key_matches = [] + keys = @values[platform].keys + keys.each do |k| + begin + if Chef::VersionConstraint::Platform.new(k).include?(node_version) + key_matches << k + end + rescue Chef::Exceptions::InvalidVersionConstraint => e + Chef::Log.debug "Caught InvalidVersionConstraint. This means that a key in value_for_platform cannot be interpreted as a Chef::VersionConstraint::Platform." + Chef::Log.debug(e) + end + end + return @values[platform][version] if key_matches.include?(version) + case key_matches.length + when 0 + return nil + when 1 + return @values[platform][key_matches.first] + else + raise "Multiple matches detected for #{platform} with values #{@values}. The matches are: #{key_matches}" + end + rescue Chef::Exceptions::InvalidCookbookVersion => e + # Lets not break because someone passes a weird string like 'default' :) + Chef::Log.debug(e) + Chef::Log.debug "InvalidCookbookVersion exceptions are common and expected here: the generic constraint matcher attempted to match something which is not a constraint. Moving on to next version or constraint" + return nil + rescue Chef::Exceptions::InvalidPlatformVersion => e + Chef::Log.debug "Caught InvalidPlatformVersion, this means that Chef::Version::Platform does not know how to turn #{node_version} into an x.y.z format" + Chef::Log.debug(e) + return nil + end + end + + def set(platforms, value) + if platforms.to_s == "default" + @values["default"] = value + else + assert_valid_platform_values!(platforms, value) + Array(platforms).each { |platform| @values[platform.to_s] = normalize_keys(value) } + value + end + end + + def normalize_keys(hash) + hash.inject({}) do |h, key_value| + keys, value = *key_value + Array(keys).each do |key| + h[key.to_s] = value + end + h + end + end + + def assert_valid_platform_values!(platforms, value) + unless value.kind_of?(Hash) + msg = "platform dependent values must be specified in the format :platform => {:version => value} " + msg << "you gave a value #{value.inspect} for platform(s) #{platforms}" + raise ArgumentError, msg + end + end + end + + # Given a hash similar to the one we use for Platforms, select a value from the hash. Supports + # per platform defaults, along with a single base default. Arrays may be passed as hash keys and + # will be expanded. + # + # === Parameters + # platform_hash:: A platform-style hash. + # + # === Returns + # value:: Whatever the most specific value of the hash is. + def value_for_platform(platform_hash) + PlatformDependentValue.new(platform_hash).value_for_node(node) + end + + # Given a list of platforms, returns true if the current recipe is being run on a node with + # that platform, false otherwise. + # + # === Parameters + # args:: A list of platforms. Each platform can be in string or symbol format. + # + # === Returns + # true:: If the current platform is in the list + # false:: If the current platform is not in the list + def platform?(*args) + has_platform = false + + args.flatten.each do |platform| + has_platform = true if platform.to_s == node[:platform] + end + + has_platform + end + + # Implementation class for determining platform family dependent values + class PlatformFamilyDependentValue < (defined?(::Chef::DSL::PlatformIntrospection::PlatformFamilyDependentValue) ? ::Chef::DSL::PlatformIntrospection::PlatformFamilyDependentValue : Object) + + # Create a platform family dependent value object. + # === Arguments + # platform_family_hash (Hash) a map of platform families to values. + # like this: + # { + # :rhel => "value for all EL variants" + # :fedora => "value for fedora variants fedora and amazon" , + # [:fedora, :rhel] => "value for all known redhat variants" + # :debian => "value for debian variants including debian, ubuntu, mint" , + # :default => "the default when nothing else matches" + # } + # * platform families can be specified as Symbols or Strings + # * multiple platform families can be grouped by using an Array as the key + # * values for platform families can be any object, with no restrictions. Some examples: + # - [:stop, :start] + # - "mysql-devel" + # - { :key => "value" } + def initialize(platform_family_hash) +super if defined?(::Chef::DSL::PlatformIntrospection::PlatformFamilyDependentValue) + @values = {} + @values["default"] = nil + platform_family_hash.each { |platform_families, value| set(platform_families, value) } + end + + def value_for_node(node) + if node.key?(:platform_family) + platform_family = node[:platform_family].to_s + if @values.key?(platform_family) + @values[platform_family] + else + @values["default"] + end + else + @values["default"] + end + end + + private + + def set(platform_family, value) + if platform_family.to_s == "default" + @values["default"] = value + else + Array(platform_family).each { |family| @values[family.to_s] = value } + value + end + end + end + + # Given a hash mapping platform families to values, select a value from the hash. Supports a single + # base default if platform family is not in the map. Arrays may be passed as hash keys and will be + # expanded + # + # === Parameters + # platform_family_hash:: A hash in the form { platform_family_name => value } + # + # === Returns + # value:: Whatever the most specific value of the hash is. + def value_for_platform_family(platform_family_hash) + PlatformFamilyDependentValue.new(platform_family_hash).value_for_node(node) + end + + # Given a list of platform families, returns true if the current recipe is being run on a + # node within that platform family, false otherwise. + # + # === Parameters + # args:: A list of platform families. Each platform family can be in string or symbol format. + # + # === Returns + # true:: if the current node platform family is in the list. + # false:: if the current node platform family is not in the list. + def platform_family?(*args) + args.flatten.any? do |platform_family| + platform_family.to_s == node[:platform_family] + end + end + + # Shamelessly stolen from https://github.com/sethvargo/chef-sugar/blob/master/lib/chef/sugar/docker.rb + # Given a node object, returns whether the node is a docker container. + # + # === Parameters + # node:: [Chef::Node] The node to check. + # + # === Returns + # true:: if the current node is a docker container + # false:: if the current node is not a docker container + def docker?(node = run_context.nil? ? nil : run_context.node) + # Using "File.exist?('/.dockerinit') || File.exist?('/.dockerenv')" makes Travis sad, + # and that makes us sad too. + node && node[:virtualization] && node[:virtualization][:systems] && + node[:virtualization][:systems][:docker] && node[:virtualization][:systems][:docker] == "guest" + end + + end + end +end + +# **DEPRECATED** +# This used to be part of chef/mixin/language. Load the file to activate the deprecation code. +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/recipe.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/recipe.rb new file mode 100644 index 0000000..f896ec7 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/recipe.rb @@ -0,0 +1,37 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/dsl/recipe' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +require "chef_compat/copied_from_chef/chef/dsl/core" +require "chef_compat/copied_from_chef/chef/mixin/lazy_module_include" +class Chef < (defined?(::Chef) ? ::Chef : Object) + module DSL + CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL) + module Recipe + CopiedFromChef.extend_chef_module(::Chef::DSL::Recipe, self) if defined?(::Chef::DSL::Recipe) + include Chef::DSL::Core + extend Chef::Mixin::LazyModuleInclude + module FullDSL + CopiedFromChef.extend_chef_module(::Chef::DSL::Recipe::FullDSL, self) if defined?(::Chef::DSL::Recipe::FullDSL) + include Chef::DSL::Recipe + extend Chef::Mixin::LazyModuleInclude + end + end + end +end +require "chef_compat/copied_from_chef/chef/resource" +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/universal.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/universal.rb new file mode 100644 index 0000000..7f529f1 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/dsl/universal.rb @@ -0,0 +1,70 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/dsl/universal' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +#-- +# Author:: Adam Jacob () +# Author:: Christopher Walters () +# Copyright:: Copyright 2008-2016 Chef Software, Inc. +# License:: Apache License, Version 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. +# + +require "chef_compat/copied_from_chef/chef/dsl/platform_introspection" +require "chef_compat/copied_from_chef/chef/mixin/powershell_out" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module DSL + CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL) + # Part of a family of DSL mixins. + # + # Chef::DSL::Recipe mixes into Recipes and LWRP Providers. + # - this does not target core chef resources and providers. + # - this is restricted to recipe/resource/provider context where a resource collection exists. + # - cookbook authors should typically include modules into here. + # + # Chef::DSL::Core mixes into Recipes, LWRP Providers and Core Providers + # - this adds cores providers on top of the Recipe DSL. + # - this is restricted to recipe/resource/provider context where a resource collection exists. + # - core chef authors should typically include modules into here. + # + # Chef::DSL::Universal mixes into Recipes, LWRP Resources+Providers, Core Resources+Providers, and Attributes files. + # - this adds resources and attributes files. + # - do not add helpers which manipulate the resource collection. + # - this is for general-purpose stuff that is useful nearly everywhere. + # - it also pollutes the namespace of nearly every context, watch out. + # + module Universal + CopiedFromChef.extend_chef_module(::Chef::DSL::Universal, self) if defined?(::Chef::DSL::Universal) + include Chef::DSL::PlatformIntrospection + include Chef::Mixin::PowershellOut + include Chef::Mixin::ShellOut + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/lazy_module_include.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/lazy_module_include.rb new file mode 100644 index 0000000..a6b5244 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/lazy_module_include.rb @@ -0,0 +1,98 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/mixin/lazy_module_include' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Copyright:: Copyright 2011-2016, Chef Software Inc. +# License:: Apache License, Version 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. +# + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module Mixin + CopiedFromChef.extend_chef_module(::Chef::Mixin, self) if defined?(::Chef::Mixin) + # If you have: + # + # module A + # extend LazyModuleInclude + # end + # + # module B + # include A + # end + # + # module C + # include B + # end + # + # module Monkeypatches + # def monkey + # puts "monkey!" + # end + # end + # + # A.send(:include, Monkeypatches) + # + # Then B and C and any classes that they're included in will also get the #monkey method patched into them. + # + module LazyModuleInclude + CopiedFromChef.extend_chef_module(::Chef::Mixin::LazyModuleInclude, self) if defined?(::Chef::Mixin::LazyModuleInclude) + + # Most of the magick is in this hook which creates a closure over the parent class and then builds an + # "infector" module which infects all descendants and which is responsible for updating the list of + # descendants in the parent class. + def included(klass) + super + parent_klass = self + infector = Module.new do + define_method(:included) do |subklass| + super(subklass) + subklass.extend(infector) + parent_klass.descendants.push(subklass) + end + end + klass.extend(infector) + parent_klass.descendants.push(klass) + end + + def descendants + @descendants ||= [] + end + + def include(*classes) + super + classes.each do |klass| + descendants.each do |descendant| + descendant.send(:include, klass) + end + end + end + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/notifying_block.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/notifying_block.rb new file mode 100644 index 0000000..0b90e27 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/notifying_block.rb @@ -0,0 +1,74 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/mixin/notifying_block' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +#-- +# Author:: Lamont Granquist +# Copyright:: Copyright 2010-2016, Chef Software Inc. +# License:: Apache License, Version 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. + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module Mixin + CopiedFromChef.extend_chef_module(::Chef::Mixin, self) if defined?(::Chef::Mixin) + module NotifyingBlock + CopiedFromChef.extend_chef_module(::Chef::Mixin::NotifyingBlock, self) if defined?(::Chef::Mixin::NotifyingBlock) + + def notifying_block(&block) + begin + subcontext = subcontext_block(&block) + Chef::Runner.new(subcontext).converge + ensure + # recipes don't have a new_resource + if respond_to?(:new_resource) + if subcontext && subcontext.resource_collection.any?(&:updated?) + new_resource.updated_by_last_action(true) + end + end + end + end + + def subcontext_block(parent_context = nil, &block) + parent_context ||= @run_context + sub_run_context = parent_context.create_child + + begin + outer_run_context = @run_context + @run_context = sub_run_context + instance_eval(&block) + ensure + @run_context = outer_run_context + end + + sub_run_context + end + + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/params_validate.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/params_validate.rb new file mode 100644 index 0000000..0a16147 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/params_validate.rb @@ -0,0 +1,510 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/mixin/params_validate' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Adam Jacob () +# Copyright:: Copyright 2008-2016, Chef Software Inc. +# License:: Apache License, Version 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. + +require "chef_compat/copied_from_chef/chef/constants" +require "chef_compat/copied_from_chef/chef/property" +require "chef_compat/copied_from_chef/chef/delayed_evaluator" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module Mixin + CopiedFromChef.extend_chef_module(::Chef::Mixin, self) if defined?(::Chef::Mixin) + module ParamsValidate + CopiedFromChef.extend_chef_module(::Chef::Mixin::ParamsValidate, self) if defined?(::Chef::Mixin::ParamsValidate) + # Takes a hash of options, along with a map to validate them. Returns the original + # options hash, plus any changes that might have been made (through things like setting + # default values in the validation map) + # + # For example: + # + # validate({ :one => "neat" }, { :one => { :kind_of => String }}) + # + # Would raise an exception if the value of :one above is not a kind_of? string. Valid + # map options are: + # + # @param opts [Hash] Validation opts. + # @option opts [Object,Array] :is An object, or list of + # objects, that must match the value using Ruby's `===` operator + # (`opts[:is].any? { |v| v === value }`). (See #_pv_is.) + # @option opts [Object,Array] :equal_to An object, or list + # of objects, that must be equal to the value using Ruby's `==` + # operator (`opts[:is].any? { |v| v == value }`) (See #_pv_equal_to.) + # @option opts [Regexp,Array] :regex An object, or + # list of objects, that must match the value with `regex.match(value)`. + # (See #_pv_regex) + # @option opts [Class,Array] :kind_of A class, or + # list of classes, that the value must be an instance of. (See + # #_pv_kind_of.) + # @option opts [Hash] :callbacks A hash of + # messages -> procs, all of which match the value. The proc must + # return a truthy or falsey value (true means it matches). (See + # #_pv_callbacks.) + # @option opts [Symbol,Array] :respond_to A method + # name, or list of method names, the value must respond to. (See + # #_pv_respond_to.) + # @option opts [Symbol,Array] :cannot_be A property, + # or a list of properties, that the value cannot have (such as `:nil` or + # `:empty`). The method with a questionmark at the end is called on the + # value (e.g. `value.empty?`). If the value does not have this method, + # it is considered valid (i.e. if you don't respond to `empty?` we + # assume you are not empty). (See #_pv_cannot_be.) + # @option opts [Proc] :coerce A proc which will be called to + # transform the user input to canonical form. The value is passed in, + # and the transformed value returned as output. Lazy values will *not* + # be passed to this method until after they are evaluated. Called in the + # context of the resource (meaning you can access other properties). + # (See #_pv_coerce.) (See #_pv_coerce.) + # @option opts [Boolean] :required `true` if this property + # must be present and not `nil`; `false` otherwise. This is checked + # after the resource is fully initialized. (See #_pv_required.) + # @option opts [Boolean] :name_property `true` if this + # property defaults to the same value as `name`. Equivalent to + # `default: lazy { name }`, except that #property_is_set? will + # return `true` if the property is set *or* if `name` is set. (See + # #_pv_name_property.) + # @option opts [Boolean] :name_attribute Same as `name_property`. + # @option opts [Object] :default The value this property + # will return if the user does not set one. If this is `lazy`, it will + # be run in the context of the instance (and able to access other + # properties). (See #_pv_default.) + # + def validate(opts, map) + map = map.validation_options if map.is_a?(Property) + + #-- + # validate works by taking the keys in the validation map, assuming it's a hash, and + # looking for _pv_:symbol as methods. Assuming it find them, it calls the right + # one. + #++ + raise ArgumentError, "Options must be a hash" unless opts.kind_of?(Hash) + raise ArgumentError, "Validation Map must be a hash" unless map.kind_of?(Hash) + + map.each do |key, validation| + unless key.kind_of?(Symbol) || key.kind_of?(String) + raise ArgumentError, "Validation map keys must be symbols or strings!" + end + case validation + when true + _pv_required(opts, key) + when false + true + when Hash + validation.each do |check, carg| + check_method = "_pv_#{check}" + if self.respond_to?(check_method, true) + self.send(check_method, opts, key, carg) + else + raise ArgumentError, "Validation map has unknown check: #{check}" + end + end + end + end + opts + end + + def lazy(&block) + DelayedEvaluator.new(&block) + end + + def set_or_return(symbol, value, validation) + property = SetOrReturnProperty.new(name: symbol, **validation) + property.call(self, value) + end + + private + + def explicitly_allows_nil?(key, validation) + validation.has_key?(:is) && _pv_is({ key => nil }, key, validation[:is], raise_error: false) + end + + # Return the value of a parameter, or nil if it doesn't exist. + def _pv_opts_lookup(opts, key) + if opts.has_key?(key.to_s) + opts[key.to_s] + elsif opts.has_key?(key.to_sym) + opts[key.to_sym] + else + nil + end + end + + # Raise an exception if the parameter is not found. + def _pv_required(opts, key, is_required = true, explicitly_allows_nil = false) + if is_required + return true if opts.has_key?(key.to_s) && (explicitly_allows_nil || !opts[key.to_s].nil?) + return true if opts.has_key?(key.to_sym) && (explicitly_allows_nil || !opts[key.to_sym].nil?) + raise Exceptions::ValidationFailed, "Required argument #{key.inspect} is missing!" + end + true + end + + # + # List of things values must be equal to. + # + # Uses Ruby's `==` to evaluate (equal_to == value). At least one must + # match for the value to be valid. + # + # `nil` passes this validation automatically. + # + # @return [Array,nil] List of things values must be equal to, or nil if + # equal_to is unspecified. + # + def _pv_equal_to(opts, key, to_be) + value = _pv_opts_lookup(opts, key) + unless value.nil? + to_be = Array(to_be) + to_be.each do |tb| + return true if value == tb + end + raise Exceptions::ValidationFailed, "Option #{key} must be equal to one of: #{to_be.join(", ")}! You passed #{value.inspect}." + end + end + + # + # List of things values must be instances of. + # + # Uses value.kind_of?(kind_of) to evaluate. At least one must match for + # the value to be valid. + # + # `nil` automatically passes this validation. + # + def _pv_kind_of(opts, key, to_be) + value = _pv_opts_lookup(opts, key) + unless value.nil? + to_be = Array(to_be) + to_be.each do |tb| + return true if value.kind_of?(tb) + end + raise Exceptions::ValidationFailed, "Option #{key} must be a kind of #{to_be}! You passed #{value.inspect}." + end + end + + # + # List of method names values must respond to. + # + # Uses value.respond_to?(respond_to) to evaluate. At least one must match + # for the value to be valid. + # + def _pv_respond_to(opts, key, method_name_list) + value = _pv_opts_lookup(opts, key) + unless value.nil? + Array(method_name_list).each do |method_name| + unless value.respond_to?(method_name) + raise Exceptions::ValidationFailed, "Option #{key} must have a #{method_name} method!" + end + end + end + end + + # + # List of things that must not be true about the value. + # + # Calls `value.?` All responses must be false for the value to be + # valid. + # Values which do not respond to ? are considered valid (because if + # a value doesn't respond to `:readable?`, then it probably isn't + # readable.) + # + # @example + # ```ruby + # property :x, cannot_be: [ :nil, :empty ] + # x [ 1, 2 ] #=> valid + # x 1 #=> valid + # x [] #=> invalid + # x nil #=> invalid + # ``` + # + def _pv_cannot_be(opts, key, predicate_method_base_name) + value = _pv_opts_lookup(opts, key) + if !value.nil? + Array(predicate_method_base_name).each do |method_name| + predicate_method = :"#{method_name}?" + + if value.respond_to?(predicate_method) + if value.send(predicate_method) + raise Exceptions::ValidationFailed, "Option #{key} cannot be #{predicate_method_base_name}" + end + end + end + end + end + + # + # The default value for a property. + # + # When the property is not assigned, this will be used. + # + # If this is a lazy value, it will either be passed the resource as a value, + # or if the lazy proc does not take parameters, it will be run in the + # context of the instance with instance_eval. + # + # @example + # ```ruby + # property :x, default: 10 + # ``` + # + # @example + # ```ruby + # property :x + # property :y, default: lazy { x+2 } + # ``` + # + # @example + # ```ruby + # property :x + # property :y, default: lazy { |r| r.x+2 } + # ``` + # + def _pv_default(opts, key, default_value) + value = _pv_opts_lookup(opts, key) + if value.nil? + default_value = default_value.freeze if !default_value.is_a?(DelayedEvaluator) + opts[key] = default_value + end + end + + # + # List of regexes values that must match. + # + # Uses regex.match() to evaluate. At least one must match for the value to + # be valid. + # + # `nil` passes regex validation automatically. + # + # @example + # ```ruby + # property :x, regex: [ /abc/, /xyz/ ] + # ``` + # + def _pv_regex(opts, key, regex) + value = _pv_opts_lookup(opts, key) + if !value.nil? + Array(regex).flatten.each do |r| + return true if r.match(value.to_s) + end + raise Exceptions::ValidationFailed, "Option #{key}'s value #{value} does not match regular expression #{regex.inspect}" + end + end + + # + # List of procs we pass the value to. + # + # All procs must return true for the value to be valid. If any procs do + # not return true, the key will be used for the message: `"Property x's + # value :y "`. + # + # @example + # ```ruby + # property :x, callbacks: { "is bigger than 10" => proc { |v| v <= 10 }, "is not awesome" => proc { |v| !v.awesome }} + # ``` + # + def _pv_callbacks(opts, key, callbacks) + raise ArgumentError, "Callback list must be a hash!" unless callbacks.kind_of?(Hash) + value = _pv_opts_lookup(opts, key) + if !value.nil? + callbacks.each do |message, zeproc| + unless zeproc.call(value) + raise Exceptions::ValidationFailed, "Option #{key}'s value #{value} #{message}!" + end + end + end + end + + # + # Allows a parameter to default to the value of the resource name. + # + # @example + # ```ruby + # property :x, name_property: true + # ``` + # + def _pv_name_property(opts, key, is_name_property = true) + if is_name_property + if opts[key].nil? + raise CannotValidateStaticallyError, "name_property cannot be evaluated without a resource." if self == Chef::Mixin::ParamsValidate + opts[key] = self.instance_variable_get(:"@name") + end + end + end + alias :_pv_name_attribute :_pv_name_property + + # + # List of valid things values can be. + # + # Uses Ruby's `===` to evaluate (is === value). At least one must match + # for the value to be valid. + # + # If a proc is passed, it is instance_eval'd in the resource, passed the + # value, and must return a truthy or falsey value. + # + # @example Class + # ```ruby + # property :x, String + # x 'valid' #=> valid + # x 1 #=> invalid + # x nil #=> invalid + # + # @example Value + # ```ruby + # property :x, [ :a, :b, :c, nil ] + # x :a #=> valid + # x nil #=> valid + # ``` + # + # @example Regex + # ```ruby + # property :x, /bar/ + # x 'foobar' #=> valid + # x 'foo' #=> invalid + # x nil #=> invalid + # ``` + # + # @example Proc + # ```ruby + # property :x, proc { |x| x > y } + # property :y, default: 2 + # x 3 #=> valid + # x 1 #=> invalid + # ``` + # + # @example Property + # ```ruby + # type = Property.new(is: String) + # property :x, type + # x 'foo' #=> valid + # x 1 #=> invalid + # x nil #=> invalid + # ``` + # + # @example RSpec Matcher + # ```ruby + # include RSpec::Matchers + # property :x, a_string_matching /bar/ + # x 'foobar' #=> valid + # x 'foo' #=> invalid + # x nil #=> invalid + # ``` + # + def _pv_is(opts, key, to_be, raise_error: true) + return true if !opts.has_key?(key.to_s) && !opts.has_key?(key.to_sym) + value = _pv_opts_lookup(opts, key) + to_be = [ to_be ].flatten(1) + errors = [] + passed = to_be.any? do |tb| + case tb + when Proc + raise CannotValidateStaticallyError, "is: proc { } must be evaluated once for each resource" if self == Chef::Mixin::ParamsValidate + instance_exec(value, &tb) + when Property + begin + validate(opts, { key => tb.validation_options }) + true + rescue Exceptions::ValidationFailed + # re-raise immediately if there is only one "is" so we get a better stack + raise if to_be.size == 1 + errors << $! + false + end + else + tb === value + end + end + if passed + true + else + message = "Property #{key} must be one of: #{to_be.map { |v| v.inspect }.join(", ")}! You passed #{value.inspect}." + unless errors.empty? + message << " Errors:\n#{errors.map { |m| "- #{m}" }.join("\n")}" + end + raise Exceptions::ValidationFailed, message + end + end + + # + # Method to mess with a value before it is validated and stored. + # + # Allows you to transform values into a canonical form that is easy to + # work with. + # + # This is passed the value to transform, and is run in the context of the + # instance (so it has access to other resource properties). It must return + # the value that will be stored in the instance. + # + # @example + # ```ruby + # property :x, Integer, coerce: { |v| v.to_i } + # ``` + # + def _pv_coerce(opts, key, coercer) + if opts.has_key?(key.to_s) + raise CannotValidateStaticallyError, "coerce must be evaluated for each resource." if self == Chef::Mixin::ParamsValidate + opts[key.to_s] = instance_exec(opts[key], &coercer) + elsif opts.has_key?(key.to_sym) + raise CannotValidateStaticallyError, "coerce must be evaluated for each resource." if self == Chef::Mixin::ParamsValidate + opts[key.to_sym] = instance_exec(opts[key], &coercer) + end + end + + # We allow Chef::Mixin::ParamsValidate.validate(), but we will raise an + # error if you try to do anything requiring there to be an actual resource. + # This way, you can statically validate things if you have constant validation + # (which is the norm). + extend self + + # Used by #set_or_return to avoid emitting a deprecation warning for + # "value nil" and to keep default stickiness working exactly the same + # @api private + class SetOrReturnProperty < (defined?(::Chef::Mixin::ParamsValidate::SetOrReturnProperty) ? ::Chef::Mixin::ParamsValidate::SetOrReturnProperty : Chef::Property) + def get(resource, nil_set: false) + value = super + # All values are sticky, frozen or not + if !is_set?(resource) + set_value(resource, value) + end + value + end + + def call(resource, value = NOT_PASSED) + # setting to nil does a get + if value.nil? && !explicitly_accepts_nil?(resource) + get(resource, nil_set: true) + else + super + end + end + end + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/powershell_out.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/powershell_out.rb new file mode 100644 index 0000000..b6b56f9 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/powershell_out.rb @@ -0,0 +1,117 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/mixin/powershell_out' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +#-- +# Copyright:: Copyright 2015-2016, Chef Software, Inc. +# License:: Apache License, Version 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. + + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module Mixin + CopiedFromChef.extend_chef_module(::Chef::Mixin, self) if defined?(::Chef::Mixin) + module PowershellOut + CopiedFromChef.extend_chef_module(::Chef::Mixin::PowershellOut, self) if defined?(::Chef::Mixin::PowershellOut) + include Chef::Mixin::ShellOut + include Chef::Mixin::WindowsArchitectureHelper + + # Run a command under powershell with the same API as shell_out. The + # options hash is extended to take an "architecture" flag which + # can be set to :i386 or :x86_64 to force the windows architecture. + # + # @param script [String] script to run + # @param options [Hash] options hash + # @return [Mixlib::Shellout] mixlib-shellout object + def powershell_out(*command_args) + script = command_args.first + options = command_args.last.is_a?(Hash) ? command_args.last : nil + + run_command_with_os_architecture(script, options) + end + + # Run a command under powershell with the same API as shell_out! + # (raises exceptions on errors) + # + # @param script [String] script to run + # @param options [Hash] options hash + # @return [Mixlib::Shellout] mixlib-shellout object + def powershell_out!(*command_args) + cmd = powershell_out(*command_args) + cmd.error! + cmd + end + + private + + # Helper function to run shell_out and wrap it with the correct + # flags to possibly disable WOW64 redirection (which we often need + # because chef-client runs as a 32-bit app on 64-bit windows). + # + # @param script [String] script to run + # @param options [Hash] options hash + # @return [Mixlib::Shellout] mixlib-shellout object + def run_command_with_os_architecture(script, options) + options ||= {} + options = options.dup + arch = options.delete(:architecture) + + with_os_architecture(nil, architecture: arch) do + shell_out( + build_powershell_command(script), + options + ) + end + end + + # Helper to build a powershell command around the script to run. + # + # @param script [String] script to run + # @retrurn [String] powershell command to execute + def build_powershell_command(script) + flags = [ + # Hides the copyright banner at startup. + "-NoLogo", + # Does not present an interactive prompt to the user. + "-NonInteractive", + # Does not load the Windows PowerShell profile. + "-NoProfile", + # always set the ExecutionPolicy flag + # see http://technet.microsoft.com/en-us/library/ee176961.aspx + "-ExecutionPolicy Unrestricted", + # Powershell will hang if STDIN is redirected + # http://connect.microsoft.com/PowerShell/feedback/details/572313/powershell-exe-can-hang-if-stdin-is-redirected + "-InputFormat None", + ] + + "powershell.exe #{flags.join(' ')} -Command \"#{script.gsub('"', '\"')}\"" + end + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/properties.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/properties.rb new file mode 100644 index 0000000..bdf9f7e --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/mixin/properties.rb @@ -0,0 +1,328 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/mixin/properties' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +require "chef_compat/copied_from_chef/chef/delayed_evaluator" +require "chef_compat/copied_from_chef/chef/mixin/params_validate" +require "chef_compat/copied_from_chef/chef/property" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + module Mixin + CopiedFromChef.extend_chef_module(::Chef::Mixin, self) if defined?(::Chef::Mixin) + module Properties + CopiedFromChef.extend_chef_module(::Chef::Mixin::Properties, self) if defined?(::Chef::Mixin::Properties) + module ClassMethods + CopiedFromChef.extend_chef_module(::Chef::Mixin::Properties::ClassMethods, self) if defined?(::Chef::Mixin::Properties::ClassMethods) + # + # The list of properties defined on this resource. + # + # Everything defined with `property` is in this list. + # + # @param include_superclass [Boolean] `true` to include properties defined + # on superclasses; `false` or `nil` to return the list of properties + # directly on this class. + # + # @return [Hash] The list of property names and types. + # + def properties(include_superclass = true) + if include_superclass + result = {} + ancestors.reverse_each { |c| result.merge!(c.properties(false)) if c.respond_to?(:properties) } + result + else + @properties ||= {} + end + end + + # + # Create a property on this resource class. + # + # If a superclass has this property, or if this property has already been + # defined by this resource, this will *override* the previous value. + # + # @param name [Symbol] The name of the property. + # @param type [Object,Array] The type(s) of this property. + # If present, this is prepended to the `is` validation option. + # @param options [Hash] Validation options. + # @option options [Object,Array] :is An object, or list of + # objects, that must match the value using Ruby's `===` operator + # (`options[:is].any? { |v| v === value }`). + # @option options [Object,Array] :equal_to An object, or list + # of objects, that must be equal to the value using Ruby's `==` + # operator (`options[:is].any? { |v| v == value }`) + # @option options [Regexp,Array] :regex An object, or + # list of objects, that must match the value with `regex.match(value)`. + # @option options [Class,Array] :kind_of A class, or + # list of classes, that the value must be an instance of. + # @option options [Hash] :callbacks A hash of + # messages -> procs, all of which match the value. The proc must + # return a truthy or falsey value (true means it matches). + # @option options [Symbol,Array] :respond_to A method + # name, or list of method names, the value must respond to. + # @option options [Symbol,Array] :cannot_be A property, + # or a list of properties, that the value cannot have (such as `:nil` or + # `:empty`). The method with a questionmark at the end is called on the + # value (e.g. `value.empty?`). If the value does not have this method, + # it is considered valid (i.e. if you don't respond to `empty?` we + # assume you are not empty). + # @option options [Proc] :coerce A proc which will be called to + # transform the user input to canonical form. The value is passed in, + # and the transformed value returned as output. Lazy values will *not* + # be passed to this method until after they are evaluated. Called in the + # context of the resource (meaning you can access other properties). + # @option options [Boolean] :required `true` if this property + # must be present; `false` otherwise. This is checked after the resource + # is fully initialized. + # @option options [Boolean] :name_property `true` if this + # property defaults to the same value as `name`. Equivalent to + # `default: lazy { name }`, except that #property_is_set? will + # return `true` if the property is set *or* if `name` is set. + # @option options [Boolean] :name_attribute Same as `name_property`. + # @option options [Object] :default The value this property + # will return if the user does not set one. If this is `lazy`, it will + # be run in the context of the instance (and able to access other + # properties). + # @option options [Boolean] :desired_state `true` if this property is + # part of desired state. Defaults to `true`. + # @option options [Boolean] :identity `true` if this property + # is part of object identity. Defaults to `false`. + # @option options [Boolean] :sensitive `true` if this property could + # contain sensitive information and whose value should be redacted + # in any resource reporting / auditing output. Defaults to `false`. + # + # @example Bare property + # property :x + # + # @example With just a type + # property :x, String + # + # @example With just options + # property :x, default: 'hi' + # + # @example With type and options + # property :x, String, default: 'hi' + # + def property(name, type = NOT_PASSED, **options) + name = name.to_sym + + options = options.inject({}) { |memo, (key, value)| memo[key.to_sym] = value; memo } + + options[:instance_variable_name] = :"@#{name}" if !options.has_key?(:instance_variable_name) + options[:name] = name + options[:declared_in] = self + + if type == NOT_PASSED + # If a type is not passed, the property derives from the + # superclass property (if any) + if properties.has_key?(name) + property = properties[name].derive(**options) + else + property = property_type(**options) + end + + # If a Property is specified, derive a new one from that. + elsif type.is_a?(Property) || (type.is_a?(Class) && type <= Property) + property = type.derive(**options) + + # If a primitive type was passed, combine it with "is" + else + if options[:is] + options[:is] = ([ type ] + [ options[:is] ]).flatten(1) + else + options[:is] = type + end + property = property_type(**options) + end + + local_properties = properties(false) + local_properties[name] = property + + property.emit_dsl + end + + # + # Create a reusable property type that can be used in multiple properties + # in different resources. + # + # @param options [Hash] Validation options. see #property for + # the list of options. + # + # @example + # property_type(default: 'hi') + # + def property_type(**options) + Property.derive(**options) + end + + # + # Create a lazy value for assignment to a default value. + # + # @param block The block to run when the value is retrieved. + # + # @return [Chef::DelayedEvaluator] The lazy value + # + def lazy(&block) + DelayedEvaluator.new(&block) + end + + # + # Get or set the list of desired state properties for this resource. + # + # State properties are properties that describe the desired state + # of the system, such as file permissions or ownership. + # In general, state properties are properties that could be populated by + # examining the state of the system (e.g., File.stat can tell you the + # permissions on an existing file). Contrarily, properties that are not + # "state properties" usually modify the way Chef itself behaves, for example + # by providing additional options for a package manager to use when + # installing a package. + # + # This list is used by the Chef client auditing system to extract + # information from resources to describe changes made to the system. + # + # This method is unnecessary when declaring properties with `property`; + # properties are added to state_properties by default, and can be turned off + # with `desired_state: false`. + # + # ```ruby + # property :x # part of desired state + # property :y, desired_state: false # not part of desired state + # ``` + # + # @param names [Array] A list of property names to set as desired + # state. + # + # @return [Array] All properties in desired state. + # + def state_properties(*names) + if !names.empty? + names = names.map { |name| name.to_sym }.uniq + + local_properties = properties(false) + # Add new properties to the list. + names.each do |name| + property = properties[name] + if !property + self.property name, instance_variable_name: false, desired_state: true + elsif !property.desired_state? + self.property name, desired_state: true + end + end + + # If state_attrs *excludes* something which is currently desired state, + # mark it as desired_state: false. + local_properties.each do |name, property| + if property.desired_state? && !names.include?(name) + self.property name, desired_state: false + end + end + end + + properties.values.select { |property| property.desired_state? } + end + + # + # Set the identity of this resource to a particular set of properties. + # + # This drives #identity, which returns data that uniquely refers to a given + # resource on the given node (in such a way that it can be correlated + # across Chef runs). + # + # This method is unnecessary when declaring properties with `property`; + # properties can be added to identity during declaration with + # `identity: true`. + # + # ```ruby + # property :x, identity: true # part of identity + # property :y # not part of identity + # ``` + # + # If no properties are marked as identity, "name" is considered the identity. + # + # @param names [Array] A list of property names to set as the identity. + # + # @return [Array] All identity properties. + # + def identity_properties(*names) + if !names.empty? + names = names.map { |name| name.to_sym } + + # Add or change properties that are not part of the identity. + names.each do |name| + property = properties[name] + if !property + self.property name, instance_variable_name: false, identity: true + elsif !property.identity? + self.property name, identity: true + end + end + + # If identity_properties *excludes* something which is currently part of + # the identity, mark it as identity: false. + properties.each do |name, property| + if property.identity? && !names.include?(name) + + self.property name, identity: false + end + end + end + + result = properties.values.select { |property| property.identity? } + result = [ properties[:name] ] if result.empty? + result + end + + def included(other) + other.extend ClassMethods + end + end + + def self.included(other) + other.extend ClassMethods + end + + include Chef::Mixin::ParamsValidate + + # + # Whether this property has been set (or whether it has a default that has + # been retrieved). + # + # @param name [Symbol] The name of the property. + # @return [Boolean] `true` if the property has been set. + # + def property_is_set?(name) + property = self.class.properties[name.to_sym] + raise ArgumentError, "Property #{name} is not defined in class #{self}" if !property + property.is_set?(self) + end + + # + # Clear this property as if it had never been set. It will thereafter return + # the default. + # been retrieved). + # + # @param name [Symbol] The name of the property. + # + def reset_property(name) + property = self.class.properties[name.to_sym] + raise ArgumentError, "Property #{name} is not defined in class #{self}" if !property + property.reset(self) + end + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/property.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/property.rb new file mode 100644 index 0000000..3399596 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/property.rb @@ -0,0 +1,713 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/property' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: John Keiser +# Copyright:: Copyright 2015-2016, John Keiser. +# License:: Apache License, Version 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. +# + +require "chef_compat/copied_from_chef/chef/delayed_evaluator" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + # + # Type and validation information for a property on a resource. + # + # A property named "x" manipulates the "@x" instance variable on a + # resource. The *presence* of the variable (`instance_variable_defined?(@x)`) + # tells whether the variable is defined; it may have any actual value, + # constrained only by validation. + # + # Properties may have validation, defaults, and coercion, and have full + # support for lazy values. + # + # @see Chef::Resource.property + # @see Chef::DelayedEvaluator + # + class Property < (defined?(::Chef::Property) ? ::Chef::Property : Object) + # + # Create a reusable property type that can be used in multiple properties + # in different resources. + # + # @param options [Hash] Validation options. See Chef::Resource.property for + # the list of options. + # + # @example + # Property.derive(default: 'hi') + # + def self.derive(**options) + new(**options) + end + + # + # Create a new property. + # + # @param options [Hash] Property options, including + # control options here, as well as validation options (see + # Chef::Mixin::ParamsValidate#validate for a description of validation + # options). + # @option options [Symbol] :name The name of this property. + # @option options [Class] :declared_in The class this property comes from. + # @option options [Symbol] :instance_variable_name The instance variable + # tied to this property. Must include a leading `@`. Defaults to `@`. + # `nil` means the property is opaque and not tied to a specific instance + # variable. + # @option options [Boolean] :desired_state `true` if this property is part of desired + # state. Defaults to `true`. + # @option options [Boolean] :identity `true` if this property is part of object + # identity. Defaults to `false`. + # @option options [Boolean] :name_property `true` if this + # property defaults to the same value as `name`. Equivalent to + # `default: lazy { name }`, except that #property_is_set? will + # return `true` if the property is set *or* if `name` is set. + # @option options [Boolean] :nillable `true` opt-in to Chef-13 style behavior where + # attempting to set a nil value will really set a nil value instead of issuing + # a warning and operating like a getter + # @option options [Object] :default The value this property + # will return if the user does not set one. If this is `lazy`, it will + # be run in the context of the instance (and able to access other + # properties) and cached. If not, the value will be frozen with Object#freeze + # to prevent users from modifying it in an instance. + # @option options [Proc] :coerce A proc which will be called to + # transform the user input to canonical form. The value is passed in, + # and the transformed value returned as output. Lazy values will *not* + # be passed to this method until after they are evaluated. Called in the + # context of the resource (meaning you can access other properties). + # @option options [Boolean] :required `true` if this property + # must be present; `false` otherwise. This is checked after the resource + # is fully initialized. + # + def initialize(**options) +super if defined?(::Chef::Property) + options = options.inject({}) { |memo, (key, value)| memo[key.to_sym] = value; memo } + @options = options + options[:name] = options[:name].to_sym if options[:name] + options[:instance_variable_name] = options[:instance_variable_name].to_sym if options[:instance_variable_name] + + # Replace name_attribute with name_property + if options.has_key?(:name_attribute) + # If we have both name_attribute and name_property and they differ, raise an error + if options.has_key?(:name_property) + raise ArgumentError, "Cannot specify both name_property and name_attribute together on property #{self}." + end + # replace name_property with name_attribute in place + options = Hash[options.map { |k, v| k == :name_attribute ? [ :name_property, v ] : [ k, v ] }] + @options = options + end + + # Only pick the first of :default, :name_property and :name_attribute if + # more than one is specified. + if options.has_key?(:default) && options[:name_property] + if options[:default].nil? || options.keys.index(:name_property) < options.keys.index(:default) + options.delete(:default) + preferred_default = :name_property + else + options.delete(:name_property) + preferred_default = :default + end + Chef.log_deprecation("Cannot specify both default and name_property together on property #{self}. Only one (#{preferred_default}) will be obeyed. In Chef 13, this will become an error. Please remove one or the other from the property.") + end + + # Validate the default early, so the user gets a good error message, and + # cache it so we don't do it again if so + begin + # If we can validate it all the way to output, do it. + @stored_default = input_to_stored_value(nil, default, is_default: true) + rescue Chef::Exceptions::CannotValidateStaticallyError + # If the validation is not static (i.e. has procs), we will have to + # coerce and validate the default each time we run + end + end + + def to_s + "#{name || ""}#{declared_in ? " of resource #{declared_in.resource_name}" : ""}" + end + + # + # The name of this property. + # + # @return [String] + # + def name + options[:name] + end + + # + # The class this property was defined in. + # + # @return [Class] + # + def declared_in + options[:declared_in] + end + + # + # The instance variable associated with this property. + # + # Defaults to `@` + # + # @return [Symbol] + # + def instance_variable_name + if options.has_key?(:instance_variable_name) + options[:instance_variable_name] + elsif name + :"@#{name}" + end + end + + # + # The raw default value for this resource. + # + # Does not coerce or validate the default. Does not evaluate lazy values. + # + # Defaults to `lazy { name }` if name_property is true; otherwise defaults to + # `nil` + # + def default + return options[:default] if options.has_key?(:default) + return Chef::DelayedEvaluator.new { name } if name_property? + nil + end + + # + # Whether this is part of the resource's natural identity or not. + # + # @return [Boolean] + # + def identity? + options[:identity] + end + + # + # Whether this is part of desired state or not. + # + # Defaults to true. + # + # @return [Boolean] + # + def desired_state? + return true if !options.has_key?(:desired_state) + options[:desired_state] + end + + # + # Whether this is name_property or not. + # + # @return [Boolean] + # + def name_property? + options[:name_property] + end + + # + # Whether this property has a default value. + # + # @return [Boolean] + # + def has_default? + options.has_key?(:default) || name_property? + end + + # + # Whether this property is required or not. + # + # @return [Boolean] + # + def required? + options[:required] + end + + # + # Whether this property is sensitive or not. + # + # Defaults to false. + # + # @return [Boolean] + # + def sensitive? + options.fetch(:sensitive, false) + end + + # + # Validation options. (See Chef::Mixin::ParamsValidate#validate.) + # + # @return [Hash] + # + def validation_options + @validation_options ||= options.reject do |k, v| + [:declared_in, :name, :instance_variable_name, :desired_state, :identity, :default, :name_property, :coerce, :required, :nillable, :sensitive].include?(k) + end + end + + # + # Handle the property being called. + # + # The base implementation does the property get-or-set: + # + # ```ruby + # resource.myprop # get + # resource.myprop value # set + # ``` + # + # Subclasses may implement this with any arguments they want, as long as + # the corresponding DSL calls it correctly. + # + # @param resource [Chef::Resource] The resource to get the property from. + # @param value The value to set (or NOT_PASSED if it is a get). + # + # @return The current value of the property. If it is a `set`, lazy values + # will be returned without running, validating or coercing. If it is a + # `get`, the non-lazy, coerced, validated value will always be returned. + # + def call(resource, value = NOT_PASSED) + if value == NOT_PASSED + return get(resource) + end + + if value.nil? && !nillable? + # In Chef 12, value(nil) does a *get* instead of a set, so we + # warn if the value would have been changed. In Chef 13, it will be + # equivalent to value = nil. + result = get(resource, nil_set: true) + + # Warn about this becoming a set in Chef 13. + begin + input_to_stored_value(resource, value) + # If nil is valid, and it would change the value, warn that this will change to a set. + if !result.nil? + Chef.log_deprecation("An attempt was made to change #{name} from #{result.inspect} to nil by calling #{name}(nil). In Chef 12, this does a get rather than a set. In Chef 13, this will change to set the value to nil.") + end + rescue Chef::Exceptions::DeprecatedFeatureError + raise + rescue + # If nil is invalid, warn that this will become an error. + Chef.log_deprecation("nil is an invalid value for #{self}. In Chef 13, this warning will change to an error. Error: #{$!}") + end + + result + else + # Anything else, such as myprop(value) is a set + set(resource, value) + end + end + + # + # Get the property value from the resource, handling lazy values, + # defaults, and validation. + # + # - If the property's value is lazy, it is evaluated, coerced and validated. + # - If the property has no value, and is required, raises ValidationFailed. + # - If the property has no value, but has a lazy default, it is evaluated, + # coerced and validated. If the evaluated value is frozen, the resulting + # - If the property has no value, but has a default, the default value + # will be returned and frozen. If the default value is lazy, it will be + # evaluated, coerced and validated, and the result stored in the property. + # - If the property has no value, but is name_property, `resource.name` + # is retrieved, coerced, validated and stored in the property. + # - Otherwise, `nil` is returned. + # + # @param resource [Chef::Resource] The resource to get the property from. + # + # @return The value of the property. + # + # @raise Chef::Exceptions::ValidationFailed If the value is invalid for + # this property, or if the value is required and not set. + # + def get(resource, nil_set: false) + # If it's set, return it (and evaluate any lazy values) + if is_set?(resource) + value = get_value(resource) + value = stored_value_to_output(resource, value) + + else + # We are getting the default value. + + # If the user does something like this: + # + # ``` + # class MyResource < Chef::Resource + # property :content + # action :create do + # file '/x.txt' do + # content content + # end + # end + # end + # ``` + # + # It won't do what they expect. This checks whether you try to *read* + # `content` while we are compiling the resource. + if !nil_set && + resource.respond_to?(:resource_initializing) && + resource.resource_initializing && + resource.respond_to?(:enclosing_provider) && + resource.enclosing_provider && + resource.enclosing_provider.new_resource && + resource.enclosing_provider.new_resource.respond_to?(name) + Chef::Log.warn("#{Chef::Log.caller_location}: property #{name} is declared in both #{resource} and #{resource.enclosing_provider}. Use new_resource.#{name} instead. At #{Chef::Log.caller_location}") + end + + if has_default? + # If we were able to cache the stored_default, grab it. + if defined?(@stored_default) + value = @stored_default + else + # Otherwise, we have to validate it now. + value = input_to_stored_value(resource, default, is_default: true) + end + value = stored_value_to_output(resource, value, is_default: true) + + # If the value is mutable (non-frozen), we set it on the instance + # so that people can mutate it. (All constant default values are + # frozen.) + if !value.frozen? && !value.nil? + set_value(resource, value) + end + + value + + elsif required? + raise Chef::Exceptions::ValidationFailed, "#{name} is required" + end + end + end + + # + # Set the value of this property in the given resource. + # + # Non-lazy values are coerced and validated before being set. Coercion + # and validation of lazy values is delayed until they are first retrieved. + # + # @param resource [Chef::Resource] The resource to set this property in. + # @param value The value to set. + # + # @return The value that was set, after coercion (if lazy, still returns + # the lazy value) + # + # @raise Chef::Exceptions::ValidationFailed If the value is invalid for + # this property. + # + def set(resource, value) + set_value(resource, input_to_stored_value(resource, value)) + end + + # + # Find out whether this property has been set. + # + # This will be true if: + # - The user explicitly set the value + # - The property has a default, and the value was retrieved. + # + # From this point of view, it is worth looking at this as "what does the + # user think this value should be." In order words, if the user grabbed + # the value, even if it was a default, they probably based calculations on + # it. If they based calculations on it and the value changes, the rest of + # the world gets inconsistent. + # + # @param resource [Chef::Resource] The resource to get the property from. + # + # @return [Boolean] + # + def is_set?(resource) + value_is_set?(resource) + end + + # + # Reset the value of this property so that is_set? will return false and the + # default will be returned in the future. + # + # @param resource [Chef::Resource] The resource to get the property from. + # + def reset(resource) + reset_value(resource) + end + + # + # Coerce an input value into canonical form for the property. + # + # After coercion, the value is suitable for storage in the resource. + # You must validate values after coercion, however. + # + # Does no special handling for lazy values. + # + # @param resource [Chef::Resource] The resource we're coercing against + # (to provide context for the coerce). + # @param value The value to coerce. + # + # @return The coerced value. + # + # @raise Chef::Exceptions::ValidationFailed If the value is invalid for + # this property. + # + def coerce(resource, value) + if options.has_key?(:coerce) + # If we have no default value, `nil` is never coerced or validated + unless !has_default? && value.nil? + value = exec_in_resource(resource, options[:coerce], value) + end + end + value + end + + # + # Validate a value. + # + # Calls Chef::Mixin::ParamsValidate#validate with #validation_options as + # options. + # + # @param resource [Chef::Resource] The resource we're validating against + # (to provide context for the validate). + # @param value The value to validate. + # + # @raise Chef::Exceptions::ValidationFailed If the value is invalid for + # this property. + # + def validate(resource, value) + # If we have no default value, `nil` is never coerced or validated + unless value.nil? && !has_default? + if resource + resource.validate({ name => value }, { name => validation_options }) + else + name = self.name || :property_type + Chef::Mixin::ParamsValidate.validate({ name => value }, { name => validation_options }) + end + end + end + + # + # Derive a new Property that is just like this one, except with some added or + # changed options. + # + # @param options [Hash] List of options that would be passed + # to #initialize. + # + # @return [Property] The new property type. + # + def derive(**modified_options) + # Since name_property, name_attribute and default override each other, + # if you specify one of them in modified_options it overrides anything in + # the original options. + options = self.options + if modified_options.has_key?(:name_property) || + modified_options.has_key?(:name_attribute) || + modified_options.has_key?(:default) + options = options.reject { |k, v| k == :name_attribute || k == :name_property || k == :default } + end + self.class.new(options.merge(modified_options)) + end + + # + # Emit the DSL for this property into the resource class (`declared_in`). + # + # Creates a getter and setter for the property. + # + def emit_dsl + # We don't create the getter/setter if it's a custom property; we will + # be using the existing getter/setter to manipulate it instead. + return if !instance_variable_name + + # We prefer this form because the property name won't show up in the + # stack trace if you use `define_method`. + declared_in.class_eval <<-EOM, __FILE__, __LINE__ + 1 + def #{name}(value=NOT_PASSED) + raise "Property `#{name}` of `\#{self}` was incorrectly passed a block. Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block_given? + self.class.properties[#{name.inspect}].call(self, value) + end + def #{name}=(value) + raise "Property `#{name}` of `\#{self}` was incorrectly passed a block. Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block_given? + self.class.properties[#{name.inspect}].set(self, value) + end + EOM + rescue SyntaxError + # If the name is not a valid ruby name, we use define_method. + declared_in.define_method(name) do |value = NOT_PASSED, &block| + raise "Property `#{name}` of `#{self}` was incorrectly passed a block! Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block + self.class.properties[name].call(self, value) + end + declared_in.define_method("#{name}=") do |value, &block| + raise "Property `#{name}` of `#{self}` was incorrectly passed a block! Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block + self.class.properties[name].set(self, value) + end + end + + # + # The options this Property will use for get/set behavior and validation. + # + # @see #initialize for a list of valid options. + # + attr_reader :options + + # + # Find out whether this type accepts nil explicitly. + # + # A type accepts nil explicitly if "is" allows nil, it validates as nil, *and* is not simply + # an empty type. + # + # A type is presumed to accept nil if it does coercion (which must handle nil). + # + # These examples accept nil explicitly: + # ```ruby + # property :a, [ String, nil ] + # property :a, [ String, NilClass ] + # property :a, [ String, proc { |v| v.nil? } ] + # ``` + # + # This does not (because the "is" doesn't exist or doesn't have nil): + # + # ```ruby + # property :x, String + # ``` + # + # These do not, even though nil would validate fine (because they do not + # have "is"): + # + # ```ruby + # property :a + # property :a, equal_to: [ 1, 2, 3, nil ] + # property :a, kind_of: [ String, NilClass ] + # property :a, respond_to: [ ] + # property :a, callbacks: { "a" => proc { |v| v.nil? } } + # ``` + # + # @param resource [Chef::Resource] The resource we're coercing against + # (to provide context for the coerce). + # + # @return [Boolean] Whether this value explicitly accepts nil. + # + # @api private + def explicitly_accepts_nil?(resource) + options.has_key?(:coerce) || + (options.has_key?(:is) && resource.send(:_pv_is, { name => nil }, name, options[:is], raise_error: false)) + end + + # @api private + def get_value(resource) + if instance_variable_name + resource.instance_variable_get(instance_variable_name) + else + resource.send(name) + end + end + + # @api private + def set_value(resource, value) + if instance_variable_name + resource.instance_variable_set(instance_variable_name, value) + else + resource.send(name, value) + end + end + + # @api private + def value_is_set?(resource) + if instance_variable_name + resource.instance_variable_defined?(instance_variable_name) + else + true + end + end + + # @api private + def reset_value(resource) + if instance_variable_name + if value_is_set?(resource) + resource.remove_instance_variable(instance_variable_name) + end + else + raise ArgumentError, "Property #{name} has no instance variable defined and cannot be reset" + end + end + + private + + def exec_in_resource(resource, proc, *args) + if resource + if proc.arity > args.size + value = proc.call(resource, *args) + else + value = resource.instance_exec(*args, &proc) + end + else + # If we don't have a resource yet, we can't exec in resource! + raise Chef::Exceptions::CannotValidateStaticallyError, "Cannot validate or coerce without a resource" + end + end + + def input_to_stored_value(resource, value, is_default: false) + unless value.is_a?(DelayedEvaluator) + value = coerce_and_validate(resource, value, is_default: is_default) + end + value + end + + def stored_value_to_output(resource, value, is_default: false) + # Crack open lazy values before giving the result to the user + if value.is_a?(DelayedEvaluator) + value = exec_in_resource(resource, value) + value = coerce_and_validate(resource, value, is_default: is_default) + end + value + end + + # Coerces and validates the value. If the value is a default, it will warn + # the user that invalid defaults are bad mmkay, and return it as if it were + # valid. + def coerce_and_validate(resource, value, is_default: false) + result = coerce(resource, value) + begin + # If the input is from a default, we need to emit an invalid default warning on validate. + validate(resource, result) + rescue Chef::Exceptions::CannotValidateStaticallyError + # This one gets re-raised + raise + rescue + # Anything else is just an invalid default: in those cases, we just + # warn and return the (possibly coerced) value to the user. + if is_default + if value.nil? + Chef.log_deprecation("Default value nil is invalid for property #{self}. Possible fixes: 1. Remove 'default: nil' if nil means 'undefined'. 2. Set a valid default value if there is a reasonable one. 3. Allow nil as a valid value of your property (for example, 'property #{name.inspect}, [ String, nil ], default: nil'). Error: #{$!}") + else + Chef.log_deprecation("Default value #{value.inspect} is invalid for property #{self}. In Chef 13 this will become an error: #{$!}.") + end + else + raise + end + end + + result + end + + def nillable? + !!options[:nillable] + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider.rb new file mode 100644 index 0000000..7ccf87b --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider.rb @@ -0,0 +1,164 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/provider' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +require "chef_compat/copied_from_chef/chef/dsl/core" +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object) + include Chef::DSL::Core + attr_accessor :action + def initialize(new_resource, run_context) +super if defined?(::Chef::Provider) + @new_resource = new_resource + @action = action + @current_resource = nil + @run_context = run_context + @converge_actions = nil + + @recipe_name = nil + @cookbook_name = nil + self.class.include_resource_dsl_module(new_resource) + end + def converge_if_changed(*properties, &converge_block) + if !converge_block + raise ArgumentError, "converge_if_changed must be passed a block!" + end + + properties = new_resource.class.state_properties.map { |p| p.name } if properties.empty? + properties = properties.map { |p| p.to_sym } + if current_resource + # Collect the list of modified properties + specified_properties = properties.select { |property| new_resource.property_is_set?(property) } + modified = specified_properties.select { |p| new_resource.send(p) != current_resource.send(p) } + if modified.empty? + properties_str = if sensitive + specified_properties.join(", ") + else + specified_properties.map { |p| "#{p}=#{new_resource.send(p).inspect}" }.join(", ") + end + Chef::Log.debug("Skipping update of #{new_resource}: has not changed any of the specified properties #{properties_str}.") + return false + end + + # Print the pretty green text and run the block + property_size = modified.map { |p| p.size }.max + modified.map! do |p| + properties_str = if sensitive + "(suppressed sensitive property)" + else + "#{new_resource.send(p).inspect} (was #{current_resource.send(p).inspect})" + end + " set #{p.to_s.ljust(property_size)} to #{properties_str}" + end + converge_by([ "update #{current_resource.identity}" ] + modified, &converge_block) + + else + # The resource doesn't exist. Mark that we are *creating* this, and + # write down any properties we are setting. + property_size = properties.map { |p| p.size }.max + created = properties.map do |property| + default = " (default value)" unless new_resource.property_is_set?(property) + properties_str = if sensitive + "(suppressed sensitive property)" + else + new_resource.send(property).inspect + end + " set #{property.to_s.ljust(property_size)} to #{properties_str}#{default}" + end + + converge_by([ "create #{new_resource.identity}" ] + created, &converge_block) + end + true + end + def self.include_resource_dsl(include_resource_dsl) + @include_resource_dsl = include_resource_dsl + end + def self.include_resource_dsl_module(resource) + if @include_resource_dsl && !defined?(@included_resource_dsl_module) + provider_class = self + @included_resource_dsl_module = Module.new do + extend Forwardable + define_singleton_method(:to_s) { "forwarder module for #{provider_class}" } + define_singleton_method(:inspect) { to_s } + # Add a delegator for each explicit property that will get the *current* value + # of the property by default instead of the *actual* value. + resource.class.properties.each do |name, property| + class_eval(<<-EOM, __FILE__, __LINE__) + def #{name}(*args, &block) + # If no arguments were passed, we process "get" by defaulting + # the value to current_resource, not new_resource. This helps + # avoid issues where resources accidentally overwrite perfectly + # valid stuff with default values. + if args.empty? && !block + if !new_resource.property_is_set?(__method__) && current_resource + return current_resource.public_send(__method__) + end + end + new_resource.public_send(__method__, *args, &block) + end + EOM + end + dsl_methods = + resource.class.public_instance_methods + + resource.class.protected_instance_methods - + provider_class.instance_methods - + resource.class.properties.keys + def_delegators(:new_resource, *dsl_methods) + end + include @included_resource_dsl_module + end + end + def self.use_inline_resources + extend InlineResources::ClassMethods + include InlineResources + end + module InlineResources + CopiedFromChef.extend_chef_module(::Chef::Provider::InlineResources, self) if defined?(::Chef::Provider::InlineResources) + def compile_and_converge_action(&block) + old_run_context = run_context + @run_context = run_context.create_child + return_value = instance_eval(&block) + Chef::Runner.new(run_context).converge + return_value + ensure + if run_context.resource_collection.any? { |r| r.updated? } + new_resource.updated_by_last_action(true) + end + @run_context = old_run_context + end + module ClassMethods + CopiedFromChef.extend_chef_module(::Chef::Provider::InlineResources::ClassMethods, self) if defined?(::Chef::Provider::InlineResources::ClassMethods) + def action(name, &block) + # We need the block directly in a method so that `super` works + define_method("compile_action_#{name}", &block) + # We try hard to use `def` because define_method doesn't show the method name in the stack. + begin + class_eval <<-EOM + def action_#{name} + compile_and_converge_action { compile_action_#{name} } + end + EOM + rescue SyntaxError + define_method("action_#{name}") { send("compile_action_#{name}") } + end + end + end + end + protected + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/apt_repository.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/apt_repository.rb new file mode 100644 index 0000000..ccc07c4 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/apt_repository.rb @@ -0,0 +1,269 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/provider/apt_repository' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Thom May () +# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# License:: Apache License, Version 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. +# + +require "chef_compat/copied_from_chef/chef/resource" +require "chef_compat/copied_from_chef/chef/dsl/declare_resource" +require "chef_compat/copied_from_chef/chef/provider/noop" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object) + class AptRepository < (defined?(::Chef::Provider::AptRepository) ? ::Chef::Provider::AptRepository : Chef::Provider) + use_inline_resources + + include Chef::Mixin::ShellOut + extend Chef::Mixin::Which + + provides :apt_repository do + which("apt-get") + end + + def whyrun_supported? + true + end + + def load_current_resource + end + + action :add do + unless new_resource.key.nil? + if is_key_id?(new_resource.key) && !has_cookbook_file?(new_resource.key) + install_key_from_keyserver + else + install_key_from_uri + end + end + + declare_resource(:execute, "apt-cache gencaches") do + ignore_failure true + action :nothing + end + + declare_resource(:apt_update, new_resource.name) do + ignore_failure true + action :nothing + end + + components = if is_ppa_url?(new_resource.uri) && new_resource.components.empty? + "main" + else + new_resource.components + end + + repo = build_repo( + new_resource.uri, + new_resource.distribution, + components, + new_resource.trusted, + new_resource.arch, + new_resource.deb_src + ) + + declare_resource(:file, "/etc/apt/sources.list.d/#{new_resource.name}.list") do + owner "root" + group "root" + mode "0644" + content repo + sensitive new_resource.sensitive + action :create + notifies :run, "execute[apt-cache gencaches]", :immediately + notifies :update, "apt_update[#{new_resource.name}]", :immediately if new_resource.cache_rebuild + end + end + + action :remove do + if ::File.exist?("/etc/apt/sources.list.d/#{new_resource.name}.list") + converge_by "Removing #{new_resource.name} repository from /etc/apt/sources.list.d/" do + declare_resource(:file, "/etc/apt/sources.list.d/#{new_resource.name}.list") do + sensitive new_resource.sensitive + action :delete + notifies :update, "apt_update[#{new_resource.name}]", :immediately if new_resource.cache_rebuild + end + + declare_resource(:apt_update, new_resource.name) do + ignore_failure true + action :nothing + end + + end + end + end + + def is_key_id?(id) + id = id[2..-1] if id.start_with?("0x") + id =~ /^\h+$/ && [8, 16, 40].include?(id.length) + end + + def extract_fingerprints_from_cmd(cmd) + so = shell_out(cmd) + so.run_command + so.stdout.split(/\n/).map do |t| + if z = t.match(/^ +Key fingerprint = ([0-9A-F ]+)/) + z[1].split.join + end + end.compact + end + + def key_is_valid?(cmd, key) + valid = true + + so = shell_out(cmd) + so.run_command + so.stdout.split(/\n/).map do |t| + if t =~ %r{^\/#{key}.*\[expired: .*\]$} + Chef::Log.debug "Found expired key: #{t}" + valid = false + break + end + end + + Chef::Log.debug "key #{key} #{valid ? "is valid" : "is not valid"}" + valid + end + + def cookbook_name + new_resource.cookbook || new_resource.cookbook_name + end + + def has_cookbook_file?(fn) + run_context.has_cookbook_file_in_cookbook?(cookbook_name, fn) + end + + def no_new_keys?(file) + installed_keys = extract_fingerprints_from_cmd("apt-key finger") + proposed_keys = extract_fingerprints_from_cmd("gpg --with-fingerprint #{file}") + (installed_keys & proposed_keys).sort == proposed_keys.sort + end + + def install_key_from_uri + key_name = new_resource.key.gsub(/[^0-9A-Za-z\-]/, "_") + cached_keyfile = ::File.join(Chef::Config[:file_cache_path], key_name) + type = if new_resource.key.start_with?("http") + :remote_file + elsif has_cookbook_file?(new_resource.key) + :cookbook_file + else + raise Chef::Exceptions::FileNotFound, "Cannot locate key file" + end + + declare_resource(type, cached_keyfile) do + source new_resource.key + mode "0644" + sensitive new_resource.sensitive + action :create + end + + raise "The key #{cached_keyfile} is invalid and cannot be used to verify an apt repository." unless key_is_valid?("gpg #{cached_keyfile}", "") + + declare_resource(:execute, "apt-key add #{cached_keyfile}") do + sensitive new_resource.sensitive + action :run + not_if do + no_new_keys?(cached_keyfile) + end + notifies :run, "execute[apt-cache gencaches]", :immediately + end + end + + def install_key_from_keyserver(key = new_resource.key, keyserver = new_resource.keyserver) + cmd = "apt-key adv --recv" + cmd << " --keyserver-options http-proxy=#{new_resource.key_proxy}" if new_resource.key_proxy + cmd << " --keyserver " + cmd << if keyserver.start_with?("hkp://") + keyserver + else + "hkp://#{keyserver}:80" + end + + cmd << " #{key}" + + declare_resource(:execute, "install-key #{key}") do + command cmd + sensitive new_resource.sensitive + not_if do + present = extract_fingerprints_from_cmd("apt-key finger").any? do |fp| + fp.end_with? key.upcase + end + present && key_is_valid?("apt-key list", key.upcase) + end + notifies :run, "execute[apt-cache gencaches]", :immediately + end + + raise "The key #{key} is invalid and cannot be used to verify an apt repository." unless key_is_valid?("apt-key list", key.upcase) + end + + def install_ppa_key(owner, repo) + url = "https://launchpad.net/api/1.0/~#{owner}/+archive/#{repo}" + key_id = Chef::HTTP::Simple.new(url).get("signing_key_fingerprint").delete('"') + install_key_from_keyserver(key_id, "keyserver.ubuntu.com") + rescue Net::HTTPServerException => e + raise "Could not access Launchpad ppa API: #{e.message}" + end + + def is_ppa_url?(url) + url.start_with?("ppa:") + end + + def make_ppa_url(ppa) + return unless is_ppa_url?(ppa) + owner, repo = ppa[4..-1].split("/") + repo ||= "ppa" + + install_ppa_key(owner, repo) + "http://ppa.launchpad.net/#{owner}/#{repo}/ubuntu" + end + + def build_repo(uri, distribution, components, trusted, arch, add_src = false) + uri = make_ppa_url(uri) if is_ppa_url?(uri) + + uri = '"' + uri + '"' unless uri.start_with?("'", '"') + components = Array(components).join(" ") + options = [] + options << "arch=#{arch}" if arch + options << "trusted=yes" if trusted + optstr = unless options.empty? + "[" + options.join(" ") + "]" + end + info = [ optstr, uri, distribution, components ].compact.join(" ") + repo = "deb #{info}\n" + repo << "deb-src #{info}\n" if add_src + repo + end + end + end +end + +Chef::Provider::Noop.provides :apt_repository +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/apt_update.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/apt_update.rb new file mode 100644 index 0000000..677cb57 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/apt_update.rb @@ -0,0 +1,105 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/provider/apt_update' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Thom May () +# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# License:: Apache License, Version 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. +# + +require "chef_compat/copied_from_chef/chef/provider" +require "chef_compat/copied_from_chef/chef/provider/noop" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object) + class AptUpdate < (defined?(::Chef::Provider::AptUpdate) ? ::Chef::Provider::AptUpdate : Chef::Provider) + use_inline_resources + + extend Chef::Mixin::Which + + provides :apt_update do + which("apt-get") + end + + APT_CONF_DIR = "/etc/apt/apt.conf.d" + STAMP_DIR = "/var/lib/apt/periodic" + + def whyrun_supported? + true + end + + def load_current_resource + end + + action :periodic do + if !apt_up_to_date? + converge_by "update new lists of packages" do + do_update + end + end + end + + action :update do + converge_by "force update new lists of packages" do + do_update + end + end + + private + + # Determines whether we need to run `apt-get update` + # + # @return [Boolean] + def apt_up_to_date? + ::File.exist?("#{STAMP_DIR}/update-success-stamp") && + ::File.mtime("#{STAMP_DIR}/update-success-stamp") > Time.now - new_resource.frequency + end + + def do_update + [STAMP_DIR, APT_CONF_DIR].each do |d| + declare_resource(:directory, d) do + recursive true + end + end + + declare_resource(:file, "#{APT_CONF_DIR}/15update-stamp") do + content "APT::Update::Post-Invoke-Success {\"touch #{STAMP_DIR}/update-success-stamp 2>/dev/null || true\";};\n" + action :create_if_missing + end + + declare_resource(:execute, "apt-get -q update") + end + + end + end +end + +Chef::Provider::Noop.provides :apt_update +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/noop.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/noop.rb new file mode 100644 index 0000000..87c34e6 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/noop.rb @@ -0,0 +1,56 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/provider/noop' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Thom May () +# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# License:: Apache License, Version 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. +# + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object) + class Noop < (defined?(::Chef::Provider::Noop) ? ::Chef::Provider::Noop : Chef::Provider) + def load_current_resource; end + + def respond_to_missing?(method_sym, include_private = false) + method_sym.to_s.start_with?("action_") || super + end + + def method_missing(method_sym, *arguments, &block) + if method_sym.to_s =~ /^action_/ + Chef::Log.debug("NoOp-ing for #{method_sym}") + else + super + end + end + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/support/yum_repo.erb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/support/yum_repo.erb new file mode 100644 index 0000000..7d9a2d0 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/support/yum_repo.erb @@ -0,0 +1,125 @@ +# This file was generated by Chef +# Do NOT modify this file by hand. + +[<%= @config.repositoryid %>] +name=<%= @config.description %> +<% if @config.baseurl %> +baseurl=<%= @config.baseurl %> +<% end %> +<% if @config.cost %> +cost=<%= @config.cost %> +<% end %> +<% if @config.enabled %> +enabled=1 +<% else %> +enabled=0 +<% end %> +<% if @config.enablegroups %> +enablegroups=1 +<% end %> +<% if @config.exclude %> +exclude=<%= @config.exclude %> +<% end %> +<% if @config.failovermethod %> +failovermethod=<%= @config.failovermethod %> +<% end %> +<% if @config.fastestmirror_enabled %> +fastestmirror_enabled=<%= @config.fastestmirror_enabled %> +<% end %> +<% if @config.gpgcheck %> +gpgcheck=1 +<% else %> +gpgcheck=0 +<% end %> +<% if @config.gpgkey %> +gpgkey=<%= case @config.gpgkey + when Array + @config.gpgkey.join("\n ") + else + @config.gpgkey + end %> +<% end -%> +<% if @config.http_caching %> +http_caching=<%= @config.http_caching %> +<% end %> +<% if @config.include_config %> +include=<%= @config.include_config %> +<% end %> +<% if @config.includepkgs %> +includepkgs=<%= @config.includepkgs %> +<% end %> +<% if @config.keepalive %> +keepalive=1 +<% end %> +<% if @config.metadata_expire %> +metadata_expire=<%= @config.metadata_expire %> +<% end %> +<% if @config.mirrorlist %> +mirrorlist=<%= @config.mirrorlist %> +<% end %> +<% if @config.mirror_expire %> +mirror_expire=<%= @config.mirror_expire %> +<% end %> +<% if @config.mirrorlist_expire %> +mirrorlist_expire=<%= @config.mirrorlist_expire %> +<% end %> +<% if @config.priority %> +priority=<%= @config.priority %> +<% end %> +<% if @config.proxy %> +proxy=<%= @config.proxy %> +<% end %> +<% if @config.proxy_username %> +proxy_username=<%= @config.proxy_username %> +<% end %> +<% if @config.proxy_password %> +proxy_password=<%= @config.proxy_password %> +<% end %> +<% if @config.username %> +username=<%= @config.username %> +<% end %> +<% if @config.password %> +password=<%= @config.password %> +<% end %> +<% if @config.repo_gpgcheck %> +repo_gpgcheck=1 +<% end %> +<% if @config.max_retries %> +retries=<%= @config.max_retries %> +<% end %> +<% if @config.report_instanceid %> +report_instanceid=<%= @config.report_instanceid %> +<% end %> +<% if @config.skip_if_unavailable %> +skip_if_unavailable=1 +<% end %> +<% if @config.sslcacert %> +sslcacert=<%= @config.sslcacert %> +<% end %> +<% if @config.sslclientcert %> +sslclientcert=<%= @config.sslclientcert %> +<% end %> +<% if @config.sslclientkey %> +sslclientkey=<%= @config.sslclientkey %> +<% end %> +<% unless @config.sslverify.nil? %> +sslverify=<%= ( @config.sslverify ) ? 'true' : 'false' %> +<% end %> +<% if @config.timeout %> +timeout=<%= @config.timeout %> +<% end %> +<% if @config.options -%> +<% @config.options.each do |key, value| -%> +<%= key %>=<%= + case value + when Array + value.join("\n ") + when TrueClass + '1' + when FalseClass + '0' + else + value + end %> +<% end -%> +<% end -%> diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/systemd_unit.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/systemd_unit.rb new file mode 100644 index 0000000..1024cb8 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/systemd_unit.rb @@ -0,0 +1,253 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/provider/systemd_unit' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Nathan Williams () +# Copyright:: Copyright 2016, Nathan Williams +# License:: Apache License, Version 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. +# + +require "chef_compat/copied_from_chef/chef/provider" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object) + class SystemdUnit < (defined?(::Chef::Provider::SystemdUnit) ? ::Chef::Provider::SystemdUnit : Chef::Provider) + include Chef::Mixin::Which + include Chef::Mixin::ShellOut + + provides :systemd_unit, os: "linux" + + def load_current_resource + @current_resource = Chef::Resource::SystemdUnit.new(new_resource.name) + + current_resource.content(::File.read(unit_path)) if ::File.exist?(unit_path) + current_resource.user(new_resource.user) + current_resource.enabled(enabled?) + current_resource.active(active?) + current_resource.masked(masked?) + current_resource.static(static?) + current_resource.triggers_reload(new_resource.triggers_reload) + + current_resource + end + + def define_resource_requirements + super + + requirements.assert(:create) do |a| + a.assertion { IniParse.parse(new_resource.to_ini) } + a.failure_message "Unit content is not valid INI text" + end + end + + def action_create + if current_resource.content != new_resource.to_ini + converge_by("creating unit: #{new_resource.name}") do + manage_unit_file(:create) + daemon_reload if new_resource.triggers_reload + end + end + end + + def action_delete + if ::File.exist?(unit_path) + converge_by("deleting unit: #{new_resource.name}") do + manage_unit_file(:delete) + daemon_reload if new_resource.triggers_reload + end + end + end + + def action_enable + if current_resource.static + Chef::Log.debug("#{new_resource.name} is a static unit, enabling is a NOP.") + end + + unless current_resource.enabled || current_resource.static + converge_by("enabling unit: #{new_resource.name}") do + systemctl_execute!(:enable, new_resource.name) + end + end + end + + def action_disable + if current_resource.static + Chef::Log.debug("#{new_resource.name} is a static unit, disabling is a NOP.") + end + + if current_resource.enabled && !current_resource.static + converge_by("disabling unit: #{new_resource.name}") do + systemctl_execute!(:disable, new_resource.name) + end + end + end + + def action_mask + unless current_resource.masked + converge_by("masking unit: #{new_resource.name}") do + systemctl_execute!(:mask, new_resource.name) + end + end + end + + def action_unmask + if current_resource.masked + converge_by("unmasking unit: #{new_resource.name}") do + systemctl_execute!(:unmask, new_resource.name) + end + end + end + + def action_start + unless current_resource.active + converge_by("starting unit: #{new_resource.name}") do + systemctl_execute!(:start, new_resource.name) + end + end + end + + def action_stop + if current_resource.active + converge_by("stopping unit: #{new_resource.name}") do + systemctl_execute!(:stop, new_resource.name) + end + end + end + + def action_restart + converge_by("restarting unit: #{new_resource.name}") do + systemctl_execute!(:restart, new_resource.name) + end + end + + def action_reload + if current_resource.active + converge_by("reloading unit: #{new_resource.name}") do + systemctl_execute!(:reload, new_resource.name) + end + else + Chef::Log.debug("#{new_resource.name} is not active, skipping reload.") + end + end + + def action_try_restart + converge_by("try-restarting unit: #{new_resource.name}") do + systemctl_execute!("try-restart", new_resource.name) + end + end + + def action_reload_or_restart + converge_by("reload-or-restarting unit: #{new_resource.name}") do + systemctl_execute!("reload-or-restart", new_resource.name) + end + end + + def action_reload_or_try_restart + converge_by("reload-or-try-restarting unit: #{new_resource.name}") do + systemctl_execute!("reload-or-try-restart", new_resource.name) + end + end + + def active? + systemctl_execute("is-active", new_resource.name).exitstatus == 0 + end + + def enabled? + systemctl_execute("is-enabled", new_resource.name).exitstatus == 0 + end + + def masked? + systemctl_execute(:status, new_resource.name).stdout.include?("masked") + end + + def static? + systemctl_execute("is-enabled", new_resource.name).stdout.include?("static") + end + + private + + def unit_path + if new_resource.user + "/etc/systemd/user/#{new_resource.name}" + else + "/etc/systemd/system/#{new_resource.name}" + end + end + + def manage_unit_file(action = :nothing) + Chef::Resource::File.new(unit_path, run_context).tap do |f| + f.owner "root" + f.group "root" + f.mode "0644" + f.content new_resource.to_ini + end.run_action(action) + end + + def daemon_reload + shell_out_with_systems_locale!("#{systemctl_path} daemon-reload") + end + + def systemctl_execute!(action, unit) + shell_out_with_systems_locale!("#{systemctl_cmd} #{action} #{unit}", systemctl_opts) + end + + def systemctl_execute(action, unit) + shell_out("#{systemctl_cmd} #{action} #{unit}", systemctl_opts) + end + + def systemctl_cmd + @systemctl_cmd ||= "#{systemctl_path} #{systemctl_args}" + end + + def systemctl_path + @systemctl_path ||= which("systemctl") + end + + def systemctl_args + @systemctl_args ||= new_resource.user ? "--user" : "--system" + end + + def systemctl_opts + @systemctl_opts ||= + if new_resource.user + { + :user => new_resource.user, + :environment => { + "DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/#{node['etc']['passwd'][new_resource.user]['uid']}/bus", + }, + } + else + {} + end + end + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/yum_repository.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/yum_repository.rb new file mode 100644 index 0000000..bfe415e --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/provider/yum_repository.rb @@ -0,0 +1,137 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/provider/yum_repository' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Thom May () +# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# License:: Apache License, Version 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. +# + +require "chef_compat/copied_from_chef/chef/resource" +require "chef_compat/copied_from_chef/chef/dsl/declare_resource" +require "chef_compat/copied_from_chef/chef/provider/noop" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Provider < (defined?(::Chef::Provider) ? ::Chef::Provider : Object) + class YumRepository < (defined?(::Chef::Provider::YumRepository) ? ::Chef::Provider::YumRepository : Chef::Provider) + use_inline_resources + + extend Chef::Mixin::Which + + provides :yum_repository do + which "yum" + end + + def whyrun_supported?; true; end + + def load_current_resource; end + + action :create do + declare_resource(:template, "/etc/yum.repos.d/#{new_resource.repositoryid}.repo") do + if template_available?(new_resource.source) + source new_resource.source + else + source ::File.expand_path("../support/yum_repo.erb", __FILE__) + local true + end + sensitive new_resource.sensitive + variables(config: new_resource) + mode new_resource.mode + if new_resource.make_cache + notifies :run, "execute[yum clean metadata #{new_resource.repositoryid}]", :immediately if new_resource.clean_metadata || new_resource.clean_headers + notifies :run, "execute[yum-makecache-#{new_resource.repositoryid}]", :immediately + notifies :create, "ruby_block[yum-cache-reload-#{new_resource.repositoryid}]", :immediately + end + end + + declare_resource(:execute, "yum clean metadata #{new_resource.repositoryid}") do + command "yum clean metadata --disablerepo=* --enablerepo=#{new_resource.repositoryid}" + action :nothing + end + + # get the metadata for this repo only + declare_resource(:execute, "yum-makecache-#{new_resource.repositoryid}") do + command "yum -q -y makecache --disablerepo=* --enablerepo=#{new_resource.repositoryid}" + action :nothing + only_if { new_resource.enabled } + end + + # reload internal Chef yum cache + declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do + block { Chef::Provider::Package::Yum::YumCache.instance.reload } + action :nothing + end + end + + action :delete do + declare_resource(:file, "/etc/yum.repos.d/#{new_resource.repositoryid}.repo") do + action :delete + notifies :run, "execute[yum clean all #{new_resource.repositoryid}]", :immediately + notifies :create, "ruby_block[yum-cache-reload-#{new_resource.repositoryid}]", :immediately + end + + declare_resource(:execute, "yum clean all #{new_resource.repositoryid}") do + command "yum clean all --disablerepo=* --enablerepo=#{new_resource.repositoryid}" + only_if "yum repolist | grep -P '^#{new_resource.repositoryid}([ \t]|$)'" + action :nothing + end + + declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do + block { Chef::Provider::Package::Yum::YumCache.instance.reload } + action :nothing + end + end + + action :makecache do + declare_resource(:execute, "yum-makecache-#{new_resource.repositoryid}") do + command "yum -q -y makecache --disablerepo=* --enablerepo=#{new_resource.repositoryid}" + action :run + only_if { new_resource.enabled } + end + + declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do + block { Chef::Provider::Package::Yum::YumCache.instance.reload } + action :run + end + end + + alias_method :action_add, :action_create + alias_method :action_remove, :action_delete + + def template_available?(path) + !path.nil? && run_context.has_template_in_cookbook?(new_resource.cookbook_name, path) + end + + end + end +end + +Chef::Provider::Noop.provides :yum_repository +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource.rb new file mode 100644 index 0000000..e5c9a14 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource.rb @@ -0,0 +1,214 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/resource' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +require "chef_compat/copied_from_chef/chef/resource/action_class" +require "chef_compat/copied_from_chef/chef/provider" +require "chef_compat/copied_from_chef/chef/mixin/properties" +require "chef_compat/copied_from_chef/chef/dsl/universal" +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Resource < (defined?(::Chef::Resource) ? ::Chef::Resource : Object) + include Chef::Mixin::Properties + property :name, String, coerce: proc { |v| v.is_a?(Array) ? v.join(", ") : v.to_s }, desired_state: false + def initialize(name, run_context = nil) +super if defined?(::Chef::Resource) + name(name) unless name.nil? + @run_context = run_context + @noop = nil + @before = nil + @params = Hash.new + @provider = nil + @allowed_actions = self.class.allowed_actions.to_a + @action = self.class.default_action + @updated = false + @updated_by_last_action = false + @supports = {} + @ignore_failure = false + @retries = 0 + @retry_delay = 2 + @not_if = [] + @only_if = [] + @source_line = nil + # We would like to raise an error when the user gives us a guard + # interpreter and a ruby_block to the guard. In order to achieve this + # we need to understand when the user overrides the default guard + # interpreter. Therefore we store the default separately in a different + # attribute. + @guard_interpreter = nil + @default_guard_interpreter = :default + @elapsed_time = 0 + @sensitive = false + end + def action(arg = nil) + if arg + arg = Array(arg).map(&:to_sym) + arg.each do |action| + validate( + { action: action }, + { action: { kind_of: Symbol, equal_to: allowed_actions } } + ) + end + @action = arg + else + @action + end + end + alias_method :action=, :action + class UnresolvedSubscribes < (defined?(::Chef::Resource::UnresolvedSubscribes) ? ::Chef::Resource::UnresolvedSubscribes : self) + alias_method :to_s, :name + alias_method :declared_key, :name + end + def state_for_resource_reporter + state = {} + state_properties = self.class.state_properties + state_properties.each do |property| + if property.identity? || property.is_set?(self) + state[property.name] = property.sensitive? ? "*sensitive value suppressed*" : send(property.name) + end + end + state + end + alias_method :state, :state_for_resource_reporter + def identity + result = {} + identity_properties = self.class.identity_properties + identity_properties.each do |property| + result[property.name] = send(property.name) + end + return result.values.first if identity_properties.size == 1 + result + end + attr_reader :resource_initializing + def resource_initializing=(value) + if value + @resource_initializing = true + else + remove_instance_variable(:@resource_initializing) + end + end + def to_hash + # Grab all current state, then any other ivars (backcompat) + result = {} + self.class.state_properties.each do |p| + result[p.name] = p.get(self) + end + safe_ivars = instance_variables.map { |ivar| ivar.to_sym } - FORBIDDEN_IVARS + safe_ivars.each do |iv| + key = iv.to_s.sub(/^@/, "").to_sym + next if result.has_key?(key) + result[key] = instance_variable_get(iv) + end + result + end + def self.identity_property(name = nil) + result = identity_properties(*Array(name)) + if result.size > 1 + raise Chef::Exceptions::MultipleIdentityError, "identity_property cannot be called on an object with more than one identity property (#{result.map { |r| r.name }.join(", ")})." + end + result.first + end + attr_accessor :allowed_actions + def allowed_actions(value = NOT_PASSED) + if value != NOT_PASSED + self.allowed_actions = value + end + @allowed_actions + end + def resource_name + @resource_name || self.class.resource_name + end + def self.use_automatic_resource_name + automatic_name = convert_to_snake_case(self.name.split("::")[-1]) + resource_name automatic_name + end + def self.allowed_actions(*actions) + @allowed_actions ||= + if superclass.respond_to?(:allowed_actions) + superclass.allowed_actions.dup + else + [ :nothing ] + end + @allowed_actions |= actions.flatten + end + def self.allowed_actions=(value) + @allowed_actions = value.uniq + end + def self.default_action(action_name = NOT_PASSED) + unless action_name.equal?(NOT_PASSED) + @default_action = Array(action_name).map(&:to_sym) + self.allowed_actions |= @default_action + end + + if @default_action + @default_action + elsif superclass.respond_to?(:default_action) + superclass.default_action + else + [:nothing] + end + end + def self.default_action=(action_name) + default_action action_name + end + def self.action(action, &recipe_block) + action = action.to_sym + declare_action_class + action_class.action(action, &recipe_block) + self.allowed_actions += [ action ] + default_action action if Array(default_action) == [:nothing] + end + def self.load_current_value(&load_block) + define_method(:load_current_value!, &load_block) + end + def current_value_does_not_exist! + raise Chef::Exceptions::CurrentValueDoesNotExist + end + def self.action_class(&block) + return @action_class if @action_class && !block + # If the superclass needed one, then we need one as well. + if block || (superclass.respond_to?(:action_class) && superclass.action_class) + @action_class = declare_action_class(&block) + end + @action_class + end + def self.declare_action_class(&block) + @action_class ||= begin + if superclass.respond_to?(:action_class) + base_provider = superclass.action_class + end + base_provider ||= Chef::Provider + + resource_class = self + Class.new(base_provider) do + include ActionClass + self.resource_class = resource_class + end + end + @action_class.class_eval(&block) if block + @action_class + end + FORBIDDEN_IVARS = [:@run_context, :@not_if, :@only_if, :@enclosing_provider] + HIDDEN_IVARS = [:@allowed_actions, :@resource_name, :@source_line, :@run_context, :@name, :@not_if, :@only_if, :@elapsed_time, :@enclosing_provider] + class << self + end + @@sorted_descendants = nil + module DeprecatedLWRPClass + CopiedFromChef.extend_chef_module(::Chef::Resource::DeprecatedLWRPClass, self) if defined?(::Chef::Resource::DeprecatedLWRPClass) + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/action_class.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/action_class.rb new file mode 100644 index 0000000..20ff8e5 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/action_class.rb @@ -0,0 +1,114 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/resource/action_class' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: John Keiser ("} action #{action ? action.inspect : ""}" + end + + def whyrun_supported? + true + end + + # + # If load_current_value! is defined on the resource, use that. + # + def load_current_resource + if new_resource.respond_to?(:load_current_value!) + # dup the resource and then reset desired-state properties. + current_resource = new_resource.dup + + # We clear desired state in the copy, because it is supposed to be actual state. + # We keep identity properties and non-desired-state, which are assumed to be + # "control" values like `recurse: true` + current_resource.class.properties.each do |name, property| + if property.desired_state? && !property.identity? && !property.name_property? + property.reset(current_resource) + end + end + + # Call the actual load_current_value! method. If it raises + # CurrentValueDoesNotExist, set current_resource to `nil`. + begin + # If the user specifies load_current_value do |desired_resource|, we + # pass in the desired resource as well as the current one. + if current_resource.method(:load_current_value!).arity > 0 + current_resource.load_current_value!(new_resource) + else + current_resource.load_current_value! + end + rescue Chef::Exceptions::CurrentValueDoesNotExist + current_resource = nil + end + end + + @current_resource = current_resource + end + + def self.included(other) + other.extend(ClassMethods) + other.use_inline_resources + other.include_resource_dsl true + end + + module ClassMethods + CopiedFromChef.extend_chef_module(::Chef::Resource::ActionClass::ClassMethods, self) if defined?(::Chef::Resource::ActionClass::ClassMethods) + # + # The Chef::Resource class this ActionClass was declared against. + # + # @return [Class] The Chef::Resource class this ActionClass was declared against. + # + attr_accessor :resource_class + + def to_s + "#{resource_class} action provider" + end + + def inspect + to_s + end + end + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/apt_repository.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/apt_repository.rb new file mode 100644 index 0000000..1580fad --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/apt_repository.rb @@ -0,0 +1,66 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/resource/apt_repository' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Thom May () +# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# License:: Apache License, Version 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. +# + +require "chef_compat/copied_from_chef/chef/resource" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Resource < (defined?(::Chef::Resource) ? ::Chef::Resource : Object) + class AptRepository < (defined?(::Chef::Resource::AptRepository) ? ::Chef::Resource::AptRepository : Chef::Resource) + resource_name :apt_repository + provides :apt_repository + + property :repo_name, String, name_property: true + property :uri, String + property :distribution, [ String, nil, false ], default: lazy { node["lsb"]["codename"] }, nillable: true, coerce: proc { |x| x ? x : nil } + property :components, Array, default: [] + property :arch, [String, nil, false], default: nil, nillable: true, coerce: proc { |x| x ? x : nil } + property :trusted, [TrueClass, FalseClass], default: false + # whether or not to add the repository as a source repo, too + property :deb_src, [TrueClass, FalseClass], default: false + property :keyserver, [String, nil, false], default: "keyserver.ubuntu.com", nillable: true, coerce: proc { |x| x ? x : nil } + property :key, [String, nil, false], default: nil, nillable: true, coerce: proc { |x| x ? x : nil } + property :key_proxy, [String, nil, false], default: nil, nillable: true, coerce: proc { |x| x ? x : nil } + + property :cookbook, [String, nil, false], default: nil, desired_state: false, nillable: true, coerce: proc { |x| x ? x : nil } + property :cache_rebuild, [TrueClass, FalseClass], default: true, desired_state: false + property :sensitive, [TrueClass, FalseClass], default: false, desired_state: false + + default_action :add + allowed_actions :add, :remove + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/apt_update.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/apt_update.rb new file mode 100644 index 0000000..31f5dc3 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/apt_update.rb @@ -0,0 +1,52 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/resource/apt_update' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Thom May () +# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# License:: Apache License, Version 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. +# + +require "chef_compat/copied_from_chef/chef/resource" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Resource < (defined?(::Chef::Resource) ? ::Chef::Resource : Object) + class AptUpdate < (defined?(::Chef::Resource::AptUpdate) ? ::Chef::Resource::AptUpdate : Chef::Resource) + resource_name :apt_update + provides :apt_update, os: "linux" + + property :frequency, Integer, default: 86_400 + + default_action :periodic + allowed_actions :update, :periodic + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/systemd_unit.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/systemd_unit.rb new file mode 100644 index 0000000..5f9f458 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/systemd_unit.rb @@ -0,0 +1,81 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/resource/systemd_unit' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Nathan Williams () +# Copyright:: Copyright 2016, Nathan Williams +# License:: Apache License, Version 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. +# + +require "chef_compat/copied_from_chef/chef/resource" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Resource < (defined?(::Chef::Resource) ? ::Chef::Resource : Object) + class SystemdUnit < (defined?(::Chef::Resource::SystemdUnit) ? ::Chef::Resource::SystemdUnit : Chef::Resource) + resource_name :systemd_unit + + default_action :nothing + allowed_actions :create, :delete, + :enable, :disable, + :mask, :unmask, + :start, :stop, + :restart, :reload, + :try_restart, :reload_or_restart, + :reload_or_try_restart + + property :enabled, [TrueClass, FalseClass] + property :active, [TrueClass, FalseClass] + property :masked, [TrueClass, FalseClass] + property :static, [TrueClass, FalseClass] + property :user, String, desired_state: false + property :content, [String, Hash] + property :triggers_reload, [TrueClass, FalseClass], + default: true, desired_state: false + + def to_ini + case content + when Hash + IniParse.gen do |doc| + content.each_pair do |sect, opts| + doc.section(sect) do |section| + opts.each_pair do |opt, val| + section.option(opt, val) + end + end + end + end.to_s + else + content.to_s + end + end + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/yum_repository.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/yum_repository.rb new file mode 100644 index 0000000..e733daa --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource/yum_repository.rb @@ -0,0 +1,98 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/resource/yum_repository' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Thom May () +# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# License:: Apache License, Version 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. +# + +require "chef_compat/copied_from_chef/chef/resource" + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class Resource < (defined?(::Chef::Resource) ? ::Chef::Resource : Object) + class YumRepository < (defined?(::Chef::Resource::YumRepository) ? ::Chef::Resource::YumRepository : Chef::Resource) + resource_name :yum_repository + provides :yum_repository + + # http://linux.die.net/man/5/yum.conf + property :baseurl, String, regex: /.*/ + property :cost, String, regex: /^\d+$/ + property :clean_headers, [TrueClass, FalseClass], default: false # deprecated + property :clean_metadata, [TrueClass, FalseClass], default: true + property :description, String, regex: /.*/, default: "Yum Repository" + property :enabled, [TrueClass, FalseClass], default: true + property :enablegroups, [TrueClass, FalseClass] + property :exclude, String, regex: /.*/ + property :failovermethod, String, equal_to: %w{priority roundrobin} + property :fastestmirror_enabled, [TrueClass, FalseClass] + property :gpgcheck, [TrueClass, FalseClass], default: true + property :gpgkey, [String, Array], regex: /.*/ + property :http_caching, String, equal_to: %w{packages all none} + property :include_config, String, regex: /.*/ + property :includepkgs, String, regex: /.*/ + property :keepalive, [TrueClass, FalseClass] + property :make_cache, [TrueClass, FalseClass], default: true + property :max_retries, [String, Integer] + property :metadata_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/, /never/] + property :mirrorexpire, String, regex: /.*/ + property :mirrorlist, String, regex: /.*/ + property :mirror_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/] + property :mirrorlist_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/] + property :mode, default: "0644" + property :priority, String, regex: /^(\d?[0-9]|[0-9][0-9])$/ + property :proxy, String, regex: /.*/ + property :proxy_username, String, regex: /.*/ + property :proxy_password, String, regex: /.*/ + property :username, String, regex: /.*/ + property :password, String, regex: /.*/ + property :repo_gpgcheck, [TrueClass, FalseClass] + property :report_instanceid, [TrueClass, FalseClass] + property :repositoryid, String, regex: /.*/, name_property: true + property :sensitive, [TrueClass, FalseClass], default: false + property :skip_if_unavailable, [TrueClass, FalseClass] + property :source, String, regex: /.*/ + property :sslcacert, String, regex: /.*/ + property :sslclientcert, String, regex: /.*/ + property :sslclientkey, String, regex: /.*/ + property :sslverify, [TrueClass, FalseClass] + property :timeout, String, regex: /^\d+$/ + property :options, Hash + + default_action :create + allowed_actions :create, :remove, :makecache, :add, :delete + + # provide compatibility with the yum cookbook < 3.0 properties + alias_method :url, :baseurl + alias_method :keyurl, :gpgkey + end + end +end +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource_builder.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource_builder.rb new file mode 100644 index 0000000..688e856 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/copied_from_chef/chef/resource_builder.rb @@ -0,0 +1,174 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +begin + require 'chef/resource_builder' +rescue LoadError; end + +require 'chef_compat/copied_from_chef' +class Chef +module ::ChefCompat +module CopiedFromChef +# +# Author:: Lamont Granquist () +# Copyright:: Copyright 2015-2016, Chef Software, Inc. +# License:: Apache License, Version 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. +# + +# NOTE: this was extracted from the Recipe DSL mixin, relevant specs are in spec/unit/recipe_spec.rb + +class Chef < (defined?(::Chef) ? ::Chef : Object) + class ResourceBuilder < (defined?(::Chef::ResourceBuilder) ? ::Chef::ResourceBuilder : Object) + attr_reader :type + attr_reader :name + attr_reader :created_at + attr_reader :params + attr_reader :run_context + attr_reader :cookbook_name + attr_reader :recipe_name + attr_reader :enclosing_provider + attr_reader :resource + + # FIXME (ruby-2.1 syntax): most of these are mandatory + def initialize(type: nil, name: nil, created_at: nil, params: nil, run_context: nil, cookbook_name: nil, recipe_name: nil, enclosing_provider: nil) +super if defined?(::Chef::ResourceBuilder) + @type = type + @name = name + @created_at = created_at + @params = params + @run_context = run_context + @cookbook_name = cookbook_name + @recipe_name = recipe_name + @enclosing_provider = enclosing_provider + end + + def build(&block) + raise ArgumentError, "You must supply a name when declaring a #{type} resource" if name.nil? + + @resource = resource_class.new(name, run_context) + if resource.resource_name.nil? + raise Chef::Exceptions::InvalidResourceSpecification, "#{resource}.resource_name is `nil`! Did you forget to put `provides :blah` or `resource_name :blah` in your resource class?" + end + resource.source_line = created_at + resource.declared_type = type + + # If we have a resource like this one, we want to steal its state + # This behavior is very counter-intuitive and should be removed. + # See CHEF-3694, https://tickets.opscode.com/browse/CHEF-3694 + # Moved to this location to resolve CHEF-5052, https://tickets.opscode.com/browse/CHEF-5052 + if prior_resource + resource.load_from(prior_resource) + end + + resource.cookbook_name = cookbook_name + resource.recipe_name = recipe_name + # Determine whether this resource is being created in the context of an enclosing Provider + resource.enclosing_provider = enclosing_provider + + # XXX: this is required for definition params inside of the scope of a + # subresource to work correctly. + resource.params = params + + # Evaluate resource attribute DSL + if block_given? + resource.resource_initializing = true + begin + resource.instance_eval(&block) + ensure + resource.resource_initializing = false + end + end + + # emit a cloned resource warning if it is warranted + if prior_resource + if is_trivial_resource?(prior_resource) && identicalish_resources?(prior_resource, resource) + emit_harmless_cloning_debug + else + emit_cloned_resource_warning + end + end + + # Run optional resource hook + resource.after_created + + resource + end + + private + + def resource_class + # Checks the new platform => short_name => resource mapping initially + # then fall back to the older approach (Chef::Resource.const_get) for + # backward compatibility + @resource_class ||= Chef::Resource.resource_for_node(type, run_context.node) + end + + def is_trivial_resource?(resource) + trivial_resource = resource_class.new(name, run_context) + # force un-lazy the name property on the created trivial resource + name_property = resource_class.properties.find { |sym, p| p.name_property? } + trivial_resource.send(name_property[0]) unless name_property.nil? + identicalish_resources?(trivial_resource, resource) + end + + # this is an equality test specific to checking for 3694 cloning warnings + def identicalish_resources?(first, second) + skipped_ivars = [ :@source_line, :@cookbook_name, :@recipe_name, :@params, :@elapsed_time, :@declared_type ] + checked_ivars = ( first.instance_variables | second.instance_variables ) - skipped_ivars + non_matching_ivars = checked_ivars.reject do |iv| + if iv == :@action && ( [first.instance_variable_get(iv)].flatten == [:nothing] || [second.instance_variable_get(iv)].flatten == [:nothing] ) + # :nothing action on either side of the comparison always matches + true + else + first.instance_variable_get(iv) == second.instance_variable_get(iv) + end + end + Chef::Log.debug("ivars which did not match with the prior resource: #{non_matching_ivars}") + non_matching_ivars.empty? + end + + def emit_cloned_resource_warning + message = "Cloning resource attributes for #{resource} from prior resource (CHEF-3694)" + message << "\nPrevious #{prior_resource}: #{prior_resource.source_line}" if prior_resource.source_line + message << "\nCurrent #{resource}: #{resource.source_line}" if resource.source_line + Chef.log_deprecation(message) + end + + def emit_harmless_cloning_debug + Chef::Log.debug("Harmless resource cloning from #{prior_resource}:#{prior_resource.source_line} to #{resource}:#{resource.source_line}") + end + + def prior_resource + @prior_resource ||= + begin + key = "#{type}[#{name}]" + run_context.resource_collection.lookup_local(key) + rescue Chef::Exceptions::ResourceNotFound + nil + end + end + + end +end + +require "chef_compat/copied_from_chef/chef/resource" +end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/mixin/properties.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/mixin/properties.rb new file mode 100644 index 0000000..a3920d1 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/mixin/properties.rb @@ -0,0 +1,8 @@ +require 'chef_compat/monkeypatches' +require 'chef_compat/copied_from_chef/chef/mixin/properties' + +module ChefCompat + module Mixin + Properties = ChefCompat::CopiedFromChef::Chef::Mixin::Properties + end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches.rb new file mode 100644 index 0000000..9ac83e8 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches.rb @@ -0,0 +1,41 @@ +class Chef + class RunContext + class ChildRunContext < RunContext + # magic that lets us re-parse the ChildRunContext without erroring due to + # cheffish and chef-provisioning hooks having been loaded (on old versions of + # chef-client without the lazy hooks for those gems) + @__skip_method_checking = true + end + end +end + +# fix to quiet constant redefined warnings +if defined?(Chef::RunContext::ChildRunContext::CHILD_STATE) + Chef::RunContext::ChildRunContext.send(:remove_const, :CHILD_STATE) +end + +require 'chef_compat/monkeypatches/chef' +require 'chef_compat/monkeypatches/chef/exceptions' +require 'chef_compat/monkeypatches/chef/log' +require 'chef_compat/monkeypatches/chef/node' +require 'chef_compat/monkeypatches/chef/mixin/params_validate' +require 'chef_compat/monkeypatches/chef/property' +require 'chef_compat/monkeypatches/chef/provider' +require 'chef_compat/monkeypatches/chef/recipe' # copied from chef +require 'chef_compat/monkeypatches/chef/recipe_hook' +require 'chef_compat/monkeypatches/chef/resource' +require 'chef_compat/monkeypatches/chef/resource_builder' +require 'chef_compat/monkeypatches/chef/resource/lwrp_base' +require 'chef_compat/monkeypatches/chef/resource_collection' +require 'chef_compat/monkeypatches/chef/resource_collection/resource_list' +require 'chef_compat/monkeypatches/chef/resource_collection/resource_set' +require 'chef_compat/monkeypatches/chef/run_context' # copied from chef +require 'chef_compat/monkeypatches/chef/runner' # copied from chef + +# fix for Chef::RunContext instance that has already been created +ObjectSpace.each_object(Chef::RunContext) do |run_context| + run_context.node.run_context = run_context + run_context.instance_variable_set(:@loaded_recipes_hash, {}) + run_context.instance_variable_set(:@loaded_attributes_hash, {}) + run_context.initialize_child_state +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef.rb new file mode 100644 index 0000000..9669f6a --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef.rb @@ -0,0 +1,33 @@ +class Chef + NOT_PASSED = Object.new if !defined?(NOT_PASSED) + # Earlier versions of Chef didn't have this message + module ChefCompatDeprecation + def log_deprecation(message, location=nil) + if !location + # Pick the first caller that is *not* part of the Chef or ChefCompat gem, + # that's the thing the user wrote. + chef_compat_gem_path = File.expand_path("../../..", __FILE__) + chef_gem_path = File.expand_path("../..",::Chef::Resource.instance_method(:initialize).source_location[0]) + caller(0..10).each do |c| + if !c.start_with?(chef_gem_path) && !c.start_with?(chef_compat_gem_path) + location = c + break + end + end + end + + begin + super + # Bleagh. `super_method` doesn't exist on older rubies and I haven't + # figured out a way to check for its existence otherwise. + rescue NoMethodError + Chef::Log.warn(message) + end + end + end + + class<= 12.5 && Chef::VERSION.to_f <= 12.8 + require 'chef/mixin/params_validate' + class Chef + module Mixin + module ParamsValidate + class SetOrReturnProperty < Chef::Property + # 12.9 introduced a new optional parameter to `get()` to avoid a nil-set warning. + # When their method gets called with 2 args, we need to ignore and call with 1. + alias_method :_original_get2, :get + def get(resource, *args) + _original_get2(resource) + end + end + end + end + end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/node.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/node.rb new file mode 100644 index 0000000..93379b0 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/node.rb @@ -0,0 +1,9 @@ +class Chef + class Node + unless method_defined?(:set_cookbook_attribute) + def set_cookbook_attribute + # this implementation deliberately left blank - we don't need to do anything we just need to not fail + end + end + end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/property.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/property.rb new file mode 100644 index 0000000..2308d32 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/property.rb @@ -0,0 +1,15 @@ +# 12.9 introduced a new optional parameter to `get()` to avoid a nil-set warning. +# We need to mimick it here. +if Chef::VERSION.to_f >= 12.5 && Chef::VERSION.to_f <= 12.8 + require 'chef/property' + class Chef + class Property + # 12.9 introduced a new optional parameter to `get()` to avoid a nil-set warning. + # When their method gets called with 2 args, we need to ignore and call with 1. + alias_method :_original_get, :get + def get(resource, *args) + _original_get(resource) + end + end + end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/provider.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/provider.rb new file mode 100644 index 0000000..591cedb --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/provider.rb @@ -0,0 +1,65 @@ +require 'chef/provider' +require 'chef/provider/lwrp_base' + +class Chef::Provider + if !defined?(InlineResources) + InlineResources = Chef::Provider::LWRPBase::InlineResources + end + module InlineResources + require 'chef/dsl/recipe' + require 'chef/dsl/platform_introspection' + require 'chef/dsl/data_query' + require 'chef/dsl/include_recipe' + include Chef::DSL::Recipe + include Chef::DSL::PlatformIntrospection + include Chef::DSL::DataQuery + include Chef::DSL::IncludeRecipe + + unless Chef::Provider::InlineResources::ClassMethods.instance_method(:action).source_location[0] =~ /chefspec/ + # Don't override action if chefspec is doing its thing + module ::ChefCompat + module Monkeypatches + module InlineResources + module ClassMethods + def action(name, &block) + super(name) { send("compile_action_#{name}") } + # We put the action in its own method so that super() works. + define_method("compile_action_#{name}", &block) + end + end + end + end + end + module ClassMethods + prepend ChefCompat::Monkeypatches::InlineResources::ClassMethods + end + end + end +end + + +class Chef + class Provider + class LWRPBase < Provider + if defined?(InlineResources) + module InlineResources + # since we upgrade the Chef::Runner and Chef::RunContext globally to >= 12.14 style classes, we need to also + # fix the use_inline_resources LWRPBase wrapper that creates a sub-resource collection with the ugpraded code + # from the Chef::Provider subclasses that do similar things in post-12.5 chef. + def recipe_eval_with_update_check(&block) + old_run_context = run_context + @run_context = run_context.create_child + return_value = instance_eval(&block) + Chef::Runner.new(run_context).converge + return_value + ensure + if run_context.resource_collection.any? { |r| r.updated? } + new_resource.updated_by_last_action(true) + end + @run_context = old_run_context + end + end + end + end + end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/recipe.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/recipe.rb new file mode 100644 index 0000000..7c4c8be --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/recipe.rb @@ -0,0 +1,118 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +if Gem::Requirement.new('< 12.16.42').satisfied_by?(Gem::Version.new(Chef::VERSION)) +#-- +# Author:: Adam Jacob () +# Author:: Christopher Walters () +# Copyright:: Copyright 2008-2016, Chef Software Inc. +# License:: Apache License, Version 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. +# + +require "chef/dsl/recipe" +require "chef/mixin/from_file" +require "chef/mixin/deprecation" + +class Chef + # == Chef::Recipe + # A Recipe object is the context in which Chef recipes are evaluated. + class Recipe + attr_accessor :cookbook_name, :recipe_name, :recipe, :params, :run_context + + include Chef::DSL::Recipe + + include Chef::Mixin::FromFile + include Chef::Mixin::Deprecation + + # Parses a potentially fully-qualified recipe name into its + # cookbook name and recipe short name. + # + # For example: + # "aws::elastic_ip" returns [:aws, "elastic_ip"] + # "aws" returns [:aws, "default"] + # "::elastic_ip" returns [ current_cookbook, "elastic_ip" ] + #-- + # TODO: Duplicates functionality of RunListItem + def self.parse_recipe_name(recipe_name, current_cookbook: nil) + case recipe_name + when /(.+?)::(.+)/ + [ $1.to_sym, $2 ] + when /^::(.+)/ + raise "current_cookbook is nil, cannot resolve #{recipe_name}" if current_cookbook.nil? + [ current_cookbook.to_sym, $1 ] + else + [ recipe_name.to_sym, "default" ] + end + end + + def initialize(cookbook_name, recipe_name, run_context) + @cookbook_name = cookbook_name + @recipe_name = recipe_name + @run_context = run_context + # TODO: 5/19/2010 cw/tim: determine whether this can be removed + @params = Hash.new + end + + # Used in DSL mixins + def node + run_context.node + end + + # Used by the DSL to look up resources when executing in the context of a + # recipe. + def resources(*args) + run_context.resource_collection.find(*args) + end + + # This was moved to Chef::Node#tag, redirecting here for compatibility + def tag(*tags) + run_context.node.tag(*tags) + end + + # Returns true if the node is tagged with *all* of the supplied +tags+. + # + # === Parameters + # tags:: A list of tags + # + # === Returns + # true:: If all the parameters are present + # false:: If any of the parameters are missing + def tagged?(*tags) + tags.each do |tag| + return false unless run_context.node.tags.include?(tag) + end + true + end + + # Removes the list of tags from the node. + # + # === Parameters + # tags:: A list of tags + # + # === Returns + # tags:: The current list of run_context.node.tags + def untag(*tags) + tags.each do |tag| + run_context.node.tags.delete(tag) + end + end + end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/recipe_hook.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/recipe_hook.rb new file mode 100644 index 0000000..24aa20f --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/recipe_hook.rb @@ -0,0 +1,20 @@ +require 'chef/recipe' +require 'chef_compat/recipe' + +class Chef::Recipe + # If the cookbook depends on compat_resource, create a ChefCompat::Recipe object + # instead of Chef::Recipe, for the extra goodies. + def self.new(cookbook_name, recipe_name, run_context) + if run_context && + cookbook_name && + recipe_name && + run_context.cookbook_collection && + run_context.cookbook_collection[cookbook_name] && + run_context.cookbook_collection[cookbook_name].metadata.dependencies.has_key?('compat_resource') && + self != ::ChefCompat::Recipe + ::ChefCompat::Recipe.new(cookbook_name, recipe_name, run_context) + else + super + end + end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource.rb new file mode 100644 index 0000000..d61b60b --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource.rb @@ -0,0 +1,156 @@ +# this is NOT an AUTOGENERATED file + +require 'chef/resource' + +class Chef + class Resource + + class UnresolvedSubscribes < self + # The full key ise given as the name in {Resource#subscribes} + alias_method :to_s, :name + alias_method :declared_key, :name + end + + # + # Force a delayed notification into this resource's run_context. + # + # This should most likely be paired with action :nothing + # + # @param arg [Array[Symbol], Symbol] A list of actions (e.g. `:create`) + # + def delayed_action(arg) + arg = Array(arg).map(&:to_sym) + arg.map do |action| + validate( + { action: action }, + { action: { kind_of: Symbol, equal_to: allowed_actions } } + ) + # the resource effectively sends a delayed notification to itself + run_context.add_delayed_action(Notification.new(self, action, self)) + end + end + + def subscribes(action, resources, timing = :delayed) + resources = [resources].flatten + resources.each do |resource| + if resource.is_a?(String) + resource = UnresolvedSubscribes.new(resource, run_context) + end + if resource.run_context.nil? + resource.run_context = run_context + end + resource.notifies(action, self, timing) + end + true + end + + def notifies(action, resource_spec, timing = :delayed) + # when using old-style resources(:template => "/foo.txt") style, you + # could end up with multiple resources. + validate_resource_spec!(resource_spec) + + resources = [ resource_spec ].flatten + resources.each do |resource| + + case timing.to_s + when "delayed" + notifies_delayed(action, resource) + when "immediate", "immediately" + notifies_immediately(action, resource) + when "before" + notifies_before(action, resource) + else + raise ArgumentError, "invalid timing: #{timing} for notifies(#{action}, #{resources.inspect}, #{timing}) resource #{self} "\ + "Valid timings are: :delayed, :immediate, :immediately, :before" + end + end + + true + end + + # + # Iterates over all immediate and delayed notifications, calling + # resolve_resource_reference on each in turn, causing them to + # resolve lazy/forward references. + def resolve_notification_references + run_context.before_notifications(self).each { |n| + n.resolve_resource_reference(run_context.resource_collection) + } + run_context.immediate_notifications(self).each { |n| + n.resolve_resource_reference(run_context.resource_collection) + } + run_context.delayed_notifications(self).each {|n| + n.resolve_resource_reference(run_context.resource_collection) + } + end + + # Helper for #notifies + def notifies_before(action, resource_spec) + run_context.notifies_before(Notification.new(resource_spec, action, self)) + end + + # Helper for #notifies + def notifies_immediately(action, resource_spec) + run_context.notifies_immediately(Notification.new(resource_spec, action, self)) + end + + # Helper for #notifies + def notifies_delayed(action, resource_spec) + run_context.notifies_delayed(Notification.new(resource_spec, action, self)) + end + + # + # Get the current actual value of this resource. + # + # This does not cache--a new value will be returned each time. + # + # @return A new copy of the resource, with values filled in from the actual + # current value. + # + def current_value + provider = provider_for_action(Array(action).first) + if provider.whyrun_mode? && !provider.whyrun_supported? + raise "Cannot retrieve #{self.class.current_resource} in why-run mode: #{provider} does not support why-run" + end + provider.load_current_resource + provider.current_resource + end + + # These methods are necessary for new resources to initialize old ones properly + attr_reader :resource_initializing + def resource_initializing=(value) + if value + @resource_initializing = value + else + remove_instance_variable(:@resource_initializing) + end + end + + if !respond_to?(:resource_name) + def self.resource_name(name=Chef::NOT_PASSED) + # Setter + if name != Chef::NOT_PASSED + # remove_canonical_dsl + + # Set the resource_name and call provides + if name + name = name.to_sym + # If our class is not already providing this name, provide it. + # Commented out: use of resource_name and provides will need to be + # mutually exclusive in this world, generally. + # if !Chef::ResourceResolver.includes_handler?(name, self) + provides name#, canonical: true + # end + @resource_name = name + else + @resource_name = nil + end + end + @resource_name + end + def self.resource_name=(name) + resource_name(name) + end + end + end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource/lwrp_base.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource/lwrp_base.rb new file mode 100644 index 0000000..5f098fd --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource/lwrp_base.rb @@ -0,0 +1,60 @@ +require 'chef_compat/resource/lwrp_base' +require 'chef/resource/lwrp_base' + +module ChefCompat + module Monkeypatches + # + # NOTE: LOTS OF METAPROGRAMMING HERE. NOT FOR FAINT OF HEART. + # + + # Add an empty module to Class so we can temporarily override it in build_from_file + module Class + end + class<<::Class + prepend(ChefCompat::Monkeypatches::Class) + end + + module Chef + module Resource + module LWRPBase + def build_from_file(cookbook_name, filename, run_context) + # If the cookbook this LWRP is from depends on compat_resource, fix its LWRPs up real good + if run_context.cookbook_collection[cookbook_name].metadata.dependencies.has_key?('compat_resource') + # All cookbooks do Class.new(Chef::Resource::LWRPBase). Change Class.new + # temporarily to translate Chef::Resource::LWRPBase to ChefCompat::Resource + ChefCompat::Monkeypatches::Class.module_eval do + def new(*args, &block) + # Trick it! Use ChefCompat::Resource instead of Chef::Resource::LWRPBase + if args == [ ::Chef::Resource::LWRPBase ] + ChefCompat::Monkeypatches::Class.module_eval do + remove_method(:new) if method_defined?(:new) + end + args = [ ChefCompat::Resource::LWRPBase ] + end + super(*args, &block) + end + end + + begin + + # Call the actual build_from_file + super + + ensure + class<) +# Copyright:: Copyright 2015-2016, Chef Software, Inc. +# License:: Apache License, Version 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. +# + +# XXX: we now have two copies of this file in the compat_resource cookbook. I'm uncertain if this is a +# bug or a feature, and I suspect it is actually a feature. The point of this file is that for all +# resources and cookbooks the global Chef::ResourceBuilder class must be upgraded to at least the +# 12.10.24 version. The point of the other copy is that for compat_resource cookbooks all their +# resources should be using the lastest version that has been sync'd. So these two files should +# diverge as times goes on. I believe that is the correct behavior and that we want to have both +# files in this cookbook. + +# NOTE: this was extracted from the Recipe DSL mixin, relevant specs are in spec/unit/recipe_spec.rb + +if Gem::Requirement.new("< 12.10.24").satisfied_by?(Gem::Version.new(Chef::VERSION)) + begin + require 'chef/resource_builder' + # we use the LoadError this creates on early 12.x to not monkeypatch chef client versions that don't have Chef::ResourceBuilder + # (it is lazily included and doesn't appear until compile time so we can't resolve the symbol during library loading) + + class Chef + class ResourceBuilder + attr_reader :type + attr_reader :name + attr_reader :created_at + attr_reader :params + attr_reader :run_context + attr_reader :cookbook_name + attr_reader :recipe_name + attr_reader :enclosing_provider + attr_reader :resource + + # FIXME (ruby-2.1 syntax): most of these are mandatory + def initialize(type:nil, name:nil, created_at: nil, params: nil, run_context: nil, cookbook_name: nil, recipe_name: nil, enclosing_provider: nil) + @type = type + @name = name + @created_at = created_at + @params = params + @run_context = run_context + @cookbook_name = cookbook_name + @recipe_name = recipe_name + @enclosing_provider = enclosing_provider + end + + def build(&block) + raise ArgumentError, "You must supply a name when declaring a #{type} resource" if name.nil? + + @resource = resource_class.new(name, run_context) + if resource.resource_name.nil? + raise Chef::Exceptions::InvalidResourceSpecification, "#{resource}.resource_name is `nil`! Did you forget to put `provides :blah` or `resource_name :blah` in your resource class?" + end + resource.source_line = created_at + resource.declared_type = type + + # If we have a resource like this one, we want to steal its state + # This behavior is very counter-intuitive and should be removed. + # See CHEF-3694, https://tickets.opscode.com/browse/CHEF-3694 + # Moved to this location to resolve CHEF-5052, https://tickets.opscode.com/browse/CHEF-5052 + if prior_resource + resource.load_from(prior_resource) + end + + resource.cookbook_name = cookbook_name + resource.recipe_name = recipe_name + # Determine whether this resource is being created in the context of an enclosing Provider + resource.enclosing_provider = enclosing_provider + + # XXX: this is required for definition params inside of the scope of a + # subresource to work correctly. + resource.params = params + + # Evaluate resource attribute DSL + if block_given? + resource.resource_initializing = true + begin + resource.instance_eval(&block) + ensure + resource.resource_initializing = false + end + end + + # emit a cloned resource warning if it is warranted + if prior_resource + if is_trivial_resource?(prior_resource) && identicalish_resources?(prior_resource, resource) + emit_harmless_cloning_debug + else + emit_cloned_resource_warning + end + end + + # Run optional resource hook + resource.after_created + + resource + end + + private + + def resource_class + # Checks the new platform => short_name => resource mapping initially + # then fall back to the older approach (Chef::Resource.const_get) for + # backward compatibility + @resource_class ||= Chef::Resource.resource_for_node(type, run_context.node) + end + + def is_trivial_resource?(resource) + identicalish_resources?(resource_class.new(name, run_context), resource) + end + + # this is an equality test specific to checking for 3694 cloning warnings + def identicalish_resources?(first, second) + skipped_ivars = [ :@source_line, :@cookbook_name, :@recipe_name, :@params, :@elapsed_time, :@declared_type ] + checked_ivars = ( first.instance_variables | second.instance_variables ) - skipped_ivars + non_matching_ivars = checked_ivars.reject do |iv| + if iv == :@action && ( [first.instance_variable_get(iv)].flatten == [:nothing] || [second.instance_variable_get(iv)].flatten == [:nothing] ) + # :nothing action on either side of the comparison always matches + true + else + first.instance_variable_get(iv) == second.instance_variable_get(iv) + end + end + Chef::Log.debug("ivars which did not match with the prior resource: #{non_matching_ivars}") + non_matching_ivars.empty? + end + + def emit_cloned_resource_warning + Chef::Log.warn("Cloning resource attributes for #{resource} from prior resource (CHEF-3694)") + Chef::Log.warn("Previous #{prior_resource}: #{prior_resource.source_line}") if prior_resource.source_line + Chef::Log.warn("Current #{resource}: #{resource.source_line}") if resource.source_line + end + + def emit_harmless_cloning_debug + Chef::Log.debug("Harmless resource cloning from #{prior_resource}:#{prior_resource.source_line} to #{resource}:#{resource.source_line}") + end + + def prior_resource + @prior_resource ||= + begin + key = "#{type}[#{name}]" + run_context.resource_collection.lookup_local(key) + rescue Chef::Exceptions::ResourceNotFound + nil + end + end + + end + end + rescue LoadError + # cool we're just on early chef 12.x, nothing to do -- we don't have to worry because there's also not parent_run_context pointer, so we don't have to + # use lookup_local to avoid resource cloning shit out of the parent run_context. the resource collection's lookup() method will always use lookup_local + # over lookup_recursive. + end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection.rb new file mode 100644 index 0000000..4f07489 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection.rb @@ -0,0 +1,103 @@ +# +# Author:: Adam Jacob () +# Author:: Christopher Walters () +# Copyright:: Copyright 2008-2016, Chef Software Inc. +# License:: Apache License, Version 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. +# + +require "chef/resource_collection/resource_set" +require "chef/resource_collection/resource_list" +require "chef/resource_collection" +require "chef/exceptions" + +module ChefCompat + module Monkeypatches + module Chef + module ResourceCollection + module RecursiveNotificationLookup + # + # Copied verbatim from Chef 12.10.24 + # + attr_accessor :run_context + + def initialize(run_context = nil) + super() + @run_context = run_context + end + + def lookup_local(key) + resource_set.lookup(key) + end + + def find_local(*args) + resource_set.find(*args) + end + + def lookup(key) + if run_context.nil? + lookup_local(key) + else + lookup_recursive(run_context, key) + end + end + + def find(*args) + if run_context.nil? + find_local(*args) + else + find_recursive(run_context, *args) + end + end + + private + + def lookup_recursive(rc, key) + rc.resource_collection.send(:resource_set).lookup(key) + rescue ::Chef::Exceptions::ResourceNotFound + raise if !rc.respond_to?(:parent_run_context) || rc.parent_run_context.nil? + lookup_recursive(rc.parent_run_context, key) + end + + def find_recursive(rc, *args) + rc.resource_collection.send(:resource_set).find(*args) + rescue ::Chef::Exceptions::ResourceNotFound + raise if !rc.respond_to?(:parent_run_context) || rc.parent_run_context.nil? + find_recursive(rc.parent_run_context, *args) + end + end + + module DeleteResources + # + # Copied verbatim from Chef 12.10.24 + # + def delete(key) + resource_list.delete(key) + resource_set.delete(key) + end + end + end + end + end +end + + +class Chef::ResourceCollection + unless method_defined?(:lookup_local) + prepend ChefCompat::Monkeypatches::Chef::ResourceCollection::RecursiveNotificationLookup + end + unless method_defined?(:delete) + prepend ChefCompat::Monkeypatches::Chef::ResourceCollection::DeleteResources + end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection/resource_list.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection/resource_list.rb new file mode 100644 index 0000000..dfbd442 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection/resource_list.rb @@ -0,0 +1,49 @@ +# +# Author:: Tyler Ball () +# Copyright:: Copyright 2014-2016, Chef Software, Inc. +# License:: Apache License, Version 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. +# + +require "chef/resource_collection/resource_list" +require "chef/exceptions" + +module ChefCompat + module Monkeypatches + module Chef + module ResourceCollection + module ResourceList + module DeleteResource + # Copied verbatim from Chef 12.10.4 + def delete(key) + raise ArgumentError, "Must pass a Chef::Resource or String to delete" unless key.is_a?(String) || key.is_a?(Chef::Resource) + key = key.to_s + ret = @resources.reject! { |r| r.to_s == key } + if ret.nil? + raise ::Chef::Exceptions::ResourceNotFound, "Cannot find a resource matching #{key} (did you define it first?)" + end + ret + end + end + end + end + end + end +end + +class Chef::ResourceCollection::ResourceList + unless method_defined?(:delete) + prepend ChefCompat::Monkeypatches::Chef::ResourceCollection::ResourceList::DeleteResource + end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection/resource_set.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection/resource_set.rb new file mode 100644 index 0000000..bcead10 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/resource_collection/resource_set.rb @@ -0,0 +1,49 @@ +# +# Author:: Tyler Ball () +# Copyright:: Copyright 2014-2016, Chef Software, Inc. +# License:: Apache License, Version 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. +# + +require "chef/resource_collection/resource_list" +require "chef/exceptions" + +module ChefCompat + module Monkeypatches + module Chef + module ResourceCollection + module ResourceSet + module DeleteResource + def delete(key) + raise ArgumentError, "Must pass a Chef::Resource or String to delete" unless key.is_a?(String) || key.is_a?(Chef::Resource) + key = key.to_s + res = @resources_by_key.delete(key) + + if res == @resources_by_key.default + raise Chef::Exceptions::ResourceNotFound, "Cannot find a resource matching #{key} (did you define it first?)" + end + res + end + end + end + end + end + end +end + +class Chef::ResourceCollection::ResourceSet + unless method_defined?(:delete) + prepend ChefCompat::Monkeypatches::Chef::ResourceCollection::ResourceSet::DeleteResource + end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/run_context.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/run_context.rb new file mode 100644 index 0000000..03c9d60 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/run_context.rb @@ -0,0 +1,691 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +if Gem::Requirement.new('< 12.16.42').satisfied_by?(Gem::Version.new(Chef::VERSION)) +# +# Author:: Adam Jacob () +# Author:: Christopher Walters () +# Author:: Tim Hinderliter () +# Copyright:: Copyright 2008-2016, Chef Software Inc. +# License:: Apache License, Version 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. + +require "chef/resource_collection" +require "chef/cookbook_version" +require "chef/node" +require "chef/role" +require "chef/log" +require "chef/recipe" +require "chef/run_context/cookbook_compiler" +require "chef/event_dispatch/events_output_stream" +require "forwardable" + +class Chef + + # == Chef::RunContext + # Value object that loads and tracks the context of a Chef run + class RunContext + # + # Global state + # + + # + # The node for this run + # + # @return [Chef::Node] + # + attr_reader :node + + # + # The set of cookbooks involved in this run + # + # @return [Chef::CookbookCollection] + # + attr_reader :cookbook_collection + + # + # Resource Definitions for this run. Populated when the files in + # +definitions/+ are evaluated (this is triggered by #load). + # + # @return [Array[Chef::ResourceDefinition]] + # + attr_reader :definitions + + # + # Event dispatcher for this run. + # + # @return [Chef::EventDispatch::Dispatcher] + # + attr_reader :events + + # + # Hash of factoids for a reboot request. + # + # @return [Hash] + # + attr_accessor :reboot_info + + # + # Scoped state + # + + # + # The parent run context. + # + # @return [Chef::RunContext] The parent run context, or `nil` if this is the + # root context. + # + attr_reader :parent_run_context + + # + # The root run context. + # + # @return [Chef::RunContext] The root run context. + # + def root_run_context + rc = self + rc = rc.parent_run_context until rc.parent_run_context.nil? + rc + end + + # + # The collection of resources intended to be converged (and able to be + # notified). + # + # @return [Chef::ResourceCollection] + # + # @see CookbookCompiler + # + attr_reader :resource_collection + + # + # The list of control groups to execute during the audit phase + # + attr_reader :audits + + # + # Notification handling + # + + # + # A Hash containing the before notifications triggered by resources + # during the converge phase of the chef run. + # + # @return [Hash[String, Array[Chef::Resource::Notification]]] A hash from + # => + # + attr_reader :before_notification_collection + + # + # A Hash containing the immediate notifications triggered by resources + # during the converge phase of the chef run. + # + # @return [Hash[String, Array[Chef::Resource::Notification]]] A hash from + # => + # + attr_reader :immediate_notification_collection + + # + # A Hash containing the delayed (end of run) notifications triggered by + # resources during the converge phase of the chef run. + # + # @return [Hash[String, Array[Chef::Resource::Notification]]] A hash from + # => + # + attr_reader :delayed_notification_collection + + # + # An Array containing the delayed (end of run) notifications triggered by + # resources during the converge phase of the chef run. + # + # @return [Array[Chef::Resource::Notification]] An array of notification objects + # + attr_reader :delayed_actions + + # Creates a new Chef::RunContext object and populates its fields. This object gets + # used by the Chef Server to generate a fully compiled recipe list for a node. + # + # @param node [Chef::Node] The node to run against. + # @param cookbook_collection [Chef::CookbookCollection] The cookbooks + # involved in this run. + # @param events [EventDispatch::Dispatcher] The event dispatcher for this + # run. + # + def initialize(node, cookbook_collection, events) + @node = node + @cookbook_collection = cookbook_collection + @events = events + + node.run_context = self + node.set_cookbook_attribute + + @definitions = Hash.new + @loaded_recipes_hash = {} + @loaded_attributes_hash = {} + @reboot_info = {} + @cookbook_compiler = nil + @delayed_actions = [] + + initialize_child_state + end + + # + # Triggers the compile phase of the chef run. + # + # @param run_list_expansion [Chef::RunList::RunListExpansion] The run list. + # @see Chef::RunContext::CookbookCompiler + # + def load(run_list_expansion) + @cookbook_compiler = CookbookCompiler.new(self, run_list_expansion, events) + cookbook_compiler.compile + end + + # + # Initialize state that applies to both Chef::RunContext and Chef::ChildRunContext + # + def initialize_child_state + @audits = {} + @resource_collection = Chef::ResourceCollection.new(self) + @before_notification_collection = Hash.new { |h, k| h[k] = [] } + @immediate_notification_collection = Hash.new { |h, k| h[k] = [] } + @delayed_notification_collection = Hash.new { |h, k| h[k] = [] } + @delayed_actions = [] + end + + # + # Adds an before notification to the +before_notification_collection+. + # + # @param [Chef::Resource::Notification] The notification to add. + # + def notifies_before(notification) + # Note for the future, notification.notifying_resource may be an instance + # of Chef::Resource::UnresolvedSubscribes when calling {Resource#subscribes} + # with a string value. + before_notification_collection[notification.notifying_resource.declared_key] << notification + end + + # + # Adds an immediate notification to the +immediate_notification_collection+. + # + # @param [Chef::Resource::Notification] The notification to add. + # + def notifies_immediately(notification) + # Note for the future, notification.notifying_resource may be an instance + # of Chef::Resource::UnresolvedSubscribes when calling {Resource#subscribes} + # with a string value. + immediate_notification_collection[notification.notifying_resource.declared_key] << notification + end + + # + # Adds a delayed notification to the +delayed_notification_collection+. + # + # @param [Chef::Resource::Notification] The notification to add. + # + def notifies_delayed(notification) + # Note for the future, notification.notifying_resource may be an instance + # of Chef::Resource::UnresolvedSubscribes when calling {Resource#subscribes} + # with a string value. + delayed_notification_collection[notification.notifying_resource.declared_key] << notification + end + + # + # Adds a delayed action to the +delayed_actions+. + # + def add_delayed_action(notification) + if delayed_actions.any? { |existing_notification| existing_notification.duplicates?(notification) } + Chef::Log.info( "#{notification.notifying_resource} not queuing delayed action #{notification.action} on #{notification.resource}"\ + " (delayed), as it's already been queued") + else + delayed_actions << notification + end + end + + # + # Get the list of before notifications sent by the given resource. + # + # @return [Array[Notification]] + # + def before_notifications(resource) + return before_notification_collection[resource.declared_key] + end + + # + # Get the list of immediate notifications sent by the given resource. + # + # @return [Array[Notification]] + # + def immediate_notifications(resource) + return immediate_notification_collection[resource.declared_key] + end + + # + # Get the list of delayed (end of run) notifications sent by the given + # resource. + # + # @return [Array[Notification]] + # + def delayed_notifications(resource) + return delayed_notification_collection[resource.declared_key] + end + + # + # Cookbook and recipe loading + # + + # + # Evaluates the recipes +recipe_names+. Used by DSL::IncludeRecipe + # + # @param recipe_names [Array[String]] The list of recipe names (e.g. + # 'my_cookbook' or 'my_cookbook::my_resource'). + # @param current_cookbook The cookbook we are currently running in. + # + # @see DSL::IncludeRecipe#include_recipe + # + def include_recipe(*recipe_names, current_cookbook: nil) + result_recipes = Array.new + recipe_names.flatten.each do |recipe_name| + if result = load_recipe(recipe_name, current_cookbook: current_cookbook) + result_recipes << result + end + end + result_recipes + end + + # + # Evaluates the recipe +recipe_name+. Used by DSL::IncludeRecipe + # + # TODO I am sort of confused why we have both this and include_recipe ... + # I don't see anything different beyond accepting and returning an + # array of recipes. + # + # @param recipe_names [Array[String]] The recipe name (e.g 'my_cookbook' or + # 'my_cookbook::my_resource'). + # @param current_cookbook The cookbook we are currently running in. + # + # @return A truthy value if the load occurred; `false` if already loaded. + # + # @see DSL::IncludeRecipe#load_recipe + # + def load_recipe(recipe_name, current_cookbook: nil) + Chef::Log.debug("Loading recipe #{recipe_name} via include_recipe") + + cookbook_name, recipe_short_name = Chef::Recipe.parse_recipe_name(recipe_name, current_cookbook: current_cookbook) + + if unreachable_cookbook?(cookbook_name) # CHEF-4367 + Chef::Log.warn(<<-ERROR_MESSAGE) +MissingCookbookDependency: +Recipe `#{recipe_name}` is not in the run_list, and cookbook '#{cookbook_name}' +is not a dependency of any cookbook in the run_list. To load this recipe, +first add a dependency on cookbook '#{cookbook_name}' in the cookbook you're +including it from in that cookbook's metadata. +ERROR_MESSAGE + end + + if loaded_fully_qualified_recipe?(cookbook_name, recipe_short_name) + Chef::Log.debug("I am not loading #{recipe_name}, because I have already seen it.") + false + else + loaded_recipe(cookbook_name, recipe_short_name) + node.loaded_recipe(cookbook_name, recipe_short_name) + cookbook = cookbook_collection[cookbook_name] + cookbook.load_recipe(recipe_short_name, self) + end + end + + # + # Load the given recipe from a filename. + # + # @param recipe_file [String] The recipe filename. + # + # @return [Chef::Recipe] The loaded recipe. + # + # @raise [Chef::Exceptions::RecipeNotFound] If the file does not exist. + # + def load_recipe_file(recipe_file) + if !File.exist?(recipe_file) + raise Chef::Exceptions::RecipeNotFound, "could not find recipe file #{recipe_file}" + end + + Chef::Log.debug("Loading recipe file #{recipe_file}") + recipe = Chef::Recipe.new("@recipe_files", recipe_file, self) + recipe.from_file(recipe_file) + recipe + end + + # + # Look up an attribute filename. + # + # @param cookbook_name [String] The cookbook name of the attribute file. + # @param attr_file_name [String] The attribute file's name (not path). + # + # @return [String] The filename. + # + # @see DSL::IncludeAttribute#include_attribute + # + # @raise [Chef::Exceptions::CookbookNotFound] If the cookbook could not be found. + # @raise [Chef::Exceptions::AttributeNotFound] If the attribute file could not be found. + # + def resolve_attribute(cookbook_name, attr_file_name) + cookbook = cookbook_collection[cookbook_name] + raise Chef::Exceptions::CookbookNotFound, "could not find cookbook #{cookbook_name} while loading attribute #{name}" unless cookbook + + attribute_filename = cookbook.attribute_filenames_by_short_filename[attr_file_name] + raise Chef::Exceptions::AttributeNotFound, "could not find filename for attribute #{attr_file_name} in cookbook #{cookbook_name}" unless attribute_filename + + attribute_filename + end + + # + # A list of all recipes that have been loaded. + # + # This is stored internally as a Hash, so ordering is predictable. + # + # TODO is the above statement true in a 1.9+ ruby world? Is it relevant? + # + # @return [Array[String]] A list of recipes in fully qualified form, e.g. + # the recipe "nginx" will be given as "nginx::default". + # + # @see #loaded_recipe? To determine if a particular recipe has been loaded. + # + def loaded_recipes + loaded_recipes_hash.keys + end + + # + # A list of all attributes files that have been loaded. + # + # Stored internally using a Hash, so order is predictable. + # + # TODO is the above statement true in a 1.9+ ruby world? Is it relevant? + # + # @return [Array[String]] A list of attribute file names in fully qualified + # form, e.g. the "nginx" will be given as "nginx::default". + # + def loaded_attributes + loaded_attributes_hash.keys + end + + # + # Find out if a given recipe has been loaded. + # + # @param cookbook [String] Cookbook name. + # @param recipe [String] Recipe name. + # + # @return [Boolean] `true` if the recipe has been loaded, `false` otherwise. + # + def loaded_fully_qualified_recipe?(cookbook, recipe) + loaded_recipes_hash.has_key?("#{cookbook}::#{recipe}") + end + + # + # Find out if a given recipe has been loaded. + # + # @param recipe [String] Recipe name. "nginx" and "nginx::default" yield + # the same results. + # + # @return [Boolean] `true` if the recipe has been loaded, `false` otherwise. + # + def loaded_recipe?(recipe) + cookbook, recipe_name = Chef::Recipe.parse_recipe_name(recipe) + loaded_fully_qualified_recipe?(cookbook, recipe_name) + end + + # + # Mark a given recipe as having been loaded. + # + # @param cookbook [String] Cookbook name. + # @param recipe [String] Recipe name. + # + def loaded_recipe(cookbook, recipe) + loaded_recipes_hash["#{cookbook}::#{recipe}"] = true + end + + # + # Find out if a given attribute file has been loaded. + # + # @param cookbook [String] Cookbook name. + # @param attribute_file [String] Attribute file name. + # + # @return [Boolean] `true` if the recipe has been loaded, `false` otherwise. + # + def loaded_fully_qualified_attribute?(cookbook, attribute_file) + loaded_attributes_hash.has_key?("#{cookbook}::#{attribute_file}") + end + + # + # Mark a given attribute file as having been loaded. + # + # @param cookbook [String] Cookbook name. + # @param attribute_file [String] Attribute file name. + # + def loaded_attribute(cookbook, attribute_file) + loaded_attributes_hash["#{cookbook}::#{attribute_file}"] = true + end + + ## + # Cookbook File Introspection + + # + # Find out if the cookbook has the given template. + # + # @param cookbook [String] Cookbook name. + # @param template_name [String] Template name. + # + # @return [Boolean] `true` if the template is in the cookbook, `false` + # otherwise. + # @see Chef::CookbookVersion#has_template_for_node? + # + def has_template_in_cookbook?(cookbook, template_name) + cookbook = cookbook_collection[cookbook] + cookbook.has_template_for_node?(node, template_name) + end + + # + # Find out if the cookbook has the given file. + # + # @param cookbook [String] Cookbook name. + # @param cb_file_name [String] File name. + # + # @return [Boolean] `true` if the file is in the cookbook, `false` + # otherwise. + # @see Chef::CookbookVersion#has_cookbook_file_for_node? + # + def has_cookbook_file_in_cookbook?(cookbook, cb_file_name) + cookbook = cookbook_collection[cookbook] + cookbook.has_cookbook_file_for_node?(node, cb_file_name) + end + + # + # Find out whether the given cookbook is in the cookbook dependency graph. + # + # @param cookbook_name [String] Cookbook name. + # + # @return [Boolean] `true` if the cookbook is reachable, `false` otherwise. + # + # @see Chef::CookbookCompiler#unreachable_cookbook? + def unreachable_cookbook?(cookbook_name) + cookbook_compiler.unreachable_cookbook?(cookbook_name) + end + + # + # Open a stream object that can be printed into and will dispatch to events + # + # @param name [String] The name of the stream. + # @param options [Hash] Other options for the stream. + # + # @return [EventDispatch::EventsOutputStream] The created stream. + # + # @yield If a block is passed, it will be run and the stream will be closed + # afterwards. + # @yieldparam stream [EventDispatch::EventsOutputStream] The created stream. + # + def open_stream(name: nil, **options) + stream = EventDispatch::EventsOutputStream.new(events, name: name, **options) + if block_given? + begin + yield stream + ensure + stream.close + end + else + stream + end + end + + # there are options for how to handle multiple calls to these functions: + # 1. first call always wins (never change reboot_info once set). + # 2. last call always wins (happily change reboot_info whenever). + # 3. raise an exception on the first conflict. + # 4. disable reboot after this run if anyone ever calls :cancel. + # 5. raise an exception on any second call. + # 6. ? + def request_reboot(reboot_info) + Chef::Log.info "Changing reboot status from #{self.reboot_info.inspect} to #{reboot_info.inspect}" + @reboot_info = reboot_info + end + + def cancel_reboot + Chef::Log.info "Changing reboot status from #{reboot_info.inspect} to {}" + @reboot_info = {} + end + + def reboot_requested? + reboot_info.size > 0 + end + + # + # Create a child RunContext. + # + def create_child + ChildRunContext.new(self) + end + + # @api private + attr_writer :resource_collection + + protected + + attr_reader :cookbook_compiler + attr_reader :loaded_attributes_hash + attr_reader :loaded_recipes_hash + + module Deprecated + ### + # These need to be settable so deploy can run a resource_collection + # independent of any cookbooks via +recipe_eval+ + def audits=(value) + Chef.log_deprecation("Setting run_context.audits will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.") + @audits = value + end + + def immediate_notification_collection=(value) + Chef.log_deprecation("Setting run_context.immediate_notification_collection will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.") + @immediate_notification_collection = value + end + + def delayed_notification_collection=(value) + Chef.log_deprecation("Setting run_context.delayed_notification_collection will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.") + @delayed_notification_collection = value + end + end + prepend Deprecated + + # + # A child run context. Delegates all root context calls to its parent. + # + # @api private + # + class ChildRunContext < RunContext + extend Forwardable + def_delegators :parent_run_context, *%w{ + cancel_reboot + config + cookbook_collection + cookbook_compiler + definitions + events + has_cookbook_file_in_cookbook? + has_template_in_cookbook? + load + loaded_attribute + loaded_attributes + loaded_attributes_hash + loaded_fully_qualified_attribute? + loaded_fully_qualified_recipe? + loaded_recipe + loaded_recipe? + loaded_recipes + loaded_recipes_hash + node + open_stream + reboot_info + reboot_info= + reboot_requested? + request_reboot + resolve_attribute + unreachable_cookbook? + } + + def initialize(parent_run_context) + @parent_run_context = parent_run_context + + # We don't call super, because we don't bother initializing stuff we're + # going to delegate to the parent anyway. Just initialize things that + # every instance needs. + initialize_child_state + end + + CHILD_STATE = %w{ + audits + audits= + create_child + add_delayed_action + delayed_actions + delayed_notification_collection + delayed_notification_collection= + delayed_notifications + immediate_notification_collection + immediate_notification_collection= + immediate_notifications + before_notification_collection + before_notifications + include_recipe + initialize_child_state + load_recipe + load_recipe_file + notifies_before + notifies_immediately + notifies_delayed + parent_run_context + root_run_context + resource_collection + resource_collection= + }.map { |x| x.to_sym } + + # Verify that we didn't miss any methods + unless @__skip_method_checking # hook specifically for compat_resource + missing_methods = superclass.instance_methods(false) - instance_methods(false) - CHILD_STATE + if !missing_methods.empty? + raise "ERROR: not all methods of RunContext accounted for in ChildRunContext! All methods must be marked as child methods with CHILD_STATE or delegated to the parent_run_context. Missing #{missing_methods.join(", ")}." + end + end + end + end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/runner.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/runner.rb new file mode 100644 index 0000000..9add7a8 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/monkeypatches/chef/runner.rb @@ -0,0 +1,153 @@ +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# +# THIS IS A FILE AUTOGENERATED BY 'rake update' DO NOT EDIT!!!! +# +# NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +# + +if Gem::Requirement.new('< 12.16.42').satisfied_by?(Gem::Version.new(Chef::VERSION)) +#-- +# Author:: Adam Jacob () +# Author:: Christopher Walters () +# Author:: Tim Hinderliter () +# Copyright:: Copyright 2008-2016, Chef Software Inc. +# License:: Apache License, Version 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. +# + +require "chef/exceptions" +require "chef/mixin/params_validate" +require "chef/node" +require "chef/resource_collection" + +class Chef + # == Chef::Runner + # This class is responsible for executing the steps in a Chef run. + class Runner + + attr_reader :run_context + + include Chef::Mixin::ParamsValidate + + def initialize(run_context) + @run_context = run_context + end + + def delayed_actions + @run_context.delayed_actions + end + + def events + @run_context.events + end + + # Determine the appropriate provider for the given resource, then + # execute it. + def run_action(resource, action, notification_type = nil, notifying_resource = nil) + # If there are any before notifications, why-run the resource + # and notify anyone who needs notifying + before_notifications = run_context.before_notifications(resource) || [] + unless before_notifications.empty? + forced_why_run do + Chef::Log.info("#{resource} running why-run #{action} action to support before action") + resource.run_action(action, notification_type, notifying_resource) + end + + if resource.updated_by_last_action? + before_notifications.each do |notification| + Chef::Log.info("#{resource} sending #{notification.action} action to #{notification.resource} (before)") + run_action(notification.resource, notification.action, :before, resource) + end + resource.updated_by_last_action(false) + end + end + + # Actually run the action for realsies + resource.run_action(action, notification_type, notifying_resource) + + # Execute any immediate and queue up any delayed notifications + # associated with the resource, but only if it was updated *this time* + # we ran an action on it. + if resource.updated_by_last_action? + run_context.immediate_notifications(resource).each do |notification| + Chef::Log.info("#{resource} sending #{notification.action} action to #{notification.resource} (immediate)") + run_action(notification.resource, notification.action, :immediate, resource) + end + + run_context.delayed_notifications(resource).each do |notification| + # send the notification to the run_context of the receiving resource + notification.resource.run_context.add_delayed_action(notification) + end + end + end + + # Iterates over the +resource_collection+ in the +run_context+ calling + # +run_action+ for each resource in turn. + def converge + # Resolve all lazy/forward references in notifications + run_context.resource_collection.each do |resource| + resource.resolve_notification_references + end + + # Execute each resource. + run_context.resource_collection.execute_each_resource do |resource| + Array(resource.action).each { |action| run_action(resource, action) } + end + + rescue Exception => e + Chef::Log.info "Running queued delayed notifications before re-raising exception" + run_delayed_notifications(e) + else + run_delayed_notifications(nil) + true + end + + private + + # Run all our :delayed actions + def run_delayed_notifications(error = nil) + collected_failures = Exceptions::MultipleFailures.new + collected_failures.client_run_failure(error) unless error.nil? + delayed_actions.each do |notification| + result = run_delayed_notification(notification) + if result.kind_of?(Exception) + collected_failures.notification_failure(result) + end + end + collected_failures.raise! + end + + def run_delayed_notification(notification) + Chef::Log.info( "#{notification.notifying_resource} sending #{notification.action}"\ + " action to #{notification.resource} (delayed)") + # Struct of resource/action to call + run_action(notification.resource, notification.action, :delayed) + true + rescue Exception => e + e + end + + # helper to run a block of code with why_run forced to true and then restore it correctly + def forced_why_run + saved = Chef::Config[:why_run] + Chef::Config[:why_run] = true + yield + ensure + Chef::Config[:why_run] = saved + end + + end +end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/property.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/property.rb new file mode 100644 index 0000000..be21113 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/property.rb @@ -0,0 +1,6 @@ +require 'chef_compat/copied_from_chef/chef/property' + +module ChefCompat + class Property < ChefCompat::CopiedFromChef::Chef::Property + end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/recipe.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/recipe.rb new file mode 100644 index 0000000..86e39d9 --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/recipe.rb @@ -0,0 +1,8 @@ +require 'chef/recipe' +require 'chef_compat/copied_from_chef/chef/dsl/recipe' + +module ChefCompat + class Recipe < Chef::Recipe + include ChefCompat::CopiedFromChef::Chef::DSL::Recipe::FullDSL + end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/resource.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/resource.rb new file mode 100644 index 0000000..bcf0fdb --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/resource.rb @@ -0,0 +1,56 @@ +require 'chef_compat/monkeypatches' +require 'chef_compat/copied_from_chef/chef/resource' + +# We do NOT want action defined if chefspec is engaged +if Chef::Provider::InlineResources::ClassMethods.instance_method(:action).source_location[0] =~ /chefspec/ + ChefCompat::CopiedFromChef::Chef::Provider::InlineResources::ClassMethods.instance_eval do + remove_method(:action) + end +end + +module ChefCompat + class Resource < ChefCompat::CopiedFromChef::Chef::Resource + def initialize(*args, &block) + super + # @resource_name is used in earlier Chef versions + @resource_name = self.class.resource_name + end + # Things we'll need to define ourselves: + # 1. provider + # 2. resource_name + + def provider(*args, &block) + super || self.class.action_class + end + def provider=(arg) + provider(arg) + end + + if !respond_to?(:resource_name) + def self.resource_name(name=Chef::NOT_PASSED) + # Setter + if name != Chef::NOT_PASSED + # remove_canonical_dsl + + # Set the resource_name and call provides + if name + name = name.to_sym + # If our class is not already providing this name, provide it. + # Commented out: use of resource_name and provides will need to be + # mutually exclusive in this world, generally. + # if !Chef::ResourceResolver.includes_handler?(name, self) + provides name#, canonical: true + # end + @resource_name = name + else + @resource_name = nil + end + end + @resource_name + end + def self.resource_name=(name) + resource_name(name) + end + end + end +end diff --git a/chef/cookbooks/compat_resource/files/lib/chef_compat/resource/lwrp_base.rb b/chef/cookbooks/compat_resource/files/lib/chef_compat/resource/lwrp_base.rb new file mode 100644 index 0000000..2ebb98f --- /dev/null +++ b/chef/cookbooks/compat_resource/files/lib/chef_compat/resource/lwrp_base.rb @@ -0,0 +1,44 @@ +require 'chef_compat/resource' +require 'chef_compat/copied_from_chef/chef/resource' +require 'chef/mixin/convert_to_class_name' +require 'chef/mixin/from_file' + +module ChefCompat + class Resource < ChefCompat::CopiedFromChef::Chef::Resource + class LWRPBase < ChefCompat::Resource + class<= 12.0").satisfied_by?(Gem::Version.new(Chef::VERSION)) + + require 'chef_compat/resource' + require 'chef_compat/property' + require 'chef_compat/mixin/properties' + + resources_dir = File.expand_path("chef_compat/copied_from_chef/chef/resource", File.dirname(__FILE__)) + providers_dir = File.expand_path("chef_compat/copied_from_chef/chef/provider", File.dirname(__FILE__)) + Dir["#{resources_dir}/*.rb"].each {|file| require file } + Dir["#{providers_dir}/*.rb"].each {|file| require file } +else + + class Chef + class Resource + def self.property(args, &block) + raise_chef_11_error + end + + def self.resource_name(args, &block) + raise_chef_11_error + end + + def self.action(args, &block) + raise_chef_11_error + end + + def self.raise_chef_11_error + raise "This resource is written with Chef 12.5 custom resources, and requires at least Chef 12.0 used with the compat_resource cookbook, it will not work with Chef 11.x clients, and those users must pin their cookbooks to older versions or upgrade." + end + end + end + +end diff --git a/chef/cookbooks/compat_resource/libraries/autoload.rb b/chef/cookbooks/compat_resource/libraries/autoload.rb new file mode 100644 index 0000000..db52cfc --- /dev/null +++ b/chef/cookbooks/compat_resource/libraries/autoload.rb @@ -0,0 +1,31 @@ +unless Gem::Requirement.new(">= 12.0").satisfied_by?(Gem::Version.new(Chef::VERSION)) + raise "This resource is written with Chef 12.5 custom resources, and requires at least Chef 12.0 used with the compat_resource cookbook, it will not work with Chef 11.x clients, and those users must pin their cookbooks to older versions or upgrade." +end + +# If users are on old verisons of ChefDK which activates an (old) gem via cheffish before this cookbook loads, then +# we just try to monkeypatch over the top of a monkeypatch. Its possible that we have checks in this cookbook which +# will defeat that purpose and fail to monkeypatch on top of monkeypatches -- in which case those checks should be +# removed -- this cookbook needs to win when it gets into a fight with the old gem versions. +if Gem.loaded_specs["compat_resource"] + Chef.log_deprecation "using compat_resource as a gem is deprecated; please update cheffish and chef-provisioning gems (or use the latest Chef/ChefDK packages) or else manually pin your compat_resource cookbook version to the same version as the gem you are using to remove this warning" +end + +# we want to not pollute the libpath with our files until after we've done the version check +require_relative '../files/lib/chef_upstream_version' + +# on any chef client later than the one we were based off of we just turn into a no-op +if Gem::Requirement.new("< #{ChefCompat::CHEF_UPSTREAM_VERSION}").satisfied_by?(Gem::Version.new(Chef::VERSION)) + Chef::Log.debug "loading compat_resource based on chef-version #{ChefCompat::CHEF_UPSTREAM_VERSION} over chef version #{Gem::Version.new(Chef::VERSION)}" + $LOAD_PATH.unshift(File.expand_path("../files/lib", File.dirname(__FILE__))) + require 'compat_resource' +else + Chef::Log.debug "NOT LOADING compat_resource based on chef-version #{ChefCompat::CHEF_UPSTREAM_VERSION} over chef version #{Gem::Version.new(Chef::VERSION)}" + unless defined?(ChefCompat::Resource) && defined?(ChefCompat::Mixin::Properties) + module ChefCompat + Resource = Chef::Resource + module Mixin + Properties = Chef::Mixin::Properties + end + end + end +end diff --git a/chef/cookbooks/compat_resource/metadata.json b/chef/cookbooks/compat_resource/metadata.json new file mode 100644 index 0000000..af64b50 --- /dev/null +++ b/chef/cookbooks/compat_resource/metadata.json @@ -0,0 +1 @@ +{"name":"compat_resource","version":"12.16.3","description":"Backports functionality introduced in the latest chef-client releases to any chef-client from 12.1 onwards","long_description":"# compat_resource cookbook\n\n[![Build Status](https://travis-ci.org/chef-cookbooks/compat_resource.svg?branch=master)](https://travis-ci.org/chef-cookbooks/compat_resource) [![Cookbook Version](https://img.shields.io/cookbook/v/compat_resource.svg)](https://supermarket.chef.io/cookbooks/compat_resource)\n\nThis cookbook backports functionality introduced in the latest chef-client releases to any chef-client from 12.1 onwards. This includes [Custom Resource](https://docs.chef.io/custom_resources.html) functionality, notification improvements, as well as new resources added to core chef. It allows for the usage of these new resources in cookbooks without requiring the very latest Chef client release.\n\n## Backported functionality\n\n- [Custom Resources](https://docs.chef.io/custom_resources.html)\n- [apt_repository](https://docs.chef.io/resource_apt_repository.html)\n- [apt_update](https://docs.chef.io/resource_apt_update.html)\n- [systemd_unit](https://docs.chef.io/resource_systemd_unit.html)\n- [yum_repository](https://docs.chef.io/resource_yum_repository.html)\n- [:before notifications](https://docs.chef.io/resources.html#timers)\n\n## Requirements\n\n### Platforms\n\n- All platforms supported by Chef\n\n### Chef\n\n- Chef 12.1+\n\n### Cookbooks\n\n- none\n\n## Usage\n\nTo use this cookbook, put `depends 'compat_resource'` in the metadata.rb of your cookbook. Once this is done, you can use all the new custom resource features to define resources. It Just Works.\n\n## Custom Resources?\n\nCurious about how to use custom resources?\n\n- Docs: \n- Slides: \n\n## License & Authors\n\n- Author:: Lamont Granquist ([lamont@chef.io](mailto:lamont@chef.io))\n- Author:: John Keiser ([jkeiser@chef.io](mailto:jkeiser@chef.io))\n\n```text\nCopyright:: 2015-2016 Chef Software, Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","maintainer":"Lamont Granquist","maintainer_email":"lamont@chef.io","license":"Apache 2.0","platforms":{},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/chef-cookbooks/compat_resource","issues_url":"https://github.com/chef-cookbooks/compat_resource/issues","chef_version":">= 12.1","ohai_version":{}} \ No newline at end of file diff --git a/chef/cookbooks/docker/.foodcritic b/chef/cookbooks/docker/.foodcritic new file mode 100644 index 0000000..913f038 --- /dev/null +++ b/chef/cookbooks/docker/.foodcritic @@ -0,0 +1 @@ +~FC005 diff --git a/chef/cookbooks/docker/CHANGELOG.md b/chef/cookbooks/docker/CHANGELOG.md new file mode 100644 index 0000000..7235bec --- /dev/null +++ b/chef/cookbooks/docker/CHANGELOG.md @@ -0,0 +1,1676 @@ +# Docker Cookbook Changelog + +This file is used to list changes made in each version of the docker cookbook. + +## 12.15.2 (2017-02-15) +- Reverting 12.15.1 changes + +## 12.15.1 (2017-02-15) +- 799 - Adding service restarts to systemd template resources + +## 12.15.0 (2017-02-15) +- Removing dependency on compat_resource. +- Now requires Chef 12.5 or higher. + +## 12.14.3 (2017-02-14) +- Defaulting package installation version to docker 1.13.1 + +## 12.14.3 (2017-02-06) +- Reverting gem vendor due to c extensions in json dep. +- Using docker-api-1.33.2 in _autoload + +## 12.14.2 (2017-01-31) +- Vendoring docker-api-1.33.2 + +## 12.14.1 (2017-01-31) +- defaulting to package installation on amazonlinux + +## 2.14.0 (2017-01-31) +- various updates for Docker 1.13.0 +- defaulting to 1.13.0 for docker_installation +- package name fixes for new debian/ubuntu schemes +- defaulting restart_policy to nil in docker_resource + +## 2.13.11 (2017-01-25) +- #798 - Temporary "fix" for delayed service restart: using :immediate + notification in docker_service resource + +## 2.13.10 (2017-01-13) +- #800 - fixing ubuntu startup script +- #802 - using chef_version methong only in 12.6.0 and higher + +## 2.13.9 (2016-12-29) +- 793 - Removing service restarts due to chef-client behavior changes. + +## 2.13.8 (2016-12-28) +- #794 - network mode bridge +- removing emacs package in upstart provider +- Adding dokken / travis test matrix + +## 2.13.7 (2016-12-24) +- adding additional logging drivers +- adding action :reload + +## 2.13.6 (2016-12-22) +- adding ip_address support for docker_containers +- adding volume_driver support + +## 2.13.5 (2016-12-21) +- Temporary work around for broke upstart provider in chef-client +- Fixing package name for ubuntu version later than 1.12.3 + +## 2.13.4 (2016-12-20) +- Fixing comparison operator docker daemon args for versions < 1.12 + +## 2.13.3 (2016-12-20) +- 792 - Reverting 791 fix + +## 2.13.2 (2016-12-20) +- 791 - Fix logic bug in docker_service daemon args calculation + +## 2.13.1 (2016-12-19) +- #786 - Adding options hash to docker_volume connection +- #787 - Adding wait loop to docker_service_manager_execute :stop + +## 2.13.0 (2016-11-25) +- Adding sysctl property to docker_container resource + +## 2.12.0 (2016-11-25) +- Updating compat_resource dep to 12.16.2 +- Updating docker-api gem dep 1.32.1 + +## 2.11.1 (2016-11-24) +- Fix for #701 - Revert commit that caused restart loops in systemd provider + +## 2.11.0 (2016-11-23) +- make systemd MountFlags configurable +- make running wait time configurable + +## 2.10.0 (2016-11-23) +- Implement network connect/disconnect +- Fixed dns options mutual exclusion +- Misc test harness cleanup + +## 2.9.10 (2016-11-14) +-renaming systemd_conf to systemd_args due to a conflict with systemd cookbook + +## 2.9.9 (2016-11-14) +-Fixing resource idempotence in labels property +-Fix regression introduced by #741, breaking Debian installation +-Added ro_rootfs => ReadonlyRootfs special cases mapping +-Enable systemd options as a docker_service attribute + +## 2.9.8 (2016-11-08) +- Fixed a typo in an error message +- Enable tarball install through docker_service +- option log_opt is defined as --log-opt value1 --log-opt value2 instead of --log-opt=value1 --log-opt=value2 +- Depend on a working compat_resource cookbook + +## 2.9.7 (2016-10-14) +- Require the most recent compat_resource +- Get foodcritic passing +- Update the Rakefile and use cookstyle +- Use cookstyle in Travis +- Add matchers for docker_installation_tarball + +## v2.9.6 +- entrypoint not entry_point README +- dockerd binary on 1.12+ for upstart +- fix docker.socket for systemd + +## v2.9.5 +- bumping docker-api gem + +## v2.9.4 +- Switch to the dockerd binary on 1.12+ +- Add links to resources overview list + +## v2.9.3 +- add uts_mode support for docker_container provider (#730) + +## v2.9.2 +- adding feature ReadonlyRootfs +- bumping docker version to 1.11.2 +- removing etcd, fails tests for xenial and swarm will have it builtin in 1.12 + +## v2.9.1 +- implement userns_mode for containers + +## v2.9.0 +- Feature - docker_installation_tarball resource +- Patch - Adding missing http_proxy support to rhel/sysvinit +- Patch #705 - Avoid installing docker-api gem in ChefSpec + +## v2.8.0 +- Feature - User namespace configuration capability for docker_service + +## v2.7.1 + +- Updated test matrix in the readme to reflect reality + +## v2.7.0 + +- Initial support for Ubuntu 16.04 +- Initial support for Fedora 22 / 23 + +## v2.6.8 + +- notifies need to restart service immediately to prevent containers from stopping +- bumping docker-api version 1.28.0 +- adding tests for image load + +## v2.6.7 + +- only wait for running state if detached +- updating systemd template and bugfix for socket + +## v2.6.6 + +- refactor of docker-wait-ready + +## v2.6.5 + +- need a guard around docker_socket incase it isn't set + +## v2.6.4 + +- passing parsed socket file to init script +- removing unused action remove_link + +## v2.6.3 + +- Implements load action for images + +## v2.6.2 + +- Include init support for oracle platform + +## v2.6.1 + +- Add support for docker_container image property with custom repository port +- Resolve restarting container races +- New resource docker_exec + +## v2.6.0 + +- :insecure_registry in the docker_service provider can now be a string or array +- scientific and oracle have been added to the metadata as supported platforms +- The effect of -1 on memory_swap has been clarified in the readme +- Tests have been updated to run faster using trap vs. nc +- Checksums for new Docker releases have been added + +## v2.5.9 + +- Depend on compat_resource >= 12.9.0 + +## v2.5.8 + +- Setting desired_state: true for volumes / binds properties +- Now redeploy container on volume change. +- Change :restart action behavior to :run containers if they don't exist yet. + +## v2.5.7 + +- Remove vendored gems in favor of chef_gem install +- Extending available log_driver options + +## v2.5.6 + +- Adding no_proxy to Upstart defaults template + +## v2.5.5 + +- Fixing up various default: nil warnings + +## v2.5.4 + +- Allowing nil as type possibility for docker_service :package_options +- property + +## v2.5.3 + +- Adding ChefSpec.define_matcher for all resources + +## v2.5.2 + +- Setting log_driver and log_opts to desired_state: false + +## v2.5.1 + +- package_options property to pass options to underlying package resource + +## v2.5.0 + +- Defaulting installation version to 1.10.0 +- Documenting docker_network resource in README +- Documenting docker_volume resource in README + +## v2.4.26 + +- Adding docker_volume resource + +## v2.4.25 + +- Various fixes to docker_network around subsequent runs +- Utilizing property coersion and converge_if_changed + +## v2.4.24 + +- Avoiding restart loops in chef-client 12.4.3 +- Using delayed notifications for service restarts + +## v2.4.23 + +- Getting rid of Chef 13 deprecation warning +- returning nil in default_tls_cert_path + +## v2.4.22 + +- Revamped systemd resources to use package native unit files +- Using /etc/systemd/system to override settings + +## v2.4.21 + +- Revamped sysvinit resources to use package native scripts.a +- Using /etc/sysconfig on rhel and /etc/default on Debian +- Ubuntu 12.04 now uses Upstart +- Debian Wheezy support +- Fixed install_method validation + +## v2.4.20 + +- Temporarily disabling validate_install_method + +## v2.4.19 + +- Adding docker_tag force property + +## v2.4.18 + +- Fixing broken version / install_method validation check + +## v2.4.17 + +- Re-doing service_manager_upstart implementation +- Using package native init config and utilizing /etc/default + +## v2.4.16 + +- Adding validation proc for docker_service.version to throw error +- when specifying version with script installations + +## v2.4.15 + +- fixing raiseure -> failure typo in docker_container validation +- Patching vendored docker-api-1.26.0 +- + +## v2.4.14 + +- Updating .gitignore and re-adding vendored docker-api gem + +## v2.4.13 + +- stricter conditionals on container validation +- updating vendored docker-api gem to 1.26.0 +- setting default Docker installation version to 1.9.1 +- updating inspec for service-execute +- updating inspec for service-sysvinit +- updating inspec for service-upstart +- updating inspec for service-systemd +- removing unused serverspec suites + +## v2.4.12 + +- Set default docker_container.exposed_port to empty Hash + +## v2.4.11 + +- Updating metadata to use compat_resource ~> 12.7.1 + +## v2.4.10 + +- (re)adding host property to docker_network + +## v2.4.9 + +- using require_relative to load files +- specifying resource_name instead of use_automatic_resource_name + +## v2.4.8 + +- removing duplicate :tls properties +- removing instances of 'default: nil' +- depending on 'compat_resource', '~> 12.5.26' + +## v2.4.7 + +- Using Gem::Version to handle semantic verisoning and be compatible for ≥ 1.10 +- v2.4.6 + +-------------------------------------------------------------------------------- + +- 613 - Fix docker_container redeploys with bad link array ordering + +## v2.4.5 + +- Fix coerce_volumes in case current value is a Chef::Node::ImmutableArray +- Adding tests for binds alias to volumes + +## v2.4.4 + +- Updating vendored docker-api to 1.25.0 +- Adding experimental docker_network resource + +## v2.4.3 + +- Setting docker_container property defaults to match Docker CLI +- Reverting image-id hack +- Adding disable-legacy-registry + +## v2.4.2 + +- Unifying volumes and binds properties on docker_container resource +- Should use "volumes" everywhere now. Aliased method for backward compatibility. + +## v2.4.1 + +- Various fixes in wait-ready loops: +- 598 - systemd manager return value check for docker-wait-ready +- 600 - execute manager last iteration check fix. + +## v2.4.0 + +- Adding support for pid_mode and ipc_mode to docker_container + +## v2.3.23 + +- Changing bridge property validation to String + +## v2.3.22 + +- using parsed_hostname to force nil value to Docker API when +- network_mode is host + +## v2.3.21 + +- reverting hostname coerce + +## v2.3.20 + +- adding coerce_hostname +- Fixing github issues #542 and #572 + +## v2.3.19 + +switching systemd unit MountFlags from slave to private + +## v2.3.18 + +- removing detach/autoremove conflict check + +## v2.3.17 + +- Reverting gem loading trickery. Reverting to LOAD_PATH.push + +## v2.3.16 + +- Adding validation checking for detach / autoremove property +- conflicts + +## v2.3.15 + +- Loading vendored gems the same way chef_gem would. +- Resolving Chef provisioning conflicts + +## v2.3.14 + +- Supporting Upstart for Linux Mint + +## v2.3.13 + +- Updating compat_resource dep to >=12.5.23 + +## v2.3.12 + +- Pinning compat_resource version to 12.5.14 to avoid warning + +## v2.3.11 + +- Using LOAD_PATH.push instead of LOAD_PATH.unshift for vendored gems + +## v2.3.10 + +- Fix method name for pidfile in docker_service_manager_execute + +## v2.3.9 + +- Adding Linux Mint to helpers_installation_package + +## v2.3.8 + +- 582 using symbols in excon opts +- Resolves 458 + +## v2.3.7 + +- 574 - updating docker to 1.9.1 +- 575 - remove nil values from container create hash +- 576 - updating centos to 7.1 +- 577 - check for conflicting properties +- 578 - Update docker_container library documentation on timeouts +- 579 - suggest adding kill_after on a failed action stop + +## v2.3.6 + +- 573 adding support for port range + +## v2.3.5 + +- fixing desired_state on docker_container force property + +## v2.3.4 + +- Fixing up ports logic +- Supporting multiple ip/ports + +## v2.3.3 + +- vendoring docker-api-1.24.1 + +## v2.3.2 + +- vendoring docker-api-1.24.0 +- setting desired_state:false for tls properties + +## v2.3.1 + +- Support for multiple docker_service instances with docker_service_manager_upstart +- Support for multiple docker_service instances with docker_service_manager_systemd + +## v2.3.0 + +- Support for multiple docker_service instances with docker_service_manager_sysvinit + +## v2.2.11 + +- Support for multiple docker_service instances with docker_service_manager_execute + +## v2.2.10 + +- 565 - Add support for --exec-opt to docker daemon +- 566 - Rename cluster-opts to cluster-opt + +## v2.2.9 + +- 560 - Add cluster-store options to docker daemon + +## v2.2.8 + +- 559 - setting tls and tls_verify should to nil by default + +## v2.2.7 + +- Supporting Docker ENV variables without explicitly setting +- per-resource host TLS information +- Serverspec -> inspec fixes + +## v2.2.6 + +- Docker 1.9 support +- Updates to pull_image id checking +- Updates default_network_mode calculation + +## v2.2.5 + +- Updating metadata to depend on compat_resource >= 12.5.14 + +## v2.2.4 + +- More minor fixes to Upstart script template + +## v2.2.3 + +- Minor fix to Upstart script template + +## v2.2.2 + +- Upstart script now waits for all filesystems instead of just local-filesystems + +## v2.2.1 + +- marking attach_ properties desired_state: false + +## v2.2.0 + +- Switching docker_installation method to auto +- Cleaning up some old Chef::Provider namespace cruft + +## v2.1.23 + +- Adding docker_service auto_restart property. Defaulting to false. + +## v2.1.22 + +- Updating README with docker_installation and docker_service_manager resources +- Adding "desired_state: false" to docker_installation properties + +## v2.1.21 + +- Refactoring docker_service into docker_service_manager_whatever +- Fixing bug in coerce_daemon_labels +- Fixes to resources-171 suite serverspec + +## v2.1.20 + +- Fixing docker_installation_script resource + +## v2.1.19 + +- Various cruft cleanup in service templates. +- Explicitly enabling ipv4 forwarding in execute provider +- docker_service_sysvinit test suite +- docker_service_upstart test suite +- docker_service_systemd test suite + +## v2.1.18 + +- Kitchen refactoring +- docker_service_execute bug fixes + +## v2.1.17 + +- Fixing merge meant for v2.1.16 + +## v2.1.16 + +- Adding install_method property to select docker_installation resource +- Using docker_installation_binary by default +- Fixing up serverspec for pre-182 resource test recipes + +## v2.1.15 + +- Updates to README around kill_after property on :stop action +- Updates to various test containers to handle SIGKILL properly + +## v2.1.14 + +- Fixing missing property regression in docker_service + +## v2.1.13 + +- Fixing up independent of docker_installation_binary resource, adding +- kitchen suites and serverspec tests + +## v2.1.12 + +- 531 - Bugfix for invalid parameters in docker_container :stop +- action + +## v2.1.11 + +- Fixing LocalJumpError in docker_container + +## v2.1.10 + +- Adding 'desired_state: false' to various timeouts + +## v2.1.9 + +- Refactoring: Moving remote file installation method into +- docker_installation_binary resource + +## v2.1.8 + +- Refactoring: Removing classes from the Chef::Resource namespace + +## v2.1.7 + +- Fixing connection information in docker_container and helpers_base +- Refactoring .kitchen.yml tests + +## v2.1.6 + +- Enabling TLS options for docker_container and docker_image +- Various test fixes + +## v2.1.5 + +- 528 - Don't enable https connection scheme if not using TLS + +## v2.1.4 + +- 517 - Disallowing nil value for Docker command + +## v2.1.3 + +- 514 - Fixing coerce and comparison logic in exposed_ports and +- volumes to prevent unwanted restarts + +## v2.1.2 + +- Adding why_run support + +## v2.1.1 + +- 511 - fix container wait state checking +- 512 - wait for registry ports to be open in test recipe +- 519 - updating README to include labels#511 - fix container + +## v2.1.0 + +- Changing docker_container default action to :run from +- :run_if_missing. + +## v2.0.4 + +- 504 - stop and start should wait for the container to complete +- 506 - restart to use the api endpoint + +## v2.0.3 + +- Allowing nil for docker_registry properties + +## v2.0.2 + +- Fixing LocalJumpError caused by next instead of return helper methods + +## v2.0.1 + +- 491 - Return best host for docker to connect +- 495 - iptables opts shouldn't be forced to true/false +- 497 - Removing property_is_set so timeout pick up defaults + +## v2.0.0 + +- Converted resources from LWRP to Chef 12.5 Custom Resources +- Added dependency on compat_resource cookbook, works back to 12.0.0 +- Various fixes around sysvinit scripts in docker_service +- Total backwards compatibility with recipes written for chef-docker 1.x + +## v1.0.49 + +- Handling NilClass error on docker_image default creds handling + +## v1.0.48 + +- Adding a 20 try timeout to the docker_wait_ready block + +## v1.0.47 + +- 484 - Fall back to creds for index.docker.io on image pull + +## v1.0.46 + +- 438 - Adding per-resource host property to docker_image and +- docker_container + +## v1.0.45 + +- Allow :redeploy on missing containers +- TLS fixes +- Updating sysvinit script to use docker_opts + +## v1.0.44 + +- Adding Label support for docker_container + +## v1.0.43 + +- Switching docker_service sysvinit provider from ::Insserv to ::Debian + +## v1.0.42 + +- Fix for docker_service to allow setting icc to false +- Get chefspec happy on latest nightly chefdk again +- Accepting both String and Array for default_ulimit + +## v1.0.41 + +- Refactoring broken sysvinit scripts +- 421 - Adding docker-wait-ready blocks +- Discovered TLS verification is broken. Disabling for now. + +## v1.0.40 + +- Fixing broken Chef::Provider::DockerService::Execute + +## v1.0.39 + +- Various fixes around sysvinit + +## v1.0.38 + +- docker_container - enabling Docker CLI syntax for ulimits + +## v1.0.37 + +- Adding tests for #416 + +## v1.0.36 + +- Replacing docker_log helper function with docker_service.logfile + +## v1.0.35 + +- Creating DockerHelpers::Service namespace and moving appropriate methods into it. +- Start of load_current_resource implementation for docker_service for #423 + +## v1.0.34 + +- notifying new_resource to restart when updating docker_bin + +## v1.0.33 + +- Registry authentication fixes and slight docker_image refactor +- Updates for foodcritic and travis + +## v1.0.32 + +- 451 Changed default docker_container memory_swap to prevent unwanted redeploys. + +## v1.0.31 + +- 447 - Fix for log-config driver type +- 448 - Fix unwanted redeploys due to calculation of exposed_port changes. +- 450 - Treat docker_container volumes attribute as unmanaged to prevent redeploys + +## v1.0.30 + +- 427 - Qualify port bindings with protocol even when implicitly tcp. +- 443 - Added docker_container log_driver and log_opts attributes. +- Changing docker_image read_timeout default to 60 +- Misc cleanup for README and Gemfile + +## v1.0.29 + +- 432 Fixing :redeploy so it returns the container the correct state +- (create vs run) +- Fixing blank variable interpolation in tmpfiles.d/docker.conf + +## v1.0.28 + +- Adding journald gelf and fluentd to logging driver whitelist +- Allow specifying multiple DNS servers for docker_service + +## v1.0.27 + +- Cleaning up code duplication across docker_service init templates + +## v1.0.26 + +- switching from get.docker.io to get.docker.com + +## v1.0.25 + +- Updating checksum in specs for 1.8.2 +- Downloading over https +- Removing nonexistent action :enable from docker_service + +## v1.0.24 + +- 410 - Fixing Dockerfile override behavior for hostname and ulimits +- on api 1.9 +- Upgrading to Docker 1.8.2 for default version + +## v1.0.23 + +- Fixing Dockerfile / resource override behavior for working_dir + +## v1.0.22 + +- Removed patch authentication header to bundled docker-api gem +- Moved credential reset logic into image provider + +## v1.0.21 + +- 379 and #356 - patching vendored docker-api gem authentication headers + +## v1.0.20 + +- Handling the situation where USER COMMAND ENV and ENTRYPOINT are set in +- an image build, but not in a docker_container resource + +## v1.0.19 + +- Raising error on authentication error in docker_registry +- Allowing an array for storage_opts in docker_service +- Fixing parsed_checksum in docker_service +- Fixing entrypoint parsing in docker_container + +## v1.0.18 + +- Removing leftover log resources used for debugging in development + +## v1.0.17 + +- Fixing up regressions in older Docker API versions introduced in cookbook release 1.0.15 +- _ Adding @api_version instance variable +- Adding serialized_log_config +- Adding parsed_network_mode + +## v1.0.16 + +- Adding CIDR support for docker_service bip property + +## v1.0.15 + +- 309 - Adding bits to enable container re-deployment when properties change + +## v1.0.14 + +- Adding api read and write timeouts + +## v1.0.13 + +- Fixing docker_service CLI argument generation for log-driver mtu and pidfile + +## v1.0.12 + +- Fixing platform_family string (redhat -> rhel) in docker_service sysvinit provider + +## v1.0.11 + +- Renaming retries to api_retries to not conflict with Chef::Resource + +## v1.0.10 + +- Accepting userland-proxy flag +- Fix bug in parsed_storage_driver method +- Correcting usage of ip_forwarding flag +- Let Docker pick --log-level instead of defaulting to :info + +## v1.0.9 + +- Fixing Upstart respawn limit + +## v1.0.8 + +- 382 - Fixing docker_service to accept an array for storage_opt + +## v1.0.7 + +- 381 - Removing prepended whitespace in DOCKER_OPTS + +## v1.0.6 + +- 369 - Fixing up HostConfig.NetworkMode to work as expected + +## v1.0.5 + +- 241 - Only updating docker_image resource on :pull if new bits were pulled +- on tag (useful for latest) +- Changing docker_image default action to :pull + +## v1.0.4 + +- 368 - Fixing port property to be kind_of [String, Array] +- Adding missing detach property. Defaulting to false. + +## v1.0.3 + +- 366 - Using docker_kernel instead of docker_arch in parsed_checksum + +## v1.0.2 + +- 365 - Fix logic for parsing an array of hosts +- 363 - Allow an array for port property + +## v1.0.1 + +- Switching docker_service default TLS setting to false to it works +- out of the box + +## v1.0.0 + +- vendoring the docker-api rubygem +- docker_image and docker_container resources now use speak to the +- Docker Remote API instead of shelling out +- docker_containers must now have unique names +- "volumes" property now acts like the VOLUMES directive in a Dockerfile +- added "binds" property for local mounting +- standardizing on "repo" and "tag" as components of an image +- identifier + +## v0.43.0 (2015-07-28) + +- Updating README to reflect docker_image and docker_tag reality +- Implementing rm, noprune, nocache and force on docker_image + +## v0.42.0 (2015-07-28) + +- removing docker_image :load and :tag action +- adding docker_tag resource +- renaming docker_tag image_name property to :repo; creating alias +- implementing docker_image :push action + +## v0.41.0 (2015-07-26) + +- vendoring docker-api rubygem +- beginning work to convert docker_image to use native API instead of shelling out +- changing docker_image default action to :pull_if_missing +- removing some deprecated interfaces + +## v0.40.3 (2015-07-14) + +- remove --no-trunc from docker container status in sysvinit script +- 334 - docker_container tag property (issue 320) +- 331 - docker_container ulimit property +- 328 - Upstart job respawn status detection +- 326 - Upstart job restart behavior fix sysvinit script examples +- 236 - README#324 - Reference DOCKER_OPTS Amazon Linux#325 + +## v0.40.2 (2015-07-14) + +- Support for older Chef versions + +## v0.40.1 (2015-07-08) + +- Changing host property to kind_of Array + +## v0.40.0 (2015-06-29) + +Important changes with this release: + +- MAJOR INTERFACE CHANGE +- Recipes replaced with docker_service resource* +- Removing a ton of dependencies +- Storage backends, kernel module loading, etc should now be handled externally +- Updating for Docker 1.6.2 +- Preferring binary install method to OS packages + +IMPORTANT + +- attributes/ will be removed in the next release. +- most are currently non-functional +- All options will be driven through resource properties + +## v0.37.0 + +Please note some important changes with this release: + +- The sysconfig DOCKER_OPTS improvement in [#250] can potentially change the behavior of that environment variable as it now allows shell interpolation of any embedded variables. This should not affect most environments. If your DOCKER_OPTS does contains any expected `$`, please escape via `\$` for previous behavior or be sure it will behave as expected before upgrading. +- The daemon restart option (which is deprecated) has been defaulted to `nil` instead of `false` when `node['docker']['container_init_type']` is set to prevent issues with container restart policies. If you're dependent on the daemon option, please be sure to update your `node['docker']['restart']` appropriately. +- This release also defaults systemd docker host to `fd://` to match upstream, enabling socket activation properly. Adjust `node['docker']['host']` if necessary. +- Bugfix: [#239]: Upstart: install inotify tools only once (avoid CHEF-3694 warning) (thanks jperville) +- Bugfix: [#240]: Fixed dead service containers not being restarted on docker_container :run (thanks jperville) +- Bugfix: [#244]: Made docker_container action :remove remove the actual upstart service file (thanks jperville) +- Bugfix: [#246]: Lengthen shell_out timeout as workaround for slow docker_container action stop (thanks jperville) +- Bugfix: [#258]: Fix checking docker container status on debian (thanks fxposter) +- Bugfix: [#260]: Fix accidental port changing when using systemd templates (thanks fxposter) +- Bugfix: [#266]: Get tests working on master (thanks tduffield) +- Bugfix: [#267]: Replace outdated testcontainerd (thanks tduffield) +- Bugfix: [#269]: Fix tests on Travis by following Rubocop style guidelines (container LWRP) (thanks fxposter) +- Bugfix: [#280] / [#281]: Fix port handling when omitted in container LWRP (thanks databus23) +- Bugfix: [#284] / [#285]: runit finish script to stop a container (thanks xmik) +- Bugfix: [#288][]: Fix docker.socket unit for RHEL7 (thanks databus23) +- Bugfix: [#292]: readme formatting fix (thanks wormzer) +- Improvement: [#208]: Add CentOS/RHEL 7 support (thanks dermusikman and intoximeters) +- Improvement: [#232]: Added support for insecure-registry docker daemon option (thanks jperville) +- Improvement: [#233] / [#234]: Added support for registry-mirror docker daemon option (thanks jperville and tarnfeld) +- Improvement: [#237]: Deprecate the restart daemon option (thanks jperville) +- Improvement: [#238]: Added docker_container restart attribute (thanks jperville) +- Improvement: [#242]: Added docker_container action :create (thanks jperville) +- Improvement: [#245]: Add a Gitter chat badge to README.md (thanks tduffield) +- Improvement: [#250]: Use double-quotes for DOCKER_OPTS (thanks rchekaluk) +- Improvement: [#259]: Use registry on image inspection (thanks fxposter) +- Improvement: [#263]: Add additional_host attribute to container resource (thanks fxposter) +- Improvement: [#264] / [#265]: Access keyserver.ubuntu.com on port 80 (thanks sauraus) +- Improvement: [#268]: Updated the /etc/init/docker.conf template (thanks jperville) +- Improvement: [#276]: Added support for docker options device and cap-add (thanks hvolkmer) +- Improvement: [#279]: Allow docker_container memory to have String value (eg. memory='1G') (thanks jperville) +- Improvement: [#287]: redhat 7 does not need the epel repository (thanks databus23) +- Improvement: [#289]: Update systemd service/socket files (from upstream) (thanks databus23) +- Improvement: [#296]: Default systemd to fd:// as well as use upstream MountFlags=slave and LimitCORE=infinity +- Improvement: [#297]: Update docker daemon SysV init scripts with upstream improvements +- Improvement: [#298]: Further deprecate daemon restart flag by default, which interferes with restart policies + +# 0.36.0 + +- Bugfix: [#181]: Fixed remove_link action (thanks jperville). +- Bugfix: [#185]: Fix for non idempotent run action on docker_container (thanks bplunkert). +- Bugfix: [#188]: Applied temporary workaround to address the libcgmanager error to users running LXC on Ubuntu 14.04. +- Bugfix: [#196]: Address Helpers module naming conflict (thanks sethrosenblum). +- Bugfix: [#200]: Fix how service actions are handled by docker_container resource (thanks brianhartsock). +- Bugfix: [#202]: Correctly check for the kernel.release version on Debian (thanks Tritlo, paweloczadly). +- Bugfix: [#203]: Fix pull notifications for tagged images (thanks hobofan). +- Bugfix: [#205]: Fix current_resource.name assignments in docker_container provider (thanks jperville). +- Bugfix: [#206]: Fixes to container name detection (thanks jperville). +- Enhancement: [#217]: Explicitly set key and keyserver for docker apt repository (thanks sethrosenblum). +- Improvement: Pull in init script changes from upstream for sysv and systemd. +- Bugfix: [#219]: Explicitly set Upstart provider for Ubuntu 14.04 and 14.10 (thanks methodx). +- Improvement: [#220]: Create graph directory if it is specified (thanks jontg). +- Bugfix: [#224]: Fix runit container template to properly use exec (thanks waisbrot). +- Bugfix: Appropriately check for LXC when using the binary recipe on Fedora. +- Bugfix: Implement workaround for docker/docker#2702 on Ubuntu 14.10. +- Enhancement: [#221]: Added NO_PROXY support (thanks jperville). +- Various Test Suite Modifications + + - Enhancement: [#192]: Allow image tags in serverspec matching (thanks bplunkert). + - Bugfix: [#223]: Convert a few occurrences of old 'should' rspec syntax to 'expect' (thanks jperville). + - Disable a few platforms that are experiencing bugs unrelated to core functionality. + - Address ChefSpec 4.1 deprecation warnings. + - Update Berksfile to reference supermarket.getchef.com instead of api.berkshelf.com + +# 0.35.2 + +- Bugfix: [#171]: Default Ubuntu 14.04 to Docker PPA +- Bugfix: [#175]: Do not set --selinux-enabled in opts unless explicitly defined for older versions +- Bugfix: [#176]: Use docker host attribute in docker_container Upstart inotifywait + +# 0.35.1 + +- Bugfix: [#172]: Generate no cidfile by default, even when deploying as service +- Bugfix: [#173]: Updated docker upstart script (should fix service docker restart) + +# 0.35.0 + +After a long personal hiatus (sorry!), this is the last minor release before 1.0 of the cookbook. If you can handle the Docker port number change and don't use anything deprecated, upgrading to 1.0.X from 0.35.X of the cookbook should be very easy. + +This release has a bunch of changes and hasn't been fully tested yet. Wanted to get it out there for broad testing. Please use caution! + +Major kudos to @tduffield for the [#147] PR, which includes: + +- Binary Installation + + - Added missing dependency resolution for using the binary. + +- Dependency Checks + + - Added `docker::dep_check` that will take an action if certain dependencies are not met. + + - `node[docker][alert_on_error_action] = :fatal` will kill the chef run and print the error message. + - `node[docker][alert_on_error_action] = :warn` will print the error message but continue with the chef run. There is no guarantee that it will succeed though. + +- KitchenCI + + - Copied MiniTests to ServerSpec Tests + - Added new platforms (Debian 7.4) + - Changed provisioner from chef-solo to chef-zero + - Removed Ubuntu 12.10 because it is not supported by Docker and the Kernel is bad and fails all the tests. + - Removed tests for the source recipe. The dotcloud/docker repo actually doesn't build any Go deliverables. + + - I think that the source recipe needs to be completely refactored. + +Other awesome work merged: + +- [#142]: Bugfix: Redeploy breaks when a link is present +- [#139]/[#153]/[#154]/[#156]/[#157]: Bugfix: container/image ID given as nil, fixes deprecated -notrunc +- [#164]: Bugfix: Removing a container should also remove its cidfile +- [#166]: Bugfix: Fix docker_inspect_id for Docker 1.0+ +- [#158]/[#160]/[#165]: Bugfix: Fix NameError when displaying error messages for timed-out commands +- [#169]: Bugfix: Specify Upstart as service provider for cgroup on Ubuntu 14.04 (workaround for CHEF-5276, fixed in Chef 11.14) +- [#137]/[#138]: Enhancement: Experimental Ubuntu 14.04 LTS support +- [#144]: Enhancement: Experimental Amazon linux support +- [#150]/[#152]: Enhancement: Add net attribute, deprecate networking +- [#168]: Enhancement: Allow override of package name +- [#161]: Enhancement: Add minitest case for SysV service +- [#149]: Enhancement: Add --selinux-enabled daemon flag +- Enhancement: container LWRP remove_link and remove_volume actions +- Enhancement: Add storage-opt daemon flag +- Enhancement: Add Docker 0.11.0, 0.11.1, 0.12.0, 1.0.0, 1.0.1 binary checksums + +# 0.34.2 + +- [#141]: Bugfix/Enhancement: Fix and enhance docker_image pull/push behavior with Docker 0.10 + + - Removes deprecated --registry and --tag CLI args from docker_image pull + - Adds support for registry attribute usage in docker_image pull and push + - Adds support for tag attribute usage in docker_image push + +# 0.34.1 + +- [#134]: Bugfix: Fix docker_registry login handling, fixes #114 + +# 0.34.0 + +Attributes now available for all docker daemon flags as well as system IP forwarding. + +- REMOVED: container_dns_ attributes (use replacement dns_ attributes on daemon for all containers or docker_container dns* attributes instead) +- DEPRECATED: bind_* attributes to match docker terminology (use host attribute instead) +- Bugfix: [#132]: Do Not Explicitly Set storage_driver Attribute +- Bugfix: [#133]: Remove explicit false defaults in resources +- Bugfix: [#114]: Error executing action login on resource docker_registry +- Enhancement: [#115]: Add IP forwarding attributes +- Enhancement: [#116]: Docker 0.10.0: Add --no-prune to docker rmi +- Enhancement: [#117]: Docker 0.10.0: Add --output flag to docker save (as well as tag support) +- Enhancement: [#118]: Docker 0.10.0: Add --input flag to docker load +- Enhancement: [#119]: Docker 0.10.0: Add support for --env-file to load environment variables from files +- Enhancement: [#120]: Docker 0.10.0: Deprecate docker insert +- Enhancement: [#123]: Add docker kill --signal +- Enhancement: [#124]: Add all docker daemon options as attributes +- Enhancement: [#125]: Use dns* attributes to set docker daemon options, not defaults per-container +- Enhancement: [#128]: Add checksum attribute for binary downloads +- Enhancement: [#126]: Set long option names for specified docker daemon options +- Enhancement: [#127]: Use a helper function to specify single line docker daemon options + +# 0.33.1 + +- Bugfix: [#112]: Defines runner methods for ChefSpec matchers +- Bugfix: [#113]: [D-15] Fedora 19 installs Docker 0.8.1, does not have the -G or -e flag + +# 0.33.0 + +This release deprecates AUFS/device-mapper handling from chef-docker, but provides backwards compatibility by still including the default recipe of the new cookbooks. Please update your dependencies, Github watching/issues, and recipes to reflect the two new community cookbooks: + +- aufs: [aufs on community site](http://community.opscode.com/cookbooks/aufs) / [chef-aufs on Github](https://github.com/bflad/chef-aufs) +- device-mapper: [device-mapper on community site](http://community.opscode.com/cookbooks/device-mapper) / [chef-device-mapper on Github](https://github.com/bflad/chef-device-mapper) +- Bugfix: [#109]: Remove on lxc-net start from docker Upstart +- Enhancement: [#88]: Migrate AUFS logic to separate cookbook +- Enhancement: [#90]: Migrate device-mapper logic to separate cookbook +- Enhancement: [#110]: Add docker Upstart pre-start script and limits configuration +- Enhancement: [#105]: Add --label for docker run +- Enhancement: [#106]: Add --opt for docker run +- Enhancement: [#107]: Add --networking for docker run +- Enhancement: [#108]: Add --dns-search for docker run +- Enhancement: [#104]: Add TMPDIR +- Enhancement: [#111]: Add DOCKER_LOGFILE configuration +- Enhancement: container_dns* attributes to set --dns and --dns-search for all containers + +# 0.32.2 + +- Bugfix: [#101]: Explicitly install lxc on Ubuntu (when lxc is exec_driver; continue to fully support LXC as a default installation path since its been since Docker 0.1) +- Bugfix: [#103]: Fix host argument (in docker run) + +# 0.32.1 + +- Bugfix: [#98]: Ensure Ruby 1.8 syntax is supported +- Bugfix: Skip empty Array values in cli_args helper + +# 0.32.0 + +_If you're using CentOS/RHEL with EPEL, upcoming docker-io 0.9.0 package upgrade can be tracked at [Bugzilla 1074880](https://bugzilla.redhat.com/show_bug.cgi?id=1074880)_ + +This release includes Docker 0.9.0 changes and defaults, such as setting exec_driver to libcontainer ("native"), setting -rm on docker build, double dash arguments on the CLI, additional flags, etc. + +- DEPRECATED: Rename storage_type attribute to storage_driver to [match Docker terminology](http://docs.docker.io/en/latest/reference/commandline/cli/#daemon) (storage_type will be removed in chef-docker 1.0) +- DEPRECATED: Rename virtualization_type attribute to exec_driver to [match Docker terminology](http://docs.docker.io/en/latest/reference/commandline/cli/#daemon) (virtualization_type will be removed in chef-docker 1.0) +- Bugfix: [#80]: Use double dashed arguments on CLI +- Bugfix: Surround String values on CLI with quotes +- Enhancement: [#77]: Improved docker ps handling +- Enhancement: [#78]: Docker 0.9.0: Make --rm the default for docker build +- Enhancement: [#81]: Docker 0.9.0: Add a -G option to specify the group which unix sockets belong +- Enhancement: [#82]: Docker 0.9.0: Add -f flag to docker rm to force removal of running containers +- Enhancement: Add -f flag for docker rmi to force removal of images +- Enhancement: [#83]: Docker 0.9.0: Add DOCKER_RAMDISK environment variable to make Docker work when the root is on a ramdisk +- Enhancement: [#84]: Docker 0.9.0: Add -e flag for execution driver +- Enhancement: [#85]: Docker 0.9.0: Default to libcontainer +- Enhancement: [#86]: Add Chefspec LWRP matchers + +# 0.31.0 + +Lots of init love this release. Now supporting runit. + +Please note change of storage_type attribute from devmapper to devicemapper (and associated recipe name change) to match docker's name for the driver. + +Cookbook now automatically adds -s option to init configurations if storage_type is defined, which is it by default. If you were specifying -s in the options attribute, you no longer need to do so. In my quick testing, docker daemon doesn't seem to mind if -s is specified twice on startup, although you'll probably want to get rid of the extra specification. + +I've also dropped the LANG= and LC_ALL= locale environment settings from the Upstart job configuration. Its not specified in the default docker job. Please open an issue in docker project and here if for some reason this is actually necessary. + +- Bugfix: Match devicemapper storage_type attribute to match docker driver name (along with recipe name) +- Enhancement: [#72]: Add initial runit init_type +- Enhancement: [#60]: Automatically set docker -d -s from storage_type attribute +- Enhancement: Simplify default/sysconfig file into one template (docker.sysconfig.erb) and source into SysV/Upstart init configurations +- Enhancement: Add Debian docker daemon SysV init template + +# 0.30.2 + +- Bugfix: [#68]: Fix CommandTimeout handling in LWRPs +- Bugfix: [#67]: Fix argument order to pull when tag specified + +# 0.30.1 + +Public or private registry login should now correctly occur and login once per credentials change. + +- Bugfix: [#64]: Correct CLI ordering of registry login +- Bugfix: [#65]: login command skipped in registry provider +- Enhancement: registry provider current resource attributes loaded from .dockercfg + +# 0.30.0 + +Awesome work by [@jcrobak] to close out two issues ([#49] and [#52]) with [#62]. Note change below in image build action. + +- Bugfix: [#52]: return codes of docker commands not verified +- Bugfix: Add missing pull_if_missing action to image resource +- Enhancement: [#56]: Switch build action to build_if_missing, build action now builds each run (be careful with image growth!) +- Enhancement: [#59]: Add Mac OS X installation support +- Enhancement: [#49]: Add docker_cmd_timeout attribute and daemon verification +- Enhancement: [#58]: Add container redeploy action +- Enhancement: [#63]: Add group_members attribute and group recipe to manage docker group + +# 0.29.0 + +- Enhancement: [#57]: Implement id checking when determining current_resource + + - Added to both container and image LWRPs + +- Enhancement: Set created and status attributes for current container resources (for handlers, wrappers, etc.) + +- Enhancement: Set created and virtual_size attributes for image resource (for handlers, wrappers, etc.) + +# 0.28.0 + +- Enhancement: [#55]: image LWRP pull action now attempts pull every run (use pull_if_missing action for old behavior) + +# 0.27.1 + +- Bugfix: [#51]: container LWRP current_resource attribute matching should also depend on container_name + +# 0.27.0 + +- Enhancement: [#48]: Accept FalseClass CLI arguments (also explicitly declare =true for TrueClass CLI arguments) + +# 0.26.0 + +- Bugfix: Add SysV init script for binary installs +- Enhancement: Add storage_type and virtualization_type attributes +- Enhancement: Initial devmapper support for binary installs on CentOS/Ubuntu +- Enhancement: [#47] Debian-specific container SysV init script +- Enhancement: [#46] Add rm attribute for build action on image LWRP +- Enhancement: Add no_cache attribute for build action on image LWRP + +# 0.25.1 + +- Bugfix: [#44] Add missing run attribute for commit action on container LWRP + +# 0.25.0 + +- DEPRECATED: image LWRP dockerfile, image_url, and path attributes (replaced with source attribute) +- Bugfix: Use docker_cmd for container LWRP remove and restart actions +- Enhancement: Add registry LWRP with login action +- Enhancement: Standardize on "smart" and reusable destination and source attributes for container and image LWRPs to define paths/URLs for various operations +- Enhancement: Add commit, cp, export, and kill actions to container LWRP +- Enhancement: Add insert, load, push, save, and tag actions to image LWRP +- Enhancement: Add local file and directory support to import action of image LWRP +- Enhancement: Add Array support to container LWRP link attribute +- Enhancement: Cleaned up LWRP documentation + +# 0.24.2 + +- Bugfix: [#43] Better formatting for container LWRP debug logging + +# 0.24.1 + +- Bugfix: Explicitly declare depends and supports in metadata +- Bugfix: Handle container run action if container exists but isn't running + +# 0.24.0 + +- Bugfix: [#42] fix(upstart): Install inotify-tools if using upstart +- Enhancement: [#38] Allow a user to specify a custom template for their container init configuration + +# 0.23.1 + +- Bugfix: [#39] Fix NoMethodError bugs in docker::aufs recipe + +# 0.23.0 + +- Bugfix: Default oracle init_type to sysv +- Enhancement: Experimental Debian 7 package support +- Enhancement: Use new yum-epel cookbook instead of yum::epel recipe +- Enhancement: Use `value_for_platform` where applicable in attributes, requires Chef 11 + +# 0.22.0 + +- Enhancement: [#35] Use kernel release for package name on saucy and newer +- Enhancement: [#37] dont include aufs recipe on ubuntu 13.10 and up; don't require docker::lxc for package installs + +# 0.21.0 + +- Enhancement: [#31] More helpful cmd_timeout error messages and catchable exceptions for container (`Chef::Provider::Docker::Container::CommandTimeout`) and image (`Chef::Provider::Docker::Image::CommandTimeout`) LWRPs + +# 0.20.0 + +- Enhancement: Default to package install_type only on distros with known packages +- Enhancement: Initial Oracle 6 platform support via binary install_type + + - + - + +- Enhancement: Split out lxc recipe for default platform lxc handling + +- Enhancement: Create cgroups recipe for default platform cgroups handling + +# 0.19.1 + +- Bugfix: [#30] apt-get throws exit code 100 when upgrading docker + +# 0.19.0 + +- Enhancement: Add `node['docker']['version']` attribute to handle version for all install_type (recommended you switch to this) +- Enhancement: `default['docker']['binary']['version']` attribute uses `node['docker']['version']` if set +- Enhancement: Add version handling to package recipe + +# 0.18.1 + +- Bugfix: Remove ExecStartPost from systemd service to match change in docker-io-0.7.0-13 + +# 0.18.0 + +- Enhancement: CentOS/RHEL 6 package support via EPEL repository +- Enhancement: Fedora 19/20 package support now in updates (stable) repository +- Enhancement: sysv recipe and init_type + +# 0.17.0 + +- Removed: configuration recipe (see bugfix below) +- Removed: config_dir attribute (see bugfix below) +- Bugfix: Revert back to specifying HTTP_PROXY and "DOCKER_OPTS" natively in systemd/Upstart (mostly to fix up systemd support) +- Bugfix: Add systemctl --system daemon-reload handling to systemd service template +- Bugfix: Add || true to container systemd/Upstart pre-start in case already running +- Bugfix: Locale environment already handled automatically by systemd +- Enhancement: Switch Fedora package installation from goldmann-docker to Fedora updates-testing repository +- Enhancement: Switch container LWRPs to named containers on Fedora since now supported +- Enhancement: Update docker systemd service contents from docker-io-0.7.0-12.fc20 + + - Add: Wants/After firewalld.service + - Add: ExecStartPost firewall-cmd + - Remove: ExecStartPost iptables commands + +# 0.16.0 + +- Bugfix: Remove protocol from docker systemd ListenStreams +- Bugfix: Lengthen shell_out timeout for stop action in container LWRP to workaround Fedora being slow +- Enhancement: Add service creation to container LWRP by default + + - Please thoroughly test before putting into production! + - `set['docker']['container_init_type'] = false` or add `init_type false` for the LWRP to disable this behavior + +- Enhancement: Add configuration recipe with template + +- Enhancement: Add container_cmd_timeout attribute to easily set global container LWRP cmd_timeout default + +- Enhancement: Add image_cmd_timeout attribute to easily set global image LWRP cmd_timeout default + +- Enhancement: Add cookbook attribute to container LWRP + +- Enhancement: Add init_type attribute to container LWRP + +- Enhancement: Add locale support for Fedora + +- Enhancement: Fail Chef run if `docker run` command errors + +# 0.15.0 + +- Enhancement: Fedora 19/20 package support via [Goldmann docker repo](http://goldmann.fedorapeople.org/repos/docker/) +- Enhancement: docker.service / docker.socket systemd support +- Enhancement: Add `node['docker']['init_type']` attribute for controlling init system + +# 0.14.0 + +- Bugfix: [#27] Only use command to determine running container if provided +- Bugfix: [#28] Upstart requires full stop and start of service instead of restart if job configuration changes while already running. Note even `initctl reload-configuration` isn't working as expected from +- Enhancement: [#26] Add ability to set package action + +# 0.13.0 + +- Bugfix: Move LWRP updated_on_last_action(true) calls so only triggered when something actually gets updated +- Enhancement: Add container LWRP wait action +- Enhancement: Add attach and stdin args to container LWRP start action +- Enhancement: Add link arg to container LWRP remove action +- Enhancement: Use cmd_timeout in container LWRP stop action arguments + +# 0.12.0 + +- Bugfix: Add default bind_uri (nil) to default attributes +- Enhancement: [#24] bind_socket attribute added + +# 0.11.0 + +- DEPRACATION: container LWRP Fixnum port attribute: use full String notation from Docker documentation in port attribute instead +- DEPRACATION: container LWRP public_port attribute: use port attribute instead +- Enhancement: Additional container LWRP attributes: + + - cidfile + - container_name + - cpu_shares + - dns + - expose + - link + - lxc_conf + - publish_exposed_ports + - remove_automatically + - volumes_from + +- Enhancement: Support Array in container LWRP attributes: + + - env + - port + - volume + +# 0.10.1 + +- Bugfix: Set default cmd_timeout in image LWRP to 300 instead of 60 because downloading images can take awhile +- Enhancement: Change docker_test Dockerfile FROM to already downloaded busybox image instead of ubuntu +- Enhancement: Add vagrant-cachier to Vagrantfile + +Other behind the scenes changes: + +- Made cookbook code Rubocop compliant +- Move licensing information to LICENSE file +- Updated .travis.yml and Gemfile + +# 0.10.0 + +- Enhancement: [#22] cmd_timeout, path (image LWRP), working_directory (container LWRP) LWRP attributes +- Bugfix: [#25] Install Go environment only when installing from source + +# 0.9.1 + +- Fix to upstart recipe to not restart service constantly (only on initial install and changes) + +# 0.9.0 + +- image LWRP now supports non-stdin build and import actions (thanks [@wingrunr21]!) + +# 0.8.1 + +- Fix in aufs recipe for FC048 Prefer Mixlib::ShellOut + +# 0.8.0 + +Lots of community contributions this release -- thanks! + +- image LWRP now supports builds via Dockerfile +- Additional privileged, public_port, and stdin parameters for container LWRP +- Support specifying binary version for installation +- Fix upstart configuration customization when installing via Apt packages +- Default to Golang 1.1 + +# 0.7.1 + +- Use HTTPS for Apt repository + +# 0.7.0 + +- Update APT repository information for Docker 0.6+ + +# 0.6.2 + +- Change Upstart config to start on runlevels [2345] instead of just 3 + +# 0.6.1 + +- Change env HTTP_PROXY to export HTTP_PROXY in Upstart configuration + +# 0.6.0 + +- Add bind_uri and options attributes + +# 0.5.0 + +- Add http_proxy attribute + +# 0.4.0 + +- Docker now provides precise/quantal/raring distributions for their PPA +- Tested Ubuntu 13.04 support + +# 0.3.0 + +- Initial `container` LWRP + +# 0.2.0 + +- Initial `image` LWRP + +# 0.1.0 + +- Initial release + +[#22]: https://github.com/bflad/chef-docker/issues/22 +[#24]: https://github.com/bflad/chef-docker/issues/24 +[#25]: https://github.com/bflad/chef-docker/issues/25 +[#26]: https://github.com/bflad/chef-docker/issues/26 +[#27]: https://github.com/bflad/chef-docker/issues/27 +[#28]: https://github.com/bflad/chef-docker/issues/28 +[#30]: https://github.com/bflad/chef-docker/issues/30 +[#31]: https://github.com/bflad/chef-docker/issues/31 +[#35]: https://github.com/bflad/chef-docker/issues/35 +[#37]: https://github.com/bflad/chef-docker/issues/37 +[#38]: https://github.com/bflad/chef-docker/issues/38 +[#39]: https://github.com/bflad/chef-docker/issues/39 +[#42]: https://github.com/bflad/chef-docker/issues/42 +[#43]: https://github.com/bflad/chef-docker/issues/43 +[#44]: https://github.com/bflad/chef-docker/issues/44 +[#46]: https://github.com/bflad/chef-docker/issues/46 +[#47]: https://github.com/bflad/chef-docker/issues/47 +[#48]: https://github.com/bflad/chef-docker/issues/48 +[#49]: https://github.com/bflad/chef-docker/issues/49 +[#51]: https://github.com/bflad/chef-docker/issues/51 +[#52]: https://github.com/bflad/chef-docker/issues/52 +[#55]: https://github.com/bflad/chef-docker/issues/55 +[#56]: https://github.com/bflad/chef-docker/issues/56 +[#57]: https://github.com/bflad/chef-docker/issues/57 +[#58]: https://github.com/bflad/chef-docker/issues/58 +[#59]: https://github.com/bflad/chef-docker/issues/59 +[#60]: https://github.com/bflad/chef-docker/issues/60 +[#62]: https://github.com/bflad/chef-docker/issues/62 +[#63]: https://github.com/bflad/chef-docker/issues/63 +[#64]: https://github.com/bflad/chef-docker/issues/64 +[#65]: https://github.com/bflad/chef-docker/issues/65 +[#67]: https://github.com/bflad/chef-docker/issues/67 +[#68]: https://github.com/bflad/chef-docker/issues/68 +[#72]: https://github.com/bflad/chef-docker/issues/72 +[#77]: https://github.com/bflad/chef-docker/issues/77 +[#78]: https://github.com/bflad/chef-docker/issues/78 +[#80]: https://github.com/bflad/chef-docker/issues/80 +[#81]: https://github.com/bflad/chef-docker/issues/81 +[#82]: https://github.com/bflad/chef-docker/issues/82 +[#83]: https://github.com/bflad/chef-docker/issues/83 +[#84]: https://github.com/bflad/chef-docker/issues/84 +[#85]: https://github.com/bflad/chef-docker/issues/85 +[#86]: https://github.com/bflad/chef-docker/issues/86 +[#88]: https://github.com/bflad/chef-docker/issues/88 +[#89]: https://github.com/bflad/chef-docker/issues/89 +[#90]: https://github.com/bflad/chef-docker/issues/90 +[#91]: https://github.com/bflad/chef-docker/issues/91 +[#98]: https://github.com/bflad/chef-docker/issues/98 +[#101]: https://github.com/bflad/chef-docker/issues/101 +[#103]: https://github.com/bflad/chef-docker/issues/103 +[#104]: https://github.com/bflad/chef-docker/issues/104 +[#105]: https://github.com/bflad/chef-docker/issues/105 +[#106]: https://github.com/bflad/chef-docker/issues/106 +[#107]: https://github.com/bflad/chef-docker/issues/107 +[#108]: https://github.com/bflad/chef-docker/issues/108 +[#109]: https://github.com/bflad/chef-docker/issues/109 +[#110]: https://github.com/bflad/chef-docker/issues/110 +[#111]: https://github.com/bflad/chef-docker/issues/111 +[#112]: https://github.com/bflad/chef-docker/issues/112 +[#113]: https://github.com/bflad/chef-docker/issues/113 +[#114]: https://github.com/bflad/chef-docker/issues/114 +[#115]: https://github.com/bflad/chef-docker/issues/115 +[#116]: https://github.com/bflad/chef-docker/issues/116 +[#117]: https://github.com/bflad/chef-docker/issues/117 +[#118]: https://github.com/bflad/chef-docker/issues/118 +[#119]: https://github.com/bflad/chef-docker/issues/119 +[#120]: https://github.com/bflad/chef-docker/issues/120 +[#123]: https://github.com/bflad/chef-docker/issues/123 +[#124]: https://github.com/bflad/chef-docker/issues/124 +[#125]: https://github.com/bflad/chef-docker/issues/125 +[#126]: https://github.com/bflad/chef-docker/issues/126 +[#127]: https://github.com/bflad/chef-docker/issues/127 +[#128]: https://github.com/bflad/chef-docker/issues/128 +[#132]: https://github.com/bflad/chef-docker/issues/132 +[#133]: https://github.com/bflad/chef-docker/issues/133 +[#134]: https://github.com/bflad/chef-docker/issues/134 +[#137]: https://github.com/bflad/chef-docker/issues/137 +[#138]: https://github.com/bflad/chef-docker/issues/138 +[#139]: https://github.com/bflad/chef-docker/issues/139 +[#141]: https://github.com/bflad/chef-docker/issues/141 +[#142]: https://github.com/bflad/chef-docker/issues/142 +[#144]: https://github.com/bflad/chef-docker/issues/144 +[#147]: https://github.com/bflad/chef-docker/issues/147 +[#149]: https://github.com/bflad/chef-docker/issues/149 +[#150]: https://github.com/bflad/chef-docker/issues/150 +[#152]: https://github.com/bflad/chef-docker/issues/152 +[#153]: https://github.com/bflad/chef-docker/issues/153 +[#154]: https://github.com/bflad/chef-docker/issues/154 +[#156]: https://github.com/bflad/chef-docker/issues/156 +[#157]: https://github.com/bflad/chef-docker/issues/157 +[#158]: https://github.com/bflad/chef-docker/issues/158 +[#160]: https://github.com/bflad/chef-docker/issues/160 +[#161]: https://github.com/bflad/chef-docker/issues/161 +[#164]: https://github.com/bflad/chef-docker/issues/164 +[#165]: https://github.com/bflad/chef-docker/issues/165 +[#166]: https://github.com/bflad/chef-docker/issues/166 +[#168]: https://github.com/bflad/chef-docker/issues/168 +[#169]: https://github.com/bflad/chef-docker/issues/169 +[#171]: https://github.com/bflad/chef-docker/issues/171 +[#172]: https://github.com/bflad/chef-docker/issues/172 +[#173]: https://github.com/bflad/chef-docker/issues/173 +[#175]: https://github.com/bflad/chef-docker/issues/175 +[#176]: https://github.com/bflad/chef-docker/issues/176 +[#181]: https://github.com/bflad/chef-docker/issues/181 +[#185]: https://github.com/bflad/chef-docker/issues/185 +[#188]: https://github.com/bflad/chef-docker/issues/188 +[#192]: https://github.com/bflad/chef-docker/issues/192 +[#196]: https://github.com/bflad/chef-docker/issues/196 +[#200]: https://github.com/bflad/chef-docker/issues/200 +[#202]: https://github.com/bflad/chef-docker/issues/202 +[#203]: https://github.com/bflad/chef-docker/issues/203 +[#205]: https://github.com/bflad/chef-docker/issues/205 +[#206]: https://github.com/bflad/chef-docker/issues/206 +[#208]: https://github.com/bflad/chef-docker/issues/208 +[#217]: https://github.com/bflad/chef-docker/issues/217 +[#219]: https://github.com/bflad/chef-docker/issues/219 +[#220]: https://github.com/bflad/chef-docker/issues/220 +[#221]: https://github.com/bflad/chef-docker/issues/221 +[#223]: https://github.com/bflad/chef-docker/issues/223 +[#224]: https://github.com/bflad/chef-docker/issues/224 +[#232]: https://github.com/bflad/chef-docker/issues/232 +[#233]: https://github.com/bflad/chef-docker/issues/233 +[#234]: https://github.com/bflad/chef-docker/issues/234 +[#237]: https://github.com/bflad/chef-docker/issues/237 +[#238]: https://github.com/bflad/chef-docker/issues/238 +[#239]: https://github.com/bflad/chef-docker/issues/239 +[#240]: https://github.com/bflad/chef-docker/issues/240 +[#242]: https://github.com/bflad/chef-docker/issues/242 +[#244]: https://github.com/bflad/chef-docker/issues/244 +[#245]: https://github.com/bflad/chef-docker/issues/245 +[#246]: https://github.com/bflad/chef-docker/issues/246 +[#250]: https://github.com/bflad/chef-docker/issues/250 +[#258]: https://github.com/bflad/chef-docker/issues/258 +[#259]: https://github.com/bflad/chef-docker/issues/259 +[#260]: https://github.com/bflad/chef-docker/issues/260 +[#263]: https://github.com/bflad/chef-docker/issues/263 +[#264]: https://github.com/bflad/chef-docker/issues/264 +[#265]: https://github.com/bflad/chef-docker/issues/265 +[#266]: https://github.com/bflad/chef-docker/issues/266 +[#267]: https://github.com/bflad/chef-docker/issues/267 +[#268]: https://github.com/bflad/chef-docker/issues/268 +[#269]: https://github.com/bflad/chef-docker/issues/269 +[#276]: https://github.com/bflad/chef-docker/issues/276 +[#279]: https://github.com/bflad/chef-docker/issues/279 +[#280]: https://github.com/bflad/chef-docker/issues/280 +[#281]: https://github.com/bflad/chef-docker/issues/281 +[#284]: https://github.com/bflad/chef-docker/issues/284 +[#285]: https://github.com/bflad/chef-docker/issues/285 +[#287]: https://github.com/bflad/chef-docker/issues/287 +[#289]: https://github.com/bflad/chef-docker/issues/289 +[#292]: https://github.com/bflad/chef-docker/issues/292 +[#296]: https://github.com/bflad/chef-docker/issues/296 +[#297]: https://github.com/bflad/chef-docker/issues/297 +[#298]: https://github.com/bflad/chef-docker/issues/298 +[@jcrobak]: https://github.com/jcrobak +[@wingrunr21]: https://github.com/wingrunr21 diff --git a/chef/cookbooks/docker/CONTRIBUTING.md b/chef/cookbooks/docker/CONTRIBUTING.md new file mode 100644 index 0000000..ef2f2b8 --- /dev/null +++ b/chef/cookbooks/docker/CONTRIBUTING.md @@ -0,0 +1,2 @@ +Please refer to +https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD diff --git a/chef/cookbooks/docker/MAINTAINERS.md b/chef/cookbooks/docker/MAINTAINERS.md new file mode 100644 index 0000000..a7645b9 --- /dev/null +++ b/chef/cookbooks/docker/MAINTAINERS.md @@ -0,0 +1,20 @@ + + +# Maintainers + +This file lists how this cookbook project is maintained. When making changes to the system, this file tells you who needs to review your patch - you need a review from an existing maintainer for the cookbook to provide a :+1: on your pull request. Additionally, you need to not receive a veto from a Lieutenant or the Project Lead. + +Check out [How Cookbooks are Maintained](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/master/CONTRIBUTING.MD) for details on the process and how to become a maintainer or the project lead. + +# Project Maintainer +* [Sean OMeara](https://github.com/someara) + +# Maintainers +* [Jennifer Davis](https://github.com/sigje) +* [Sean OMeara](https://github.com/someara) +* [Tim Smith](https://github.com/tas50) +* [Thom May](https://github.com/thommay) +* [Anthony Scalisi](https://github.com/scalp42) +* [Chase Bolt](https://github.com/chasebolt) +* [Brian Flad](https://github.com/bflad) +* [Tom Duffield](https://github.com/tduffield) diff --git a/chef/cookbooks/docker/README.md b/chef/cookbooks/docker/README.md new file mode 100644 index 0000000..e6ac39b --- /dev/null +++ b/chef/cookbooks/docker/README.md @@ -0,0 +1,1417 @@ +# Docker Cookbook + +[![Build Status](https://travis-ci.org/chef-cookbooks/docker.svg?branch=master)](https://travis-ci.org/chef-cookbooks/docker) +[![Cookbook Version](https://img.shields.io/cookbook/v/docker.svg)](https://supermarket.chef.io/cookbooks/docker) +[![Gitter](https://badges.gitter.im/Join +Chat.svg)](https://gitter.im/someara/chef-docker?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +The Docker Cookbook is a library cookbook that provides custom +resources for use in recipes. + +## Scope + +This cookbook is concerned with the [Docker](http://docker.io) +container engine as distributed by Docker, Inc. It does not address +Docker ecosystem tooling or prerequisite technology such as cgroups or +aufs. + + +## Requirements + +- Chef 12.5.x or higher. Chef 11 is NOT SUPPORTED, please do not open issues about it. +- Ruby 2.1 or higher (preferably, the Chef full-stack installer) +- Network accessible web server hosting the docker binary. +- SELinux permissive/disabled if CentOS [Docker Issue #15498](https://github.com/docker/docker/issues/15498) + +## Platform Support + +The following platforms have been tested with Test Kitchen: You may be +able to get it working on other platforms, with appropriate +configuration of cgroups and storage back ends. + +| | 1.7.1 | 1.8.3 | 1.9.1 | 1.10.3 | 1.11.1 | 1.12.3 | 1.13.0 | +|--------------|:-----:|:------|:-----:|:------:|:------:|:------:|:-------| +| amazon linux | | | | | | | ✔ | +| debian-7 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| debian-8 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| centos-7 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| fedora | | | ✔ | ✔ | ✔ | ✔ | ✔ | +| ubuntu-12.04 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| ubuntu-14.04 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| ubuntu-16.04 | | | | | ✔ | ✔ | ✔ | + + +## Cookbook Dependencies + +- [compat_resource](https://supermarket.chef.io/cookbooks/compat_resource) + +## Usage + +- Add `depends 'docker', '~> 2.0'` to your cookbook's metadata.rb +- Use the resources shipped in cookbook in a recipe, the same way + you'd use core Chef resources (file, template, directory, package, + etc). + +```ruby +docker_service 'default' do + action [:create, :start] +end + +docker_image 'busybox' do + action :pull +end + +docker_container 'an-echo-server' do + repo 'busybox' + port '1234:1234' + command "nc -ll -p 1234 -e /bin/cat" +end +``` + +## Test Cookbooks as Examples + +The cookbooks ran under test-kitchen make excellent usage examples. + +The test recipes are found at: + +```ruby +test/cookbooks/docker_test/ +``` + +## Cgroups, Execution and Storage drivers + +Beginning in chef-docker 1.0, support for LXC execution driver has +been removed in favor of native. Cgroups and storage drivers are now +loosely coupled dependencies and should be configured using other +cookbooks if needed. + +Storage drivers can be selected with the `storage_driver` property on +the `docker_service` resource like this: + +```ruby +docker_service 'default' do + storage_driver 'zfs' +end +``` + +Configuration of the backing storage driver, including kernel module loading, is out of scope for this cookbook. + +## Resources Overview + +- [docker_service](#docker_service): composite resource that uses + docker_installation and docker_service_manager +- [docker_installation](#docker_installation): automatically select an + installation method +- [docker_service_manager](#docker_service_manager): automatically + selects a service manager +- [docker_installation_binary](#docker_installation_binary): copies a + pre-compiled docker binary onto disk +- [docker_installation_script](#docker_installation_script): curl | bash +- [docker_installation_package](#docker_installation_package): package + 'docker-engine' +- [docker_service_manager_execute](#docker_service_manager_execute): + manage docker daemon with Chef +- [docker_service_manager_sysvinit](#docker_service_manager_sysvinit): + manage docker daemon with a sysvinit script +- [docker_service_manager_upstart](#docker_service_manager_upstart): + manage docker daemon with upstart script +- [docker_service_manager_systemd](#docker_service_manager_systemd): + manage docker daemon with systemd unit files +- [docker_image](#docker_image): image/repository operations +- [docker_container](#docker_container): container operations +- [docker_tag](#docker_tag): image tagging operations +- [docker_registry](#docker_registry): registry operations +- [docker_network](#docker_network): network operations +- [docker_volume](#docker_volume): volume operations + +## Getting Started + +Here's a quick example of pulling the latest image and running a +container with exposed ports. + +```ruby +# Pull latest image +docker_image 'nginx' do + tag 'latest' + action :pull + notifies :redeploy, 'docker_container[my_nginx]' +end + +# Run container exposing ports +docker_container 'my_nginx' do + repo 'nginx' + tag 'latest' + port '80:80' + host_name 'www' + domain_name 'computers.biz' + env 'FOO=bar' + volumes [ '/some/local/files/:/etc/nginx/conf.d' ] +end +``` + +You might run a private registry and multiple Docker hosts. + +```ruby +# Login to private registry +docker_registry 'https://registry.computers.biz/' do + username 'shipper' + password 'iloveshipping' + email 'shipper@computers.biz' +end + +# Pull tagged image +docker_image 'registry.computers.biz:443/my_project/my_container' do + tag 'latest' + action :pull + host 'tcp://host-1.computers.biz:2376' +end + +# Run container +docker_container 'crowsnest' do + repo 'registry.computers.biz:443/my_project/my_container' + tag 'latest' + host 'tcp://host-2.computers.biz:2376' + tls_verify true + tls_ca_cert "/path/to/ca.pem" + tls_client_cert "/path/to/cert.pem" + tls_client_key "/path/to/key.pem" + action :run +end +``` + +You can manipulate Docker volumes and networks + +```ruby +docker_network 'my_network' do + subnet '10.9.8.0/24' + gateway '10.9.8.1' +end + +docker_volume 'my_volume' do + action :create +end + +docker_container 'my_container' do + repo 'alpine' + tag '3.1' + command "nc -ll -p 1234 -e /bin/cat" + volumes 'my_volume:/my_data' + network_mode 'my_network' + action :run +end +``` + +See full documentation for each resource and action below for more information. + +## Resources Details +## docker_installation + +The `docker_installation` resource auto-selects one of the below +resources with the provider resolution system. + +### Example + +```ruby +docker_installation 'default' do + action :create +end +``` + +## docker_installation_binary + +The `docker_installation_binary` resource copies the precompiled Go +binary onto the disk. It exists to help run older Docker versions. It +should not be used in production, especially with devicemapper. + +### Example + +```ruby +docker_installation_binary 'default' do + version '1.8.2' + source 'https://my.computers.biz/dist/docker' + checksum '97a3f5924b0b831a310efa8bf0a4c91956cd6387c4a8667d27e2b2dd3da67e4d' + action :create +end +``` + +### Properties + +- `version` - The desired version of docker. Used to calculate source. +- `source` - Path to network accessible Docker binary. Ignores version +- `checksum` - SHA-256 + +## docker_installation_tarball + +The `docker_installation_tarball` resource copies the precompiled Go +binary tarball onto the disk. It exists to help run newer Docker +versions from 1.11.0 onwards. It should not be used in production, +especially with devicemapper. + +### Example + +```ruby +docker_installation_tarball 'default' do + version '1.11.0' + source 'https://my.computers.biz/dist/docker.tgz' + checksum '97a3f5924b0b831a310efa8bf0a4c91956cd6387c4a8667d27e2b2dd3da67e4d' + action :create +end +``` + +### Properties + +- `version` - The desired version of docker. Used to calculate source. +- `source` - Path to network accessible Docker binary tarball. Ignores + version +- `checksum` - SHA-256 + +## docker_installation_script + +The `docker_installation_script` resource runs the script hosted by +Docker, Inc at . It configures package +repositories and installs a dynamically compiled binary. + +### Example + +```ruby +docker_installation_script 'default' do + repo 'main' + script_url 'https://my.computers.biz/dist/scripts/docker.sh' + action :create +end +``` + +### Properties + +- `repo` - One of 'main', 'test', or 'experimental'. Used to calculate + script_url in its absense. Defaults to 'main' +- `script_url` - 'URL of script to pipe into /bin/sh as root. + +## docker_installation_package + +The `docker_installation_package` resource uses the system package +manager to install Docker. It relies on the pre-configuration of the +system's package repositories. The `chef-yum-docker` and +`chef-apt-docker` Supermarket cookbooks are used to do this in +test-kitchen. + +**_This is the recommended production installation method._** + +### Example + +```ruby +docker_installation_package 'default' do + version '1.8.3' + action :create + package_options %q|--force-yes -o Dpkg::Options::='--force-confold' -o Dpkg::Options::='--force-all'| # if Ubuntu for example +end +``` + +### Properties + +- `version` - Used to calculate package_version string +- `package_version` - Manually specify the package version string +- `package_name` - Name of package to install. Defaults to + 'docker-engine' +- `package_options` - Manually specify additional options, like + apt-get directives for example + +## docker_service_manager + +The `docker_service_manager` resource auto-selects a strategy from the +`docker_service_manager_*` group of resources based on platform and +version. The `docker_service` family share a common set of properties. + +### Example + +```ruby +docker_service_manager 'default' do + action :start +end +``` + +## docker_service_manager_execute + +### Example + +```ruby +docker_service_manager_execute 'default' do + action :start +end +``` + +## docker_service_manager_sysvinit + +### Example + +```ruby +docker_service_manager_sysvinit 'default' do + host 'unix:///var/run/docker.sock' + action :stop +end +``` + +## docker_service_manager_upstart + +### Example + +```ruby +docker_service_manager_upstart 'default' do + host ['unix:///var/run/docker.sock', 'tcp://127.0.0.1:2376'] + action :start +end +``` + +## docker_service_manager_systemd + +### Example + +```ruby +docker_service_manager_systemd 'default' do + host ['unix:///var/run/docker.sock', 'tcp://127.0.0.1:2376'] + tls_verify true + tls_ca_cert "/path/to/ca.pem" + tls_server_cert "/path/to/server.pem" + tls_server_key "/path/to/server-key.pem" + tls_client_cert "/path/to/cert.pem" + tls_client_key "/path/to/key.pem" + systemd_opts ["TasksMax=infinity","MountFlags=private"] + action :start +end +``` + +## docker_service + +The `docker_service`: resource is a composite resource that uses +`docker_installation` and `docker_service_manager` resources. + +- The `:create` action uses a `docker_installation` +- The `:delete` action uses a `docker_installation` +- The `:start` action uses a `docker_service_manager` +- The `:stop` action uses a `docker_service_manager` + +The service management strategy for the host platform is dynamically +chosen based on platform, but can be overridden. + +### Example + +```ruby +docker_service 'tls_test:2376' do + host [ "tcp://#{node['ipaddress']}:2376", 'unix:///var/run/docker.sock' ] + tls_verify true + tls_ca_cert '/path/to/ca.pem' + tls_server_cert '/path/to/server.pem' + tls_server_key '/path/to/server-key.pem' + tls_client_cert '/path/to/client.pem' + tls_client_key '/path/to/client-key.pem' + action [:create, :start] +end +``` + +WARNING - When creating multiple `docker_service` resources on the +same machine, you will need to specify unique graph properties to +avoid unexpected behavior and possible data corruption. + +### Properties + +The `docker_service` resource property list mostly corresponds to the +options found in the +[Docker Command Line Reference](https://docs.docker.com/reference/commandline/cli/) + +- `install_method` - Select binary, script, package, tarball, none, or auto. Defaults to `auto`. +- `source` - URL to the pre-compiled Docker binary used for installation. Defaults to a calculated URL based on kernel version, Docker version, and platform arch. By default, this will try to get to "". +- `version` - Docker version to install +- `checksum` - sha256 checksum of Docker binary +- `api_cors_header` - Set CORS headers in the remote API +- `bridge` - Attach containers to a network bridge +- `bip` - Specify network bridge IP +- `debug` - Enable debug mode +- `cluster_store` - Cluster store to use +- `cluster_advertise` - IP and port that this daemon should advertise + to the cluster +- `cluster_store_opts` - Cluster store options +- `daemon` - Enable daemon mode +- `dns` - DNS server(s) to use +- `dns_search` - DNS search domains to use +- `exec_driver` - Exec driver to use +- `fixed_cidr` - IPv4 subnet for fixed IPs +- `fixed_cidr_v6` - IPv6 subnet for fixed IPs +- `group` - Posix group for the unix socket +- `graph` - Root of the Docker runtime - Effectively, the "data + directory" +- `host` - Daemon socket(s) to connect to - `tcp://host:port`, + `unix:///path/to/socket`, `fd://*` or `fd://socketfd` +- `icc` - Enable inter-container communication +- `insecure_registry` - Enable insecure registry communication +- `ip` - Default IP when binding container ports +- `ip_forward` - Enable ip forwarding +- `ipv4_forward` - Enable net.ipv4.ip_forward +- `ipv6_forward` - Enable net.ipv6.ip_forward +- `ip_masq` - Enable IP masquerading +- `iptables` - Enable addition of iptables rules +- `ipv6` - Enable IPv6 networking +- `log_level` - Set the logging level +- `labels` A string or array to set metadata on the daemon in the form ['foo:bar', 'hello:world']` +- `log_driver` - Container's logging driver (json-file/syslog/journald/gelf/fluentd/none) +- `labels` A string or array to set metadata on the daemon in the form ['foo:bar', 'hello:world']` +- `log_driver` - Container's logging driver (json-file/syslog/journald/gelf/fluentd/awslogs/splunk/etwlogs/gcplogs/none) +- `log_opts` - Container's logging driver options (driver-specific) +- `mtu` - Set the containers network MTU +- `pidfile` - Path to use for daemon PID file +- `registry_mirror` - Preferred Docker registry mirror +- `storage_driver` - Storage driver to use +- `selinux_enabled` - Enable selinux support +- `storage_opts` - Set storage driver options +- `tls` - Use TLS; implied by --tlsverify. Defaults to ENV['DOCKER_TLS'] if set +- `tls_verify` - Use TLS and verify the remote. Defaults to ENV['DOCKER_TLS_VERIFY'] if set +- `tls_ca_cert` - Trust certs signed only by this CA. Defaults to ENV['DOCKER_CERT_PATH'] if set +- `tls_server_cert` - Path to TLS certificate file for docker service +- `tls_server_key` - Path to TLS key file for docker service +- `tls_client_cert` - Path to TLS certificate file for docker cli. Defaults to ENV['DOCKER_CERT_PATH'] if set +- `tls_client_key` - Path to TLS key file for docker cli. Defaults to ENV['DOCKER_CERT_PATH'] if set +- `default_ulimit` - Set default ulimit settings for containers +- `http_proxy` - ENV variable set before for Docker daemon starts +- `https_proxy` - ENV variable set before for Docker daemon starts +- `no_proxy` - ENV variable set before for Docker daemon starts +- `tmpdir` - ENV variable set before for Docker daemon starts +- `logfile` - Location of Docker daemon log file +- `userland_proxy`- Enables or disables docker-proxy +- `disable_legacy_registry` - Do not contact legacy registries +- `userns_remap` - Enable user namespace remapping options - + `default`, `uid`, `uid:gid`, `username`, `username:groupname` (see: [Docker User Namespaces](see: https://docs.docker.com/v1.10/engine/reference/commandline/daemon/#daemon-user-namespace-options)) +- `mount_flags` - Set the systemd mount propagation flag. Defaults to slave. + +#### Miscellaneous Options + +- `misc_opts` - Pass the docker daemon any other options bypassing + flag validation, supplied as `--flag=value` + +#### Systemd-specific Options + +- `systemd_opts` - An array of strings that will be included as + individual lines in the systemd service unit for Docker. *Note*: + This option is only relevant for systems where systemd is the + default service manager or where systemd is specified explicitly as + the service manager. + +### Actions + +- `:create` - Lays the Docker bits out on disk +- `:delete` - Removes the Docker bits from the disk +- `:start` - Makes sure the service provider is set up properly and start it +- `:stop` - Stops the service +- `:restart` - Restarts the service + +### `docker_service` implementations + +- `docker_service_execute` - The simplest docker_service. Just starts + a process. Fire and forget. +- `docker_service_sysvinit` - Uses a SystemV init script to manage the + service state. +- `docker_service_upstart` - Uses an Upstart script to manage the + service state. +- `docker_service_systemd` - Uses an Systemd unit file to manage the + service state. NOTE: This does NOT enable systemd socket activation. + +## docker_image + +The `docker_image` is responsible for managing Docker image pulls, +builds, and deletions. It speaks directly to the +[Docker remote API](https://docs.docker.com/reference/api/docker_remote_api_v1.20/). + +### Examples + +- default action, default properties + +```ruby +docker_image 'hello-world' +``` + +- non-default name attribute + +```ruby +docker_image "Tom's container" do + repo 'tduffield/testcontainerd' + action :pull +end +``` + +- pull every time + +```ruby +docker_image 'busybox' do + action :pull +end +``` + +- specify a tag + +```ruby +docker_image 'alpine' do + tag '3.1' +end +``` + +- specify read/write timeouts + +```ruby +docker_image 'alpine' do + read_timeout 60 + write_timeout 60 +end +``` + +```ruby +docker_image 'vbatts/slackware' do + action :remove +end +``` + +- save + +```ruby +docker_image 'save hello-world' do + repo 'hello-world' + destination '/tmp/hello-world.tar' + not_if { ::File.exist?('/tmp/hello-world.tar') } + action :save +end +``` + +- build from a Dockerfile on every chef-client run + +```ruby +docker_image 'image_1' do + tag 'v0.1.0' + source '/src/myproject/container1/Dockerfile' + action :build +end +``` + +- build from a directory, only if image is missing + +```ruby +docker_image 'image_2' do + tag 'v0.1.0' + source '/src/myproject/container2' + action :build_if_missing +end +``` + +- build from a tarball NOTE: this is not an "export" tarball generated + from an an image save. The contents should be a Dockerfile, and + anything it references to COPY or ADD + +```ruby +docker_image 'image_3' do + tag 'v0.1.0' + source '/tmp/image_3.tar' + action :build +end +``` + +```ruby +docker_image 'hello-again' do + tag 'v0.1.0' + source '/tmp/hello-world.tar' + action :import +end +``` + +- push + +```ruby +docker_image 'my.computers.biz:5043/someara/hello-again' do + action :push +end + ``` + +- Connect to an external docker daemon and pull an image + +```ruby +docker_image 'alpine' do + host 'tcp://127.0.0.1:2376' + tag '2.7' +end +``` + +### Properties + +The `docker_image` resource properties mostly corresponds to the +[Docker Remote API](https://docs.docker.com/reference/api/docker_remote_api_v1.20/#2-2-images) +as driven by the +[Swipley docker-api Ruby gem](https://github.com/swipely/docker-api) + + +A `docker_image`'s full identifier is a string in the form +"\:\". There is some nuance around naming using the +public registry vs a private one. + +- `repo` - aka `image_name` - The first half of a Docker image's + identity. This is a string in the form: + `registry:port/owner/image_name`. If the `registry:port` portion is + left off, Docker will implicitly use the Docker public + registry. "Official Images" omit the owner part. This means a repo + id can be as short as `busybox`, `alpine`, or `centos`. These names refer + to official images on the public registry. Names can be as long as + `my.computers.biz:5043/what/ever` to refer to custom images on an + private registry. Often you'll see something like `chef/chef` to + refer to private images on the public registry. - Defaults to + resource name. +- `tag` - The second half of a Docker image's identity. - Defaults to + `latest` +- `source` - Path to input for the `:import`, `:build` and + `:build_if_missing` actions. For building, this can be a Dockerfile, + a tarball containing a Dockerfile in its root, or a directory + containing a Dockerfile. For `:import`, this should be a tarball + containing Docker formatted image, as generated with `:save`. +- `destination` - Path for output from the `:save` action. +- `force` - A force boolean used in various actions - Defaults to + false +- `nocache` - Used in `:build` operations. - Defaults to false +- `noprune` - Used in `:remove` operations - Defaults to false +- `rm` - Remove intermediate containers after a successful build + (default behavior) - Defaults to `true` +- `read_timeout` - May need to increase for long image builds/pulls +- `write_timeout` - May need to increase for long image builds/pulls +- `host` - A string containing the host the API should communicate + with. Defaults to `ENV['DOCKER_HOST']` if set. +- `tls` - Use TLS; implied by --tlsverify. Defaults to + ENV['DOCKER_TLS'] if set. +- `tls_verify` - Use TLS and verify the remote. Defaults to + `ENV['DOCKER_TLS_VERIFY']` if set +- `tls_ca_cert` - Trust certs signed only by this CA. Defaults to + `ENV['DOCKER_CERT_PATH']` if set. +- `tls_client_cert` - Path to TLS certificate file for docker + cli. Defaults to `ENV['DOCKER_CERT_PATH']` if set +- `tls_client_key` - Path to TLS key file for docker cli. Defaults to + `ENV['DOCKER_CERT_PATH']` if set. + +### Actions + +The following actions are available for a `docker_image` +resource. Defaults to `pull_if_missing` + +- `:pull` - Pulls an image from the registry +- `:pull_if_missing` - Pulls an image from the registry, only if it missing +- `:build` - Builds an image from a Dockerfile, directory, or tarball +- `:build_if_missing` - Same build, but only if it is missing +- `:save` - Exports an image to a tarball at `destination` +- `:import` - Imports an image from a tarball at `destination` +- `:remove` - Removes (untags) an image +- `:push` - Pushes an image to the registry + +## docker_tag + +Docker tags work very much like hard links in a Unix filesystem. They +are just references to an existing image. Therefore, the docker_tag +resource has taken inspiration from the Chef `link` resource. + +### Examples + +```ruby +docker_tag 'private repo tag for hello-again:1.0.1' do + target_repo 'hello-again' + target_tag 'v0.1.0' + to_repo 'localhost:5043/someara/hello-again' + to_tag 'latest' + action :tag +end +``` + +### Properties + +- `target_repo` - The repo half of the source image identifier. +- `target_tag` - The tag half of the source image identifier. +- `to_repo` - The repo half of the new image identifier +- `to_tag`- The tag half of the new image identifier + +### Actions + +- `:tag` - Tags the image + +## docker_container + +The `docker_container` is responsible for managing Docker container +actions. It speaks directly to the +[Docker remote API](https://docs.docker.com/reference/api/docker_remote_api_v1.20/). + + +Containers are process oriented, and move through an event +cycle. Thanks to [Glider Labs](http://gliderlabs.com/) for this +excellent +diagram. ![alt tag](http://gliderlabs.com/images/docker_events.png) + + +### Examples + +- Create a container without starting it. + +```ruby +docker_container 'hello-world' do + command '/hello' + action :create +end +``` + +- This will exit succesfully. It will happen on every chef-client run. + +```ruby +docker_container 'busybox_ls' do + repo 'busybox' + command 'ls -la /' + action :run +end +``` + +- The :run action contains both :create and :start the container in one action. Redeploys the container on resource change. It is the default action. + +```ruby +docker_container 'alpine_ls' do + repo 'alpine' + tag '3.1' + command 'ls -la /' + action :run +end +``` + +- Set environment variables in a container + +```ruby +docker_container 'env' do + repo 'debian' + env ['PATH=/usr/bin', 'FOO=bar'] + command 'env' + action :run +end +``` + +- This process remains running between chef-client runs, :run will do nothing on subsequent converges. + +```ruby +docker_container 'an_echo_server' do + repo 'alpine' + tag '3.1' + command 'nc -ll -p 7 -e /bin/cat' + port '7:7' + action :run +end +``` + +- Let docker pick the host port + +```ruby +docker_container 'another_echo_server' do + repo 'alpine' + tag '3.1' + command 'nc -ll -p 7 -e /bin/cat' + port '7' + action :run +end +``` + +- Specify the udp protocol + +```ruby +docker_container 'an_udp_echo_server' do + repo 'alpine' + tag '3.1' + command 'nc -ul -p 7 -e /bin/cat' + port '5007:7/udp' + action :run +end +``` + +- Kill a container + +```ruby +docker_container 'bill' do + action :kill +end +``` + +- Stop a container + +```ruby +docker_container 'hammer_time' do + action :stop +end +``` + +- Force-stop a container after 30 seconds + +```ruby +docker_container 'hammer_time' do + kill_after 30 + action :stop +end +``` + +- Pause a container + +```ruby +docker_container 'red_light' do + action :pause +end +``` + +- Unpause a container + +```ruby +docker_container 'green_light' do + action :unpause +end +``` + +- Restart a container + +```ruby +docker_container 'restarter' do + action :restart +end +``` + +- Delete a container + +```ruby +docker_container 'deleteme' do + remove_volumes true + action :delete +end +``` + +- Redeploy a container + +```ruby +docker_container 'redeployer' do + repo 'alpine' + tag '3.1' + command 'nc -ll -p 7777 -e /bin/cat' + port '7' + action :run +end + +execute 'redeploy redeployer' do + notifies :redeploy, 'docker_container[redeployer]', :immediately + action :run +end +``` + +- Bind mount local directories + +```ruby +docker_container 'bind_mounter' do + repo 'busybox' + command 'ls -la /bits /more-bits' + volumes ['/hostbits:/bits', '/more-hostbits:/more-bits'] + action :run_if_missing +end +``` + +- Mount volumes from another container + +```ruby +docker_container 'chef_container' do + command 'true' + volumes '/opt/chef' + action :create +end + +docker_container 'ohai_debian' do + command '/opt/chef/embedded/bin/ohai platform' + repo 'debian' + volumes_from 'chef_container' +end +``` + +- Set a container's entrypoint + +```ruby +docker_container 'ohai_again_debian' do + repo 'debian' + volumes_from 'chef_container' + entrypoint '/opt/chef/embedded/bin/ohai' + command 'platform' + action :run_if_missing +end +``` + +- Automatically remove a container after it exits + +```ruby +docker_container 'sean_was_here' do + command "touch /opt/chef/sean_was_here-#{Time.new.strftime('%Y%m%d%H%M')}" + repo 'debian' + volumes_from 'chef_container' + autoremove true + action :run +end +``` + +- Grant NET_ADMIN rights to a container + +```ruby +docker_container 'cap_add_net_admin' do + repo 'debian' + command 'bash -c "ip addr add 10.9.8.7/24 brd + dev eth0 label eth0:0 ; ip addr list"' + cap_add 'NET_ADMIN' + action :run_if_missing +end +``` + +- Revoke MKNOD rights to a container + +```ruby +docker_container 'cap_drop_mknod' do + repo 'debian' + command 'bash -c "mknod -m 444 /dev/urandom2 c 1 9 ; ls -la /dev/urandom2"' + cap_drop 'MKNOD' + action :run_if_missing +end +``` + +- Set a container's hostname and domainname + +```ruby +docker_container 'fqdn' do + repo 'debian' + command 'hostname -f' + host_name 'computers' + domain_name 'biz' + action :run_if_missing +end +``` + +- Set a container's DNS resolution + +```ruby +docker_container 'dns' do + repo 'debian' + command 'cat /etc/resolv.conf' + host_name 'computers' + dns ['4.3.2.1', '1.2.3.4'] + dns_search ['computers.biz', 'chef.io'] + action :run_if_missing +end +``` + +- Add extra hosts to a container's `/etc/hosts` + +```ruby +docker_container 'extra_hosts' do + repo 'debian' + command 'cat /etc/hosts' + extra_hosts ['east:4.3.2.1', 'west:1.2.3.4'] + action :run_if_missing +end +``` + +- Manage container's restart_policy + +```ruby +docker_container 'try_try_again' do + repo 'alpine' + tag '3.1' + command 'grep asdasdasd /etc/passwd' + restart_policy 'on-failure' + restart_maximum_retry_count 2 + action :run_if_missing +end + +docker_container 'reboot_survivor' do + repo 'alpine' + tag '3.1' + command 'nc -ll -p 123 -e /bin/cat' + port '123' + restart_policy 'always' + action :run_if_missing +end +``` + +- Manage container links + +```ruby +docker_container 'link_source' do + repo 'alpine' + tag '3.1' + env ['FOO=bar', 'BIZ=baz'] + command 'nc -ll -p 321 -e /bin/cat' + port '321' + action :run_if_missing +end + +docker_container 'link_target_1' do + repo 'alpine' + tag '3.1' + env ['ASD=asd'] + command 'ping -c 1 hello' + links ['link_source:hello'] + action :run_if_missing +end + +docker_container 'link_target_2' do + repo 'alpine' + tag '3.1' + command 'env' + links ['link_source:hello'] + action :run_if_missing +end + +execute 'redeploy_link_source' do + command 'touch /marker_container_redeploy_link_source' + creates '/marker_container_redeploy_link_source' + notifies :redeploy, 'docker_container[link_source]', :immediately + notifies :redeploy, 'docker_container[link_target_1]', :immediately + notifies :redeploy, 'docker_container[link_target_2]', :immediately + action :run +end +``` + +- Mutate a container between chef-client runs + +```ruby +docker_tag 'mutator_from_busybox' do + target_repo 'busybox' + target_tag 'latest' + to_repo 'someara/mutator' + target_tag 'latest' +end + +docker_container 'mutator' do + repo 'someara/mutator' + tag 'latest' + command "sh -c 'touch /mutator-`date +\"%Y-%m-%d_%H-%M-%S\"`'" + outfile '/mutator.tar' + force true + action :run_if_missing +end + +execute 'commit mutator' do + command 'true' + notifies :commit, 'docker_container[mutator]', :immediately + notifies :export, 'docker_container[mutator]', :immediately + notifies :redeploy, 'docker_container[mutator]', :immediately + action :run +end +``` + +- Specify read/write timeouts + +```ruby +docker_container 'api_timeouts' do + repo 'alpine' + read_timeout 60 + write_timeout 60 +end +``` + +- Specify a custom logging driver and its options + +```ruby +docker_container 'syslogger' do + repo 'alpine' + tag '3.1' + command 'nc -ll -p 780 -e /bin/cat' + log_driver 'syslog' + log_opts 'syslog-tag=container-syslogger' +end +``` + +- Connect to an external docker daemon and create a container + +```ruby +docker_container 'external_daemon' do + repo 'alpine' + host 'tcp://1.2.3.4:2376' + action :create +end +``` + +### Properties + +Most `docker_container` properties are the `snake_case` version of the `CamelCase` keys found in the [Docker Remote Api](https://docs.docker.com/reference/api/docker_remote_api_v1.20/) + +- `container_name` - The name of the container. Defaults to the name of the `docker_container` resource. +- `repo` - aka `image_name`. The first half of a the complete identifier for a Docker Image. +- `tag` - The second half of a Docker image's identity. - Defaults to `latest`. +- `command` - The command to run when starting the container. +- `autoremove` - Boolean - Automatically delete a container when it's command exits. Defaults to `false`. +- `volumes` - An array of volume bindings for this container. Each volume binding is a string in one of these forms: `container_path` to create a new volume for the container. `host_path:container_path` to bind-mount a host path into the container. `host_path:container_path:ro` to make the bind-mount read-only inside the container. +- `cap_add` - An array Linux Capabilities (`man 7 capabilities`) to add to grant the container beyond what it normally gets. +- `cap_drop` - An array Linux Capabilities (`man 7 capabilities`) to revoke that the container normally has. +- `cpu_shares` - An integer value containing the CPU Shares for the container. +- `devices` - A Hash of devices to add to the container. +- `dns` - An array of DNS servers the container will use for name resolution. +- `dns_search` - An array of domains the container will search for name resolution. +- `domain_name` - Set's the container's dnsdomainname as returned by the `dnsdomainname` command. +- `entrypoint` - Set the entry point for the container as a string or an array of strings. +- `env` - Set environment variables in the container in the form `['FOO=bar', 'BIZ=baz']` +- `extra_hosts` - An array of hosts to add to the container's `/etc/hosts` in the form `['host_a:10.9.8.7', 'host_b:10.9.8.6']` +- `force` - A boolean to use in container operations that support a `force` option. Defaults to `false` +- `host` - A string containing the host the API should communicate with. Defaults to ENV['DOCKER_HOST'] if set +- `host_name` - The hostname for the container. +- `labels` A string, array, or hash to set metadata on the container in the form ['foo:bar', 'hello:world']` +- `links` - An array of source container/alias pairs to link the container to in the form `[container_a:www', container_b:db']` +- `log_driver` - Sets a custom logging driver for the container (json-file/syslog/journald/gelf/fluentd/none). +- `log_opts` - Configures the above logging driver options (driver-specific). +- `ip_address` - Container IPv4 address (e.g. 172.30.100.104) +- `mac_address` - The mac address for the container to use. +- `memory` - Memory limit in bytes. +- `memory_swap` - Total memory limit (memory + swap); set `-1` to disable swap limit (unlimited). You must use this with memory and make the swap value larger than memory. +- `network_disabled` - Boolean to disable networking. Defaults to `false`. +- `network_mode` - Sets the networking mode for the container. One of `bridge`, `host`, `container`. +- `open_stdin` - Boolean value, opens stdin. Defaults to `false`. +- `outfile` - The path to write the file when using `:export` action. +- `port` - The port configuration to use in the container. Matches the syntax used by the `docker` CLI tool. +- `privileged` - Boolean to start the container in privileged more. Defaults to `false` +- `publish_all_ports` - Allocates a random host port for all of a container's exposed ports. +- `remove_volumes` - A boolean to clean up "dangling" volumes when removing the last container with a reference to it. Default to `false` to match the Docker CLI behavior. +- `restart_policy` - One of `no`, `on-failure`, `unless-stopped`, or `always`. Use `always` if you want a service container to survive a Dockerhost reboot. Defaults to `no`. +- `restart_maximum_retry_count` - Maximum number of restarts to try when `restart_policy` is `on-failure`. Defaults to an ever increasing delay (double the previous delay, starting at 100mS), to prevent flooding the server. +- `running_wait_time` - Amount of seconds `docker_container` wait to determine if a process is running.` +- `security_opts` - A list of string values to customize labels for MLS systems, such as SELinux. +- `signal` - The signal to send when using the `:kill` action. Defaults to `SIGTERM`. +- `sysctls` - A hash of sysctls to set on the container. Defaults to `{}`. +- `tty` - Boolean value to allocate a pseudo-TTY. Defaults to `false`. +- `user` - A string value specifying the user inside the container. +- `volumes` - An Array of paths inside the container to expose. Does the same thing as the `VOLUME` directive in a Dockerfile, but works on container creation. +- `volumes_from` - A list of volumes to inherit from another container. Specified in the form `[:]` +- `volume_driver` - Driver that this container users to mount volumes. +- `working_dir` - A string specifying the working directory for commands to run in. +- `read_timeout` - May need to increase for commits or exports that are slow +- `write_timeout` - May need to increase for commits or exports that are slow +- `kill_after` - Number of seconds to wait before killing the container. Defaults to wait indefinitely; eventually will hit read_timeout limit. +- `timeout` - Seconds to wait for an attached container to return +- `tls` - Use TLS; implied by --tlsverify. Defaults to ENV['DOCKER_TLS'] if set +- `tls_verify` - Use TLS and verify the remote. Defaults to ENV['DOCKER_TLS_VERIFY'] if set +- `tls_ca_cert` - Trust certs signed only by this CA. Defaults to ENV['DOCKER_CERT_PATH'] if set +- `tls_client_cert` - Path to TLS certificate file for docker cli. Defaults to ENV['DOCKER_CERT_PATH'] if set +- `tls_client_key` - Path to TLS key file for docker cli. Defaults to ENV['DOCKER_CERT_PATH'] if set +- `userns_mode` - Modify the user namespace mode - Defaults to `nil`, example option: `host` +- `pid_mode` - Set the PID (Process) Namespace mode for the container. `host`: use the host's PID namespace inside the container. +- `ipc_mode` - Set the IPC mode for the container - Defaults to `nil`, example option: `host` +- `uts_mode` - Set the UTS namespace mode for the container. The UTS namespace is for setting the hostname and the domain that is visible to running processes in that namespace. By default, all containers, including those with `--network=host`, have their own UTS namespace. The host setting will result in the container using the same UTS namespace as the host. Note that --hostname is invalid in host UTS mode. +- `ro_rootfs` - Mount the container's root filesystem as read only. Defaults to `false` + +### Actions + +- `:create` - Creates the container but does not start it. Useful for Volume containers. +- `:start` - Starts the container. Useful for containers that run jobs.. command that exit. +- `:run` - The default action. Both `:create` and `:start` the container in one action. Redeploys the container on resource change. +- `:run_if_missing` - Runs a container only once. +- `:stop` - Stops the container. +- `:restart` - Stops the starts the container. +- `:kill` - Send a signal to the container process. Defaults to `SIGKILL`. +- `:pause` - Pauses the container. +- `:unpause` - Unpauses the container. +- `:delete` - Deletes the container. +- `:redeploy` - Deletes and runs the container. +- `:reload` - Sends SIGHUP to pid 1 in the container + +## docker_registry + +The `docker_registry` resource is responsible for managing the +connection auth information to a Docker registry. + +### docker_registry action :login + +- Log into or register with public registry: + +```ruby +docker_registry 'https://index.docker.io/v1/' do + username 'publicme' + password 'hope_this_is_in_encrypted_databag' + email 'publicme@computers.biz' +end +``` + +Log into private registry with optional port: + +```ruby +docker_registry 'my local registry' do + serveraddress 'https://registry.computers.biz:8443/' + username 'privateme' + password 'still_hope_this_is_in_encrypted_databag' + email 'privateme@computers.biz' +end +``` + +## docker_network + +The `docker_network` resource is responsible for managing Docker named +networks. Usage of `overlay` driver requires the `docker_service` to +be configured to use a distributed key/value store like `etcd`, +`consul`, or `zookeeper`. + +### docker_network action :create + +```ruby +docker_network 'my_network' do + subnet '192.168.88.0/24' + gateway '192.168.88.1' + action :create +end + +docker_container 'echo-base' do + repo 'alpine' + tag '3.1' + command 'nc -ll -p 1337 -e /bin/cat' + port '1337' + network_mode 'my_network' + action :run +end +``` + +### Properties + +- `driver` - The network driver to use. Defaults to `bridge`, other + options include `overlay`. +- `subnet` - Specify the subnet(s) for the network. Ex: + `192.168.0.0/16` +- `gateway` - Specify the gateway(s) for the network. Ex: + `192.168.0.1` +- `ip_range` - Specify a range of IPs to allocate for containers. Ex: + `192.168.1.0/24` +- `aux_address` - Auxillary addresses for the network. Ex: + `['a=192.168.1.5', 'b=192.168.1.6']` +- `container` - Container-id/name to be connected/disconnected to/from + the network. Used only by `:connect` and `:disconnect` actions + + +### Example + +```ruby +docker_network 'network_g' do + driver 'overlay' + subnet ['192.168.0.0/16', '192.170.0.0/16'] + gateway ['192.168.0.100', '192.170.0.100'] + ip_range '192.168.1.0/24' + aux_address ['a=192.168.1.5', 'b=192.168.1.6', 'a=192.170.1.5', 'b=192.170.1.6'] +end +``` + +Connect to multiple networks + +```ruby +docker_network 'network_h1' do + action :create +end + +docker_network 'network_h2' do + action :create +end + +docker_container 'echo-base-networks_h' do + repo 'alpine' + tag '3.1' + command 'nc -ll -p 1337 -e /bin/cat' + port '1337' + network_mode 'network_h1' + action :run +end + +docker_network 'network_h2' do + container 'echo-base-networks_h' + action :connect +end +``` + +### Actions + +- `:create` - create a network +- `:delete` - delete a network +- `:connect` - connect a container to a network +- `:disconnect` - disconnect a container from a network + +## docker_volume + +The `docker_volume` resource is responsible for managing Docker named +volumes. + +### docker_volume action :create + +```ruby +docker_volume 'hello' do + action :create +end + +docker_container 'file_writer' do + repo 'alpine' + tag '3.1' + volumes 'hello:/hello' + command 'touch /hello/sean_was_here' + action :run_if_missing +end +``` + +### Actions + +- `:create` - create a volume +- `:remove` - remove a volume + +## docker_execute + +The `docker_execute` resource allows you to execute commands inside of +a running container. + +### Examples + +```ruby +docker_exec 'touch_it' do + container 'busybox_exec' + command ['touch', '/tmp/onefile'] +end +``` + +### Properties + +- `host` - Daemon socket(s) to connect to - `tcp://host:port`, + `unix:///path/to/socket`, `fd://*` or `fd://socketfd`. +- `command` - A command structured as an Array similar to `CMD` in a + Dockerfile. +- `container` - Name of the container to execute the command in. +- `timeout`- Seconds to wait for an attached container to + return. Defaults to 60 seconds. + +### Actions + +- `:run` - Runs the command + +## Testing and Development + +- Full development and testing workflow with Test Kitchen and friends: + + + + +## Contributing + +Please see contributing information in: + + + + +## Maintainers + +- Sean OMeara ([sean@sean.io](mailto:sean@sean.io)) +- Brian Flad ([bflad417@gmail.com](mailto:bflad417@gmail.com)) +- Tom Duffield () +- Fletcher Nichol ([fnichol@nichol.ca](mailto:fnichol@nichol.ca)) +- Chase Bolt ([chase.bolt@gmail.com](mailto:chase.bolt@gmail.com)) + +## License + +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. diff --git a/chef/cookbooks/docker/files/default/vendor/cache/docker-api-1.33.2.gem b/chef/cookbooks/docker/files/default/vendor/cache/docker-api-1.33.2.gem new file mode 100644 index 0000000000000000000000000000000000000000..3ea1b66252b159f697423012a9b021a2d7ab38b2 GIT binary patch literal 27648 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 literal 0 HcmV?d00001 diff --git a/chef/cookbooks/docker/files/default/vendor/cache/excon-0.54.0.gem b/chef/cookbooks/docker/files/default/vendor/cache/excon-0.54.0.gem new file mode 100644 index 0000000000000000000000000000000000000000..dd686c6f02fadf313345e85288fb03a751f05e28 GIT binary patch literal 236032 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

VRg@gG}>dmf#$Ue;0x=}29{bV|l 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

>JBJ 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

eAkBUTJTHR=;Jl-^qkIwd1 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

p&ovc%+37hrBl5;Am8oNgIt2{M^cOeQ2Fb# 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%0D4^W19MiAN_sO>zF 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

qK%tD$?p`vZ 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 P$a?JGgb~xgcZ{|0*_2C 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 literal 0 HcmV?d00001 diff --git a/chef/cookbooks/docker/files/default/vendor/gems/excon-0.54.0/Gemfile.lock b/chef/cookbooks/docker/files/default/vendor/gems/excon-0.54.0/Gemfile.lock new file mode 100644 index 0000000..80a6583 --- /dev/null +++ b/chef/cookbooks/docker/files/default/vendor/gems/excon-0.54.0/Gemfile.lock @@ -0,0 +1,301 @@ +PATH + remote: . + specs: + excon (0.54.0) + +GEM + remote: http://rubygems.org/ + specs: + activesupport (3.2.6) + i18n (~> 0.6) + multi_json (~> 1.0) + backports (3.6.4) + chronic (0.6.7) + delorean (2.0.0) + chronic + diff-lcs (1.2.5) + eventmachine (1.0.4) + eventmachine (1.0.4-java) + ffi2-generators (0.1.1) + formatador (0.2.3) + i18n (0.6.0) + jruby-openssl (0.9.17-java) + json (1.8.2) + json (1.8.2-java) + kgio (2.9.2) + minitest (4.7.5) + multi_json (1.3.6) + open4 (1.3.0) + puma (3.6.0) + puma (3.6.0-java) + rack (1.6.0) + rack-protection (1.2.0) + rack + rack-test (0.6.3) + rack (>= 1.0) + raindrops (0.13.0) + rake (0.9.2.2) + rdoc (3.12) + json (~> 1.4) + rspec (3.5.0) + rspec-core (~> 3.5.0) + rspec-expectations (~> 3.5.0) + rspec-mocks (~> 3.5.0) + rspec-core (3.5.0) + rspec-support (~> 3.5.0) + rspec-expectations (3.5.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.5.0) + rspec-mocks (3.5.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.5.0) + rspec-support (3.5.0) + rubysl (2.0.14) + rubysl-abbrev (~> 2.0) + rubysl-base64 (~> 2.0) + rubysl-benchmark (~> 2.0) + rubysl-bigdecimal (~> 2.0) + rubysl-cgi (~> 2.0) + rubysl-cgi-session (~> 2.0) + rubysl-cmath (~> 2.0) + rubysl-complex (~> 2.0) + rubysl-continuation (~> 2.0) + rubysl-coverage (~> 2.0) + rubysl-csv (~> 2.0) + rubysl-curses (~> 2.0) + rubysl-date (~> 2.0) + rubysl-delegate (~> 2.0) + rubysl-digest (~> 2.0) + rubysl-drb (~> 2.0) + rubysl-e2mmap (~> 2.0) + rubysl-english (~> 2.0) + rubysl-enumerator (~> 2.0) + rubysl-erb (~> 2.0) + rubysl-etc (~> 2.0) + rubysl-expect (~> 2.0) + rubysl-fcntl (~> 2.0) + rubysl-fiber (~> 2.0) + rubysl-fileutils (~> 2.0) + rubysl-find (~> 2.0) + rubysl-forwardable (~> 2.0) + rubysl-getoptlong (~> 2.0) + rubysl-gserver (~> 2.0) + rubysl-io-console (~> 2.0) + rubysl-io-nonblock (~> 2.0) + rubysl-io-wait (~> 2.0) + rubysl-ipaddr (~> 2.0) + rubysl-irb (~> 2.0) + rubysl-logger (~> 2.0) + rubysl-mathn (~> 2.0) + rubysl-matrix (~> 2.0) + rubysl-mkmf (~> 2.0) + rubysl-monitor (~> 2.0) + rubysl-mutex_m (~> 2.0) + rubysl-net-ftp (~> 2.0) + rubysl-net-http (~> 2.0) + rubysl-net-imap (~> 2.0) + rubysl-net-pop (~> 2.0) + rubysl-net-protocol (~> 2.0) + rubysl-net-smtp (~> 2.0) + rubysl-net-telnet (~> 2.0) + rubysl-nkf (~> 2.0) + rubysl-observer (~> 2.0) + rubysl-open-uri (~> 2.0) + rubysl-open3 (~> 2.0) + rubysl-openssl (~> 2.0) + rubysl-optparse (~> 2.0) + rubysl-ostruct (~> 2.0) + rubysl-pathname (~> 2.0) + rubysl-prettyprint (~> 2.0) + rubysl-prime (~> 2.0) + rubysl-profile (~> 2.0) + rubysl-profiler (~> 2.0) + rubysl-pstore (~> 2.0) + rubysl-pty (~> 2.0) + rubysl-rational (~> 2.0) + rubysl-readline (~> 2.0) + rubysl-resolv (~> 2.0) + rubysl-rexml (~> 2.0) + rubysl-rinda (~> 2.0) + rubysl-rss (~> 2.0) + rubysl-scanf (~> 2.0) + rubysl-securerandom (~> 2.0) + rubysl-set (~> 2.0) + rubysl-shellwords (~> 2.0) + rubysl-singleton (~> 2.0) + rubysl-socket (~> 2.0) + rubysl-stringio (~> 2.0) + rubysl-strscan (~> 2.0) + rubysl-sync (~> 2.0) + rubysl-syslog (~> 2.0) + rubysl-tempfile (~> 2.0) + rubysl-test-unit (~> 2.0) + rubysl-thread (~> 2.0) + rubysl-thwait (~> 2.0) + rubysl-time (~> 2.0) + rubysl-timeout (~> 2.0) + rubysl-tmpdir (~> 2.0) + rubysl-tsort (~> 2.0) + rubysl-un (~> 2.0) + rubysl-uri (~> 2.0) + rubysl-weakref (~> 2.0) + rubysl-webrick (~> 2.0) + rubysl-xmlrpc (~> 2.0) + rubysl-yaml (~> 2.0) + rubysl-zlib (~> 2.0) + rubysl-abbrev (2.0.4) + rubysl-base64 (2.0.0) + rubysl-benchmark (2.0.1) + rubysl-bigdecimal (2.0.2) + rubysl-cgi (2.0.1) + rubysl-cgi-session (2.0.1) + rubysl-cmath (2.0.0) + rubysl-complex (2.0.0) + rubysl-continuation (2.0.0) + rubysl-coverage (2.0.3) + rubysl-csv (2.0.2) + rubysl-english (~> 2.0) + rubysl-curses (2.0.0) + rubysl-date (2.0.6) + rubysl-delegate (2.0.1) + rubysl-digest (2.0.3) + rubysl-drb (2.0.1) + rubysl-e2mmap (2.0.0) + rubysl-english (2.0.0) + rubysl-enumerator (2.0.0) + rubysl-erb (2.0.1) + rubysl-etc (2.0.3) + ffi2-generators (~> 0.1) + rubysl-expect (2.0.0) + rubysl-fcntl (2.0.4) + ffi2-generators (~> 0.1) + rubysl-fiber (2.0.0) + rubysl-fileutils (2.0.3) + rubysl-find (2.0.1) + rubysl-forwardable (2.0.1) + rubysl-getoptlong (2.0.0) + rubysl-gserver (2.0.0) + rubysl-socket (~> 2.0) + rubysl-thread (~> 2.0) + rubysl-io-console (2.0.0) + rubysl-io-nonblock (2.0.0) + rubysl-io-wait (2.0.0) + rubysl-ipaddr (2.0.0) + rubysl-irb (2.0.4) + rubysl-e2mmap (~> 2.0) + rubysl-mathn (~> 2.0) + rubysl-readline (~> 2.0) + rubysl-thread (~> 2.0) + rubysl-logger (2.0.0) + rubysl-mathn (2.0.0) + rubysl-matrix (2.1.0) + rubysl-e2mmap (~> 2.0) + rubysl-mkmf (2.0.1) + rubysl-fileutils (~> 2.0) + rubysl-shellwords (~> 2.0) + rubysl-monitor (2.0.0) + rubysl-mutex_m (2.0.0) + rubysl-net-ftp (2.0.1) + rubysl-net-http (2.0.4) + rubysl-cgi (~> 2.0) + rubysl-erb (~> 2.0) + rubysl-singleton (~> 2.0) + rubysl-net-imap (2.0.1) + rubysl-net-pop (2.0.1) + rubysl-net-protocol (2.0.1) + rubysl-net-smtp (2.0.1) + rubysl-net-telnet (2.0.0) + rubysl-nkf (2.0.1) + rubysl-observer (2.0.0) + rubysl-open-uri (2.0.0) + rubysl-open3 (2.0.0) + rubysl-openssl (2.0.4) + rubysl-optparse (2.0.1) + rubysl-shellwords (~> 2.0) + rubysl-ostruct (2.0.4) + rubysl-pathname (2.0.0) + rubysl-prettyprint (2.0.2) + rubysl-prime (2.0.0) + rubysl-profile (2.0.0) + rubysl-profiler (2.0.1) + rubysl-pstore (2.0.0) + rubysl-pty (2.0.2) + rubysl-rational (2.0.1) + rubysl-readline (2.0.2) + rubysl-resolv (2.0.0) + rubysl-rexml (2.0.2) + rubysl-rinda (2.0.0) + rubysl-rss (2.0.0) + rubysl-scanf (2.0.0) + rubysl-securerandom (2.0.0) + rubysl-set (2.0.1) + rubysl-shellwords (2.0.0) + rubysl-singleton (2.0.0) + rubysl-socket (2.0.1) + rubysl-stringio (2.0.0) + rubysl-strscan (2.0.0) + rubysl-sync (2.0.0) + rubysl-syslog (2.0.1) + ffi2-generators (~> 0.1) + rubysl-tempfile (2.0.1) + rubysl-test-unit (2.0.1) + minitest (~> 4.7) + rubysl-thread (2.0.2) + rubysl-thwait (2.0.0) + rubysl-time (2.0.3) + rubysl-timeout (2.0.0) + rubysl-tmpdir (2.0.0) + rubysl-tsort (2.0.1) + rubysl-un (2.0.0) + rubysl-fileutils (~> 2.0) + rubysl-optparse (~> 2.0) + rubysl-uri (2.0.0) + rubysl-weakref (2.0.0) + rubysl-webrick (2.0.0) + rubysl-xmlrpc (2.0.0) + rubysl-yaml (2.0.3) + rubysl-zlib (2.0.1) + shindo (0.3.4) + formatador (>= 0.1.1) + sinatra (1.3.2) + rack (~> 1.3, >= 1.3.6) + rack-protection (~> 1.2) + tilt (~> 1.3, >= 1.3.3) + sinatra-contrib (1.3.2) + backports (>= 2.0) + eventmachine + rack-protection + rack-test + sinatra (~> 1.3.0) + tilt (~> 1.3) + tilt (1.3.3) + unicorn (4.8.3) + kgio (~> 2.6) + rack + raindrops (~> 0.7) + +PLATFORMS + java + ruby + +DEPENDENCIES + activesupport + delorean + eventmachine (>= 1.0.4) + excon! + jruby-openssl (~> 0.9) + json (>= 1.8.2) + open4 + puma + rack (~> 1.6) + rake + rdoc + rspec (>= 3.5.0) + rubysl (~> 2.0) + shindo + sinatra + sinatra-contrib + unicorn + +BUNDLED WITH + 1.13.1 diff --git a/chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/Makefile b/chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/Makefile new file mode 100644 index 0000000..db374b9 --- /dev/null +++ b/chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/Makefile @@ -0,0 +1,196 @@ + +SHELL = /bin/sh + +# V=0 quiet, V=1 verbose. other values don't work. +V = 0 +Q1 = $(V:1=) +Q = $(Q1:0=@) +ECHO1 = $(V:1=@:) +ECHO = $(ECHO1:0=@echo) +NULLCMD = : + +#### Start of system configuration section. #### + +srcdir = . +topdir = /opt/chefdk/embedded/include/ruby-2.3.0 +hdrdir = $(topdir) +arch_hdrdir = /opt/chefdk/embedded/include/ruby-2.3.0/x86_64-darwin13 +PATH_SEPARATOR = : +VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby +prefix = $(DESTDIR)/opt/chefdk/embedded +rubysitearchprefix = $(rubylibprefix)/$(sitearch) +rubyarchprefix = $(rubylibprefix)/$(arch) +rubylibprefix = $(libdir)/$(RUBY_BASE_NAME) +exec_prefix = $(prefix) +vendorarchhdrdir = $(vendorhdrdir)/$(sitearch) +sitearchhdrdir = $(sitehdrdir)/$(sitearch) +rubyarchhdrdir = $(rubyhdrdir)/$(arch) +vendorhdrdir = $(rubyhdrdir)/vendor_ruby +sitehdrdir = $(rubyhdrdir)/site_ruby +rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME) +vendorarchdir = $(vendorlibdir)/$(sitearch) +vendorlibdir = $(vendordir)/$(ruby_version) +vendordir = $(rubylibprefix)/vendor_ruby +sitearchdir = $(DESTDIR)./.gem.20170131-68034-1687ce7 +sitelibdir = $(DESTDIR)./.gem.20170131-68034-1687ce7 +sitedir = $(rubylibprefix)/site_ruby +rubyarchdir = $(rubylibdir)/$(arch) +rubylibdir = $(rubylibprefix)/$(ruby_version) +sitearchincludedir = $(includedir)/$(sitearch) +archincludedir = $(includedir)/$(arch) +sitearchlibdir = $(libdir)/$(sitearch) +archlibdir = $(libdir)/$(arch) +ridir = $(datarootdir)/$(RI_BASE_NAME) +mandir = $(datarootdir)/man +localedir = $(datarootdir)/locale +libdir = $(exec_prefix)/lib +psdir = $(docdir) +pdfdir = $(docdir) +dvidir = $(docdir) +htmldir = $(docdir) +infodir = $(datarootdir)/info +docdir = $(datarootdir)/doc/$(PACKAGE) +oldincludedir = $(DESTDIR)/usr/include +includedir = $(SDKROOT)$(prefix)/include +localstatedir = $(prefix)/var +sharedstatedir = $(prefix)/com +sysconfdir = $(prefix)/etc +datadir = $(datarootdir) +datarootdir = $(prefix)/share +libexecdir = $(exec_prefix)/libexec +sbindir = $(exec_prefix)/sbin +bindir = $(exec_prefix)/bin +archdir = $(rubyarchdir) + + +CC = clang +CXX = g++ +LIBRUBY = $(LIBRUBY_SO) +LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a +LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME) +LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static -framework CoreFoundation +empty = +OUTFLAG = -o $(empty) +COUTFLAG = -o $(empty) + +RUBY_EXTCONF_H = +cflags = $(optflags) $(debugflags) $(warnflags) +cxxflags = $(optflags) $(debugflags) $(warnflags) +optflags = -O3 -fno-fast-math +debugflags = -ggdb3 +warnflags = -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -diag-disable=2259 -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration -Wdivision-by-zero -Wdeprecated-declarations -Wextra-tokens +CCDLFLAGS = -fno-common +CFLAGS = $(CCDLFLAGS) -I/opt/chefdk/embedded/include -O2 -I/opt/chefdk/embedded/include/ncurses -O3 -g -pipe -Qunused-arguments -fno-common $(ARCH_FLAG) +INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir) +DEFS = +CPPFLAGS = -I/opt/chefdk/embedded/include -O2 -I/opt/chefdk/embedded/include/ncurses -arch x86_64 -m64 -O3 -g -pipe -Qunused-arguments -I/opt/chefdk/embedded/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT $(DEFS) $(cppflags) +CXXFLAGS = $(CCDLFLAGS) -I/opt/chefdk/embedded/include -O2 -I/opt/chefdk/embedded/include/ncurses -O3 -g -pipe -Qunused-arguments $(ARCH_FLAG) +ldflags = -L. -L/opt/chefdk/embedded/lib -fstack-protector -L/opt/chefdk/embedded/lib +dldflags = -Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress -L/opt/chefdk/embedded/lib +ARCH_FLAG = -m64 +DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG) +LDSHARED = $(CC) -dynamic -bundle +LDSHAREDXX = $(CXX) -dynamic -bundle +AR = ar +EXEEXT = + +RUBY_INSTALL_NAME = $(RUBY_BASE_NAME) +RUBY_SO_NAME = ruby.2.3.0 +RUBYW_INSTALL_NAME = +RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version) +RUBYW_BASE_NAME = rubyw +RUBY_BASE_NAME = ruby + +arch = x86_64-darwin13 +sitearch = $(arch) +ruby_version = 2.3.0 +ruby = $(bindir)/$(RUBY_BASE_NAME) +RUBY = $(ruby) +ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/defines.h $(hdrdir)/ruby/missing.h $(hdrdir)/ruby/intern.h $(hdrdir)/ruby/st.h $(hdrdir)/ruby/subst.h $(arch_hdrdir)/ruby/config.h + +RM = rm -f +RM_RF = $(RUBY) -run -e rm -- -rf +RMDIRS = rmdir -p +MAKEDIRS = mkdir -p +INSTALL = /usr/bin/install -c +INSTALL_PROG = $(INSTALL) -m 0755 +INSTALL_DATA = $(INSTALL) -m 644 +COPY = cp +TOUCH = exit > + +#### End of system configuration section. #### + +preload = + +libpath = . $(libdir) /opt/chefdk/embedded/lib +LIBPATH = -L. -L$(libdir) -L/opt/chefdk/embedded/lib +DEFFILE = + +CLEANFILES = mkmf.log +DISTCLEANFILES = +DISTCLEANDIRS = + +extout = +extout_prefix = +target_prefix = +LOCAL_LIBS = +LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl -lobjc +ORIG_SRCS = +SRCS = $(ORIG_SRCS) +OBJS = +HDRS = +TARGET = +TARGET_NAME = +TARGET_ENTRY = Init_$(TARGET_NAME) +DLLIB = +EXTSTATIC = +STATIC_LIB = + +TIMESTAMP_DIR = . +BINDIR = $(bindir) +RUBYCOMMONDIR = $(sitedir)$(target_prefix) +RUBYLIBDIR = $(sitelibdir)$(target_prefix) +RUBYARCHDIR = $(sitearchdir)$(target_prefix) +HDRDIR = $(rubyhdrdir)/ruby$(target_prefix) +ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix) + +TARGET_SO = $(DLLIB) +CLEANLIBS = $(TARGET).bundle +CLEANOBJS = *.o *.bak + +all: Makefile +static: $(STATIC_LIB) install-rb +.PHONY: all install static install-so install-rb +.PHONY: clean clean-so clean-static clean-rb + +clean-static:: +clean-rb-default:: +clean-rb:: +clean-so:: +clean: clean-so clean-static clean-rb-default clean-rb + -$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time + +distclean-rb-default:: +distclean-rb:: +distclean-so:: +distclean-static:: +distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb + -$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log + -$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES) + -$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true + +realclean: distclean +install: install-so install-rb + +install-so: Makefile +install-rb: pre-install-rb install-rb-default +install-rb-default: pre-install-rb-default +pre-install-rb: Makefile +pre-install-rb-default: Makefile +pre-install-rb-default: + @$(NULLCMD) + +site-install: site-install-so site-install-rb +site-install-so: install-so +site-install-rb: install-rb + diff --git a/chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/generator/Makefile b/chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/generator/Makefile new file mode 100644 index 0000000..0e1776b --- /dev/null +++ b/chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/generator/Makefile @@ -0,0 +1,262 @@ + +SHELL = /bin/sh + +# V=0 quiet, V=1 verbose. other values don't work. +V = 0 +Q1 = $(V:1=) +Q = $(Q1:0=@) +ECHO1 = $(V:1=@:) +ECHO = $(ECHO1:0=@echo) +NULLCMD = : + +#### Start of system configuration section. #### + +srcdir = . +topdir = /opt/chefdk/embedded/include/ruby-2.3.0 +hdrdir = $(topdir) +arch_hdrdir = /opt/chefdk/embedded/include/ruby-2.3.0/x86_64-darwin13 +PATH_SEPARATOR = : +VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby +prefix = $(DESTDIR)/opt/chefdk/embedded +rubysitearchprefix = $(rubylibprefix)/$(sitearch) +rubyarchprefix = $(rubylibprefix)/$(arch) +rubylibprefix = $(libdir)/$(RUBY_BASE_NAME) +exec_prefix = $(prefix) +vendorarchhdrdir = $(vendorhdrdir)/$(sitearch) +sitearchhdrdir = $(sitehdrdir)/$(sitearch) +rubyarchhdrdir = $(rubyhdrdir)/$(arch) +vendorhdrdir = $(rubyhdrdir)/vendor_ruby +sitehdrdir = $(rubyhdrdir)/site_ruby +rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME) +vendorarchdir = $(vendorlibdir)/$(sitearch) +vendorlibdir = $(vendordir)/$(ruby_version) +vendordir = $(rubylibprefix)/vendor_ruby +sitearchdir = $(DESTDIR)./.gem.20170131-68034-12q3abg +sitelibdir = $(DESTDIR)./.gem.20170131-68034-12q3abg +sitedir = $(rubylibprefix)/site_ruby +rubyarchdir = $(rubylibdir)/$(arch) +rubylibdir = $(rubylibprefix)/$(ruby_version) +sitearchincludedir = $(includedir)/$(sitearch) +archincludedir = $(includedir)/$(arch) +sitearchlibdir = $(libdir)/$(sitearch) +archlibdir = $(libdir)/$(arch) +ridir = $(datarootdir)/$(RI_BASE_NAME) +mandir = $(datarootdir)/man +localedir = $(datarootdir)/locale +libdir = $(exec_prefix)/lib +psdir = $(docdir) +pdfdir = $(docdir) +dvidir = $(docdir) +htmldir = $(docdir) +infodir = $(datarootdir)/info +docdir = $(datarootdir)/doc/$(PACKAGE) +oldincludedir = $(DESTDIR)/usr/include +includedir = $(SDKROOT)$(prefix)/include +localstatedir = $(prefix)/var +sharedstatedir = $(prefix)/com +sysconfdir = $(prefix)/etc +datadir = $(datarootdir) +datarootdir = $(prefix)/share +libexecdir = $(exec_prefix)/libexec +sbindir = $(exec_prefix)/sbin +bindir = $(exec_prefix)/bin +archdir = $(rubyarchdir) + + +CC = clang +CXX = g++ +LIBRUBY = $(LIBRUBY_SO) +LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a +LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME) +LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static -framework CoreFoundation +empty = +OUTFLAG = -o $(empty) +COUTFLAG = -o $(empty) + +RUBY_EXTCONF_H = +cflags = $(optflags) $(debugflags) $(warnflags) +cxxflags = $(optflags) $(debugflags) $(warnflags) +optflags = -O3 -fno-fast-math +debugflags = -ggdb3 +warnflags = -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -diag-disable=2259 -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration -Wdivision-by-zero -Wdeprecated-declarations -Wextra-tokens +CCDLFLAGS = -fno-common +CFLAGS = $(CCDLFLAGS) -I/opt/chefdk/embedded/include -O2 -I/opt/chefdk/embedded/include/ncurses -O3 -g -pipe -Qunused-arguments -fno-common $(ARCH_FLAG) +INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir) +DEFS = +CPPFLAGS = -DJSON_GENERATOR -I/opt/chefdk/embedded/include -O2 -I/opt/chefdk/embedded/include/ncurses -arch x86_64 -m64 -O3 -g -pipe -Qunused-arguments -I/opt/chefdk/embedded/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT $(DEFS) $(cppflags) +CXXFLAGS = $(CCDLFLAGS) -I/opt/chefdk/embedded/include -O2 -I/opt/chefdk/embedded/include/ncurses -O3 -g -pipe -Qunused-arguments $(ARCH_FLAG) +ldflags = -L. -L/opt/chefdk/embedded/lib -fstack-protector -L/opt/chefdk/embedded/lib +dldflags = -Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress -L/opt/chefdk/embedded/lib +ARCH_FLAG = -m64 +DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG) +LDSHARED = $(CC) -dynamic -bundle +LDSHAREDXX = $(CXX) -dynamic -bundle +AR = ar +EXEEXT = + +RUBY_INSTALL_NAME = $(RUBY_BASE_NAME) +RUBY_SO_NAME = ruby.2.3.0 +RUBYW_INSTALL_NAME = +RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version) +RUBYW_BASE_NAME = rubyw +RUBY_BASE_NAME = ruby + +arch = x86_64-darwin13 +sitearch = $(arch) +ruby_version = 2.3.0 +ruby = $(bindir)/$(RUBY_BASE_NAME) +RUBY = $(ruby) +ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/defines.h $(hdrdir)/ruby/missing.h $(hdrdir)/ruby/intern.h $(hdrdir)/ruby/st.h $(hdrdir)/ruby/subst.h $(arch_hdrdir)/ruby/config.h + +RM = rm -f +RM_RF = $(RUBY) -run -e rm -- -rf +RMDIRS = rmdir -p +MAKEDIRS = mkdir -p +INSTALL = /usr/bin/install -c +INSTALL_PROG = $(INSTALL) -m 0755 +INSTALL_DATA = $(INSTALL) -m 644 +COPY = cp +TOUCH = exit > + +#### End of system configuration section. #### + +preload = + +libpath = . $(libdir) /opt/chefdk/embedded/lib +LIBPATH = -L. -L$(libdir) -L/opt/chefdk/embedded/lib +DEFFILE = + +CLEANFILES = mkmf.log +DISTCLEANFILES = +DISTCLEANDIRS = + +extout = +extout_prefix = +target_prefix = /json/ext +LOCAL_LIBS = +LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl -lobjc +ORIG_SRCS = generator.c +SRCS = $(ORIG_SRCS) +OBJS = generator.o +HDRS = $(srcdir)/generator.h +TARGET = generator +TARGET_NAME = generator +TARGET_ENTRY = Init_$(TARGET_NAME) +DLLIB = $(TARGET).bundle +EXTSTATIC = +STATIC_LIB = + +TIMESTAMP_DIR = . +BINDIR = $(bindir) +RUBYCOMMONDIR = $(sitedir)$(target_prefix) +RUBYLIBDIR = $(sitelibdir)$(target_prefix) +RUBYARCHDIR = $(sitearchdir)$(target_prefix) +HDRDIR = $(rubyhdrdir)/ruby$(target_prefix) +ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix) + +TARGET_SO = $(DLLIB) +CLEANLIBS = $(TARGET).bundle +CLEANOBJS = *.o *.bak + +all: $(DLLIB) +static: $(STATIC_LIB) install-rb +.PHONY: all install static install-so install-rb +.PHONY: clean clean-so clean-static clean-rb + +clean-static:: +clean-rb-default:: +clean-rb:: +clean-so:: +clean: clean-so clean-static clean-rb-default clean-rb + -$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time + +distclean-rb-default:: +distclean-rb:: +distclean-so:: +distclean-static:: +distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb + -$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log + -$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES) + -$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true + +realclean: distclean +install: install-so install-rb + +install-so: $(DLLIB) $(TIMESTAMP_DIR)/.RUBYARCHDIR.-.json.-.ext.time + $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR) +clean-static:: + -$(Q)$(RM) $(STATIC_LIB) +install-rb: pre-install-rb install-rb-default +install-rb-default: pre-install-rb-default +pre-install-rb: Makefile +pre-install-rb-default: Makefile +pre-install-rb-default: + @$(NULLCMD) +$(TIMESTAMP_DIR)/.RUBYARCHDIR.-.json.-.ext.time: + $(Q) $(MAKEDIRS) $(@D) $(RUBYARCHDIR) + $(Q) $(TOUCH) $@ + +site-install: site-install-so site-install-rb +site-install-so: install-so +site-install-rb: install-rb + +.SUFFIXES: .c .m .cc .mm .cxx .cpp .o .S + +.cc.o: + $(ECHO) compiling $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $< + +.cc.S: + $(ECHO) translating $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $< + +.mm.o: + $(ECHO) compiling $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $< + +.mm.S: + $(ECHO) translating $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $< + +.cxx.o: + $(ECHO) compiling $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $< + +.cxx.S: + $(ECHO) translating $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $< + +.cpp.o: + $(ECHO) compiling $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $< + +.cpp.S: + $(ECHO) translating $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $< + +.c.o: + $(ECHO) compiling $(<) + $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $< + +.c.S: + $(ECHO) translating $(<) + $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $< + +.m.o: + $(ECHO) compiling $(<) + $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $< + +.m.S: + $(ECHO) translating $(<) + $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $< + +$(DLLIB): $(OBJS) Makefile + $(ECHO) linking shared-object json/ext/$(DLLIB) + -$(Q)$(RM) $(@) + $(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS) + $(Q) $(POSTLINK) + + + +### +generator.o: generator.c generator.h $(srcdir)/../fbuffer/fbuffer.h diff --git a/chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/generator/generator.bundle b/chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/generator/generator.bundle new file mode 100755 index 0000000000000000000000000000000000000000..58caf84dacda8c113a410bc832f5c4a625c02142 GIT binary patch literal 49508 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 N{&bW1KW=(z{4Y0Bh1>uD literal 0 HcmV?d00001 diff --git a/chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/generator/generator.o b/chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/generator/generator.o new file mode 100644 index 0000000000000000000000000000000000000000..8d72eda80bd9580ae4e63f38f1abdb4f4d5d25c4 GIT binary patch literal 114500 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 + +#### End of system configuration section. #### + +preload = + +libpath = . $(libdir) /opt/chefdk/embedded/lib +LIBPATH = -L. -L$(libdir) -L/opt/chefdk/embedded/lib +DEFFILE = + +CLEANFILES = mkmf.log +DISTCLEANFILES = +DISTCLEANDIRS = + +extout = +extout_prefix = +target_prefix = /json/ext +LOCAL_LIBS = +LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl -lobjc +ORIG_SRCS = parser.c +SRCS = $(ORIG_SRCS) +OBJS = parser.o +HDRS = $(srcdir)/parser.h +TARGET = parser +TARGET_NAME = parser +TARGET_ENTRY = Init_$(TARGET_NAME) +DLLIB = $(TARGET).bundle +EXTSTATIC = +STATIC_LIB = + +TIMESTAMP_DIR = . +BINDIR = $(bindir) +RUBYCOMMONDIR = $(sitedir)$(target_prefix) +RUBYLIBDIR = $(sitelibdir)$(target_prefix) +RUBYARCHDIR = $(sitearchdir)$(target_prefix) +HDRDIR = $(rubyhdrdir)/ruby$(target_prefix) +ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix) + +TARGET_SO = $(DLLIB) +CLEANLIBS = $(TARGET).bundle +CLEANOBJS = *.o *.bak + +all: $(DLLIB) +static: $(STATIC_LIB) install-rb +.PHONY: all install static install-so install-rb +.PHONY: clean clean-so clean-static clean-rb + +clean-static:: +clean-rb-default:: +clean-rb:: +clean-so:: +clean: clean-so clean-static clean-rb-default clean-rb + -$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time + +distclean-rb-default:: +distclean-rb:: +distclean-so:: +distclean-static:: +distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb + -$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log + -$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES) + -$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true + +realclean: distclean +install: install-so install-rb + +install-so: $(DLLIB) $(TIMESTAMP_DIR)/.RUBYARCHDIR.-.json.-.ext.time + $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR) +clean-static:: + -$(Q)$(RM) $(STATIC_LIB) +install-rb: pre-install-rb install-rb-default +install-rb-default: pre-install-rb-default +pre-install-rb: Makefile +pre-install-rb-default: Makefile +pre-install-rb-default: + @$(NULLCMD) +$(TIMESTAMP_DIR)/.RUBYARCHDIR.-.json.-.ext.time: + $(Q) $(MAKEDIRS) $(@D) $(RUBYARCHDIR) + $(Q) $(TOUCH) $@ + +site-install: site-install-so site-install-rb +site-install-so: install-so +site-install-rb: install-rb + +.SUFFIXES: .c .m .cc .mm .cxx .cpp .o .S + +.cc.o: + $(ECHO) compiling $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $< + +.cc.S: + $(ECHO) translating $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $< + +.mm.o: + $(ECHO) compiling $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $< + +.mm.S: + $(ECHO) translating $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $< + +.cxx.o: + $(ECHO) compiling $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $< + +.cxx.S: + $(ECHO) translating $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $< + +.cpp.o: + $(ECHO) compiling $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $< + +.cpp.S: + $(ECHO) translating $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $< + +.c.o: + $(ECHO) compiling $(<) + $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $< + +.c.S: + $(ECHO) translating $(<) + $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $< + +.m.o: + $(ECHO) compiling $(<) + $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $< + +.m.S: + $(ECHO) translating $(<) + $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $< + +$(DLLIB): $(OBJS) Makefile + $(ECHO) linking shared-object json/ext/$(DLLIB) + -$(Q)$(RM) $(@) + $(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS) + $(Q) $(POSTLINK) + + + +### +parser.o: parser.c parser.h $(srcdir)/../fbuffer/fbuffer.h diff --git a/chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/parser/parser.bundle b/chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/parser/parser.bundle new file mode 100755 index 0000000000000000000000000000000000000000..49a099e537dfa9a3bbdd7dfa4289c495e499949e GIT binary patch literal 32908 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 literal 0 HcmV?d00001 diff --git a/chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/parser/parser.o b/chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/ext/json/ext/parser/parser.o new file mode 100644 index 0000000000000000000000000000000000000000..3dfeb765306e081097c6c21e3c452869d7c4cef9 GIT binary patch literal 54384 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 N{&bW1KW=(z{4Y0Bh1>uD literal 0 HcmV?d00001 diff --git a/chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/lib/json/ext/parser.bundle b/chef/cookbooks/docker/files/default/vendor/gems/json-2.0.3/lib/json/ext/parser.bundle new file mode 100755 index 0000000000000000000000000000000000000000..49a099e537dfa9a3bbdd7dfa4289c495e499949e GIT binary patch literal 32908 zcmeHw3wTu3_3sHJ5Fl_OqDDm-5fo7JfM62^NtDPLnL&Jj+@cO4nV3i(FqsjkQi3xn z9LDh-{}bB`YDRbbzRx~ z>jWwJGA9`-jG zyJXqYWK5Wof{@Aj684ckSGBu#iQ5B-RDDfXN<9Zy31Ku#;`c54DjMn=6BSO?x5Oc{ zX0txRN%c)=7AcpjqS5QAslS=&srs6nl99$nnb=g5WGjd+m#=p7-AQyq;r%5VOtKl4q1*yXyp!K?$3Q|-%UdvZ7r;Z%K-m?!hsmj9pZ8^`*ZxL*ld z^-+DNB1rvgaUQ}}eHK+B>2fV}vKjX41X)oQa-5%x@3cuw^|b05ttd@GbfH{lG7-<0qT;#`I3E+BrBYF-FKDb$ z90q;?aXKoscBrBZL7JObxff{)RL*?}g$T#`Em^84?xQfz1dYmRs~)!W@jHu$uK($O zonE@*pJ$8#Et}-C28%Gk#6-g{3xV3jv{mWf4~u9&C9h$LH?N}FT~)a_&t133U0La_ z%&V?&RG3+{zWerk*0J9%UC=Ax+8iHG0f^*RE*vy6bW;OXQN}C+B+~ zT9WfMEV`v4x73?RLP6DHa8NZa`?@uN1X{$-wmy+~`BsCFfuOz)pq~NqC1!qb(94N*Dp?KOxNva~P zp;Io!S^lXQeugI5&60hMWIqItYrziVLdmOQM{2a#xr6b(wzJEdsIB6ksXCJxK&J=2OJA`Qjqe#7-%52{HAIsZw;BMf7zN6(;^dirS>; zIZ|}AMf3?06>a2^q8UY=;xTh?eq}BSRzF$q-doSbz4Mtk*MgVGAXJ_QM(kq(jxi?5+#?SafTF~C`EIn zXr4uMOG}h1Q?adDmjDf1l>#LXeCrMaHd; zV599>8xal@VS7mq(iGDeq?qO(V!Db5Eo9fPn6K%(7nI&~<5qRl4Ay^r>AceGuGRb> zXWR8%cKu8JD=b_eVU#-bLq>ZZW!rA|Pgm6D5zql!KBY+=a_)A7%DM`|`nwK&zfnX+ z_*Zsi`li~q&m32YLQA*L)W~^?rR;rZ!vZrGl_+?vAZ&CBtut-vxC}c6O{sd)%%aGf zXhO)&hmi3C1T=lC7F^kde18GyX;M`X*7P@wb;SJbAuN2}$wESZ$GC$t9NH@AW7|)m zlCfkQ%9XJl0;T%Qana$hOV}69q!h%c)X!m|F*m8y>B*&zNR)cES!!0Crv5anwuVu_ zg+lFxtoC=L_J}aStc(GYr83VDQ&uLf_AhZ-Ty3FHi-s50jwH2@B&oeSS#4EZg?F@R z?M+1U?>VI2(}BqwSFJ?{Q&*AdKcjNG70W4P83rcS&y{Xi7BSv<{BwG7}MOZnWz)FBAex}f$F+5KHtEBe_y((#aORPWI z_Ojiwt)|?9o2XHG0adF=Q3DT)u{b}|5nPzP~o}uw70a-&`m(`MQXrl+R~-A?(`oXtomtY(860r>)>|icj%uRMOc)vLOYvdYG4=yL|um>;n2Ia zSSM~LiTg?EI#q3d)!#Ez4ZMnpLuOp)@3E%e|JCijz0rNKE{P|Tk<Clh1RQ-o1cnkf9(U$Fy*8JiAN%HpM=hVP2!BJZ?Q3IH%g-WPB=aHzR_y8zs zpaTM>YU@CM_XOYh_SklZepnsV1S0D7inI7@?|c+B&>p%f4HDj{zdO%+D#T!juQR$l z$v(XsCW`KE&PE$XGtt86Df9|aLNq2kB3gF!>aex zhZrOUVW-}0(Bmu;-bI&J>GC37w$o(`U7o>27*DqZF%fc*8xvtTa>0b?2D&^@)iUx( zEcUl=PE0U$O+OBurtFdvWJ7OtG0U^c9gSw?A1!@6d3uvQ7XMguvWIxIAHx#&5_;Cy zh=-lj(akaMfEy!o&L@;{0o?{f@1KEn4!u7D^u+w*^CWgy!Ap!CLcwh|BP&7V`kvMC&={dxY|} zB42z_e=mAki`w4h?-{akjK3#S%H6e!w9vxLwQ8G zb|jd!YV#A4*`Jvk6U;`n`CelBx26m0U;s0R_z%0)<`qEp?E|O@Bd_9R3rqPoCA4_d z<~gJ#QGRKH=~J606Vty{l#hWlhMBU6Q-M$fMwJq&PcGss)R?PSuQq=o>u*-^odmNA z^_NVuiX91N4eBqMqKas_jR_{y-Yc0I+&F6zOypc4nFE-4OM>ZDn{NPegcc9PO`-S$ zHQ*FX+`pXY%@u0%G+^waFT{+v?IbinFyrhCXdn!TtV4sA;{Kr7Vq>$s9WMyk_2-?1S=>(n{8PmAT}HnsT_+Sp;U_@i!yx$=YN@tka!v4FBla~rL9qLu@9!-BSPeV_z->F&p?~TO z)us9NM|1o=E7d^RFy2D#@E`7{`l;dU`hV;pA6emB8(AG!^Z~M}fu+D|>oAl=yG3}p zKG$&kF8)#tTu+?#VOnTj8rfmM4)32KLV8|`6oV@&Ki-z8{CX5FD!)K&z8h(W?h9j7 zU?+qT+6;mg%D4b?jdo|2^&k5xrxLnathi1zMvG_+8cuR(qi=)=nQ^&jj+;mq`qJDl zV{`i%=o@^ef>%XEr~adVQtCtq#;3TcPFatiw^8skBc0stQ12+n6qX(&L3aEUZ>Dae-VQi!89s0f* z!Ll}ERd+0g;~MIq2Fj`6(3BbIB8+!zR>Rmu*!`68u%mDQhVsenAk6rt}DYx>J&XZdf6;{Mb^EJw13C;#(Vg3NTYUT z3T~+AVce0MZ>M`3dYIZ*9A4fEB!Zhi_B^PhcpfA*H`r6TCCT=x#!GI+>XJ5pjMwgw;l# zU&v1(&o5PKJGywt%0_=TPJ(Z*ninbKtk@DjObwh)Cd=K>d15#8hB^vk&L05puzfpB%~uwi@RJzMOc^3*%u0f)9_VJfqGu%|0RX3#;AZ`_@L z>(az7?*eazzh|OvoZY`&+$%A)A0@@>RG3W$VA&o-C(kuM0XdpYdO`R1V7s>(6iZWh zoiIn$clvkQPPz?3@QxE ziQcpP-T9ag-V2*Lu&L}Q*n#B;*yD`cL!A*SODoucfr`})P;Je|;^(tzG3+q+cxSH5 z6cu?Dxq2|=pHuH}K`NR@qhp609qJkfSriLnf_P8m3_F0S=cDjCAe%#f&oMqqo#_m& znh#$c_7o^g?D*}$RpR85MfWLt@G9()qi}#xdU`uFE5?K~sO7fX^;MbnpbEcJjy(vU zl)e)_YKMMM8^3KX#u4g!k(~q0Cqw-QRHJQHnK8%@HD%AJ?K}#gk3luX`#Y1wc;1N zUuwmFzjdT2TzX`TWo8!a{7HUWdL~A{aHnm?F$_ns<(ci6go@$Ifg$<;dkjsrS8Lv( zg-T;~b;k2J^l9W;yHPsVFebI}Z%Ava(T-)@jvJuE9xM}fXE}pqIS#$9tsoYiU=OZT zL?ddtGi>ZdDY#!?7MEp03L~owcCE}NX@|ZAcU)?h@keHbuA2x)5x_1#a-SZ?($#Y-k{MUTl}IL z*bkt#;#P#iaih4e7KaXWCl{sr!( zxPRZLrS*_MK$Bbbd?6>c>c!&jJ&F|J?k&n3PF&%2q=(n?uKhEz`MX|>i}$peCLZD`M))|Lug0-JaO9L2%jClU#kHP8xY==?}$7M39)Qq{ly*Q z9#Xx%tP}fG+|RJ`{%JiwU)6;@;JB_EYm5ZJU zN94cG60^6<5iIL`8utU-5R4$0j$(J48puU%jQTd5iLgGjt+VX)u7S&DG&Xmrfree5 zM!P<&`*JiK{F168M#BOz8a@Cae#qGkz}q&=+qyP!%K0FAn*T6PIdm&9w|uJqF^CES za7Up!(O7F@z(FU4v@iUJM=$$6{I`#Zag()9OM5l8S7-{A z$QJnWi+Br^h!%Jc1kGR8*57dnwe0HzgD{6@#mhA8sfNCHqd~L&p4E}x3pvz8xU=Oj zT2H!; zO-=vdOz(Aggyo}~XK>107Lj>E1W#(FYzC8_#F4+SgsAf2<4CZ64VFDPjE@#1FbV?V z9`$_WMGQ8qlkfosr(H+|gr)?rv=)SebHm0&QWTsvLeguQ-e#NvI%S%G4QF&LrEJDD zk`-?Dw{fpTHw}RJQwLGq=;aVI&WiJ&k^KFqg8wrNJaWSu#tIzdjc#(S2qo*KPzMRU zD`tpY-)&q+LVu47HIh*51r+u(lG{&(?W$@y_2XDfIYGhH^^?!OyUwXx_QvRU&-350 zH~7i7%Xt**(Q)fMjyi7YrG4{{p=;bxY&Grlz~+Y$?m0oh)b%GUA;+uJ2^&fe$6}jK zP%w3!((~PQnzFSg$cEnPVwPu>I~vW(KU(^D^7JNqEdH_RWDoI55KlTm;dpgDVJY_` zxPuCSe{+I@sY}5|=y-MB02?-9-d=iwf~jjJ=Ja>fY0CCsZTzlz{yTDJc~%`qqgnY! zOPhJ##JYAgzLjRmT4~nwvG~WLQ(ofjM!fh0h2z!riKSc{(o)AY^6Kl8ftUu+sM^*9f;!n zoz`%4w#9$z3@wAN77t4vk{WR~^Z6!#ipMdawg_rFs3ohW2uC1!0ZSvaR}}tl;hMIo zcdP{gFK8emjQCV-ejoe4$W)S|XR$MHAC~@*5Y156+(@FKW$B`TivZy369uU80?v#S z9X0D{nKeUX?RSi<-=OGkm-->7@JtSH7JsG&UIrkCCsk{(S!xugd|~UUZ0i80enh?F zJUVQxp@Q`zk<$T^pYN<2AadP+=K^?r0p}vMc|8(%vT^H7duZl2)DMWiLX3wVV_!sH zMs9;gn0iTx!cj^BPJO>4=nhAnZFB;alux4{3ltsi(6>g0!j0L6Y)bTuHY9OEX@fUI ziDtFo1g1nY+HevzGmKL{gif!EZv^o0%((m^P+l>`o|YmcA_ zK*<0l-4+O|Yd@j3>)4yF4ce)7>_fCm>)4Oz!0P?V*I=zaqU=VN=0Q;92wgq^MQ>Ku zY(Z0E4rclf-=H?rI96L{4fG%Op&6gSlQ+>Qc+m_}b~wFTXJwL&=LB}Ne-l%b<#W{5 zYX^~$qXVx=%B5;+<6uyxo>vlxNzw%%4Y>klo>vwKOHxjfq5sr6K1{a{>UO{b)3Il; z`ef%=*nyr5V4S5XtM|v~;lm)b;npEIv}yVQhyF@*7GOpjnE{&K(Gkg7y<-pBV6F3Y zLIeDJr?1}8BnbcT@0mVSB+GVbA>Zpy(-@49kAifNN`LpNWm#*>UMFs(lo-=u7>vs% z3stLkgoU2h6MFt3^w2nroJQiIDR2Wp zwJ+7+U5SGJDGH+55_ue#ZDp@dkIbWyqi>DBUn3qM-QXSOD8@V43(`EFMIMGIyx5NM zTW%d@*S|r_8arUDL;nn2k0%|Mr-_~oX&e2APhWN}9{XZ!AjdYXBKVbnji z2Z?8qh~{IB_RRqL1EJAKJW7evk$9LA*+{fdVjvPa5<)*T4QNOvdv4b)ol0tUFg>dKLVOTr9M7y-oF%E|wBUaNUn-iSgV!g# zq)U$W#}e}J(I0Z?M~rbGi6Uq`<8K5K&jw;+w_t&djeSmBw~1?~xb76!7sd5uaqSY< z*TnU8aor`ZyT$cQaeYf%-x1e6;<`^<-xt^Y;%bQNN8G^ML zY`3`fi0jwldPH0mjHTGve&U)gt^>q1Q(Om&YnHeU6W45U9WJgT#Pw8h%@Nl##C4>& zo-M96TpgjaR%2-|y*4&>DdLuDw4@T*k6x{Y6IF@4MXB>B^%|w7QL2+tb12nLsX9vi znNoL9>QPGloKhPo^%SM>4pC}3rOw0%iPTeywhj>*U)A#{^?gb; zP-+gPXrmIjf>MuAYAU6|l$u1Tzf)=)r3^})O{uRaHG)#vm_w1llscDE3ZLBj; z)mKyMV@g#~Y9FP3NU7bF`Z1+mrqo7CJx8f0DfKj^UZT`yO1(p=-%#q`l=?ZP24K;R z{FqW_QEDxv@+tL0N@JVEsYKJc@+(Hbq)2(mDgT1TPed=(&m(V8u1k}!WUmGL7B(XU{Yqg8@>1vm?YKI z*LZ8nYioYsR+dmUrLn>1scRAf6nXRG9HWo!SB4dM%YE5$i>w_{90rN(oI|=-jOTFN#Id9v`+D3Rer#2JoW2(5Yk|HN z=xc$#7U*k%z82_ffxZ^#Yk|HN=xc%hfh};-IpY=Y8hUFuUJ=#@9?`8;ZySPST*f7on~n*vN4v9lbXvtD_rh+uV;nQ zqAbl%(CXdGh*Fe9aaEKrDJODCg1p4nSWP62NsSdXHARbRywFMaH-XilI01S z%iG|pTvSWcrZh>WqJ$-tF7}H3fc$0^B(v6(al=jLb_u$x3Jxe@wj?u!FAd-9r&b1c zeKNPs?X7O8B*ummMnk2qRl9qR=dhQ z?kbW#kVI^hCUskhRSj?y!p{idrhc*;ga)=?Ez@c$C&5!lQY|K>-s|?%Pa@KKCM_xV zR!@?SOi(v4HD2pYCc(YbSK|>zZ)Q>>9E>pf=0;N2W)i&~*CJn)*%)C9xuRS&TBnuN zP=70pZ_?0Zp;!8r5NWrCgeHgSMBQVddfbiV7zWiyP%&3rx0cuX1pNThecq~~q^Z;` z82DnnYk8H&Eo7VeQ)3EJU1AWY5=Ha1B&g^M8t}4J`wuU1)w$~`mWXv=13}EC`ieTL zkocv!>~LATgfH8pWcOFXYggDSz}Bqmt7U{Uind9Js1~ zn)1_wE%S*_ez06z$d^jLfp{=6#)9bsS^>!tSCSut0H10c&j!(oNnZ(GU#8#LkRyF2 z{vL2Zvc%QYw~%RsNuL#yz74EzHtRF7ncrIe(d@C|k51{gi1VA+%)c3Q`Vpr5R!rr0 zjTUTWDd#t_nZHD`PG(6dtd5vKfBO!>Ps!B%#1 zeiNJddA7v!oA~dLKM$da{lqt1KYkeZFz#mD9}i)PuUsSLPhy`W?#*Z*AVZ4*E#`qn^a~P-LNj2%4&p4a$ zLdKIBS2HeQyo53Rc{1f+&UhK)CdT(OUd#9y#x0EL`90-d&-gRO8yM5`bmDJfJPQ3z zcr)WkjN2H`WgKSgX57hmE#of6_c7kh_-V#_7;j~4Fy7Dj0ONyIG^!jjEfl4H#eyK62>&%E9t_&x4|C4Yuw z?*YQ7pE>`2#n_yGzhkU$e>}xFlW`~GY{mxT9LAqAwlO{lWm9?M7>{I}&v-iHBF0xS zE@A9ptTFx(<2j6f%XmKHHpUAX|BG=oV}tP$#zSBm*|(hWD8@~UFJruxv72!VV=v?N zjPGN-fiZnjhxBh^yq)o8#&0riWBd){Fyo?TM7=PV0uwn{)1uo(Mv~GOdt5L;*J#jQVM=I z1%Hx)>18GPPnMU3p0?uCQ}CD+oS%ZHr(k;uo|}RzQgCAmUX_AdQt;1H@b6ME{fVx% zJ};!;w^MK=1s_Vm^lFt=->DKqO8!Qr;PoK?4B>u+2N38*wFeO%LfC-tON3t`JdCgr z;nxViL3jjV6T)v1XpBFG@HoOB5H=(H5#dh=Paymm;V%fS2u~ukA<%1ZG#CDg@Hd2K z5ZV!*MF=BwAZ$U{itrr5^9b7zwjB;nn)*{RLM}frv&ZWjwwNoyQBn)JEKfwx}gXk z)Bhxx-*P-zs8)}Yh0LxdD@FR4zC~f@644WGM1c}cL;;grP9}wXO=eoUTL_unC6SK1 zl>}mc5~Y(JNkmC_kP?VoM{#8OjN$~dpV>=9bm?Q6Br;k2Lc~f~=wVL~Q4=m8fh@is z6O+>?o;JNbCV|{MW}5vwCS=DB!-PkN2+6J-cGw6XPO|eR2~n+tXD9Bii92S#<>k$r zi?T}L=i$GF6;LFk+b2)H%IL|hQ2y_iC5y~$NL~b(>Zw&+74#k^ zJEUBV(oIXw(cHY;+`KAy^Qx$-GS01r{2cN6CWcG=&CEDWs7;9QyP7Uh0{K1_nUuXH zsc0_p;Yo(b&)z#Lgy%!ttWjK*H8;bHCft0DoR`fKZgE!~DUTbXxZIK}UHdL~ z(krIc)iF0d5AcpC7C*S!71!nTvS}|;xdr(UjK3h+t274W<;kzD_L`+oan-mIFSF9i ztuD+Ui$C!w*5?*nl$;Iq=`BYQVbx~9BQ+pArZMU9hQ1MaP$$*64&?zf4Tg?r7xm8VyVdzBT{PI~dU*DRvu zcs=<$jG;nN-;}qQdn=$&)>zzzdKqzrqN?HvNUvH&O>5m%-p1;hD(|tEulSnOw@%^7 uNqjZyTc@xC@ZxD?{JsC)MqJ-Im3Uxvv>VLizIE!`n}*!NlywT{$o~yhX13J; literal 0 HcmV?d00001 diff --git a/chef/cookbooks/docker/libraries/_autoload.rb b/chef/cookbooks/docker/libraries/_autoload.rb new file mode 100644 index 0000000..3c007fd --- /dev/null +++ b/chef/cookbooks/docker/libraries/_autoload.rb @@ -0,0 +1,13 @@ +begin + gem 'docker-api', '= 1.33.2' +rescue LoadError + unless defined?(ChefSpec) + run_context = Chef::RunContext.new(Chef::Node.new, {}, Chef::EventDispatch::Dispatcher.new) + + require 'chef/resource/chef_gem' + + docker = Chef::Resource::ChefGem.new('docker-api', run_context) + docker.version '= 1.33.2' + docker.run_action(:install) + end +end diff --git a/chef/cookbooks/docker/libraries/docker_base.rb b/chef/cookbooks/docker/libraries/docker_base.rb new file mode 100644 index 0000000..b7cd1a6 --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_base.rb @@ -0,0 +1,90 @@ +module DockerCookbook + class DockerBase < Chef::Resource + require_relative 'helpers_auth' + require_relative 'helpers_base' + + include DockerHelpers::Base + + ######### + # Classes + ######### + + class UnorderedArray < Array + def ==(other) + # If I (desired env) am a subset of the current env, let == return true + other.is_a?(Array) && all? { |val| other.include?(val) } + end + end + + class ShellCommandString < String + def ==(other) + other.is_a?(String) && Shellwords.shellwords(self) == Shellwords.shellwords(other) + end + end + + class PartialHash < Hash + def ==(other) + other.is_a?(Hash) && all? { |key, val| other.key?(key) && other[key] == val } + end + end + + ################ + # Type Constants + # + # These will be used when declaring resource property types in the + # docker_service, docker_container, and docker_image resource. + # + ################ + + ArrayType = property_type( + is: [Array, nil], + coerce: proc { |v| v.nil? ? nil : Array(v) } + ) unless defined?(ArrayType) + + Boolean = property_type( + is: [true, false], + default: false + ) unless defined?(Boolean) + + NonEmptyArray = property_type( + is: [Array, nil], + coerce: proc { |v| Array(v).empty? ? nil : Array(v) } + ) unless defined?(NonEmptyArray) + + ShellCommand = property_type( + is: [String], + coerce: proc { |v| coerce_shell_command(v) } + ) unless defined?(ShellCommand) + + UnorderedArrayType = property_type( + is: [UnorderedArray, nil], + coerce: proc { |v| v.nil? ? nil : UnorderedArray.new(Array(v)) } + ) unless defined?(UnorderedArrayType) + + PartialHashType = property_type( + is: [PartialHash, nil], + coerce: proc { |v| v.nil? ? nil : PartialHash[v] } + ) unless defined?(PartialHashType) + + ##################### + # Resource properties + ##################### + + property :api_retries, Integer, default: 3, desired_state: false + property :read_timeout, [Integer, nil], default: 60, desired_state: false + property :write_timeout, [Integer, nil], desired_state: false + property :running_wait_time, [Integer, nil], default: 20, desired_state: false + + property :tls, [Boolean, nil], default: lazy { default_tls }, desired_state: false + property :tls_verify, [Boolean, nil], default: lazy { default_tls_verify }, desired_state: false + property :tls_ca_cert, [String, nil], default: lazy { default_tls_cert_path('ca') }, desired_state: false + property :tls_server_cert, [String, nil], desired_state: false + property :tls_server_key, [String, nil], desired_state: false + property :tls_client_cert, [String, nil], default: lazy { default_tls_cert_path('cert') }, desired_state: false + property :tls_client_key, [String, nil], default: lazy { default_tls_cert_path('key') }, desired_state: false + + declare_action_class.class_eval do + include DockerHelpers::Authentication + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_container.rb b/chef/cookbooks/docker/libraries/docker_container.rb new file mode 100644 index 0000000..1a8f0a6 --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_container.rb @@ -0,0 +1,437 @@ +module DockerCookbook + class DockerContainer < DockerBase + require 'docker' + require 'shellwords' + require_relative 'helpers_container' + + include DockerHelpers::Container + + resource_name :docker_container + + ########################################################### + # In Chef 12.5 and later, we no longer have to use separate + # classes for resource and providers. Instead, we have + # everything in a single class. + # + # For the purposes of my own sanity, I'm going to place all the + # "resource" related bits at the top of the files, and the + # providerish bits at the bottom. + # + # + # Methods for default values and coersion are found in + # helpers_container.rb + ########################################################### + + # ~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ + # Begin classic Chef "resource" section + # ~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ + + # The non-standard types Boolean, ArrayType, ShellCommand, etc + # are found in the DockerBase class. + property :container_name, String, name_property: true + property :repo, String, default: lazy { container_name } + property :tag, String, default: 'latest' + property :command, ShellCommand + property :attach_stderr, Boolean, default: false, desired_state: false + property :attach_stdin, Boolean, default: false, desired_state: false + property :attach_stdout, Boolean, default: false, desired_state: false + property :autoremove, Boolean, desired_state: false + property :cap_add, NonEmptyArray + property :cap_drop, NonEmptyArray + property :cgroup_parent, String, default: '' + property :cpu_shares, [Integer, nil], default: 0 + property :cpuset_cpus, String, default: '' + property :detach, Boolean, default: true, desired_state: false + property :devices, Array, default: [] + property :dns, Array, default: [] + property :dns_search, Array, default: [] + property :domain_name, String, default: '' + property :entrypoint, ShellCommand + property :env, UnorderedArrayType, default: [] + property :extra_hosts, NonEmptyArray + property :exposed_ports, PartialHashType, default: {} + property :force, Boolean, desired_state: false + property :host, [String, nil], default: lazy { default_host }, desired_state: false + property :hostname, String + property :ipc_mode, String, default: '' + property :labels, [String, Array, Hash], default: {}, coerce: proc { |v| coerce_labels(v) } + property :links, UnorderedArrayType, coerce: proc { |v| coerce_links(v) } + property :log_driver, %w( json-file syslog journald gelf fluentd awslogs splunk etwlogs gcplogs none ), default: 'json-file', desired_state: false + property :log_opts, [Hash, nil], coerce: proc { |v| coerce_log_opts(v) }, desired_state: false + property :ip_address, String + property :mac_address, String + property :memory, Integer, default: 0 + property :memory_swap, Integer, default: 0 + property :network_disabled, Boolean, default: false + property :network_mode, [String, NilClass], default: 'bridge' + property :open_stdin, Boolean, default: false, desired_state: false + property :outfile, [String, NilClass] + property :port_bindings, PartialHashType, default: {} + property :pid_mode, String, default: '' + property :privileged, Boolean, default: false + property :publish_all_ports, Boolean, default: false + property :remove_volumes, Boolean + property :restart_maximum_retry_count, Integer, default: 0 + property :restart_policy, String + property :ro_rootfs, Boolean, default: false + property :security_opts, [String, ArrayType] + property :signal, String, default: 'SIGTERM' + property :stdin_once, Boolean, default: false, desired_state: false + property :sysctls, Hash, default: {} + property :timeout, [Integer, nil], desired_state: false + property :tty, Boolean, default: false + property :ulimits, [Array, nil], coerce: proc { |v| coerce_ulimits(v) } + property :user, String, default: '' + property :userns_mode, String, default: '' + property :uts_mode, String, default: '' + property :volumes, PartialHashType, default: {}, coerce: proc { |v| coerce_volumes(v) } + property :volumes_from, ArrayType + property :volume_driver, String + property :working_dir, [String, NilClass], default: '' + + # Used to store the bind property since binds is an alias to volumes + property :volumes_binds, Array + + # Used to store the state of the Docker container + property :container, Docker::Container, desired_state: false + + # Used by :stop action. If the container takes longer than this + # many seconds to stop, kill itinstead. -1 (the default) means + # never kill the container. + property :kill_after, Numeric, default: -1, desired_state: false + + alias cmd command + alias additional_host extra_hosts + alias rm autoremove + alias remove_automatically autoremove + alias host_name hostname + alias domainname domain_name + alias dnssearch dns_search + alias restart_maximum_retries restart_maximum_retry_count + alias volume volumes + alias binds volumes + alias volume_from volumes_from + alias destination outfile + alias workdir working_dir + + # ~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ + # Begin classic Chef "provider" section + # ~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ + + ######################################################## + # Load Current Value + ######################################################## + + load_current_value do + # Grab the container and assign the container property + begin + with_retries { container Docker::Container.get(container_name, {}, connection) } + rescue Docker::Error::NotFoundError + current_value_does_not_exist! + end + + # Go through everything in the container and set corresponding properties: + # c.info['Config']['ExposedPorts'] -> exposed_ports + (container.info['Config'].to_a + container.info['HostConfig'].to_a).each do |key, value| + next if value.nil? || key == 'RestartPolicy' || key == 'Binds' || key == 'ReadonlyRootfs' + + # Image => image + # Set exposed_ports = ExposedPorts (etc.) + property_name = to_snake_case(key) + public_send(property_name, value) if respond_to?(property_name) + end + + # load container specific labels (without engine/image ones) + load_container_labels + + # these are a special case for us because our names differ from theirs + restart_policy container.info['HostConfig']['RestartPolicy']['Name'] + restart_maximum_retry_count container.info['HostConfig']['RestartPolicy']['MaximumRetryCount'] + volumes_binds container.info['HostConfig']['Binds'] + ro_rootfs container.info['HostConfig']['ReadonlyRootfs'] + end + + ######### + # Actions + ######### + + # Super handy visual reference! + # http://gliderlabs.com/images/docker_events.png + + default_action :run + + declare_action_class.class_eval do + def whyrun_supported? + true + end + + def call_action(action) + send("action_#{action}") + load_current_resource + end + + def state + current_resource ? current_resource.state : {} + end + end + + # Loads container specific labels excluding those of engine or image. + # This insures idempotency. + def load_container_labels + image_labels = Docker::Image.get(container.info['Image'], {}, connection).info['Config']['Labels'] || {} + engine_labels = Docker.info(connection)['Labels'] || {} + + labels = (container.info['Config']['Labels'] || {}).reject do |key, val| + image_labels.any? { |k, v| k == key && v == val } || + engine_labels.any? { |k, v| k == key && v == val } + end + + public_send(:labels, labels) + end + + def validate_container_create + if property_is_set?(:restart_policy) && + restart_policy != 'no' && + restart_policy != 'always' && + restart_policy != 'unless-stopped' && + restart_policy != 'on-failure' + raise Chef::Exceptions::ValidationFailed, 'restart_policy must be either no, always, unless-stopped, or on-failure.' + end + + if autoremove == true && (property_is_set?(:restart_policy) && restart_policy != 'no') + raise Chef::Exceptions::ValidationFailed, 'Conflicting options restart_policy and autoremove.' + end + + if detach == true && + ( + attach_stderr == true || + attach_stdin == true || + attach_stdout == true || + stdin_once == true + ) + raise Chef::Exceptions::ValidationFailed, 'Conflicting options detach, attach_stderr, attach_stdin, attach_stdout, stdin_once.' + end + + if network_mode == 'host' && + ( + !(hostname.nil? || hostname.empty?) || + !(mac_address.nil? || mac_address.empty?) + ) + raise Chef::Exceptions::ValidationFailed, 'Cannot specify hostname or mac_address when network_mode is host.' + end + + if network_mode == 'container' && + ( + !(hostname.nil? || hostname.empty?) || + !(dns.nil? || dns.empty?) || + !(dns_search.nil? || dns_search.empty?) || + !(mac_address.nil? || mac_address.empty?) || + !(extra_hosts.nil? || extra_hosts.empty?) || + !(exposed_ports.nil? || exposed_ports.empty?) || + !(port_bindings.nil? || port_bindings.empty?) || + !(publish_all_ports.nil? || publish_all_ports.empty?) || + !port.nil? + ) + raise Chef::Exceptions::ValidationFailed, 'Cannot specify hostname, dns, dns_search, mac_address, extra_hosts, exposed_ports, port_bindings, publish_all_ports, port when network_mode is container.' + end + end + + def parsed_hostname + return nil if network_mode == 'host' + hostname + end + + action :create do + validate_container_create + + converge_if_changed do + action_delete + + with_retries do + config = { + 'name' => container_name, + 'Image' => "#{repo}:#{tag}", + 'Labels' => labels, + 'Cmd' => to_shellwords(command), + 'AttachStderr' => attach_stderr, + 'AttachStdin' => attach_stdin, + 'AttachStdout' => attach_stdout, + 'Domainname' => domain_name, + 'Entrypoint' => to_shellwords(entrypoint), + 'Env' => env, + 'ExposedPorts' => exposed_ports, + 'Hostname' => parsed_hostname, + 'MacAddress' => mac_address, + 'NetworkDisabled' => network_disabled, + 'OpenStdin' => open_stdin, + 'StdinOnce' => stdin_once, + 'Tty' => tty, + 'User' => user, + 'Volumes' => volumes, + 'WorkingDir' => working_dir, + 'HostConfig' => { + 'Binds' => volumes_binds, + 'CapAdd' => cap_add, + 'CapDrop' => cap_drop, + 'CgroupParent' => cgroup_parent, + 'CpuShares' => cpu_shares, + 'CpusetCpus' => cpuset_cpus, + 'Devices' => devices, + 'Dns' => dns, + 'DnsSearch' => dns_search, + 'ExtraHosts' => extra_hosts, + 'IpcMode' => ipc_mode, + 'Links' => links, + 'LogConfig' => log_config, + 'Memory' => memory, + 'MemorySwap' => memory_swap, + 'NetworkMode' => network_mode, + 'Privileged' => privileged, + 'PidMode' => pid_mode, + 'PortBindings' => port_bindings, + 'PublishAllPorts' => publish_all_ports, + 'RestartPolicy' => { + 'Name' => restart_policy, + 'MaximumRetryCount' => restart_maximum_retry_count, + }, + 'ReadonlyRootfs' => ro_rootfs, + 'Sysctls' => sysctls, + 'Ulimits' => ulimits_to_hash, + 'UsernsMode' => userns_mode, + 'UTSMode' => uts_mode, + 'VolumesFrom' => volumes_from, + 'VolumeDriver' => volume_driver, + }, + } + net_config = { + 'NetworkingConfig' => { + 'EndpointsConfig' => { + network_mode => { + 'IPAMConfig' => { + 'IPv4Address' => ip_address, + }, + }, + }, + }, + } if network_mode + config.merge! net_config + + Docker::Container.create(config, connection) + end + end + end + + action :start do + return if state['Restarting'] + return if state['Running'] + converge_by "starting #{container_name}" do + with_retries do + container.start + timeout ? container.wait(timeout) : container.wait unless detach + end + wait_running_state(true) if detach + end + end + + action :stop do + return unless state['Running'] + kill_after_str = " (will kill after #{kill_after}s)" if kill_after != -1 + converge_by "stopping #{container_name} #{kill_after_str}" do + begin + with_retries do + container.stop!('timeout' => kill_after) + wait_running_state(false) + end + rescue Docker::Error::TimeoutError + raise Docker::Error::TimeoutError, "Container failed to stop, consider adding kill_after to the container #{container_name}" + end + end + end + + action :kill do + return unless state['Running'] + converge_by "killing #{container_name}" do + with_retries { container.kill(signal: signal) } + end + end + + action :run do + validate_container_create + call_action(:create) + call_action(:start) + call_action(:delete) if autoremove + end + + action :run_if_missing do + return if current_resource + call_action(:run) + end + + action :pause do + return if state['Paused'] + converge_by "pausing #{container_name}" do + with_retries { container.pause } + end + end + + action :unpause do + return if current_resource && !state['Paused'] + converge_by "unpausing #{container_name}" do + with_retries { container.unpause } + end + end + + action :restart do + kill_after_str = " (will kill after #{kill_after}s)" if kill_after != -1 + converge_by "restarting #{container_name} #{kill_after_str}" do + current_resource ? container.restart('timeout' => kill_after) : call_action(:run) + end + end + + action :reload do + converge_by "reloading #{container_name}" do + with_retries { container.kill(signal: 'SIGHUP') } + end + end + + action :redeploy do + validate_container_create + + # never start containers resulting from a previous action :create #432 + should_create = state['Running'] == false && state['StartedAt'] == '0001-01-01T00:00:00Z' + call_action(:delete) + call_action(should_create ? :create : :run) + end + + action :delete do + return unless current_resource + call_action(:unpause) + call_action(:stop) + converge_by "deleting #{container_name}" do + with_retries { container.delete(force: force, v: remove_volumes) } + end + end + + action :remove do + call_action(:delete) + end + + action :commit do + converge_by "committing #{container_name}" do + with_retries do + new_image = container.commit + new_image.tag('repo' => repo, 'tag' => tag, 'force' => force) + end + end + end + + action :export do + raise "Please set outfile property on #{container_name}" if outfile.nil? + converge_by "exporting #{container_name}" do + with_retries do + ::File.open(outfile, 'w') { |f| container.export { |chunk| f.write(chunk) } } + end + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_exec.rb b/chef/cookbooks/docker/libraries/docker_exec.rb new file mode 100644 index 0000000..0491d0d --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_exec.rb @@ -0,0 +1,21 @@ +module DockerCookbook + class DockerExec < DockerBase + resource_name :docker_exec + + property :host, [String, nil], default: lazy { default_host } + property :command, Array + property :container, String + property :timeout, Numeric, default: 60 + + property :container_obj, Docker::Container, desired_state: false + + alias cmd command + + action :run do + converge_by "executing #{command} on #{container}" do + with_retries { container_obj Docker::Container.get(container, {}, connection) } + container_obj.exec(command, wait: timeout) + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_image.rb b/chef/cookbooks/docker/libraries/docker_image.rb new file mode 100644 index 0000000..8455194 --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_image.rb @@ -0,0 +1,94 @@ +module DockerCookbook + class DockerImage < DockerBase + require 'docker' + require_relative 'helpers_image' + + resource_name :docker_image + + # Modify the default of read_timeout from 60 to 120 + property :read_timeout, default: 120, desired_state: false + + # https://docs.docker.com/reference/api/docker_remote_api_v1.20/ + property :destination, [String, nil] + property :force, Boolean, default: false + property :host, [String, nil], default: lazy { default_host }, desired_state: false + property :nocache, Boolean, default: false + property :noprune, Boolean, default: false + property :repo, String, name_property: true + property :rm, Boolean, default: true + property :source, String + property :tag, String, default: 'latest' + + alias image repo + alias image_name repo + alias no_cache nocache + alias no_prune noprune + + ######### + # Actions + ######### + + default_action :pull + + declare_action_class.class_eval do + include DockerHelpers::Image + def whyrun_supported? + true + end + end + + action :build do + converge_by "Build image #{image_identifier}" do + build_image + end + end + + action :build_if_missing do + return if Docker::Image.exist?(image_identifier, {}, connection) + action_build + end + + action :import do + return if Docker::Image.exist?(image_identifier, {}, connection) + converge_by "Import image #{image_identifier}" do + import_image + end + end + + action :pull do + # We already did the work, but we need to report what we did! + converge_by "Pull image #{image_identifier}" do + end if pull_image + end + + action :pull_if_missing do + return if Docker::Image.exist?(image_identifier, {}, connection) + action_pull + end + + action :push do + converge_by "Push image #{image_identifier}" do + push_image + end + end + + action :remove do + return unless Docker::Image.exist?(image_identifier, {}, connection) + converge_by "Remove image #{image_identifier}" do + remove_image + end + end + + action :save do + converge_by "Save image #{image_identifier}" do + save_image + end + end + + action :load do + converge_by "load image #{image_identifier}" do + load_image + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_installation_binary.rb b/chef/cookbooks/docker/libraries/docker_installation_binary.rb new file mode 100644 index 0000000..041dab4 --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_installation_binary.rb @@ -0,0 +1,40 @@ +module DockerCookbook + class DockerInstallationBinary < DockerBase + require_relative 'helpers_installation_binary' + + include DockerHelpers::InstallationBinary + + ##################### + # Resource properties + ##################### + resource_name :docker_installation_binary + + property :checksum, String, default: lazy { default_checksum }, desired_state: false + property :source, String, default: lazy { default_source }, desired_state: false + property :version, String, default: lazy { default_version }, desired_state: false + + default_action :create + + ######### + # Actions + ######### + + action :create do + # Pull a precompiled binary off the network + remote_file docker_bin do + source new_resource.source + checksum new_resource.checksum + owner 'root' + group 'root' + mode '0755' + action :create + end + end + + action :delete do + file docker_bin do + action :delete + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_installation_package.rb b/chef/cookbooks/docker/libraries/docker_installation_package.rb new file mode 100644 index 0000000..6d789cd --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_installation_package.rb @@ -0,0 +1,32 @@ +module DockerCookbook + class DockerInstallationPackage < DockerBase + require_relative 'helpers_installation_package' + + include DockerHelpers::InstallationPackage + + # Resource properties + resource_name :docker_installation_package + + provides :docker_installation, platform: 'amazon' + + property :package_name, String, default: lazy { default_package_name }, desired_state: false + property :package_version, String, default: lazy { version_string(version) }, desired_state: false + property :version, String, default: lazy { default_docker_version }, desired_state: false + property :package_options, String, desired_state: false + + # Actions + action :create do + package package_name do + version package_version + options package_options + action :install + end + end + + action :delete do + package package_name do + action :remove + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_installation_script.rb b/chef/cookbooks/docker/libraries/docker_installation_script.rb new file mode 100644 index 0000000..305031a --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_installation_script.rb @@ -0,0 +1,51 @@ +module DockerCookbook + class DockerInstallationScript < DockerBase + ##################### + # Resource properties + ##################### + resource_name :docker_installation_script + + provides :docker_installation, os: 'linux' + + property :repo, %w(main test experimental), default: 'main', desired_state: false + property :script_url, String, default: lazy { default_script_url }, desired_state: false + + default_action :create + + ################ + # helper methods + ################ + + def default_script_url + case repo + when 'main' + 'https://get.docker.com/' + when 'test' + 'https://test.docker.com/' + when 'experimental' + 'https://experimental.docker.com/' + end + end + + ######### + # Actions + ######### + + action :create do + package 'curl' do + action :install + end + + execute 'install docker' do + command "curl -sSL #{script_url} | sh" + creates '/usr/bin/docker' + end + end + + action :delete do + package 'docker-engine' do + action :remove + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_installation_tarball.rb b/chef/cookbooks/docker/libraries/docker_installation_tarball.rb new file mode 100644 index 0000000..d9b1d31 --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_installation_tarball.rb @@ -0,0 +1,47 @@ +module DockerCookbook + class DockerInstallationTarball < DockerBase + require_relative 'helpers_installation_tarball' + + include DockerHelpers::InstallationTarball + + ##################### + # Resource properties + ##################### + resource_name :docker_installation_tarball + + property :checksum, String, default: lazy { default_checksum }, desired_state: false + property :source, String, default: lazy { default_source }, desired_state: false + property :version, String, default: lazy { default_version }, desired_state: false + + default_action :create + + ######### + # Actions + ######### + + action :create do + # Pull a precompiled binary off the network + remote_file docker_tarball do + source new_resource.source + checksum new_resource.checksum + owner 'root' + group 'root' + mode '0755' + action :create + notifies :run, 'execute[extract tarball]', :immediately + end + + execute 'extract tarball' do + action :nothing + command "tar -xzf #{docker_tarball} --strip-components=1 -C #{docker_bin_prefix}" + creates docker_bin + end + end + + action :delete do + file docker_bin do + action :delete + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_network.rb b/chef/cookbooks/docker/libraries/docker_network.rb new file mode 100644 index 0000000..050db8a --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_network.rb @@ -0,0 +1,127 @@ +module DockerCookbook + class DockerNetwork < DockerBase + require 'docker' + require_relative 'helpers_network' + include DockerHelpers::Network + + resource_name :docker_network + + property :auxiliary_addresses, [String, Array, nil], coerce: proc { |v| coerce_auxiliary_addresses(v) } + property :container, String, desired_state: false + property :driver, String + property :driver_opts, PartialHashType + property :gateway, [String, Array, nil], coerce: proc { |v| coerce_gateway(v) } + property :host, [String, nil], default: lazy { default_host }, desired_state: false + property :id, String + property :ip_range, [String, Array, nil], coerce: proc { |v| coerce_ip_range(v) } + property :ipam_driver, String + property :network, Docker::Network, desired_state: false + property :network_name, String, name_property: true + property :subnet, [String, Array, nil], coerce: proc { |v| coerce_subnet(v) } + + alias aux_address auxiliary_addresses + + load_current_value do + begin + with_retries { network Docker::Network.get(network_name, {}, connection) } + rescue Docker::Error::NotFoundError + current_value_does_not_exist! + end + + aux_addr_ray = [] + gateway_ray = [] + ip_range_ray = [] + subnet_ray = [] + + network.info['IPAM']['Config'].to_a.each do |conf| + conf.each do |key, value| + case key + when 'AuxiliaryAddresses' + aux_addr_ray << value + when 'Gateway' + gateway_ray << value + when 'IPRange' + ip_range_ray << value + when 'Subnet' + subnet_ray << value + end + end + end + + auxiliary_addresses aux_addr_ray + gateway gateway_ray + ip_range ip_range_ray + subnet subnet_ray + + driver network.info['Driver'] + driver_opts network.info['Options'] + end + + action :create do + converge_if_changed do + action_delete + + with_retries do + options = {} + options['Driver'] = driver if driver + options['Options'] = driver_opts if driver_opts + ipam_options = consolidate_ipam(subnet, ip_range, gateway, aux_address) + options['IPAM'] = { 'Config' => ipam_options } unless ipam_options.empty? + options['IPAM']['Driver'] = ipam_driver if ipam_driver + Docker::Network.create(network_name, options) + end + end + end + + action :delete do + return unless current_resource + converge_by "deleting #{network_name}" do + with_retries do + network.delete + end + end + end + + action :remove do + action_delete + end + + action :connect do + unless container + raise Chef::Exceptions::ValidationFailed, 'Container id or name is required for action :connect' + end + + if current_resource + container_index = network.info['Containers'].values.index { |c| c['Name'] == container } + if container_index.nil? + converge_by("connect #{container}") do + with_retries do + network.connect(container) + end + end + end + else + Chef::Log.warn("Cannot connect to #{network_name}: network does not exist") + end + end + + action :disconnect do + unless container + raise Chef::Exceptions::ValidationFailed, 'Container id or name is required for action :disconnect' + end + + if current_resource + container_index = network.info['Containers'].values.index { |c| c['Name'] == container } + unless container_index.nil? + converge_by("disconnect #{container}") do + with_retries do + network.disconnect(container) + end + end + end + else + Chef::Log.warn("Cannot disconnect from #{network_name}: network does not exist") + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_registry.rb b/chef/cookbooks/docker/libraries/docker_registry.rb new file mode 100644 index 0000000..58eeff6 --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_registry.rb @@ -0,0 +1,38 @@ +module DockerCookbook + class DockerRegistry < DockerBase + require 'docker' + require_relative 'helpers_auth' + + resource_name :docker_registry + + property :email, [String, nil] + property :password, [String, nil] + property :serveraddress, [String, nil], name_property: true + property :username, [String, nil] + + action :login do + tries = api_retries + + registry_host = parse_registry_host(serveraddress) + + (node.run_state['docker_auth'] ||= {})[registry_host] = { + 'serveraddress' => registry_host, + 'username' => username, + 'password' => password, + 'email' => email, + } + + begin + Docker.connection.post( + '/auth', {}, + body: node.run_state['docker_auth'][registry_host].to_json + ) + rescue Docker::Error::ServerError, Docker::Error::UnauthorizedError + raise Docker::Error::AuthenticationError, "#{username} failed to authenticate with #{serveraddress}" if (tries -= 1) == 0 + retry + end + + true + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_service.rb b/chef/cookbooks/docker/libraries/docker_service.rb new file mode 100644 index 0000000..10725c2 --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_service.rb @@ -0,0 +1,129 @@ +module DockerCookbook + require_relative 'docker_service_base' + + class DockerService < DockerServiceBase + resource_name :docker_service + + # register with the resource resolution system + provides :docker_service + + # installation type and service_manager + property :install_method, %w(binary script package tarball none auto), default: 'auto', desired_state: false + property :service_manager, %w(execute sysvinit upstart systemd auto), default: 'auto', desired_state: false + + # docker_installation_script + property :repo, desired_state: false + property :script_url, String, desired_state: false + + # docker_installation_binary and tarball + property :checksum, String, desired_state: false + property :docker_bin, String, desired_state: false + property :source, String, desired_state: false + + # docker_installation_package + property :package_version, String, desired_state: false + + # binary, package and tarball + property :version, String, desired_state: false + property :package_options, [String, nil], desired_state: false + + ################ + # Helper Methods + ################ + def validate_install_method + if property_is_set?(:version) && + install_method != 'binary' && + install_method != 'package' && + install_method != 'tarball' + raise Chef::Exceptions::ValidationFailed, 'Version property only supported for binary, package and tarball installation methods' + end + end + + def copy_properties_to(to, *properties) + properties = self.class.properties.keys if properties.empty? + properties.each do |p| + # If the property is set on from, and exists on to, set the + # property on to + if to.class.properties.include?(p) && property_is_set?(p) + to.send(p, send(p)) + end + end + end + + action_class.class_eval do + def installation(&block) + case install_method + when 'auto' + install = docker_installation(name, &block) + when 'binary' + install = docker_installation_binary(name, &block) + when 'script' + install = docker_installation_script(name, &block) + when 'package' + install = docker_installation_package(name, &block) + when 'tarball' + install = docker_installation_tarball(name, &block) + when 'none' + Chef::Log.info('Skipping Docker installation. Assuming it was handled previously.') + return + end + copy_properties_to(install) + install + end + + def svc_manager(&block) + case service_manager + when 'auto' + svc = docker_service_manager(name, &block) + when 'execute' + svc = docker_service_manager_execute(name, &block) + when 'sysvinit' + svc = docker_service_manager_sysvinit(name, &block) + when 'upstart' + svc = docker_service_manager_upstart(name, &block) + when 'systemd' + svc = docker_service_manager_systemd(name, &block) + end + copy_properties_to(svc) + svc + end + end + + ######### + # Actions + ######### + + action :create do + validate_install_method + + installation do + action :create + notifies :restart, new_resource, :immediately + end + end + + action :delete do + installation do + action :delete + end + end + + action :start do + svc_manager do + action :start + end + end + + action :stop do + svc_manager do + action :stop + end + end + + action :restart do + svc_manager do + action :restart + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_service_base.rb b/chef/cookbooks/docker/libraries/docker_service_base.rb new file mode 100644 index 0000000..fa2393e --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_service_base.rb @@ -0,0 +1,123 @@ +module DockerCookbook + class DockerServiceBase < DockerBase + ################ + # Helper Methods + ################ + require 'docker' + require_relative 'helpers_service' + include DockerHelpers::Service + + ##################### + # resource properties + ##################### + + resource_name :docker_service_base + + # register with the resource resolution system + provides :docker_service_manager + + # daemon management + property :instance, String, name_property: true, required: true, desired_state: false + property :auto_restart, Boolean, default: false + property :api_cors_header, [String, nil] + property :bridge, [String, nil] + property :bip, [IPV4_ADDR, IPV4_CIDR, IPV6_ADDR, IPV6_CIDR, nil] + property :cluster_store, [String, nil] + property :cluster_advertise, [String, nil] + property :cluster_store_opts, ArrayType + property :debug, [Boolean, nil] + property :daemon, Boolean, default: true + property :dns, ArrayType + property :dns_search, [Array, nil] + property :exec_driver, ['native', 'lxc', nil] + property :exec_opts, ArrayType + property :fixed_cidr, [String, nil] + property :fixed_cidr_v6, [String, nil] + property :group, [String, nil] + property :graph, [String, nil] + property :host, [String, Array], coerce: proc { |v| coerce_host(v) } + property :icc, [Boolean, nil] + property :insecure_registry, [Array, String, nil], coerce: proc { |v| coerce_insecure_registry(v) } + property :ip, [IPV4_ADDR, IPV6_ADDR, nil] + property :ip_forward, [Boolean, nil] + property :ipv4_forward, Boolean, default: true + property :ipv6_forward, Boolean, default: true + property :ip_masq, [Boolean, nil] + property :iptables, [Boolean, nil] + property :ipv6, [Boolean, nil] + property :log_level, [:debug, :info, :warn, :error, :fatal, nil] + property :labels, [String, Array], coerce: proc { |v| coerce_daemon_labels(v) }, desired_state: false + property :log_driver, %w( json-file syslog journald gelf fluentd awslogs splunk none ) + property :log_opts, ArrayType + property :mount_flags, String, default: 'slave' + property :mtu, [String, nil] + property :pidfile, String, default: lazy { "/var/run/#{docker_name}.pid" } + property :registry_mirror, [String, nil] + property :storage_driver, ArrayType + property :selinux_enabled, [Boolean, nil] + property :storage_opts, ArrayType + property :default_ulimit, ArrayType + property :userland_proxy, [Boolean, nil] + property :disable_legacy_registry, [Boolean, nil] + property :userns_remap, [String, nil] + + # These are options specific to systemd configuration such as + # LimitNOFILE or TasksMax that you may wannt to use to customize + # the environment in which Docker runs. + property :systemd_opts, ArrayType + + # These are unvalidated daemon arguments passed in as a string. + property :misc_opts, [String, nil] + + # environment variables to set before running daemon + property :http_proxy, [String, nil] + property :https_proxy, [String, nil] + property :no_proxy, [String, nil] + property :tmpdir, [String, nil] + + # logging + property :logfile, String, default: '/var/log/docker.log' + + # docker-wait-ready timeout + property :service_timeout, Integer, default: 20 + + allowed_actions :start, :stop, :restart + + alias label labels + alias tlscacert tls_ca_cert + alias tlscert tls_server_cert + alias tlskey tls_server_key + alias tlsverify tls_verify + alias run_group group + + declare_action_class.class_eval do + def libexec_dir + return '/usr/libexec/docker' if node['platform_family'] == 'rhel' + '/usr/lib/docker' + end + + def create_docker_wait_ready + directory libexec_dir do + owner 'root' + group 'root' + mode '0755' + action :create + end + + template "#{libexec_dir}/#{docker_name}-wait-ready" do + source 'default/docker-wait-ready.erb' + owner 'root' + group 'root' + mode '0755' + variables( + docker_cmd: docker_cmd, + libexec_dir: libexec_dir, + service_timeout: service_timeout + ) + cookbook 'docker' + action :create + end + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_service_manager_execute.rb b/chef/cookbooks/docker/libraries/docker_service_manager_execute.rb new file mode 100644 index 0000000..01dc20e --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_service_manager_execute.rb @@ -0,0 +1,56 @@ +module DockerCookbook + class DockerServiceManagerExecute < DockerServiceBase + resource_name :docker_service_manager_execute + + provides :docker_service_manager, os: 'linux' + + # Start the service + action :start do + # enable ipv4 forwarding + execute 'enable net.ipv4.conf.all.forwarding' do + command '/sbin/sysctl net.ipv4.conf.all.forwarding=1' + not_if '/sbin/sysctl -q -n net.ipv4.conf.all.forwarding | grep ^1$' + action :run + end + + # enable ipv6 forwarding + execute 'enable net.ipv6.conf.all.forwarding' do + command '/sbin/sysctl net.ipv6.conf.all.forwarding=1' + not_if '/sbin/sysctl -q -n net.ipv6.conf.all.forwarding | grep ^1$' + action :run + end + + # Go doesn't support detaching processes natively, so we have + # to manually fork it from the shell with & + # https://github.com/docker/docker/issues/2758 + bash "start docker #{name}" do + code "#{docker_daemon_cmd} >> #{logfile} 2>&1 &" + environment 'HTTP_PROXY' => http_proxy, + 'HTTPS_PROXY' => https_proxy, + 'NO_PROXY' => no_proxy, + 'TMPDIR' => tmpdir + not_if "ps -ef | grep -v grep | grep #{Shellwords.escape(docker_daemon_cmd)}" + action :run + end + + create_docker_wait_ready + + execute 'docker-wait-ready' do + command "#{libexec_dir}/#{docker_name}-wait-ready" + end + end + + action :stop do + execute "stop docker #{name}" do + command "kill `cat #{pidfile}` && while [ -e #{pidfile} ]; do sleep 1; done" + timeout 10 + only_if "#{docker_cmd} ps | head -n 1 | grep ^CONTAINER" + end + end + + action :restart do + action_stop + action_start + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_service_manager_systemd.rb b/chef/cookbooks/docker/libraries/docker_service_manager_systemd.rb new file mode 100644 index 0000000..f26994c --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_service_manager_systemd.rb @@ -0,0 +1,116 @@ +module DockerCookbook + class DockerServiceManagerSystemd < DockerServiceBase + resource_name :docker_service_manager_systemd + + provides :docker_service_manager, platform: 'fedora' + + provides :docker_service_manager, platform: %w(redhat centos scientific oracle) do |node| # ~FC005 + node['platform_version'].to_f >= 7.0 + end + + provides :docker_service_manager, platform: 'debian' do |node| + node['platform_version'].to_f >= 8.0 + end + + provides :docker_service_manager, platform: 'ubuntu' do |node| + node['platform_version'].to_f >= 15.04 + end + + action :start do + create_docker_wait_ready + + # stock systemd unit file + template "/lib/systemd/system/#{docker_name}.service" do + source 'systemd/docker.service.erb' + owner 'root' + group 'root' + mode '0644' + variables( + docker_name: docker_name, + docker_socket: connect_socket.sub(%r{unix://|fd://}, ''), + docker_mount_flags: mount_flags + ) + cookbook 'docker' + action :create + not_if { docker_name == 'default' && ::File.exist?('/lib/systemd/system/docker.service') } + end + + # stock systemd socket file + template "/lib/systemd/system/#{docker_name}.socket" do + source 'systemd/docker.socket.erb' + owner 'root' + group 'root' + mode '0644' + variables( + docker_name: docker_name, + docker_socket: connect_socket.sub(%r{unix://|fd://}, '') + ) + cookbook 'docker' + action :create + not_if { docker_name == 'default' && ::File.exist?('/lib/systemd/system/docker.socket') } + end + + template "/etc/systemd/system/#{docker_name}.service" do + source 'systemd/docker.service-override.erb' + owner 'root' + group 'root' + mode '0644' + variables( + config: new_resource, + docker_daemon_cmd: docker_daemon_cmd, + systemd_args: systemd_args, + docker_wait_ready: "#{libexec_dir}/#{docker_name}-wait-ready", + docker_mount_flags: mount_flags + ) + cookbook 'docker' + notifies :run, 'execute[systemctl daemon-reload]', :immediately + action :create + end + + # this overrides the main systemd socket + template "/etc/systemd/system/#{docker_name}.socket" do + source 'systemd/docker.socket-override.erb' + owner 'root' + group 'root' + mode '0644' + variables( + config: new_resource, + docker_name: docker_name, + docker_socket: connect_socket.sub(%r{unix://|fd://}, '') + ) + cookbook 'docker' + notifies :run, 'execute[systemctl daemon-reload]', :immediately + action :create + end + + # avoid 'Unit file changed on disk' warning + execute 'systemctl daemon-reload' do + command '/bin/systemctl daemon-reload' + action :nothing + end + + # service management resource + service docker_name do + provider Chef::Provider::Service::Systemd + supports status: true + action [:enable, :start] + only_if { ::File.exist?("/lib/systemd/system/#{docker_name}.service") } + end + end + + action :stop do + # service management resource + service docker_name do + provider Chef::Provider::Service::Systemd + supports status: true + action [:disable, :stop] + only_if { ::File.exist?("/lib/systemd/system/#{docker_name}.service") } + end + end + + action :restart do + action_stop + action_start + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_service_manager_sysvinit_debian.rb b/chef/cookbooks/docker/libraries/docker_service_manager_sysvinit_debian.rb new file mode 100644 index 0000000..12e0b0c --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_service_manager_sysvinit_debian.rb @@ -0,0 +1,87 @@ +module DockerCookbook + class DockerServiceManagerSysvinitDebian < DockerServiceBase + resource_name :docker_service_manager_sysvinit_debian + + provides :docker_service_manager, platform: 'debian' do |node| + node['platform_version'].to_f < 8.0 + end + + provides :docker_service_manager, platform: 'ubuntu' do |node| + node['platform_version'].to_f < 12.04 + end + + provides :docker_service_manager_sysvinit, platform: 'debian' do |node| + node['platform_version'].to_f < 8.0 + end + + provides :docker_service_manager_sysvinit, platform: 'ubuntu' do |node| + node['platform_version'].to_f < 12.04 + end + + action :start do + create_docker_wait_ready + create_init + create_service + end + + action :stop do + create_init + s = create_service + s.action :stop + end + + action :restart do + action_stop + action_start + end + + action_class.class_eval do + def create_init + execute 'groupadd docker' do + not_if 'getent group docker' + action :run + end + + link dockerd_bin_link do + to dockerd_bin + link_type :hard + action :create + end + + template "/etc/init.d/#{docker_name}" do + source 'sysvinit/docker-debian.erb' + owner 'root' + group 'root' + mode '0755' + variables( + docker_name: docker_name, + dockerd_bin_link: dockerd_bin_link, + docker_daemon_arg: docker_daemon_arg, + docker_wait_ready: "#{libexec_dir}/#{docker_name}-wait-ready" + ) + cookbook 'docker' + action :create + end + + template "/etc/default/#{docker_name}" do + source 'default/docker.erb' + variables( + config: new_resource, + dockerd_bin_link: dockerd_bin_link, + docker_daemon_opts: docker_daemon_opts.join(' ') + ) + cookbook 'docker' + action :create + end + end + + def create_service + service docker_name do + provider Chef::Provider::Service::Init::Debian + supports restart: true, status: true + action [:enable, :start] + end + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_service_manager_sysvinit_rhel.rb b/chef/cookbooks/docker/libraries/docker_service_manager_sysvinit_rhel.rb new file mode 100644 index 0000000..6480d04 --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_service_manager_sysvinit_rhel.rb @@ -0,0 +1,81 @@ +module DockerCookbook + class DockerServiceManagerSysvinitRhel < DockerServiceBase + resource_name :docker_service_manager_sysvinit_rhel + + provides :docker_service_manager, platform: 'amazon' + provides :docker_service_manager, platform: 'suse' + provides :docker_service_manager, platform: %w(redhat centos scientific oracle) do |node| # ~FC005 + node['platform_version'].to_f <= 7.0 + end + + provides :docker_service_manager_sysvinit, platform: 'amazon' + provides :docker_service_manager_sysvinit, platform: 'suse' + provides :docker_service_manager_sysvinit, platform: %w(redhat centos scientific oracle) do |node| # ~FC005 + node['platform_version'].to_f <= 7.0 + end + + action :start do + create_docker_wait_ready + create_init + create_service + end + + action :stop do + create_init + s = create_service + s.action :stop + end + + action :restart do + action_stop + action_start + end + + action_class.class_eval do + def create_init + execute 'groupadd docker' do + not_if 'getent group docker' + action :run + end + + link dockerd_bin_link do + to dockerd_bin + link_type :hard + action :create + end + + template "/etc/init.d/#{docker_name}" do + source 'sysvinit/docker-rhel.erb' + owner 'root' + group 'root' + mode '0755' + variables( + docker_name: docker_name, + dockerd_bin_link: dockerd_bin_link, + docker_daemon_cmd: docker_daemon_cmd, + docker_wait_ready: "#{libexec_dir}/#{docker_name}-wait-ready" + ) + cookbook 'docker' + action :create + end + + template "/etc/sysconfig/#{docker_name}" do + source 'sysconfig/docker.erb' + variables( + config: new_resource, + docker_daemon_opts: docker_daemon_opts.join(' ') + ) + cookbook 'docker' + action :create + end + end + + def create_service + service docker_name do + supports restart: true, status: true + action [:enable, :start] + end + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_service_manager_upstart.rb b/chef/cookbooks/docker/libraries/docker_service_manager_upstart.rb new file mode 100644 index 0000000..93997c1 --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_service_manager_upstart.rb @@ -0,0 +1,63 @@ +module DockerCookbook + class DockerServiceManagerUpstart < DockerServiceBase + resource_name :docker_service_manager_upstart + + provides :docker_service_manager, platform: 'ubuntu' + provides :docker_service_manager, platform: 'linuxmint' + + action :start do + create_docker_wait_ready + + link dockerd_bin_link do + to dockerd_bin + link_type :hard + action :create + end + + template "/etc/init/#{docker_name}.conf" do + source 'upstart/docker.conf.erb' + owner 'root' + group 'root' + mode '0644' + variables( + docker_name: docker_name, + dockerd_bin_link: dockerd_bin_link, + docker_daemon_arg: docker_daemon_arg, + docker_wait_ready: "#{libexec_dir}/#{docker_name}-wait-ready" + ) + cookbook 'docker' + action :create + end + + template "/etc/default/#{docker_name}" do + source 'default/docker.erb' + variables( + config: new_resource, + dockerd_bin_link: dockerd_bin_link, + docker_daemon_opts: docker_daemon_opts.join(' ') + ) + cookbook 'docker' + action :create + end + + service docker_name do + provider Chef::Provider::Service::Upstart + supports status: true + action :start + end + end + + action :stop do + service docker_name do + provider Chef::Provider::Service::Upstart + supports status: true + action :stop + end + end + + action :restart do + action_stop + action_start + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_tag.rb b/chef/cookbooks/docker/libraries/docker_tag.rb new file mode 100644 index 0000000..e9fc471 --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_tag.rb @@ -0,0 +1,27 @@ +module DockerCookbook + class DockerTag < DockerBase + resource_name :docker_tag + + property :target_repo, String, name_property: true + property :target_tag, String + property :to_repo, String + property :to_tag, String + property :force, Boolean, default: false + + ######### + # Actions + ######### + + action :tag do + return if force == false && Docker::Image.exist?("#{to_repo}:#{to_tag}") + begin + converge_by "update #{target_repo}:#{target_tag} to #{to_repo}:#{to_tag}" do + i = Docker::Image.get("#{target_repo}:#{target_tag}") + i.tag('repo' => to_repo, 'tag' => to_tag, 'force' => force) + end + rescue Docker::Error => e + raise e.message + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/docker_volume.rb b/chef/cookbooks/docker/libraries/docker_volume.rb new file mode 100644 index 0000000..9bc735f --- /dev/null +++ b/chef/cookbooks/docker/libraries/docker_volume.rb @@ -0,0 +1,33 @@ +module DockerCookbook + class DockerVolume < DockerBase + require 'docker' + + resource_name :docker_volume + + property :driver, String, desired_state: false + property :host, [String, nil], default: lazy { default_host }, desired_state: false + property :opts, [String, Array, nil], desired_state: false + property :volume, Docker::Volume, desired_state: false + property :volume_name, String, name_property: true + + load_current_value do + begin + with_retries { volume Docker::Volume.get(volume_name, connection) } + rescue Docker::Error::NotFoundError + current_value_does_not_exist! + end + end + + action :create do + converge_by "creating volume #{volume_name}" do + Docker::Volume.create(volume_name, {}, connection) + end if volume.nil? + end + + action :remove do + converge_by "removing volume #{volume_name}" do + volume.remove + end unless volume.nil? + end + end +end diff --git a/chef/cookbooks/docker/libraries/helpers_auth.rb b/chef/cookbooks/docker/libraries/helpers_auth.rb new file mode 100644 index 0000000..40b3654 --- /dev/null +++ b/chef/cookbooks/docker/libraries/helpers_auth.rb @@ -0,0 +1,10 @@ +module DockerCookbook + module DockerHelpers + module Authentication + # https://github.com/docker/docker/blob/4fcb9ac40ce33c4d6e08d5669af6be5e076e2574/registry/auth.go#L231 + def parse_registry_host(val) + val.sub(%r{https?://}, '').split('/').first + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/helpers_base.rb b/chef/cookbooks/docker/libraries/helpers_base.rb new file mode 100644 index 0000000..43b8f30 --- /dev/null +++ b/chef/cookbooks/docker/libraries/helpers_base.rb @@ -0,0 +1,110 @@ +module DockerCookbook + module DockerHelpers + module Base + require 'shellwords' + + # Misc + def to_snake_case(name) + # ExposedPorts -> _exposed_ports + name = name.gsub(/[A-Z]/) { |x| "_#{x.downcase}" } + # _exposed_ports -> exposed_ports + name = name[1..-1] if name.start_with?('_') + name + end + + ########## + # coersion + ########## + + def coerce_labels(v) + case v + when Hash, nil + v + else + Array(v).each_with_object({}) do |label, h| + parts = label.split(':') + h[parts[0]] = parts[1] + end + end + end + + def coerce_shell_command(v) + return nil if v.nil? + return DockerBase::ShellCommandString.new( + ::Shellwords.join(v) + ) if v.is_a?(Array) + DockerBase::ShellCommandString.new(v) + end + + ################ + # Helper methods + ################ + + def api_version + @api_version ||= Docker.version(connection)['ApiVersion'] + end + + def connection + @connection ||= begin + opts = {} + opts[:read_timeout] = read_timeout if read_timeout + opts[:write_timeout] = write_timeout if write_timeout + + if host =~ /^tcp:/ + opts[:scheme] = 'https' if tls || !tls_verify.nil? + opts[:ssl_ca_file] = tls_ca_cert if tls_ca_cert + opts[:client_cert] = tls_client_cert if tls_client_cert + opts[:client_key] = tls_client_key if tls_client_key + end + Docker::Connection.new(host || Docker.url, opts) + end + end + + def with_retries(&_block) + tries = api_retries + begin + yield + # Only catch errors that can be fixed with retries. + rescue Docker::Error::ServerError, # 404 + Docker::Error::UnexpectedResponseError, # 400 + Docker::Error::TimeoutError, + Docker::Error::IOError + tries -= 1 + retry if tries > 0 + raise + end + end + + def call_action(_action) + new_resource.run_action + end + + def default_host + return nil unless ENV['DOCKER_HOST'] + ENV['DOCKER_HOST'] + end + + def default_tls + return nil unless ENV['DOCKER_TLS'] + ENV['DOCKER_TLS'] + end + + def default_tls_verify + return nil unless ENV['DOCKER_TLS_VERIFY'] + ENV['DOCKER_TLS_VERIFY'] + end + + def default_tls_cert_path(v) + return nil unless ENV['DOCKER_CERT_PATH'] + case v + when 'ca' + "#{ENV['DOCKER_CERT_PATH']}/ca.pem" + when 'cert' + "#{ENV['DOCKER_CERT_PATH']}/cert.pem" + when 'key' + "#{ENV['DOCKER_CERT_PATH']}/key.pem" + end + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/helpers_container.rb b/chef/cookbooks/docker/libraries/helpers_container.rb new file mode 100644 index 0000000..66e8dca --- /dev/null +++ b/chef/cookbooks/docker/libraries/helpers_container.rb @@ -0,0 +1,236 @@ +module DockerCookbook + module DockerHelpers + module Container + def coerce_links(v) + case v + when DockerBase::UnorderedArray, nil + v + else + return nil if v.empty? + # Parse docker input of /source:/container_name/dest into source:dest + DockerBase::UnorderedArray.new(Array(v)).map! do |link| + if link =~ %r{^/(?.+):/#{name}/(?.+)} + link = "#{Regexp.last_match[:source]}:#{Regexp.last_match[:dest]}" + end + link + end + end + end + + def coerce_log_opts(v) + case v + when Hash, nil + v + else + Array(v).each_with_object({}) do |log_opt, memo| + key, value = log_opt.split('=', 2) + memo[key] = value + end + end + end + + def coerce_ulimits(v) + return v if v.nil? + Array(v).map do |u| + u = "#{u['Name']}=#{u['Soft']}:#{u['Hard']}" if u.is_a?(Hash) + u + end + end + + def coerce_volumes(v) + case v + when DockerBase::PartialHash, nil + v + when Hash + DockerBase::PartialHash[v] + else + b = [] + v = Array(v).to_a # in case v.is_A?(Chef::Node::ImmutableArray) + v.delete_if do |x| + parts = x.split(':') + b << x if parts.length > 1 + end + b = nil if b.empty? + volumes_binds b + return DockerBase::PartialHash.new if v.empty? + v.each_with_object(DockerBase::PartialHash.new) { |volume, h| h[volume] = {} } + end + end + + def state + # Always return the latest state, see #510 + return Docker::Container.get(container_name, {}, connection).info['State'] + rescue + return {} + end + + def wait_running_state(v) + tries = running_wait_time + tries.times do + return if state['Running'] == v + sleep 1 + end + return if state['Running'] == v + + # Container failed to reach correct state: Throw an error + desired_state_str = v ? 'running' : 'not running' + raise Docker::Error::TimeoutError, "Container #{container_name} failed to change to #{desired_state_str} state after #{tries} seconds" + end + + def port(v = nil) + return @port if v.nil? + exposed_ports coerce_exposed_ports(v) + port_bindings coerce_port_bindings(v) + @port = v + @port + end + + def parse_port(v) + parts = v.split(':') + case parts.length + when 3 + host_ip = parts[0] + host_port = parts[1] + container_port = parts[2] + when 2 + host_ip = '0.0.0.0' + host_port = parts[0] + container_port = parts[1] + when 1 + host_ip = '' + host_port = '' + container_port = parts[0] + end + port_range, protocol = container_port.split('/') + if port_range.include?('-') + port_range = container_port.split('-') + port_range.map!(&:to_i) + Chef::Log.fatal("FATAL: Invalid port range! #{container_port}") if port_range[0] > port_range[1] + port_range = (port_range[0]..port_range[1]).to_a + end + # qualify the port-binding protocol even when it is implicitly tcp #427. + protocol = 'tcp' if protocol.nil? + Array(port_range).map do |port| + { + 'host_ip' => host_ip, + 'host_port' => host_port, + 'container_port' => "#{port}/#{protocol}", + } + end + end + + def coerce_exposed_ports(v) + case v + when Hash, nil + v + else + x = Array(v).map { |a| parse_port(a) } + x.flatten! + x.each_with_object({}) do |y, h| + h[y['container_port']] = {} + end + end + end + + def coerce_port_bindings(v) + case v + when Hash, nil + v + else + x = Array(v).map { |a| parse_port(a) } + x.flatten! + x.each_with_object({}) do |y, h| + h[y['container_port']] = [] unless h[y['container_port']] + h[y['container_port']] << { + 'HostIp' => y['host_ip'], + 'HostPort' => y['host_port'], + } + end + end + end + + # log_driver and log_opts really handle this + def log_config(value = Chef::NOT_PASSED) + if value != Chef::NOT_PASSED + @log_config = value + log_driver value['Type'] + log_opts value['Config'] + end + return @log_config if defined?(@log_config) + def_logcfg = {} + def_logcfg['Type'] = log_driver if property_is_set?(:log_driver) + def_logcfg['Config'] = log_opts if property_is_set?(:log_opts) + def_logcfg = nil if def_logcfg.empty? + def_logcfg + end + + # TODO: test image property in serverspec and kitchen, not only in rspec + # for full specs of image parsing, see spec/helpers_container_spec.rb + # + # If you say: `repo 'blah'` + # Image will be: `blah:latest` + # + # If you say: `repo 'blah'; tag '3.1'` + # Image will be: `blah:3.1` + # + # If you say: `image 'blah'` + # Repo will be: `blah` + # Tag will be: `latest` + # + # If you say: `image 'blah:3.1'` + # Repo will be: `blah` + # Tag will be: `3.1` + # + # If you say: `image 'repo/blah'` + # Repo will be: `repo/blah` + # Tag will be: `latest` + # + # If you say: `image 'repo/blah:3.1'` + # Repo will be: `repo/blah` + # Tag will be: `3.1` + # + # If you say: `image 'repo:1337/blah'` + # Repo will be: `repo:1337/blah` + # Tag will be: `latest' + # + # If you say: `image 'repo:1337/blah:3.1'` + # Repo will be: `repo:1337/blah` + # Tag will be: `3.1` + # + def image(image = nil) + if image + if image.include?('/') + # pathological case, a ':' may be present which starts the 'port' + # part of the image name and not a tag. example: 'host:1337/blah' + # fortunately, tags are only found in the 'basename' part of image + # so we can split on '/' and rebuild once the tag has been parsed. + dirname, _, basename = image.rpartition('/') + r, t = basename.split(':', 2) + r = [dirname, r].join('/') + else + # normal case, the ':' starts the tag part + r, t = image.split(':', 2) + end + repo r + tag t if t + end + "#{repo}:#{tag}" + end + + def to_shellwords(command) + return nil if command.nil? + Shellwords.shellwords(command) + end + + def ulimits_to_hash + return nil if ulimits.nil? + ulimits.map do |u| + name = u.split('=')[0] + soft = u.split('=')[1].split(':')[0] + hard = u.split('=')[1].split(':')[1] + { 'Name' => name, 'Soft' => soft.to_i, 'Hard' => hard.to_i } + end + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/helpers_image.rb b/chef/cookbooks/docker/libraries/helpers_image.rb new file mode 100644 index 0000000..f08614c --- /dev/null +++ b/chef/cookbooks/docker/libraries/helpers_image.rb @@ -0,0 +1,104 @@ +module DockerCookbook + module DockerHelpers + module Image + ################ + # Helper methods + ################ + + def build_from_directory + i = Docker::Image.build_from_dir( + source, + { + 'nocache' => nocache, + 'rm' => rm, + }, + connection + ) + i.tag('repo' => repo, 'tag' => tag, 'force' => force) + end + + def build_from_dockerfile + i = Docker::Image.build( + IO.read(source), + { + 'nocache' => nocache, + 'rm' => rm, + }, + connection + ) + i.tag('repo' => repo, 'tag' => tag, 'force' => force) + end + + def build_from_tar + i = Docker::Image.build_from_tar( + ::File.open(source, 'r'), + { + 'nocache' => nocache, + 'rm' => rm, + }, + connection + ) + i.tag('repo' => repo, 'tag' => tag, 'force' => force) + end + + def build_image + if ::File.directory?(source) + build_from_directory + elsif ::File.extname(source) == '.tar' + build_from_tar + else + build_from_dockerfile + end + end + + def image_identifier + "#{repo}:#{tag}" + end + + def import_image + with_retries do + i = Docker::Image.import(source, {}, connection) + i.tag('repo' => repo, 'tag' => tag, 'force' => force) + end + end + + def pull_image + with_retries do + registry_host = parse_registry_host(repo) + creds = node.run_state['docker_auth'] && node.run_state['docker_auth'][registry_host] || (node.run_state['docker_auth'] ||= {})['index.docker.io'] + + original_image = Docker::Image.get(image_identifier, {}, connection) if Docker::Image.exist?(image_identifier, {}, connection) + new_image = Docker::Image.create({ 'fromImage' => image_identifier }, creds, connection) + + !(original_image && original_image.id.start_with?(new_image.id)) + end + end + + def push_image + with_retries do + i = Docker::Image.get(image_identifier, {}, connection) + i.push + end + end + + def remove_image + with_retries do + i = Docker::Image.get(image_identifier, {}, connection) + i.remove(force: force, noprune: noprune) + end + end + + def save_image + with_retries do + Docker::Image.save(repo, destination, connection) + end + end + + def load_image + with_retries do + Docker::Image.load(source, {}, connection) + end + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/helpers_installation_binary.rb b/chef/cookbooks/docker/libraries/helpers_installation_binary.rb new file mode 100644 index 0000000..625c8dc --- /dev/null +++ b/chef/cookbooks/docker/libraries/helpers_installation_binary.rb @@ -0,0 +1,66 @@ +module DockerCookbook + module DockerHelpers + module InstallationBinary + def docker_bin + '/usr/bin/docker' + end + + def docker_kernel + node['kernel']['name'] + end + + def docker_arch + node['kernel']['machine'] + end + + def default_source + "https://get.docker.com/builds/#{docker_kernel}/#{docker_arch}/docker-#{version}" + end + + def default_checksum + case docker_kernel + when 'Darwin' + case version + when '1.6.0' then '9e960e925561b4ec2b81f52b6151cd129739c1f4fba91ce94bdc0333d7d98c38' + when '1.6.2' then 'f29b8b2185c291bd276f7cdac45a674f904e964426d5b969fda7b8ef6b8ab557' + when '1.7.0' then '1c8ee59249fdde401afebc9a079cb75d7674f03d2491789fb45c88020a8c5783' + when '1.7.1' then 'b8209b4382d0b4292c756dd055c12e5efacec2055d5900ac91efc8e81d317cf9' + when '1.8.1' then '0f5db35127cf14b57614ad7513296be600ddaa79182d8d118d095cb90c721e3a' + when '1.8.2' then 'cef593612752e5a50bd075931956075a534b293b7002892072397c3093fe11a6' + when '1.8.3' then 'b5a63a0e6fb393de8c3543c83433224796c7545901963ff3e3e9a41b1430c9cd' + when '1.9.0' then '91a8701e41a479def5371a333657c58c36478602e1f5eb1835457a3880232a2e' + when '1.9.1' then '8750ccc2098ec94ef7db110e0016ab02cfa47a1a76f0deb3faa50335b5ec0df9' + when '1.10.0' then 'f8dc0c7ef2a7efbe0e062017822066e55a40c752b9e92a636359f59ef562d79f' + when '1.10.1' then 'de4057057acd259ec38b5244a40d806993e2ca219e9869ace133fad0e09cedf2' + when '1.10.2' then '29249598587ad8f8597235bbeb11a11888fffb977b8089ea80b5ac5267ba9f2e' + end + when 'Linux' + case version + when '1.6.0' then '526fbd15dc6bcf2f24f99959d998d080136e290bbb017624a5a3821b63916ae8' + when '1.6.2' then 'e131b2d78d9f9e51b0e5ca8df632ac0a1d48bcba92036d0c839e371d6cf960ec' + when '1.7.1' then '4d535a62882f2123fb9545a5d140a6a2ccc7bfc7a3c0ec5361d33e498e4876d5' + when '1.8.1' then '843f90f5001e87d639df82441342e6d4c53886c65f72a5cc4765a7ba3ad4fc57' + when '1.8.2' then '97a3f5924b0b831a310efa8bf0a4c91956cd6387c4a8667d27e2b2dd3da67e4d' + when '1.8.3' then 'f024bc65c45a3778cf07213d26016075e8172de8f6e4b5702bedde06c241650f' + when '1.9.0' then '5d46455aac507e231fd2a558459779f1994f7151d6cb027efabfa36f568cf017' + when '1.9.1' then '52286a92999f003e1129422e78be3e1049f963be1888afc3c9a99d5a9af04666' + when '1.10.0' then 'a66b20423b7d849aa8ef448b98b41d18c45a30bf3fe952cc2ba4760600b18087' + when '1.10.1' then 'de4057057acd259ec38b5244a40d806993e2ca219e9869ace133fad0e09cedf2' + when '1.10.2' then '3fcac4f30e1c1a346c52ba33104175ae4ccbd9b9dbb947f56a0a32c9e401b768' + end + end + end + + def default_version + if node['platform'] == 'amazon' || + node['platform'] == 'ubuntu' && node['platform_version'].to_f < 15.04 || + node['platform_family'] == 'rhel' && node['platform_version'].to_i < 7 || + node['platform_family'] == 'debian' && node['platform_version'].to_i <= 7 + '1.6.2' + else + '1.10.2' + end + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/helpers_installation_package.rb b/chef/cookbooks/docker/libraries/helpers_installation_package.rb new file mode 100644 index 0000000..6d738fa --- /dev/null +++ b/chef/cookbooks/docker/libraries/helpers_installation_package.rb @@ -0,0 +1,105 @@ +module DockerCookbook + module DockerHelpers + module InstallationPackage + def el6? + return true if node['platform_family'] == 'rhel' && node['platform_version'].to_i == 6 + false + end + + def el7? + return true if node['platform_family'] == 'rhel' && node['platform_version'].to_i == 7 + false + end + + def fedora? + return true if node['platform'] == 'fedora' + false + end + + def wheezy? + return true if node['platform'] == 'debian' && node['platform_version'].to_i == 7 + false + end + + def jesse? + return true if node['platform'] == 'debian' && node['platform_version'].to_i == 8 + false + end + + def precise? + return true if node['platform'] == 'ubuntu' && node['platform_version'] == '12.04' + false + end + + def trusty? + return true if node['platform'] == 'ubuntu' && node['platform_version'] == '14.04' + return true if node['platform'] == 'linuxmint' && node['platform_version'] =~ /^17\.[0-9]$/ + false + end + + def vivid? + return true if node['platform'] == 'ubuntu' && node['platform_version'] == '15.04' + false + end + + def wily? + return true if node['platform'] == 'ubuntu' && node['platform_version'] == '15.10' + false + end + + def xenial? + return true if node['platform'] == 'ubuntu' && node['platform_version'] == '16.04' + false + end + + def amazon? + return true if node['platform'] == 'amazon' + false + end + + # https://github.com/chef/chef/issues/4103 + def version_string(v) + ubuntu_prefix = if Gem::Version.new(v) > Gem::Version.new('1.12.3') + 'ubuntu-' + else + '' + end + + debian_prefix = if Gem::Version.new(v) > Gem::Version.new('1.12.3') + 'debian-' + else + '' + end + + return "#{v}-1.el6" if el6? + return "#{v}-1.el7.centos" if el7? + return "#{v}-1.17.amzn1" if amazon? + return "#{v}-1.fc#{node['platform_version'].to_i}" if fedora? + return "#{v}-0~#{debian_prefix}wheezy" if wheezy? + return "#{v}-0~#{debian_prefix}jessie" if jesse? + return "#{v}-0~#{ubuntu_prefix}precise" if precise? + return "#{v}-0~#{ubuntu_prefix}trusty" if trusty? + return "#{v}-0~#{ubuntu_prefix}vivid" if vivid? + return "#{v}-0~#{ubuntu_prefix}wily" if wily? + return "#{v}-0~#{ubuntu_prefix}xenial" if xenial? + v + end + + def default_docker_version + return '1.7.1' if el6? + return '1.9.1' if vivid? + return '1.12.6' if amazon? + '1.13.1' + end + + def default_package_name + return 'docker' if amazon? + 'docker-engine' + end + + def docker_bin + '/usr/bin/docker' + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/helpers_installation_tarball.rb b/chef/cookbooks/docker/libraries/helpers_installation_tarball.rb new file mode 100644 index 0000000..dd3c27c --- /dev/null +++ b/chef/cookbooks/docker/libraries/helpers_installation_tarball.rb @@ -0,0 +1,50 @@ +module DockerCookbook + module DockerHelpers + module InstallationTarball + def docker_bin_prefix + '/usr/bin' + end + + def docker_bin + "#{docker_bin_prefix}/docker" + end + + def docker_tarball + "#{Chef::Config[:file_cache_path]}/docker-#{version}.tgz" + end + + def docker_kernel + node['kernel']['name'] + end + + def docker_arch + node['kernel']['machine'] + end + + def default_source + "https://get.docker.com/builds/#{docker_kernel}/#{docker_arch}/docker-#{version}.tgz" + end + + def default_checksum + case docker_kernel + when 'Darwin' + case version + when '1.11.0' then '25e4f5f37e2e17beb20e5a468674750350824059bdeeca09d6a941bca8fc4f73' + when '1.11.1' then '6d35487fbcc7e3f722f3d5f3e5c070a41d87c88e3770f52ae28460a689c40efd' + when '1.11.2' then 'f44da1025c355c51ae6e150fcc0672b87a738b9c8ad98e5fa6091502211da19a' + end + when 'Linux' + case version + when '1.11.0' then '87331b3b75d32d3de5d507db9a19a24dd30ff9b2eb6a5a9bdfaba954da15e16b' + when '1.11.1' then '893e3c6e89c0cd2c5f1e51ea41bc2dd97f5e791fcfa3cee28445df277836339d' + when '1.11.2' then '8c2e0c35e3cda11706f54b2d46c2521a6e9026a7b13c7d4b8ae1f3a706fc55e1' + end + end + end + + def default_version + '1.11.2' + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/helpers_network.rb b/chef/cookbooks/docker/libraries/helpers_network.rb new file mode 100644 index 0000000..b42ee24 --- /dev/null +++ b/chef/cookbooks/docker/libraries/helpers_network.rb @@ -0,0 +1,118 @@ +module DockerCookbook + module DockerHelpers + module Network + require 'ipaddr' + + ################### + # property coersion + ################### + + def coerce_auxiliary_addresses(v) + ray = [] + Array(v).each do |e| + case e + when String, Array, nil + ray += Array(e) + when Hash + e.each { |key, val| ray << "#{key}=#{val}" } + end + end + ray.length == 1 ? ray[0] : ray + end + + def coerce_gateway(v) + case v + when String + v.split('/')[0] + when Array + ray = Array(v).map { |a| a.split('/')[0] } + ray.length == 1 ? ray[0] : ray + end + end + + def coerce_subnet(v) + Array(v).length == 1 ? Array(v)[0] : v + end + + def coerce_ip_range(v) + Array(v).length == 1 ? Array(v)[0] : v + end + + ###### + # IPAM + ###### + + def consolidate_ipam(subnets, ranges, gateways, auxaddrs) + subnets = Array(subnets) + ranges = Array(ranges) + gateways = Array(gateways) + auxaddrs = Array(auxaddrs) + subnets = [] if subnets.empty? + ranges = [] if ranges.empty? + gateways = [] if gateways.empty? + auxaddrs = [] if auxaddrs.empty? + if subnets.size < ranges.size || subnets.size < gateways.size + raise 'every ip-range or gateway myust have a corresponding subnet' + end + + data = {} + + # Check overlapping subnets + subnets.each do |s| + data.each do |k, _| + if subnet_matches(s, k) || subnet_matches(k, s) + raise 'multiple overlapping subnet configuration is not supported' + end + end + data[s] = { 'Subnet' => s, 'AuxiliaryAddresses' => {} } + end + + ranges.each do |r| + match = false + subnets.each do |s| + ok = subnet_matches(s, r) + next unless ok + if data[s].fetch('IPRange', '') != '' + raise 'cannot configure multiple ranges on the same subnet' + end + data[s]['IPRange'] = r + match = true + end + raise "no matching subnet for range #{r}" unless match + end + + gateways.each do |g| + match = false + subnets.each do |s| + ok = subnet_matches(s, g) + next unless ok + unless data[s].fetch('Gateway', '').empty? + raise "cannot configure multiple gateways (#{g}, #{data[s]['Gateway']}) for the same subnet (#{s})" + end + data[s]['Gateway'] = g + match = true + end + raise "no matching subnet for gateway #{s}" unless match + end + + auxaddrs.each do |aa| + key, a = aa.split('=') + match = false + subnets.each do |s| + # require 'pry' ; binding.pry + ok = subnet_matches(s, a) + next unless ok + data[s]['AuxiliaryAddresses'][key] = a + match = true + end + raise "no matching subnet for aux-address #{a}" unless match + end + data.values + end + + def subnet_matches(subnet, data) + IPAddr.new(subnet).include?(IPAddr.new(data)) + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/helpers_service.rb b/chef/cookbooks/docker/libraries/helpers_service.rb new file mode 100644 index 0000000..320ab63 --- /dev/null +++ b/chef/cookbooks/docker/libraries/helpers_service.rb @@ -0,0 +1,223 @@ +# Constants +IPV6_ADDR ||= /( +([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}| +([0-9a-fA-F]{1,4}:){1,7}:| +([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}| +([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}| +([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}| +([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}| +([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}| +[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})| +:((:[0-9a-fA-F]{1,4}){1,7}|:)| +fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}| +::(ffff(:0{1,4}){0,1}:){0,1} +((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3} +(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])| +([0-9a-fA-F]{1,4}:){1,4}: +((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3} +(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]) +)/ + +IPV4_ADDR ||= /((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])/ + +IPV6_CIDR ||= /s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*/ + +IPV4_CIDR ||= %r{(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))} + +module DockerCookbook + module DockerHelpers + module Service + def docker_bin + '/usr/bin/docker' + end + + def dockerd_bin + return '/usr/bin/docker' if Gem::Version.new(docker_major_version) < Gem::Version.new('1.12') + '/usr/bin/dockerd' + end + + def dockerd_bin_link + "/usr/bin/dockerd-#{name}" + end + + def docker_name + return 'docker' if name == 'default' + "docker-#{name}" + end + + def installed_docker_version + o = shell_out("#{docker_bin} --version") + o.stdout.split[2].chomp(',') + end + + def connect_host + return nil unless host + sorted = coerce_host(host).sort do |a, b| + c_a = 1 if a =~ /^unix:/ + c_a = 2 if a =~ /^fd:/ + c_a = 3 if a =~ %r{^tcp://127.0.0.1:} + c_a = 4 if a =~ %r{^tcp://(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.).*:} + c_a = 5 if a =~ %r{^tcp://0.0.0.0:} + c_a = 6 unless c_a + c_b = 1 if b =~ /^unix:/ + c_b = 2 if b =~ /^fd:/ + c_b = 3 if b =~ %r{^tcp://127.0.0.1:} + c_b = 4 if b =~ %r{^tcp://(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.).*:} + c_b = 5 if b =~ %r{^tcp://0.0.0.0:} + c_b = 6 unless c_b + c_a <=> c_b + end + if sorted.first =~ %r{^tcp://0.0.0.0:} + r = sorted.first.match(%r{(?.*)://(?[^:]+):?(?\d+)?}) + return "tcp://127.0.0.1:#{r['port']}" + end + sorted.first + end + + def connect_socket + return "/var/run/#{docker_name}.sock" unless host + sorted = coerce_host(host).sort do |a, b| + c_a = 1 if a =~ /^unix:/ + c_a = 2 if a =~ /^fd:/ + c_a = 3 unless c_a + c_b = 1 if b =~ /^unix:/ + c_b = 2 if b =~ /^fd:/ + c_b = 3 unless c_b + c_a <=> c_b + end + sorted.first + end + + def coerce_host(v) + v = v.split if v.is_a?(String) + Array(v).each_with_object([]) do |s, r| + if s.match(/^unix:/) || s.match(/^tcp:/) || s.match(/^fd:/) + r << s + else + Chef::Log.info("WARNING: docker_service host property #{s} not valid") + end + end + end + + def coerce_daemon_labels(v) + Array(v).each_with_object([]) do |label, a| + if label =~ /:/ + parts = label.split(':') + a << "#{parts[0]}=\"#{parts[1]}\"" + elsif label =~ /=/ + parts = label.split('=') + a << "#{parts[0]}=#{parts[1]}" + else + Chef::Log.info("WARNING: docker_service label #{label} not valid") + end + end + end + + def coerce_insecure_registry(v) + case v + when Array, nil + v + else + Array(v) + end + end + + def docker_major_version + ray = installed_docker_version.split('.') + ray.pop + ray.push.join('.') + end + + def docker_daemon_arg + if Gem::Version.new(docker_major_version) < Gem::Version.new('1.8') + '-d' + elsif Gem::Version.new(docker_major_version) < Gem::Version.new('1.12') + 'daemon' + else + '' + end + end + + def docker_daemon_cmd + [dockerd_bin, docker_daemon_arg, docker_daemon_opts].join(' ') + end + + def docker_cmd + [docker_bin, docker_opts].join(' ') + end + + def docker_opts + opts = [] + opts << "--host=#{connect_host}" if connect_host + if connect_host =~ /^tcp:/ + opts << "--tls=#{tls}" unless tls.nil? + opts << "--tlsverify=#{tls_verify}" unless tls_verify.nil? + opts << "--tlscacert=#{tls_ca_cert}" if tls_ca_cert + opts << "--tlscert=#{tls_client_cert}" if tls_client_cert + opts << "--tlskey=#{tls_client_key}" if tls_client_key + end + opts + end + + def systemd_args + opts = '' + systemd_opts.each { |systemd_opt| opts << "#{systemd_opt}\n" } if systemd_opts + opts + end + + def docker_daemon_opts + opts = [] + opts << "--api-cors-header=#{api_cors_header}" if api_cors_header + opts << "--bridge=#{bridge}" if bridge + opts << "--bip=#{bip}" if bip + opts << '--debug' if debug + opts << "--cluster-advertise=#{cluster_advertise}" if cluster_advertise + opts << "--cluster-store=#{cluster_store}" if cluster_store + cluster_store_opts.each { |store_opt| opts << "--cluster-store-opt=#{store_opt}" } if cluster_store_opts + default_ulimit.each { |u| opts << "--default-ulimit=#{u}" } if default_ulimit + dns.each { |dns| opts << "--dns=#{dns}" } if dns + dns_search.each { |dns| opts << "--dns-search=#{dns}" } if dns_search + opts << "--exec-driver=#{exec_driver}" if exec_driver + exec_opts.each { |exec_opt| opts << "--exec-opt=#{exec_opt}" } if exec_opts + opts << "--fixed-cidr=#{fixed_cidr}" if fixed_cidr + opts << "--fixed-cidr-v6=#{fixed_cidr_v6}" if fixed_cidr_v6 + opts << "--group=#{group}" if group + opts << "--graph=#{graph}" if graph + host.each { |h| opts << "-H #{h}" } if host + opts << "--icc=#{icc}" unless icc.nil? + insecure_registry.each { |i| opts << "--insecure-registry=#{i}" } if insecure_registry + opts << "--ip=#{ip}" if ip + opts << "--ip-forward=#{ip_forward}" unless ip_forward.nil? + opts << "--ip-masq=#{ip_masq}" unless ip_masq.nil? + opts << "--iptables=#{iptables}" unless iptables.nil? + opts << "--ipv6=#{ipv6}" unless ipv6.nil? + opts << "--log-level=#{log_level}" if log_level + labels.each { |l| opts << "--label=#{l}" } if labels + opts << "--log-driver=#{log_driver}" if log_driver + log_opts.each { |log_opt| opts << "--log-opt #{log_opt}" } if log_opts + opts << "--mtu=#{mtu}" if mtu + opts << "--pidfile=#{pidfile}" if pidfile + opts << "--registry-mirror=#{registry_mirror}" if registry_mirror + storage_driver.each { |s| opts << "--storage-driver=#{s}" } if storage_driver + opts << "--selinux-enabled=#{selinux_enabled}" unless selinux_enabled.nil? + storage_opts.each { |storage_opt| opts << "--storage-opt=#{storage_opt}" } if storage_opts + opts << "--tls=#{tls}" unless tls.nil? + opts << "--tlsverify=#{tls_verify}" unless tls_verify.nil? + opts << "--tlscacert=#{tls_ca_cert}" if tls_ca_cert + opts << "--tlscert=#{tls_server_cert}" if tls_server_cert + opts << "--tlskey=#{tls_server_key}" if tls_server_key + opts << "--userland-proxy=#{userland_proxy}" unless userland_proxy.nil? + opts << "--disable-legacy-registry=#{disable_legacy_registry}" unless disable_legacy_registry.nil? + opts << "--userns-remap=#{userns_remap}" if userns_remap + opts << misc_opts if misc_opts + opts + end + + def docker_running? + o = shell_out("#{docker_cmd} ps | head -n 1 | grep ^CONTAINER") + return true if o.stdout =~ /CONTAINER/ + false + end + end + end +end diff --git a/chef/cookbooks/docker/libraries/matchers.rb b/chef/cookbooks/docker/libraries/matchers.rb new file mode 100644 index 0000000..87cb23d --- /dev/null +++ b/chef/cookbooks/docker/libraries/matchers.rb @@ -0,0 +1,339 @@ +if defined?(ChefSpec) + ##################### + # docker_installation + ##################### + ChefSpec.define_matcher :docker_installation + + def create_docker_installation(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_installation, :create, resource_name) + end + + def delete_docker_installation(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_installation, :delete, resource_name) + end + + def create_docker_installation_binary(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_installation_binary, :create, resource_name) + end + + def delete_docker_installation_binary(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_installation_binary, :delete, resource_name) + end + + def create_docker_installation_script(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_installation_script, :create, resource_name) + end + + def delete_docker_installation_script(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_installation_script, :delete, resource_name) + end + + def create_docker_installation_package(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_installation_package, :create, resource_name) + end + + def delete_docker_installation_package(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_installation_package, :delete, resource_name) + end + + def create_docker_installation_tarball(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_installation_tarball, :create, resource_name) + end + + def delete_docker_installation_tarball(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_installation_tarball, :delete, resource_name) + end + + ################ + # docker_service + ################ + ChefSpec.define_matcher :docker_service + + def create_docker_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service, :create, resource_name) + end + + def delete_docker_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service, :delete, resource_name) + end + + def start_docker_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service, :start, resource_name) + end + + def stop_docker_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service, :stop, resource_name) + end + + def restart_docker_service(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service, :restart, resource_name) + end + + ######################## + # docker_service_manager + ######################## + ChefSpec.define_matcher :docker_service_manager + + def create_docker_service_manager(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager, :create, resource_name) + end + + def delete_docker_service_manager(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager, :delete, resource_name) + end + + def start_docker_service_manager(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager, :start, resource_name) + end + + def stop_docker_service_manager(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager, :stop, resource_name) + end + + def restart_docker_service_manager(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager, :restart, resource_name) + end + + def create_docker_service_manager_execute(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_execute, :create, resource_name) + end + + def delete_docker_service_manager_execute(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_execute, :delete, resource_name) + end + + def start_docker_service_manager_execute(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_execute, :start, resource_name) + end + + def stop_docker_service_manager_execute(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_execute, :stop, resource_name) + end + + def restart_docker_service_manager_execute(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_execute, :restart, resource_name) + end + + def create_docker_service_manager_sysvinit(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_sysvinit, :create, resource_name) + end + + def delete_docker_service_manager_sysvinit(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_sysvinit, :delete, resource_name) + end + + def start_docker_service_manager_sysvinit(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_sysvinit, :start, resource_name) + end + + def stop_docker_service_manager_sysvinit(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_sysvinit, :stop, resource_name) + end + + def restart_docker_service_manager_sysvinit(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_sysvinit, :restart, resource_name) + end + + def create_docker_service_manager_upstart(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_upstart, :create, resource_name) + end + + def delete_docker_service_manager_upstart(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_upstart, :delete, resource_name) + end + + def start_docker_service_manager_upstart(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_upstart, :start, resource_name) + end + + def stop_docker_service_manager_upstart(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_upstart, :stop, resource_name) + end + + def restart_docker_service_manager_upstart(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_upstart, :restart, resource_name) + end + + def create_docker_service_manager_systemd(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_systemd, :create, resource_name) + end + + def delete_docker_service_manager_systemd(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_systemd, :delete, resource_name) + end + + def start_docker_service_manager_systemd(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_systemd, :start, resource_name) + end + + def stop_docker_service_manager_systemd(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_systemd, :stop, resource_name) + end + + def restart_docker_service_manager_systemd(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_service_manager_systemd, :restart, resource_name) + end + + ############## + # docker_image + ############## + ChefSpec.define_matcher :docker_image + + def build_docker_image(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_image, :build, resource_name) + end + + def build_if_missing_docker_image(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_image, :build_if_missing, resource_name) + end + + def pull_docker_image(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_image, :pull, resource_name) + end + + def pull_if_missing_docker_image(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_image, :pull_if_missing, resource_name) + end + + def import_docker_image(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_image, :import, resource_name) + end + + def push_docker_image(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_image, :push, resource_name) + end + + def remove_docker_image(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_image, :remove, resource_name) + end + + def save_docker_image(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_image, :save, resource_name) + end + + def load_docker_image(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_image, :load, resource_name) + end + + ################## + # docker_container + ################## + ChefSpec.define_matcher :docker_container + + def create_docker_container(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_container, :create, resource_name) + end + + def start_docker_container(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_container, :start, resource_name) + end + + def stop_docker_container(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_container, :stop, resource_name) + end + + def kill_docker_container(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_container, :kill, resource_name) + end + + def run_docker_container(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_container, :run, resource_name) + end + + def run_if_missing_docker_container(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_container, :run_if_missing, resource_name) + end + + def pause_docker_container(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_container, :pause, resource_name) + end + + def unpause_docker_container(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_container, :unpause, resource_name) + end + + def restart_docker_container(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_container, :restart, resource_name) + end + + def redeploy_docker_container(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_container, :redeploy, resource_name) + end + + def delete_docker_container(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_container, :delete, resource_name) + end + + def remove_docker_container(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_container, :remove, resource_name) + end + + def commit_docker_container(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_container, :commit, resource_name) + end + + def export_docker_container(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_container, :export, resource_name) + end + + ############## + # docker_tag + ############## + ChefSpec.define_matcher :docker_tag + + def tag_docker_tag(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_tag, :tag, resource_name) + end + + ################# + # docker_registry + ################# + ChefSpec.define_matcher :docker_registry + + def login_docker_registry(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_registry, :login, resource_name) + end + + ################ + # docker_network + ################ + ChefSpec.define_matcher :docker_network + + def create_docker_network(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_network, :create, resource_name) + end + + def delete_docker_network(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_network, :delete, resource_name) + end + + def connect_docker_network(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_network, :connect, resource_name) + end + + def disconnect_docker_network(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_network, :disconnect, resource_name) + end + + ############### + # docker_volume + ############### + ChefSpec.define_matcher :docker_volume + + def create_docker_volume(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_volume, :create, resource_name) + end + + def remove_docker_volume(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_volume, :remove, resource_name) + end + + ############### + # docker_exec + ############### + ChefSpec.define_matcher :docker_exec + + def run_docker_exec(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:docker_exec, :run, resource_name) + end +end diff --git a/chef/cookbooks/docker/metadata.json b/chef/cookbooks/docker/metadata.json new file mode 100644 index 0000000..d40d638 --- /dev/null +++ b/chef/cookbooks/docker/metadata.json @@ -0,0 +1 @@ +{"name":"docker","version":"2.15.2","description":"Provides docker_service, docker_image, and docker_container resources","long_description":"","maintainer":"Cookbook Engineering Team","maintainer_email":"cookbooks@chef.io","license":"Apache 2.0","platforms":{"amazon":">= 0.0.0","centos":">= 0.0.0","scientific":">= 0.0.0","oracle":">= 0.0.0","debian":">= 0.0.0","fedora":">= 0.0.0","redhat":">= 0.0.0","ubuntu":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{}} \ No newline at end of file diff --git a/chef/cookbooks/docker/templates/default/default/docker-wait-ready.erb b/chef/cookbooks/docker/templates/default/default/docker-wait-ready.erb new file mode 100644 index 0000000..3531221 --- /dev/null +++ b/chef/cookbooks/docker/templates/default/default/docker-wait-ready.erb @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +i=0 +while [ $i -lt <%= @service_timeout * 2 %> ]; do + <%= @docker_cmd %> ps | head -n 1 | grep ^CONTAINER > /dev/null 2>&1 + [ $? -eq 0 ] && break + ((i++)) + sleep 0.5 +done +[ $i -eq <%= @service_timeout * 2 %> ] && exit 1 +exit 0 diff --git a/chef/cookbooks/docker/templates/default/default/docker.erb b/chef/cookbooks/docker/templates/default/default/docker.erb new file mode 100644 index 0000000..d798cec --- /dev/null +++ b/chef/cookbooks/docker/templates/default/default/docker.erb @@ -0,0 +1,24 @@ +# Docker Upstart and SysVinit configuration file + +# Customize location of Docker binary (especially for development testing). +DOCKER="<%= @dockerd_bin_link %>" + +# Use DOCKER_OPTS to modify the daemon startup options. +DOCKER_OPTS="<%= @docker_daemon_opts %>" + +# If you need Docker to use an HTTP proxy, it can also be specified here. +<% if @config.http_proxy %> +export http_proxy="<%= @config.http_proxy %>" +<% end %> +<% if @config.https_proxy %> +export https_proxy="<%= @config.https_proxy %>" +<% end %> + +<% if @config.no_proxy %> +export no_proxy="<%= @config.no_proxy %>" +<% end %> + +# This is also a handy place to tweak where Docker's temporary files go. +<% if @config.tmpdir %> +export TMPDIR="<%= @config.tmpdir %>" +<% end %> diff --git a/chef/cookbooks/docker/templates/default/sysconfig/docker.erb b/chef/cookbooks/docker/templates/default/sysconfig/docker.erb new file mode 100755 index 0000000..b132240 --- /dev/null +++ b/chef/cookbooks/docker/templates/default/sysconfig/docker.erb @@ -0,0 +1,19 @@ +# /etc/sysconfig/docker +# +# Other arguments to pass to the docker daemon process +# These will be parsed by the sysv initscript and appended +# to the arguments list passed to docker + +other_args="<%= @docker_daemon_opts %>" + +# If you need Docker to use an HTTP proxy, it can also be specified here. +<% if @config.http_proxy %> +export http_proxy="<%= @config.http_proxy %>" +<% end %> +<% if @config.https_proxy %> +export https_proxy="<%= @config.https_proxy %>" +<% end %> + +<% if @config.no_proxy %> +export no_proxy="<%= @config.no_proxy %>" +<% end %> diff --git a/chef/cookbooks/docker/templates/default/systemd/docker.service-override.erb b/chef/cookbooks/docker/templates/default/systemd/docker.service-override.erb new file mode 100644 index 0000000..8c0f83e --- /dev/null +++ b/chef/cookbooks/docker/templates/default/systemd/docker.service-override.erb @@ -0,0 +1,36 @@ +[Unit] +Description=Docker Application Container Engine +Documentation=http://docs.docker.com +After=network.target + +[Service] +Type=notify +<% if @config.http_proxy %> +Environment="HTTP_PROXY=<%= @config.http_proxy %>" +<% end %> +<% if @config.https_proxy %> +Environment="HTTPS_PROXY=<%= @config.https_proxy %>" +<% end %> +<% if @config.no_proxy %> +Environment="NO_PROXY=<%= @config.no_proxy %>" +<% end %> +<% if @config.tmpdir %> +Environment="TMPDIR=<%= @config.tmpdir %>" +<% end %> +<% if @config.ipv4_forward %> +ExecStartPre=/sbin/sysctl -w net.ipv4.ip_forward=1 +<% end %> +<% if @config.ipv6_forward %> +ExecStartPre=/sbin/sysctl -w net.ipv6.conf.all.forwarding=1 +<% end %> +ExecStart=<%= @docker_daemon_cmd %> +ExecStartPost=<%= @docker_wait_ready %> +Restart=always +MountFlags=<%= @docker_mount_flags %> +LimitNOFILE=1048576 +LimitNPROC=1048576 +LimitCORE=infinity +<%= @systemd_args %> + +[Install] +WantedBy=multi-user.target diff --git a/chef/cookbooks/docker/templates/default/systemd/docker.service.erb b/chef/cookbooks/docker/templates/default/systemd/docker.service.erb new file mode 100644 index 0000000..5c924d8 --- /dev/null +++ b/chef/cookbooks/docker/templates/default/systemd/docker.service.erb @@ -0,0 +1,18 @@ +[Unit] +Description=Docker Application Container Engine +Documentation=https://docs.docker.com +After=network.target <%= @docker_name %>.socket +Requires=<%= @docker_name %>.socket + +[Service] +Type=notify +ExecStart=/usr/bin/docker daemon -H fd:// +MountFlags=<%= @docker_mount_flags %> +LimitNOFILE=1048576 +LimitNPROC=1048576 +LimitCORE=infinity +TasksMax=1048576 +TimeoutStartSec=0 + +[Install] +WantedBy=multi-user.target diff --git a/chef/cookbooks/docker/templates/default/systemd/docker.socket-override.erb b/chef/cookbooks/docker/templates/default/systemd/docker.socket-override.erb new file mode 100644 index 0000000..7e6b705 --- /dev/null +++ b/chef/cookbooks/docker/templates/default/systemd/docker.socket-override.erb @@ -0,0 +1,12 @@ +[Unit] +Description=Docker Socket for the API +PartOf=<%= @docker_name %>.service + +[Socket] +ListenStream=<%= @docker_socket %> +SocketMode=0660 +SocketUser=root +SocketGroup=<%= @config.group %> + +[Install] +WantedBy=sockets.target diff --git a/chef/cookbooks/docker/templates/default/systemd/docker.socket.erb b/chef/cookbooks/docker/templates/default/systemd/docker.socket.erb new file mode 100644 index 0000000..22b452d --- /dev/null +++ b/chef/cookbooks/docker/templates/default/systemd/docker.socket.erb @@ -0,0 +1,12 @@ +[Unit] +Description=Docker Socket for the API +PartOf=<%= @docker_name %>.service + +[Socket] +ListenStream=<%= @docker_socket %> +SocketMode=0660 +SocketUser=root +SocketGroup=docker + +[Install] +WantedBy=sockets.target diff --git a/chef/cookbooks/docker/templates/default/systemd/tmpfiles.d.conf.erb b/chef/cookbooks/docker/templates/default/systemd/tmpfiles.d.conf.erb new file mode 100644 index 0000000..a77e3fd --- /dev/null +++ b/chef/cookbooks/docker/templates/default/systemd/tmpfiles.d.conf.erb @@ -0,0 +1 @@ +d /var/run/docker 0755 root <%= @config.group || 'root' %> - diff --git a/chef/cookbooks/docker/templates/default/sysvinit/docker-debian.erb b/chef/cookbooks/docker/templates/default/sysvinit/docker-debian.erb new file mode 100644 index 0000000..bd1ffbf --- /dev/null +++ b/chef/cookbooks/docker/templates/default/sysvinit/docker-debian.erb @@ -0,0 +1,149 @@ +#!/bin/sh +set -e + +### BEGIN INIT INFO +# Provides: <%= @docker_name %> +# Required-Start: $syslog $remote_fs +# Required-Stop: $syslog $remote_fs +# Should-Start: cgroupfs-mount cgroup-lite +# Should-Stop: cgroupfs-mount cgroup-lite +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Create lightweight, portable, self-sufficient containers. +# Description: +# Docker is an open-source project to easily create lightweight, portable, +# self-sufficient containers from any application. The same container that a +# developer builds and tests on a laptop can run at scale, in production, on +# VMs, bare metal, OpenStack clusters, public clouds and more. +### END INIT INFO + +export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin + +BASE=<%= @docker_name %> + +# modify these in /etc/default/$BASE (/etc/default/docker) +DOCKER=<%= @dockerd_bin_link %> +# This is the pid file managed by docker itself +DOCKER_PIDFILE=/var/run/$BASE.pid +# This is the pid file created/managed by start-stop-daemon +DOCKER_SSD_PIDFILE=/var/run/$BASE-ssd.pid +DOCKER_LOGFILE=/var/log/$BASE.log +DOCKER_DESC="Docker" + +# Get lsb functions +. /lib/lsb/init-functions + +if [ -f /etc/default/$BASE ]; then + . /etc/default/$BASE +fi + +# Check docker is present +if [ ! -x $DOCKER ]; then + log_failure_msg "$DOCKER not present or not executable" + exit 1 +fi + +check_init() { + # see also init_is_upstart in /lib/lsb/init-functions (which isn't available in Ubuntu 12.04, or we'd use it directly) + if [ -x /sbin/initctl ] && /sbin/initctl version 2>/dev/null | grep -q upstart; then + log_failure_msg "$DOCKER_DESC is managed via upstart, try using service $BASE $1" + exit 1 + fi +} + +fail_unless_root() { + if [ "$(id -u)" != '0' ]; then + log_failure_msg "$DOCKER_DESC must be run as root" + exit 1 + fi +} + +cgroupfs_mount() { + # see also https://github.com/tianon/cgroupfs-mount/blob/master/cgroupfs-mount + if grep -v '^#' /etc/fstab | grep -q cgroup \ + || [ ! -e /proc/cgroups ] \ + || [ ! -d /sys/fs/cgroup ]; then + return + fi + if ! mountpoint -q /sys/fs/cgroup; then + mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup + fi + ( + cd /sys/fs/cgroup + for sys in $(awk '!/^#/ { if ($4 == 1) print $1 }' /proc/cgroups); do + mkdir -p $sys + if ! mountpoint -q $sys; then + if ! mount -n -t cgroup -o $sys cgroup $sys; then + rmdir $sys || true + fi + fi + done + ) +} + +case "$1" in + start) + check_init + + fail_unless_root + + cgroupfs_mount + + touch "$DOCKER_LOGFILE" + chgrp docker "$DOCKER_LOGFILE" + + ulimit -n 1048576 + if [ "$BASH" ]; then + ulimit -u 1048576 + else + ulimit -p 1048576 + fi + + log_begin_msg "Starting $DOCKER_DESC: $BASE" + start-stop-daemon --start --background \ + --no-close \ + --exec "$DOCKER" \ + --pidfile "$DOCKER_SSD_PIDFILE" \ + --make-pidfile \ + -- \ + <%= @docker_daemon_arg %> -p "$DOCKER_PID_FILE" \ + $DOCKER_OPTS \ + >> "$DOCKER_LOGFILE" 2>&1 + <%= @docker_wait_ready %> + log_end_msg $? + ;; + + stop) + check_init + fail_unless_root + log_begin_msg "Stopping $DOCKER_DESC: $BASE" + start-stop-daemon --stop --pidfile "$DOCKER_SSD_PIDFILE" --retry 10 + log_end_msg $? + ;; + + restart) + check_init + fail_unless_root + docker_pid=`cat "$DOCKER_SSD_PIDFILE" 2>/dev/null` + [ -n "$docker_pid" ] \ + && ps -p $docker_pid > /dev/null 2>&1 \ + && $0 stop + $0 start + ;; + + force-reload) + check_init + fail_unless_root + $0 restart + ;; + + status) + check_init + status_of_proc -p "$DOCKER_SSD_PIDFILE" "$DOCKER" "$DOCKER_DESC" + ;; + + *) + echo "Usage: service docker {start|stop|restart|status}" + exit 1 + ;; +esac diff --git a/chef/cookbooks/docker/templates/default/sysvinit/docker-rhel.erb b/chef/cookbooks/docker/templates/default/sysvinit/docker-rhel.erb new file mode 100644 index 0000000..98e758f --- /dev/null +++ b/chef/cookbooks/docker/templates/default/sysvinit/docker-rhel.erb @@ -0,0 +1,133 @@ +#!/bin/sh +# +# /etc/rc.d/init.d/<%= @docker_name %> +# +# Daemon for docker.com +# +# chkconfig: 2345 95 95 +# description: Daemon for docker.com + +### BEGIN INIT INFO +# Provides: docker +# Required-Start: $network cgconfig +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: start and stop docker +# Description: Daemon for docker.com +### END INIT INFO + +# Source function library. +. /etc/rc.d/init.d/functions + +prog="<%= @dockerd_bin_link %>" +instance=<%= @docker_name %> +unshare=/usr/bin/unshare +exec="$prog" +pidfile="/var/run/$instance.pid" +lockfile="/var/lock/subsys/$instance" +logfile="/var/log/$instance" + +[ -e /etc/sysconfig/$instance ] && . /etc/sysconfig/$instance + +prestart() { + service cgconfig status > /dev/null + + if [[ $? != 0 ]]; then + service cgconfig start + fi + +} + +start() { + [ -x $exec ] || exit 5 + + check_for_cleanup + + if ! [ -f $pidfile ]; then + prestart + printf "Starting $prog:\t" + echo "\n$(date)\n" >> $logfile + "$unshare" -m -- <%= @docker_daemon_cmd %> &>> $logfile & + <%= @docker_wait_ready %> + [ $? -eq 0 ] && success || failure + echo + else + failure + echo + printf "$pidfile still exists...\n" + exit 7 + fi +} + +stop() { + echo -n $"Stopping $prog: " + killproc -p $pidfile -d 300 $prog + retval=$? + echo + [ $retval -eq 0 ] && rm -f $lockfile + return $retval +} + +restart() { + stop + start +} + +reload() { + restart +} + +force_reload() { + restart +} + +rh_status() { + status -p $pidfile $prog +} + +rh_status_q() { + rh_status >/dev/null 2>&1 +} + + +check_for_cleanup() { + if [ -f ${pidfile} ]; then + /bin/ps -fp $(cat ${pidfile}) > /dev/null || rm ${pidfile} + fi +} + +case "$1" in + start) + rh_status_q && exit 0 + $1 + ;; + stop) + rh_status_q || exit 0 + $1 + ;; + restart) + $1 + ;; + reload) + rh_status_q || exit 7 + $1 + ;; + force-reload) + force_reload + ;; + status) + rh_status + ;; + condrestart|try-restart) + rh_status_q || exit 0 + restart + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}" + exit 2 +esac + +exit $? diff --git a/chef/cookbooks/docker/templates/default/upstart/docker.conf.erb b/chef/cookbooks/docker/templates/default/upstart/docker.conf.erb new file mode 100644 index 0000000..4189fe6 --- /dev/null +++ b/chef/cookbooks/docker/templates/default/upstart/docker.conf.erb @@ -0,0 +1,57 @@ +description "Docker daemon" + +start on (filesystem and net-device-up IFACE!=lo) +stop on runlevel [!2345] +limit nofile 524288 1048576 +limit nproc 524288 1048576 + +respawn + +kill timeout 20 + +pre-start script + # see also https://github.com/tianon/cgroupfs-mount/blob/master/cgroupfs-mount + if grep -v '^#' /etc/fstab | grep -q cgroup \ + || [ ! -e /proc/cgroups ] \ + || [ ! -d /sys/fs/cgroup ]; then + exit 0 + fi + if ! mountpoint -q /sys/fs/cgroup; then + mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup + fi + ( + cd /sys/fs/cgroup + for sys in $(awk '!/^#/ { if ($4 == 1) print $1 }' /proc/cgroups); do + mkdir -p $sys + if ! mountpoint -q $sys; then + if ! mount -n -t cgroup -o $sys cgroup $sys; then + rmdir $sys || true + fi + fi + done + ) +end script + +script + # modify these in /etc/default/$UPSTART_JOB (/etc/default/docker) + DOCKER=<%= @dockerd_bin_link %> + DOCKER_OPTS= + if [ -f /etc/default/$UPSTART_JOB ]; then + . /etc/default/$UPSTART_JOB + fi + exec "$DOCKER" <%= @docker_daemon_arg %> $DOCKER_OPTS --raw-logs +end script + +post-start script + DOCKER_OPTS= + if [ -f /etc/default/$UPSTART_JOB ]; then + . /etc/default/$UPSTART_JOB + fi + <%= @docker_wait_ready %> + if [ $? -eq 0 ]; then + echo "<%= @docker_socket %> is up" + else + echo "<%= @docker_socket %> failed to come start" + exit 1 + fi +end script