from-scratch 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Berksfile.lock +11 -0
  4. data/chefignore +1 -0
  5. data/cookbooks/apt/CHANGELOG.md +248 -0
  6. data/cookbooks/apt/README.md +294 -0
  7. data/cookbooks/apt/attributes/default.rb +51 -0
  8. data/cookbooks/apt/files/default/15update-stamp +1 -0
  9. data/cookbooks/apt/files/default/apt-proxy-v2.conf +50 -0
  10. data/cookbooks/apt/libraries/helpers.rb +61 -0
  11. data/cookbooks/apt/libraries/matchers.rb +17 -0
  12. data/cookbooks/apt/libraries/network.rb +31 -0
  13. data/cookbooks/apt/metadata.json +1 -0
  14. data/cookbooks/apt/providers/preference.rb +84 -0
  15. data/cookbooks/apt/providers/repository.rb +246 -0
  16. data/cookbooks/apt/recipes/cacher-client.rb +83 -0
  17. data/cookbooks/apt/recipes/cacher-ng.rb +43 -0
  18. data/cookbooks/apt/recipes/default.rb +112 -0
  19. data/cookbooks/apt/recipes/unattended-upgrades.rb +47 -0
  20. data/cookbooks/apt/resources/preference.rb +37 -0
  21. data/cookbooks/apt/resources/repository.rb +60 -0
  22. data/cookbooks/apt/templates/debian-6.0/acng.conf.erb +173 -0
  23. data/cookbooks/apt/templates/default/01proxy.erb +9 -0
  24. data/cookbooks/apt/templates/default/10recommends.erb +3 -0
  25. data/cookbooks/apt/templates/default/20auto-upgrades.erb +2 -0
  26. data/cookbooks/apt/templates/default/50unattended-upgrades.erb +68 -0
  27. data/cookbooks/apt/templates/default/acng.conf.erb +275 -0
  28. data/cookbooks/apt/templates/default/unattended-upgrades.seed.erb +1 -0
  29. data/cookbooks/apt/templates/ubuntu-10.04/acng.conf.erb +269 -0
  30. data/cookbooks/build-essential/CHANGELOG.md +136 -0
  31. data/cookbooks/build-essential/README.md +108 -0
  32. data/cookbooks/build-essential/attributes/default.rb +20 -0
  33. data/cookbooks/build-essential/libraries/matchers.rb +5 -0
  34. data/cookbooks/build-essential/libraries/timing.rb +124 -0
  35. data/cookbooks/build-essential/libraries/xcode_command_line_tools.rb +210 -0
  36. data/cookbooks/build-essential/metadata.json +1 -0
  37. data/cookbooks/build-essential/recipes/_debian.rb +28 -0
  38. data/cookbooks/build-essential/recipes/_fedora.rb +32 -0
  39. data/cookbooks/build-essential/recipes/_freebsd.rb +24 -0
  40. data/cookbooks/build-essential/recipes/_mac_os_x.rb +22 -0
  41. data/cookbooks/build-essential/recipes/_omnios.rb +33 -0
  42. data/cookbooks/build-essential/recipes/_rhel.rb +36 -0
  43. data/cookbooks/build-essential/recipes/_smartos.rb +27 -0
  44. data/cookbooks/build-essential/recipes/_solaris2.rb +48 -0
  45. data/cookbooks/build-essential/recipes/_suse.rb +29 -0
  46. data/cookbooks/build-essential/recipes/default.rb +29 -0
  47. data/cookbooks/chef-sugar/CHANGELOG.md +159 -0
  48. data/cookbooks/chef-sugar/README.md +464 -0
  49. data/cookbooks/chef-sugar/metadata.json +1 -0
  50. data/cookbooks/chef-sugar/recipes/default.rb +34 -0
  51. data/cookbooks/openssl/CHANGELOG.md +30 -0
  52. data/cookbooks/openssl/README.md +115 -0
  53. data/cookbooks/openssl/attributes/default.rb +21 -0
  54. data/cookbooks/openssl/libraries/secure_password.rb +37 -0
  55. data/cookbooks/openssl/metadata.json +31 -0
  56. data/cookbooks/openssl/providers/x509.rb +94 -0
  57. data/cookbooks/openssl/recipes/default.rb +18 -0
  58. data/cookbooks/openssl/recipes/upgrade.rb +39 -0
  59. data/cookbooks/openssl/resources/x509.rb +16 -0
  60. data/cookbooks/postgresql/CHANGELOG.md +220 -0
  61. data/cookbooks/postgresql/README.md +464 -0
  62. data/cookbooks/postgresql/attributes/default.rb +549 -0
  63. data/cookbooks/postgresql/files/default/tests/minitest/apt_pgdg_postgresql_test.rb +39 -0
  64. data/cookbooks/postgresql/files/default/tests/minitest/default_test.rb +27 -0
  65. data/cookbooks/postgresql/files/default/tests/minitest/ruby_test.rb +28 -0
  66. data/cookbooks/postgresql/files/default/tests/minitest/server_test.rb +43 -0
  67. data/cookbooks/postgresql/files/default/tests/minitest/support/helpers.rb +29 -0
  68. data/cookbooks/postgresql/libraries/default.rb +377 -0
  69. data/cookbooks/postgresql/metadata.json +56 -0
  70. data/cookbooks/postgresql/recipes/apt_pgdg_postgresql.rb +18 -0
  71. data/cookbooks/postgresql/recipes/client.rb +32 -0
  72. data/cookbooks/postgresql/recipes/config_initdb.rb +148 -0
  73. data/cookbooks/postgresql/recipes/config_pgtune.rb +284 -0
  74. data/cookbooks/postgresql/recipes/contrib.rb +44 -0
  75. data/cookbooks/postgresql/recipes/default.rb +18 -0
  76. data/cookbooks/postgresql/recipes/ruby.rb +117 -0
  77. data/cookbooks/postgresql/recipes/server.rb +89 -0
  78. data/cookbooks/postgresql/recipes/server_conf.rb +34 -0
  79. data/cookbooks/postgresql/recipes/server_debian.rb +38 -0
  80. data/cookbooks/postgresql/recipes/server_redhat.rb +100 -0
  81. data/cookbooks/postgresql/recipes/yum_pgdg_postgresql.rb +45 -0
  82. data/cookbooks/postgresql/templates/default/pg_hba.conf.erb +35 -0
  83. data/cookbooks/postgresql/templates/default/pgsql.sysconfig.erb +4 -0
  84. data/cookbooks/postgresql/templates/default/postgresql.conf.erb +21 -0
  85. data/cookbooks/scratchify/.chef/knife.rb +2 -5
  86. data/cookbooks/scratchify/Berksfile +2 -1
  87. data/cookbooks/scratchify/Berksfile.lock +11 -0
  88. data/cookbooks/scratchify/README.md +34 -17
  89. data/cookbooks/scratchify/bin/scratchify +1 -1
  90. data/cookbooks/scratchify/chefignore +1 -0
  91. data/cookbooks/scratchify/from-scratch.gemspec +2 -5
  92. data/cookbooks/scratchify/lib/from-scratch.rb +25 -0
  93. data/cookbooks/scratchify/lib/{from/scratch → from-scratch}/version.rb +1 -1
  94. data/cookbooks/scratchify/metadata.json +2 -1
  95. data/cookbooks/scratchify/templates/node.json.erb +34 -0
  96. data/cookbooks/scratchify/templates/user.json.erb +6 -0
  97. data/lib/from-scratch.rb +2 -2
  98. data/lib/from-scratch/version.rb +1 -1
  99. data/templates/node.json.erb +6 -3
  100. metadata +85 -10
  101. data/cookbooks/scratchify/bin/console +0 -14
  102. data/cookbooks/scratchify/bin/setup +0 -7
  103. data/cookbooks/scratchify/data_bags/users/deploy.json +0 -6
  104. data/cookbooks/scratchify/environments/.gitkeep +0 -0
  105. data/cookbooks/scratchify/lib/from/scratch.rb +0 -31
  106. data/cookbooks/scratchify/lib/from/scratch/interviewer.rb +0 -35
  107. data/cookbooks/scratchify/nodes/normfood.ru.json +0 -75
  108. data/cookbooks/scratchify/roles/.gitkeep +0 -0
@@ -0,0 +1,51 @@
1
+ #
2
+ # Cookbook Name:: apt
3
+ # Attributes:: default
4
+ #
5
+ # Copyright 2009-2013, Chef Software, Inc.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ default['apt']['cacher-client']['restrict_environment'] = false
21
+ default['apt']['cacher_dir'] = '/var/cache/apt-cacher-ng'
22
+ default['apt']['cacher_interface'] = nil
23
+ default['apt']['cacher_port'] = 3142
24
+ default['apt']['cacher_ssl_support'] = false
25
+ default['apt']['caching_server'] = false
26
+ default['apt']['compiletime'] = false
27
+ default['apt']['compile_time_update'] = false
28
+ default['apt']['key_proxy'] = ''
29
+ default['apt']['cache_bypass'] = {}
30
+ default['apt']['periodic_update_min_delay'] = 86_400
31
+ default['apt']['launchpad_api_version'] = '1.0'
32
+ default['apt']['unattended_upgrades']['enable'] = false
33
+ default['apt']['unattended_upgrades']['update_package_lists'] = true
34
+ # this needs a good default
35
+ codename = node.attribute?('lsb') ? node['lsb']['codename'] : 'notlinux'
36
+ default['apt']['unattended_upgrades']['allowed_origins'] = [
37
+ "#{node['platform'].capitalize} #{codename}"
38
+ ]
39
+ default['apt']['unattended_upgrades']['package_blacklist'] = []
40
+ default['apt']['unattended_upgrades']['auto_fix_interrupted_dpkg'] = false
41
+ default['apt']['unattended_upgrades']['minimal_steps'] = false
42
+ default['apt']['unattended_upgrades']['install_on_shutdown'] = false
43
+ default['apt']['unattended_upgrades']['mail'] = nil
44
+ default['apt']['unattended_upgrades']['mail_only_on_error'] = true
45
+ default['apt']['unattended_upgrades']['remove_unused_dependencies'] = false
46
+ default['apt']['unattended_upgrades']['automatic_reboot'] = false
47
+ default['apt']['unattended_upgrades']['automatic_reboot_time'] = 'now'
48
+ default['apt']['unattended_upgrades']['dl_limit'] = nil
49
+
50
+ default['apt']['confd']['install_recommends'] = true
51
+ default['apt']['confd']['install_suggests'] = false
@@ -0,0 +1 @@
1
+ APT::Update::Post-Invoke-Success {"touch /var/lib/apt/periodic/update-success-stamp 2>/dev/null || true";};
@@ -0,0 +1,50 @@
1
+ [DEFAULT]
2
+ ;; All times are in seconds, but you can add a suffix
3
+ ;; for minutes(m), hours(h) or days(d)
4
+
5
+ ;; commented out address so apt-proxy will listen on all IPs
6
+ ;; address = 127.0.0.1
7
+ port = 9999
8
+ cache_dir = /var/cache/apt-proxy
9
+
10
+ ;; Control files (Packages/Sources/Contents) refresh rate
11
+ min_refresh_delay = 1s
12
+ complete_clientless_downloads = 1
13
+
14
+ ;; Debugging settings.
15
+ debug = all:4 db:0
16
+
17
+ time = 30
18
+ passive_ftp = on
19
+
20
+ ;;--------------------------------------------------------------
21
+ ;; Cache housekeeping
22
+
23
+ cleanup_freq = 1d
24
+ max_age = 120d
25
+ max_versions = 3
26
+
27
+ ;;---------------------------------------------------------------
28
+ ;; Backend servers
29
+ ;;
30
+ ;; Place each server in its own [section]
31
+
32
+ [ubuntu]
33
+ ; Ubuntu archive
34
+ backends =
35
+ http://us.archive.ubuntu.com/ubuntu
36
+
37
+ [ubuntu-security]
38
+ ; Ubuntu security updates
39
+ backends = http://security.ubuntu.com/ubuntu
40
+
41
+ [debian]
42
+ ;; Backend servers, in order of preference
43
+ backends =
44
+ http://debian.osuosl.org/debian/
45
+
46
+ [security]
47
+ ;; Debian security archive
48
+ backends =
49
+ http://security.debian.org/debian-security
50
+ http://ftp2.de.debian.org/debian-security
@@ -0,0 +1,61 @@
1
+ #
2
+ # Cookbook Name:: apt
3
+ # Library:: helpers
4
+ #
5
+ # Copyright 2013 Chef Software, Inc.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ module Apt
21
+ # Helpers for apt
22
+ module Helpers
23
+ # Determines if apt is installed on a system.
24
+ #
25
+ # @return [Boolean]
26
+ def apt_installed?
27
+ !which('apt-get').nil?
28
+ end
29
+
30
+ # Determines whether we need to run `apt-get update`
31
+ #
32
+ # @return [Boolean]
33
+ def apt_up_to_date?
34
+ if ::File.exist?('/var/lib/apt/periodic/update-success-stamp') &&
35
+ ::File.mtime('/var/lib/apt/periodic/update-success-stamp') > Time.now - node['apt']['periodic_update_min_delay']
36
+ true
37
+ else
38
+ false
39
+ end
40
+ end
41
+
42
+ # Finds a command in $PATH
43
+ #
44
+ # @return [String, nil]
45
+ def which(cmd)
46
+ ENV['PATH'] = '' if ENV['PATH'].nil?
47
+ paths = (ENV['PATH'].split(::File::PATH_SEPARATOR) + %w(/bin /usr/bin /sbin /usr/sbin))
48
+
49
+ paths.each do |path|
50
+ possible = File.join(path, cmd)
51
+ return possible if File.executable?(possible)
52
+ end
53
+
54
+ nil
55
+ end
56
+ end
57
+ end
58
+
59
+ Chef::Recipe.send(:include, ::Apt::Helpers)
60
+ Chef::Resource.send(:include, ::Apt::Helpers)
61
+ Chef::Provider.send(:include, ::Apt::Helpers)
@@ -0,0 +1,17 @@
1
+ if defined?(ChefSpec)
2
+ def add_apt_preference(resource_name)
3
+ ChefSpec::Matchers::ResourceMatcher.new(:apt_preference, :add, resource_name)
4
+ end
5
+
6
+ def remove_apt_preference(resource_name)
7
+ ChefSpec::Matchers::ResourceMatcher.new(:apt_preference, :remove, resource_name)
8
+ end
9
+
10
+ def add_apt_repository(resource_name)
11
+ ChefSpec::Matchers::ResourceMatcher.new(:apt_repository, :add, resource_name)
12
+ end
13
+
14
+ def remove_apt_repository(resource_name)
15
+ ChefSpec::Matchers::ResourceMatcher.new(:apt_repository, :remove, resource_name)
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+ #
2
+ # Cookbook Name:: apt
3
+ # library:: network
4
+ #
5
+ # Copyright 2013, Chef Software, Inc.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ module ::Apt
21
+ def interface_ipaddress(host, interface)
22
+ if interface
23
+ addresses = host['network']['interfaces'][interface]['addresses']
24
+ addresses.select do |ip, data|
25
+ return ip if data['family'].eql?('inet')
26
+ end
27
+ else
28
+ return host.ipaddress
29
+ end
30
+ end
31
+ end
@@ -0,0 +1 @@
1
+ {"name":"apt","version":"2.9.2","description":"Configures apt and apt services. Ships resources for managing apt repositories","long_description":"","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache 2.0","platforms":{"ubuntu":">= 0.0.0","debian":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{"apt::default":"Runs apt-get update during compile phase and sets up preseed directories","apt::cacher-ng":"Set up an apt-cacher-ng caching proxy","apt::cacher-client":"Client for the apt::cacher-ng caching proxy"}}
@@ -0,0 +1,84 @@
1
+ #
2
+ # Cookbook Name:: apt
3
+ # Provider:: preference
4
+ #
5
+ # Copyright 2010-2011, Chef Software, Inc.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ use_inline_resources if defined?(use_inline_resources)
21
+
22
+ def whyrun_supported?
23
+ true
24
+ end
25
+
26
+ # Build preferences.d file contents
27
+ def build_pref(package_name, pin, pin_priority)
28
+ "Package: #{package_name}\nPin: #{pin}\nPin-Priority: #{pin_priority}\n"
29
+ end
30
+
31
+ def safe_name(name)
32
+ name.tr('.', '_').gsub('*', 'wildcard')
33
+ end
34
+
35
+ action :add do
36
+ preference = build_pref(
37
+ new_resource.glob || new_resource.package_name,
38
+ new_resource.pin,
39
+ new_resource.pin_priority
40
+ )
41
+
42
+ directory '/etc/apt/preferences.d' do
43
+ owner 'root'
44
+ group 'root'
45
+ mode 00755
46
+ recursive true
47
+ action :create
48
+ end
49
+
50
+ name = safe_name(new_resource.name)
51
+
52
+ file "/etc/apt/preferences.d/#{new_resource.name}.pref" do
53
+ action :delete
54
+ if ::File.exist?("/etc/apt/preferences.d/#{new_resource.name}.pref")
55
+ Chef::Log.warn "Replacing #{new_resource.name}.pref with #{name}.pref in /etc/apt/preferences.d/"
56
+ end
57
+ only_if { name != new_resource.name }
58
+ end
59
+
60
+ file "/etc/apt/preferences.d/#{new_resource.name}" do
61
+ action :delete
62
+ if ::File.exist?("/etc/apt/preferences.d/#{new_resource.name}")
63
+ Chef::Log.warn "Replacing #{new_resource.name} with #{new_resource.name}.pref in /etc/apt/preferences.d/"
64
+ end
65
+ end
66
+
67
+ file "/etc/apt/preferences.d/#{name}.pref" do
68
+ owner 'root'
69
+ group 'root'
70
+ mode 00644
71
+ content preference
72
+ action :create
73
+ end
74
+ end
75
+
76
+ action :remove do
77
+ name = safe_name(new_resource.name)
78
+ if ::File.exist?("/etc/apt/preferences.d/#{name}.pref")
79
+ Chef::Log.info "Un-pinning #{name} from /etc/apt/preferences.d/"
80
+ file "/etc/apt/preferences.d/#{name}.pref" do
81
+ action :delete
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,246 @@
1
+ #
2
+ # Cookbook Name:: apt
3
+ # Provider:: repository
4
+ #
5
+ # Copyright 2010-2011, Chef Software, Inc.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ use_inline_resources if defined?(use_inline_resources)
21
+
22
+ def whyrun_supported?
23
+ true
24
+ end
25
+
26
+ # install apt key from keyserver
27
+ def install_key_from_keyserver(key, keyserver, key_proxy)
28
+ execute "install-key #{key}" do
29
+ if keyserver.start_with?('hkp://')
30
+ command "apt-key adv --keyserver #{keyserver} --recv #{key}"
31
+ elsif key_proxy.empty?
32
+ command "apt-key adv --keyserver hkp://#{keyserver}:80 --recv #{key}"
33
+ else
34
+ command "apt-key adv --keyserver-options http-proxy=#{key_proxy} --keyserver hkp://#{keyserver}:80 --recv #{key}"
35
+ end
36
+ sensitive new_resource.sensitive if respond_to?(:sensitive)
37
+ action :run
38
+ not_if do
39
+ key_present = extract_fingerprints_from_cmd('apt-key finger').any? do |fingerprint|
40
+ fingerprint.end_with?(key.upcase)
41
+ end
42
+
43
+ key_present && key_is_valid('apt-key list', key.upcase)
44
+ end
45
+ end
46
+
47
+ ruby_block "validate-key #{key}" do
48
+ block do
49
+ fail "The key #{key} is no longer valid and cannot be used for an apt repository."
50
+ end
51
+ not_if { key_is_valid('apt-key list', key.upcase) }
52
+ end
53
+ end
54
+
55
+ # run command and extract gpg ids
56
+ def extract_fingerprints_from_cmd(cmd)
57
+ so = Mixlib::ShellOut.new(cmd, env: { 'LANG' => 'en_US', 'LANGUAGE' => 'en_US' })
58
+ so.run_command
59
+ so.stdout.split(/\n/).map do |t|
60
+ if z = t.match(/^ +Key fingerprint = ([0-9A-F ]+)/)
61
+ z[1].split.join
62
+ end
63
+ end.compact
64
+ end
65
+
66
+ # determine whether apt thinks the key is still valid
67
+ def key_is_valid(cmd, key)
68
+ valid = true
69
+
70
+ so = Mixlib::ShellOut.new(cmd, env: { 'LANG' => 'en_US', 'LANGUAGE' => 'en_US' })
71
+ so.run_command
72
+ # rubocop:disable Style/Next
73
+ so.stdout.split(/\n/).map do |t|
74
+ if t.match(%r{^\/#{key}.*\[expired: .*\]$})
75
+ Chef::Log.debug "Found expired key: #{t}"
76
+ valid = false
77
+ break
78
+ end
79
+ end
80
+
81
+ Chef::Log.debug "key #{key} validity: #{valid}"
82
+ valid
83
+ end
84
+
85
+ # install apt key from URI
86
+ def install_key_from_uri(uri)
87
+ key_name = uri.split(%r{\/}).last
88
+ cached_keyfile = "#{Chef::Config[:file_cache_path]}/#{key_name}"
89
+ if new_resource.key =~ /http/
90
+ remote_file cached_keyfile do
91
+ source new_resource.key
92
+ mode 00644
93
+ sensitive new_resource.sensitive if respond_to?(:sensitive)
94
+ action :create
95
+ end
96
+ else
97
+ cookbook_file cached_keyfile do
98
+ source new_resource.key
99
+ cookbook new_resource.cookbook
100
+ mode 00644
101
+ sensitive new_resource.sensitive if respond_to?(:sensitive)
102
+ action :create
103
+ end
104
+
105
+ ruby_block "validate-key #{cached_keyfile}" do
106
+ block do
107
+ fail "The key #{cached_keyfile} is no longer valid and cannot be used for an apt repository." unless key_is_valid("gpg #{cached_keyfile}", '')
108
+ end
109
+ end
110
+ end
111
+
112
+ execute "install-key #{key_name}" do
113
+ command "apt-key add #{cached_keyfile}"
114
+ sensitive new_resource.sensitive if respond_to?(:sensitive)
115
+ action :run
116
+ not_if do
117
+ installed_keys = extract_fingerprints_from_cmd('apt-key finger')
118
+ proposed_keys = extract_fingerprints_from_cmd("gpg --with-fingerprint #{cached_keyfile}")
119
+ (installed_keys & proposed_keys).sort == proposed_keys.sort
120
+ end
121
+ end
122
+ end
123
+
124
+ # build repo file contents
125
+ def build_repo(uri, distribution, components, trusted, arch, add_deb_src)
126
+ uri = '"' + uri + '"' unless uri.start_with?("\"", "'")
127
+ components = components.join(' ') if components.respond_to?(:join)
128
+ repo_options = []
129
+ repo_options << "arch=#{arch}" if arch
130
+ repo_options << 'trusted=yes' if trusted
131
+ repo_opts = '[' + repo_options.join(' ') + ']' unless repo_options.empty?
132
+ repo_info = "#{repo_opts} #{uri} #{distribution} #{components}\n".lstrip
133
+ repo = "deb #{repo_info}"
134
+ repo << "deb-src #{repo_info}" if add_deb_src
135
+ repo
136
+ end
137
+
138
+ def get_ppa_key(ppa_owner, ppa_repo, key_proxy)
139
+ # Launchpad has currently only one stable API which is marked as EOL April 2015.
140
+ # The new api in devel still uses the same api call for +archive, so I made the version
141
+ # configurable to provide some sort of workaround if api 1.0 ceases to exist.
142
+ # See https://launchpad.net/+apidoc/
143
+ launchpad_ppa_api = "https://launchpad.net/api/#{node['apt']['launchpad_api_version']}/~%s/+archive/%s"
144
+ default_keyserver = 'keyserver.ubuntu.com'
145
+
146
+ require 'open-uri'
147
+ api_query = format("#{launchpad_ppa_api}/signing_key_fingerprint", ppa_owner, ppa_repo)
148
+ begin
149
+ key_id = open(api_query).read.delete('"')
150
+ rescue OpenURI::HTTPError => e
151
+ error = 'Could not access launchpad ppa key api: HttpError: ' + e.message
152
+ raise error
153
+ rescue SocketError => e
154
+ error = 'Could not access launchpad ppa key api: SocketError: ' + e.message
155
+ raise error
156
+ end
157
+
158
+ install_key_from_keyserver(key_id, default_keyserver, key_proxy)
159
+ end
160
+
161
+ # fetch ppa key, return full repo url
162
+ def get_ppa_url(ppa, key_proxy)
163
+ repo_schema = 'http://ppa.launchpad.net/%s/%s/ubuntu'
164
+
165
+ # ppa:user/repo logic ported from
166
+ # http://bazaar.launchpad.net/~ubuntu-core-dev/software-properties/main/view/head:/softwareproperties/ppa.py#L86
167
+ return false unless ppa.start_with?('ppa:')
168
+
169
+ ppa_name = ppa.split(':')[1]
170
+ ppa_owner = ppa_name.split('/')[0]
171
+ ppa_repo = ppa_name.split('/')[1]
172
+ ppa_repo = 'ppa' if ppa_repo.nil?
173
+
174
+ get_ppa_key(ppa_owner, ppa_repo, key_proxy)
175
+
176
+ format(repo_schema, ppa_owner, ppa_repo)
177
+ end
178
+
179
+ action :add do
180
+ # add key
181
+ if new_resource.keyserver && new_resource.key
182
+ install_key_from_keyserver(new_resource.key, new_resource.keyserver, new_resource.key_proxy)
183
+ elsif new_resource.key
184
+ install_key_from_uri(new_resource.key)
185
+ end
186
+
187
+ file '/var/lib/apt/periodic/update-success-stamp' do
188
+ action :nothing
189
+ end
190
+
191
+ execute 'apt-cache gencaches' do
192
+ ignore_failure true
193
+ action :nothing
194
+ end
195
+
196
+ execute 'apt-get update' do
197
+ command "apt-get update -o Dir::Etc::sourcelist='sources.list.d/#{new_resource.name}.list' -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0'"
198
+ ignore_failure true
199
+ sensitive new_resource.sensitive if respond_to?(:sensitive)
200
+ action :nothing
201
+ notifies :run, 'execute[apt-cache gencaches]', :immediately
202
+ end
203
+
204
+ if new_resource.uri.start_with?('ppa:')
205
+ # build ppa repo file
206
+ repository = build_repo(
207
+ get_ppa_url(new_resource.uri, new_resource.key_proxy),
208
+ new_resource.distribution,
209
+ 'main',
210
+ new_resource.trusted,
211
+ new_resource.arch,
212
+ new_resource.deb_src
213
+ )
214
+ else
215
+ # build repo file
216
+ repository = build_repo(
217
+ new_resource.uri,
218
+ new_resource.distribution,
219
+ new_resource.components,
220
+ new_resource.trusted,
221
+ new_resource.arch,
222
+ new_resource.deb_src
223
+ )
224
+ end
225
+
226
+ file "/etc/apt/sources.list.d/#{new_resource.name}.list" do
227
+ owner 'root'
228
+ group 'root'
229
+ mode 00644
230
+ content repository
231
+ sensitive new_resource.sensitive if respond_to?(:sensitive)
232
+ action :create
233
+ notifies :delete, 'file[/var/lib/apt/periodic/update-success-stamp]', :immediately
234
+ notifies :run, 'execute[apt-get update]', :immediately if new_resource.cache_rebuild
235
+ end
236
+ end
237
+
238
+ action :remove do
239
+ if ::File.exist?("/etc/apt/sources.list.d/#{new_resource.name}.list")
240
+ Chef::Log.info "Removing #{new_resource.name} repository from /etc/apt/sources.list.d/"
241
+ file "/etc/apt/sources.list.d/#{new_resource.name}.list" do
242
+ sensitive new_resource.sensitive if respond_to?(:sensitive)
243
+ action :delete
244
+ end
245
+ end
246
+ end