chef-dk 0.2.0 → 0.2.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.
- 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
|