from-scratch 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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