chef-dk 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/chef-dk/authenticated_http.rb +40 -0
- data/lib/chef-dk/chef_runner.rb +5 -0
- data/lib/chef-dk/command/exec.rb +4 -1
- data/lib/chef-dk/command/generate.rb +11 -0
- data/lib/chef-dk/command/generator_commands.rb +20 -365
- data/lib/chef-dk/command/generator_commands/app.rb +99 -0
- data/lib/chef-dk/command/generator_commands/attribute.rb +37 -0
- data/lib/chef-dk/command/generator_commands/base.rb +76 -0
- data/lib/chef-dk/command/generator_commands/cookbook.rb +100 -0
- data/lib/chef-dk/command/generator_commands/cookbook_code_file.rb +99 -0
- data/lib/chef-dk/command/generator_commands/cookbook_file.rb +45 -0
- data/lib/chef-dk/command/generator_commands/lwrp.rb +36 -0
- data/lib/chef-dk/command/generator_commands/recipe.rb +36 -0
- data/lib/chef-dk/command/generator_commands/repo.rb +96 -0
- data/lib/chef-dk/command/generator_commands/template.rb +45 -0
- data/lib/chef-dk/command/verify.rb +28 -0
- data/lib/chef-dk/component_test.rb +16 -3
- data/lib/chef-dk/cookbook_omnifetch.rb +2 -0
- data/lib/chef-dk/cookbook_profiler/identifiers.rb +3 -15
- data/lib/chef-dk/exceptions.rb +15 -0
- data/lib/chef-dk/generator.rb +102 -25
- data/lib/chef-dk/policyfile/community_cookbook_source.rb +0 -7
- data/lib/chef-dk/policyfile/{cookbook_spec.rb → cookbook_location_specification.rb} +35 -6
- data/lib/chef-dk/policyfile/cookbook_locks.rb +305 -0
- data/lib/chef-dk/policyfile/dsl.rb +26 -12
- data/lib/chef-dk/policyfile/read_cookbook_for_compat_mode_upload.rb +70 -0
- data/lib/chef-dk/policyfile/solution_dependencies.rb +204 -0
- data/lib/chef-dk/policyfile/storage_config.rb +77 -0
- data/lib/chef-dk/policyfile/uploader.rb +110 -0
- data/lib/chef-dk/policyfile_compiler.rb +59 -29
- data/lib/chef-dk/policyfile_lock.rb +104 -160
- data/lib/chef-dk/skeletons/code_generator/files/default/Berksfile +1 -1
- data/lib/chef-dk/skeletons/code_generator/files/default/chefignore +0 -1
- data/lib/chef-dk/skeletons/code_generator/files/default/repo/README.md +66 -0
- data/lib/chef-dk/skeletons/code_generator/files/default/repo/Rakefile +65 -0
- data/lib/chef-dk/skeletons/code_generator/files/default/repo/certificates/README.md +19 -0
- data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/README-policy.md +9 -0
- data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/README.md +54 -0
- data/lib/chef-dk/skeletons/code_generator/files/default/repo/data_bags/README.md +63 -0
- data/lib/chef-dk/skeletons/code_generator/files/default/repo/environments/README.md +5 -0
- data/lib/chef-dk/skeletons/code_generator/files/default/repo/roles/README.md +16 -0
- data/lib/chef-dk/skeletons/code_generator/recipes/cookbook.rb +7 -1
- data/lib/chef-dk/skeletons/code_generator/recipes/repo.rb +62 -0
- data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.all_rights.erb +3 -0
- data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.apache2.erb +201 -0
- data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.gplv2.erb +339 -0
- data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.gplv3.erb +674 -0
- data/lib/chef-dk/skeletons/code_generator/templates/default/LICENSE.mit.erb +21 -0
- data/lib/chef-dk/skeletons/code_generator/templates/default/default_recipe.rb.erb +1 -4
- data/lib/chef-dk/skeletons/code_generator/templates/default/metadata.rb.erb +3 -3
- data/lib/chef-dk/skeletons/code_generator/templates/default/repo/config/rake.rb.erb +38 -0
- data/lib/chef-dk/skeletons/code_generator/templates/default/repo/gitignore.erb +11 -0
- data/lib/chef-dk/version.rb +1 -1
- data/spec/shared/a_file_generator.rb +121 -0
- data/spec/shared/a_generated_file.rb +12 -0
- data/spec/shared/fixture_cookbook_checksums.rb +47 -0
- data/spec/spec_helper.rb +4 -2
- data/spec/unit/chef_runner_spec.rb +12 -5
- data/spec/unit/cli_spec.rb +4 -4
- data/spec/unit/command/base_spec.rb +1 -1
- data/spec/unit/command/exec_spec.rb +37 -27
- data/spec/unit/command/generate_spec.rb +3 -3
- data/spec/unit/command/generator_commands/app_spec.rb +131 -0
- data/spec/unit/command/generator_commands/attribute_spec.rb +32 -0
- data/spec/unit/command/generator_commands/cookbook_file_spec.rb +32 -0
- data/spec/unit/command/generator_commands/cookbook_spec.rb +205 -0
- data/spec/unit/command/generator_commands/lwrp_spec.rb +32 -0
- data/spec/unit/command/generator_commands/recipe_spec.rb +32 -0
- data/spec/unit/command/generator_commands/repo_spec.rb +287 -0
- data/spec/unit/command/generator_commands/template_spec.rb +32 -0
- data/spec/unit/command/shell_init_spec.rb +4 -4
- data/spec/unit/command/verify_spec.rb +9 -9
- data/spec/unit/commands_map_spec.rb +1 -1
- data/spec/unit/component_test_spec.rb +3 -3
- data/spec/unit/cookbook_profiler/git_spec.rb +7 -7
- data/spec/unit/cookbook_profiler/identifiers_spec.rb +12 -8
- data/spec/unit/fixtures/cookbook_cache/baz-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/Berksfile +1 -1
- data/spec/unit/fixtures/cookbook_cache/dep_of_bar-1.2.3/Berksfile +1 -1
- data/spec/unit/fixtures/cookbook_cache/foo-1.0.0/Berksfile +1 -1
- data/spec/unit/fixtures/example_cookbook/Berksfile +1 -1
- data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/README.md +4 -0
- data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/chefignore +96 -0
- data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/metadata.rb +8 -0
- data/spec/unit/fixtures/local_path_cookbooks/another-local-cookbook/recipes/default.rb +8 -0
- data/spec/unit/fixtures/local_path_cookbooks/local-cookbook/Berksfile +1 -1
- data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/.kitchen.yml +16 -0
- data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/README.md +4 -0
- data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/metadata.rb +8 -0
- data/spec/unit/fixtures/local_path_cookbooks/noignore-f59ee7a5bca6a4e606b67f7f856b768d847c39bb/recipes/default.rb +8 -0
- data/spec/unit/generator_spec.rb +120 -0
- data/spec/unit/policyfile/{cookbook_spec_spec.rb → cookbook_location_specification_spec.rb} +83 -38
- data/spec/unit/policyfile/cookbook_locks_spec.rb +354 -0
- data/spec/unit/policyfile/read_cookbook_for_compat_mode_upload_spec.rb +85 -0
- data/spec/unit/policyfile/solution_dependencies_spec.rb +145 -0
- data/spec/unit/policyfile/storage_config_spec.rb +98 -0
- data/spec/unit/policyfile/uploader_spec.rb +292 -0
- data/spec/unit/policyfile_demands_spec.rb +177 -24
- data/spec/unit/policyfile_evaluation_spec.rb +40 -12
- data/spec/unit/{policyfile_builder_spec.rb → policyfile_lock_build_spec.rb} +179 -64
- data/spec/unit/policyfile_lock_install_spec.rb +138 -0
- data/spec/unit/policyfile_lock_validation_spec.rb +610 -0
- metadata +103 -59
- data/spec/unit/command/generator_commands_spec.rb +0 -504
@@ -0,0 +1,70 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 2014 Chef Software Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'chef/cookbook/cookbook_version_loader'
|
19
|
+
|
20
|
+
require 'chef/cookbook/chefignore'
|
21
|
+
|
22
|
+
module ChefDK
|
23
|
+
module Policyfile
|
24
|
+
class ReadCookbookForCompatModeUpload
|
25
|
+
|
26
|
+
# Convenience method to load a cookbook, set up name and version overrides
|
27
|
+
# as necessary, and return a Chef::CookbookVersion object.
|
28
|
+
def self.load(name, version_override, directory_path)
|
29
|
+
new(name, version_override, directory_path).cookbook_version
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :cookbook_name
|
33
|
+
attr_reader :directory_path
|
34
|
+
attr_reader :version_override
|
35
|
+
|
36
|
+
def initialize(cookbook_name, version_override, directory_path)
|
37
|
+
@cookbook_name = cookbook_name
|
38
|
+
@version_override = version_override
|
39
|
+
@directory_path = directory_path
|
40
|
+
|
41
|
+
@cookbook_version = nil
|
42
|
+
@loader = nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def cookbook_version
|
46
|
+
@cookbook_version ||=
|
47
|
+
begin
|
48
|
+
cookbook_version = loader.cookbook_version
|
49
|
+
cookbook_version.version = version_override
|
50
|
+
cookbook_version.freeze_version
|
51
|
+
cookbook_version
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def loader
|
56
|
+
@loader ||=
|
57
|
+
begin
|
58
|
+
cbvl = Chef::Cookbook::CookbookVersionLoader.new(directory_path, chefignore)
|
59
|
+
cbvl.load!
|
60
|
+
cbvl
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def chefignore
|
65
|
+
@chefignore ||= Chef::Cookbook::Chefignore.new(File.join(directory_path, "chefignore"))
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,204 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 2014 Chef Software Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'semverse'
|
19
|
+
|
20
|
+
require 'chef-dk/exceptions'
|
21
|
+
|
22
|
+
module ChefDK
|
23
|
+
module Policyfile
|
24
|
+
|
25
|
+
class SolutionDependencies
|
26
|
+
|
27
|
+
Cookbook = Struct.new(:name, :version)
|
28
|
+
|
29
|
+
class Cookbook
|
30
|
+
|
31
|
+
def self.parse(str)
|
32
|
+
name, version_w_parens = str.split(' ')
|
33
|
+
version = version_w_parens[/\(([^)]+)\)/, 1]
|
34
|
+
new(name, version)
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
"#{name} (#{version})"
|
39
|
+
end
|
40
|
+
|
41
|
+
def eql?(other)
|
42
|
+
other.kind_of?(self.class) and
|
43
|
+
other.name == name and
|
44
|
+
other.version == version
|
45
|
+
end
|
46
|
+
|
47
|
+
def hash
|
48
|
+
[name, version].hash
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.from_lock(lock_data)
|
54
|
+
new.tap {|e| e.consume_lock_data(lock_data) }
|
55
|
+
end
|
56
|
+
|
57
|
+
attr_reader :policyfile_dependencies
|
58
|
+
|
59
|
+
attr_reader :cookbook_dependencies
|
60
|
+
|
61
|
+
def initialize
|
62
|
+
@policyfile_dependencies = []
|
63
|
+
@cookbook_dependencies = {}
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_policyfile_dep(cookbook, constraint)
|
67
|
+
@policyfile_dependencies << [ cookbook, Semverse::Constraint.new(constraint) ]
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_cookbook_dep(cookbook_name, version, dependency_list)
|
71
|
+
cookbook = Cookbook.new(cookbook_name, version)
|
72
|
+
add_cookbook_obj_dep(cookbook, dependency_list)
|
73
|
+
end
|
74
|
+
|
75
|
+
def update_cookbook_dep(cookbook_name, new_version, new_dependency_list)
|
76
|
+
@cookbook_dependencies.delete_if { |cb, _deps| cb.name == cookbook_name }
|
77
|
+
add_cookbook_dep(cookbook_name, new_version, new_dependency_list)
|
78
|
+
end
|
79
|
+
|
80
|
+
def consume_lock_data(lock_data)
|
81
|
+
policyfile_dependencies_data = lock_data["Policyfile"] || []
|
82
|
+
policyfile_dependencies_data.each do |cookbook_name, constraint|
|
83
|
+
add_policyfile_dep(cookbook_name, constraint)
|
84
|
+
end
|
85
|
+
cookbook_dependencies_data = lock_data["dependencies"] || {}
|
86
|
+
cookbook_dependencies_data.each do |name_and_version, deps_list|
|
87
|
+
cookbook = Cookbook.parse(name_and_version)
|
88
|
+
add_cookbook_obj_dep(cookbook, deps_list)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_conflict!(cookbook_name, version)
|
93
|
+
unless have_cookbook_dep?(cookbook_name, version)
|
94
|
+
raise CookbookNotInWorkingSet, "Cookbook #{cookbook_name} (#{version}) not in the working set, cannot test for conflicts"
|
95
|
+
end
|
96
|
+
|
97
|
+
assert_cookbook_version_valid!(cookbook_name, version)
|
98
|
+
assert_cookbook_deps_valid!(cookbook_name, version)
|
99
|
+
end
|
100
|
+
|
101
|
+
def to_lock
|
102
|
+
{ "Policyfile" => policyfile_dependencies_for_lock, "dependencies" => cookbook_deps_for_lock }
|
103
|
+
end
|
104
|
+
|
105
|
+
def policyfile_dependencies_for_lock
|
106
|
+
policyfile_dependencies.map do |name, constraint|
|
107
|
+
[ name, constraint.to_s ]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def cookbook_deps_for_lock
|
112
|
+
cookbook_dependencies.inject({}) do |map, (cookbook, deps)|
|
113
|
+
map[cookbook.to_s] = deps.map do |name, constraint|
|
114
|
+
[ name, constraint.to_s ]
|
115
|
+
end
|
116
|
+
map
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
def add_cookbook_obj_dep(cookbook, dependency_map)
|
123
|
+
@cookbook_dependencies[cookbook] = dependency_map.map do |dep_name, constraint|
|
124
|
+
[ dep_name, Semverse::Constraint.new(constraint) ]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def assert_cookbook_version_valid!(cookbook_name, version)
|
129
|
+
policyfile_conflicts = policyfile_conflicts_with(cookbook_name, version)
|
130
|
+
cookbook_conflicts = cookbook_conflicts_with(cookbook_name, version)
|
131
|
+
all_conflicts = policyfile_conflicts + cookbook_conflicts
|
132
|
+
|
133
|
+
return false if all_conflicts.empty?
|
134
|
+
|
135
|
+
details = all_conflicts.map { |source, name, constraint| "#{source} depends on #{name} #{constraint}" }
|
136
|
+
message = "Cookbook #{cookbook_name} (#{version}) conflicts with other dependencies:\n"
|
137
|
+
full_message = message + details.join("\n")
|
138
|
+
raise DependencyConflict, full_message
|
139
|
+
end
|
140
|
+
|
141
|
+
def assert_cookbook_deps_valid!(cookbook_name, version)
|
142
|
+
dependency_conflicts = cookbook_deps_conflicts_for(cookbook_name, version)
|
143
|
+
return false if dependency_conflicts.empty?
|
144
|
+
message = "Cookbook #{cookbook_name} (#{version}) has dependency constraints that cannot be met by the existing cookbook set:\n"
|
145
|
+
full_message = message + dependency_conflicts.join("\n")
|
146
|
+
raise DependencyConflict, full_message
|
147
|
+
end
|
148
|
+
|
149
|
+
def policyfile_conflicts_with(cookbook_name, version)
|
150
|
+
policyfile_conflicts = []
|
151
|
+
|
152
|
+
@policyfile_dependencies.each do |dep_name, constraint|
|
153
|
+
if dep_name == cookbook_name and !constraint.satisfies?(version)
|
154
|
+
policyfile_conflicts << ['Policyfile', dep_name, constraint]
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
policyfile_conflicts
|
159
|
+
end
|
160
|
+
|
161
|
+
def cookbook_conflicts_with(cookbook_name, version)
|
162
|
+
cookbook_conflicts = []
|
163
|
+
|
164
|
+
@cookbook_dependencies.each do |top_level_dep_name, dependencies|
|
165
|
+
dependencies.each do |dep_name, constraint|
|
166
|
+
if dep_name == cookbook_name and !constraint.satisfies?(version)
|
167
|
+
cookbook_conflicts << [top_level_dep_name, dep_name, constraint]
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
cookbook_conflicts
|
173
|
+
end
|
174
|
+
|
175
|
+
def cookbook_deps_conflicts_for(cookbook_name, version)
|
176
|
+
conflicts = []
|
177
|
+
transitive_deps = find_cookbook_dep_by_name_and_version(cookbook_name, version)
|
178
|
+
transitive_deps.each do |name, constraint|
|
179
|
+
existing_cookbook = find_cookbook_dep_by_name(name)
|
180
|
+
if existing_cookbook.nil?
|
181
|
+
conflicts << "Cookbook #{name} isn't included in the existing cookbook set."
|
182
|
+
elsif !constraint.satisfies?(existing_cookbook[0].version)
|
183
|
+
conflicts << "Dependency on #{name} #{constraint} conflicts with existing version #{existing_cookbook[0]}"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
conflicts
|
187
|
+
end
|
188
|
+
|
189
|
+
def have_cookbook_dep?(name, version)
|
190
|
+
@cookbook_dependencies.key?(Cookbook.new(name, version))
|
191
|
+
end
|
192
|
+
|
193
|
+
def find_cookbook_dep_by_name(name)
|
194
|
+
@cookbook_dependencies.find { |k,v| k.name == name }
|
195
|
+
end
|
196
|
+
|
197
|
+
def find_cookbook_dep_by_name_and_version(name, version)
|
198
|
+
@cookbook_dependencies[Cookbook.new(name, version)]
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 2014 Chef Software Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'chef-dk/cookbook_omnifetch'
|
19
|
+
|
20
|
+
module ChefDK
|
21
|
+
module Policyfile
|
22
|
+
|
23
|
+
class StorageConfig
|
24
|
+
|
25
|
+
attr_accessor :relative_paths_root
|
26
|
+
attr_accessor :cache_path
|
27
|
+
|
28
|
+
attr_reader :policyfile_filename
|
29
|
+
attr_reader :policyfile_lock_filename
|
30
|
+
|
31
|
+
def initialize(options = {})
|
32
|
+
@relative_paths_root = Dir.pwd
|
33
|
+
@cache_path = CookbookOmnifetch.storage_path
|
34
|
+
@policyfile_filename = "<< Policyfile filename not specified >>"
|
35
|
+
@policyfile_lock_filename = "<< Policyfile lock filename not specified >>"
|
36
|
+
handle_options(options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def use_policyfile(policyfile_filename)
|
40
|
+
@policyfile_filename = policyfile_filename
|
41
|
+
@relative_paths_root = File.dirname(policyfile_filename)
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
def use_policyfile_lock(policyfile_lock_filename)
|
46
|
+
@policyfile_lock_filename = policyfile_lock_filename
|
47
|
+
@relative_paths_root = File.dirname(policyfile_lock_filename)
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def handle_options(options)
|
54
|
+
@cache_path = options[:cache_path] if options[:cache_path]
|
55
|
+
@relative_paths_root = options[:relative_paths_root] if options.key?(:relative_paths_root)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
module StorageConfigDelegation
|
60
|
+
|
61
|
+
def cache_path
|
62
|
+
storage_config.cache_path
|
63
|
+
end
|
64
|
+
|
65
|
+
def relative_paths_root
|
66
|
+
storage_config.relative_paths_root
|
67
|
+
end
|
68
|
+
|
69
|
+
def policyfile_filename
|
70
|
+
storage_config.policyfile_filename
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
@@ -0,0 +1,110 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 2014 Chef Software Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'chef/cookbook_uploader'
|
19
|
+
require 'chef-dk/policyfile/read_cookbook_for_compat_mode_upload'
|
20
|
+
|
21
|
+
module ChefDK
|
22
|
+
module Policyfile
|
23
|
+
class Uploader
|
24
|
+
|
25
|
+
COMPAT_MODE_DATA_BAG_NAME = "policyfiles".freeze
|
26
|
+
|
27
|
+
attr_reader :policyfile_lock
|
28
|
+
attr_reader :policy_group
|
29
|
+
attr_reader :http_client
|
30
|
+
|
31
|
+
def initialize(policyfile_lock, policy_group, http_client: nil)
|
32
|
+
@policyfile_lock = policyfile_lock
|
33
|
+
@policy_group = policy_group
|
34
|
+
@http_client = http_client
|
35
|
+
end
|
36
|
+
|
37
|
+
def upload
|
38
|
+
uploader.upload_cookbooks
|
39
|
+
data_bag_create
|
40
|
+
data_bag_item_create
|
41
|
+
end
|
42
|
+
|
43
|
+
def data_bag_create
|
44
|
+
http_client.post("data", {"name" => COMPAT_MODE_DATA_BAG_NAME})
|
45
|
+
rescue Net::HTTPServerException => e
|
46
|
+
raise e unless e.response.code == "409"
|
47
|
+
end
|
48
|
+
|
49
|
+
def data_bag_item_create
|
50
|
+
policy_id = "#{policyfile_lock.name}-#{policy_group}"
|
51
|
+
lock_data = policyfile_lock.to_lock.dup
|
52
|
+
|
53
|
+
lock_data["id"] = policy_id
|
54
|
+
|
55
|
+
data_item = {
|
56
|
+
"id" => policy_id,
|
57
|
+
"name" => "data_bag_item_#{COMPAT_MODE_DATA_BAG_NAME}_#{policy_id}",
|
58
|
+
"data_bag" => COMPAT_MODE_DATA_BAG_NAME,
|
59
|
+
"raw_data" => lock_data,
|
60
|
+
# we'd prefer to leave this out, but the "compatibility mode"
|
61
|
+
# implementation in chef-client relies on magical class inflation
|
62
|
+
"json_class" => "Chef::DataBagItem"
|
63
|
+
}
|
64
|
+
|
65
|
+
upload_lockfile_as_data_bag_item(policy_id, data_item)
|
66
|
+
end
|
67
|
+
|
68
|
+
def uploader
|
69
|
+
# TODO: uploader runs cookbook validation; we want to do this at a different time.
|
70
|
+
@uploader ||= Chef::CookbookUploader.new(cookbook_versions_to_upload, :rest => http_client)
|
71
|
+
end
|
72
|
+
|
73
|
+
def cookbook_versions_to_upload
|
74
|
+
cookbook_versions_for_policy.reject do |cookbook|
|
75
|
+
remote_already_has_cookbook?(cookbook)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def remote_already_has_cookbook?(cookbook)
|
80
|
+
return false unless existing_cookbook_on_remote.key?(cookbook.name.to_s)
|
81
|
+
|
82
|
+
existing_cookbook_on_remote[cookbook.name.to_s]["versions"].any? do |cookbook_info|
|
83
|
+
cookbook_info["version"] == cookbook.version
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def existing_cookbook_on_remote
|
88
|
+
@existing_cookbook_on_remote ||= http_client.get('cookbooks?num_versions=all')
|
89
|
+
end
|
90
|
+
|
91
|
+
# An Array of Chef::CookbookVersion objects representing the full set that
|
92
|
+
# the policyfile lock requires.
|
93
|
+
def cookbook_versions_for_policy
|
94
|
+
policyfile_lock.validate_cookbooks!
|
95
|
+
policyfile_lock.cookbook_locks.map do |name, lock|
|
96
|
+
ReadCookbookForCompatModeUpload.load(name, lock.dotted_decimal_identifier, lock.cookbook_path)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def upload_lockfile_as_data_bag_item(policy_id, data_item)
|
103
|
+
http_client.put("data/#{COMPAT_MODE_DATA_BAG_NAME}/#{policy_id}", data_item)
|
104
|
+
rescue Net::HTTPServerException => e
|
105
|
+
raise e unless e.response.code == "404"
|
106
|
+
http_client.post("data/#{COMPAT_MODE_DATA_BAG_NAME}", data_item)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|