knife-tar 1.3.0

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.
@@ -0,0 +1,276 @@
1
+
2
+ require 'open-uri'
3
+ require 'chef/mixin/command'
4
+ require 'tmp_directory'
5
+
6
+ #A class for handling a tar file that contains chef components.
7
+
8
+ class Chef
9
+ class TarFile
10
+
11
+ #The named conventions for chef components
12
+ COOKBOOKS_PATH = "cookbooks"
13
+ ROLES_PATH = "roles"
14
+ ENVIRONMENTS_PATH = "environments"
15
+ DATA_BAGS_PATH = "data_bags"
16
+ API_CLIENTS_PATH = "api_clients"
17
+ WEB_USERS_PATH = "web_users"
18
+ NODES_PATH = "nodes"
19
+
20
+ #A list of valid chef file extensions
21
+ CHEF_FILE_EXTENSIONS = [".js", ".json", ".rb"]
22
+
23
+ def initialize tarPath, create=false
24
+
25
+ if tarPath==nil
26
+ raise ArgumentError, "A tar file path must be given"
27
+ end
28
+
29
+ @create_tar = create
30
+
31
+ unless create
32
+ @temp_directory = TmpDirectory.new.path
33
+
34
+ #Assume for now that the components live directly inside the tar file
35
+ @tar_contents_path = @temp_directory
36
+
37
+ localTarFile = File.join(@temp_directory, 'cookbooks.tgz')
38
+
39
+ #Move/Download tar file to tmp directory
40
+ File.open(localTarFile, 'wb') do |f|
41
+ open(tarPath) do |r|
42
+ f.write(r.read)
43
+ end
44
+ end
45
+
46
+ #Untar file
47
+ Chef::Mixin::Command.run_command(:command => "tar zxfC #{localTarFile} #{@temp_directory}")
48
+
49
+ #Verify tar file structure and update tar_contents_path if necessary
50
+
51
+ dirList = get_directories_names @tar_contents_path
52
+
53
+ if !is_tar_valid? dirList
54
+ #The tar does not contain any immediate chef component directories, check to see if there is a top-level project folder
55
+ #that contains any chef component directories
56
+
57
+ if dirList.size!=1 or !is_tar_valid? get_directories_names(File.join(@tar_contents_path, dirList.first))
58
+ raise InvalidStructureError, "The tar file has an invalid structure"
59
+ end
60
+
61
+ #The tar file is valid but contains a top-level project folder so update the @tar_contents_path
62
+ @tar_contents_path = File.join(@tar_contents_path, dirList.first)
63
+ end
64
+
65
+ #Remove tar file
66
+ FileUtils.rm_f localTarFile
67
+
68
+ else
69
+
70
+ # Verify that the tarPath doesn't already exist
71
+ if File.exists? tarPath
72
+ raise ArgumentError, "We cannot create a tar file at path : #{tarPath} because it already exists"
73
+ end
74
+
75
+ @temp_directory = TmpDirectory.new("chef-server").path
76
+
77
+ #We will create the tar file such that their is no single root directory inside the tar file
78
+ @tar_contents_path = @temp_directory
79
+
80
+ FileUtils.mkdir_p @temp_directory
81
+
82
+ @create_tar_path = File.absolute_path tarPath
83
+
84
+ # We are setting up a directory to become a Chef TarFile so create the resource directories
85
+ FileUtils.mkdir_p File.join @tar_contents_path, COOKBOOKS_PATH
86
+ FileUtils.mkdir_p File.join @tar_contents_path, ROLES_PATH
87
+ FileUtils.mkdir_p File.join @tar_contents_path, ENVIRONMENTS_PATH
88
+ FileUtils.mkdir_p File.join @tar_contents_path, DATA_BAGS_PATH
89
+ FileUtils.mkdir_p File.join @tar_contents_path, API_CLIENTS_PATH
90
+ FileUtils.mkdir_p File.join @tar_contents_path, WEB_USERS_PATH
91
+ FileUtils.mkdir_p File.join @tar_contents_path, NODES_PATH
92
+
93
+ end
94
+
95
+ end
96
+
97
+ #Returns the absolute path to the cookbooks directory
98
+ def cookbooks_path
99
+ verify_path COOKBOOKS_PATH
100
+ File.join @tar_contents_path, COOKBOOKS_PATH
101
+ end
102
+
103
+ #Returns list of absolute paths of the cookbooks
104
+ def cookbooks
105
+ get_directories_absolute_paths cookbooks_path
106
+ end
107
+
108
+ #Returns the absolute path to the roles directory
109
+ def roles_path
110
+ verify_path ROLES_PATH
111
+ File.join @tar_contents_path, ROLES_PATH
112
+ end
113
+
114
+ #Returns a list of absolute paths to the roles json files
115
+ def roles
116
+ get_chef_files_absolute_paths roles_path
117
+ end
118
+
119
+ #Returns the absolute path to the environments directory
120
+ def environments_path
121
+ verify_path ENVIRONMENTS_PATH
122
+ File.join @tar_contents_path, ENVIRONMENTS_PATH
123
+ end
124
+
125
+ #Returns a list of absolute paths to the environemnts json files
126
+ def environments
127
+ get_chef_files_absolute_paths environments_path
128
+ end
129
+
130
+ #Returns the absolute path to the data_bags directory
131
+ def data_bags_path
132
+ verify_path DATA_BAGS_PATH
133
+ File.join @tar_contents_path, DATA_BAGS_PATH
134
+ end
135
+
136
+ #Returns a list of absolute paths to the data_bags json files
137
+ def data_bags
138
+
139
+ #Data bags follow a different structure then the other components, their structure is
140
+ #|- data_bags
141
+ #\ \- data_bag_1
142
+ #| | |- values_1.json
143
+ #| ...
144
+
145
+ dir_list = get_directories_absolute_paths(data_bags_path)
146
+
147
+ data_bags_absolute_paths = Array.new
148
+
149
+ dir_list.each do |dir_path|
150
+ data_bags_absolute_paths = data_bags_absolute_paths | get_chef_files_absolute_paths(dir_path)
151
+ end
152
+
153
+ data_bags_absolute_paths
154
+ end
155
+
156
+ #Returns the absolute path to the api_clients directory
157
+ def api_clients_path
158
+ verify_path API_CLIENTS_PATH
159
+ File.join @tar_contents_path, API_CLIENTS_PATH
160
+ end
161
+
162
+ #Returns a list of absolute paths to the api_clients json files
163
+ def api_clients
164
+ get_chef_files_absolute_paths api_clients_path
165
+ end
166
+
167
+ #Returns the absolute path of the nodes directory
168
+ def nodes_path
169
+ verify_path NODES_PATH
170
+ File.join @tar_contents_path, NODES_PATH
171
+ end
172
+
173
+ #Returns a list of absolute paths to the nodes json files
174
+ def nodes
175
+ get_chef_files_absolute_paths nodes_path
176
+ end
177
+
178
+ #Returns the absolute path of the web_users directory
179
+ def web_users_path
180
+ verify_path WEB_USERS_PATH
181
+ File.join @tar_contents_path, WEB_USERS_PATH
182
+ end
183
+
184
+ #Returns a list of absolute paths to the web_users json files
185
+ def web_users
186
+ get_chef_files_absolute_paths web_users_path
187
+ end
188
+
189
+ def save
190
+ if @create_tar
191
+
192
+ #Tar up the directory from the parent directory of the tar's contents (this will really be /tmp)
193
+ Chef::Mixin::Command.run_command(:cwd => File.expand_path("..",@tar_contents_path), :command => "tar zfc #{@create_tar_path} #{File.basename @tar_contents_path}")
194
+
195
+ @create_tar = false
196
+ else
197
+ raise StandardError, "The tar file is not in the correct state to be saved"
198
+ end
199
+ end
200
+
201
+ private
202
+
203
+ #Returns true if the list of directories contains at least one chef component
204
+ def is_tar_valid? dir_list
205
+
206
+ #Remove unnessary directories
207
+ dir_list.delete(".")
208
+ dir_list.delete("..")
209
+
210
+ dir_list.each do |dir|
211
+ [API_CLIENTS_PATH, COOKBOOKS_PATH, DATA_BAGS_PATH, ENVIRONMENTS_PATH, NODES_PATH, ROLES_PATH, WEB_USERS_PATH].each do |component|
212
+ if dir == component
213
+ return true
214
+ end
215
+ end
216
+ end
217
+ return false
218
+ end
219
+
220
+ #Throws an exception if the given component does not exist within the tar's contents
221
+ def verify_path component
222
+ if !File.exists? File.join @tar_contents_path, component
223
+ raise MissingChefComponentError, "The '#{component}' directory does not exist within the tar file"
224
+ end
225
+ end
226
+
227
+ #Returns a list of the base file names for all the directories at the given path
228
+ def get_directories_names path
229
+ get_directories_absolute_paths(path).map {|dir| File.basename(dir) }
230
+ end
231
+
232
+ #Returns a list of the absolute paths of all the directories at the given path
233
+ def get_directories_absolute_paths path
234
+ dir_list = Dir["#{path}/*/"]
235
+
236
+ #Remove unnecessary directories
237
+ dir_list.delete(File.join(path, "."))
238
+ dir_list.delete(File.join(path, ".."))
239
+
240
+ dir_list
241
+ end
242
+
243
+ #Returns a list of the base file names for all files at the given path
244
+ def get_file_names path
245
+ Dir.entries(path).select { |file| !File.directory? File.join(path, file) }
246
+ end
247
+
248
+ #Returns a list of the absolute paths of all the files at the given path
249
+ def get_file_absolute_paths path
250
+ get_file_names(path).map { |file| File.join(path, file) }
251
+ end
252
+
253
+ #Returns a list of the absolute paths of all the valid chef component files at the given path
254
+ def get_chef_files_absolute_paths path
255
+ get_file_absolute_paths(path).select { |file| is_valid_chef_component_file?(file) }
256
+ end
257
+
258
+ #Returns true if the filename is a valid chef component file
259
+ def is_valid_chef_component_file? filename
260
+ extension = File.extname(filename)
261
+ CHEF_FILE_EXTENSIONS.each do |validExtension|
262
+ if extension.casecmp(validExtension) == 0
263
+ return true
264
+ end
265
+ end
266
+ return false
267
+ end
268
+
269
+ #Error when a Chef::TarFile does not have the correct structure
270
+ class InvalidStructureError < StandardError; end
271
+
272
+ #Error thrown when a chef component that is accessed cannot be found
273
+ class MissingChefComponentError < StandardError; end
274
+
275
+ end
276
+ end
@@ -0,0 +1,25 @@
1
+ require 'tmpdir'
2
+
3
+ class TmpDirectory
4
+
5
+ attr_reader :path
6
+
7
+ def initialize name="tmp"
8
+ @path = ::File.join(Dir.tmpdir, "#{name}-#{Time.now.strftime("%Y%m%d%H%M%S")}-#{Random.rand}")
9
+
10
+ FileUtils.mkdir_p @path
11
+
12
+ #Add shutdown hook to remove tar tmp directory
13
+ Kernel.at_exit do
14
+ cleanup
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ #Remove the created temp directory
21
+ def cleanup
22
+ FileUtils.rm_rf @path
23
+ end
24
+
25
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: knife-tar
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Bryan Baugher
8
+ - Aaron Blythe
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-01-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: chef
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '>='
19
+ - !ruby/object:Gem::Version
20
+ version: 0.10.0
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '>='
26
+ - !ruby/object:Gem::Version
27
+ version: 0.10.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: 0.9.2.2
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ version: 0.9.2.2
42
+ description: This is a knife plugin for Chef which can install and upload chef components
43
+ from a tar file or url
44
+ email: Bryan.Baugher@Cerner.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - lib/chef/knife/client_tar_download.rb
50
+ - lib/chef/knife/client_tar_upload.rb
51
+ - lib/chef/knife/cookbook_tar_download.rb
52
+ - lib/chef/knife/cookbook_tar_upload.rb
53
+ - lib/chef/knife/data_bag_tar_download.rb
54
+ - lib/chef/knife/data_bag_tar_upload.rb
55
+ - lib/chef/knife/environment_tar_download.rb
56
+ - lib/chef/knife/environment_tar_upload.rb
57
+ - lib/chef/knife/node_tar_download.rb
58
+ - lib/chef/knife/node_tar_upload.rb
59
+ - lib/chef/knife/role_tar_download.rb
60
+ - lib/chef/knife/role_tar_upload.rb
61
+ - lib/chef/knife/tar_download_all.rb
62
+ - lib/chef/knife/tar_upload_all.rb
63
+ - lib/chef/knife/user_tar_download.rb
64
+ - lib/chef/knife/user_tar_upload.rb
65
+ - lib/chef/tar_file.rb
66
+ - lib/tmp_directory.rb
67
+ - Gemfile
68
+ - Rakefile
69
+ - README.md
70
+ homepage: http://github.com/Cerner/knife-tar
71
+ licenses:
72
+ - Apache License, Version 2.0
73
+ metadata: {}
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 2.0.3
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: A Chef knife plugin to install/upload chef components from a tar file or
94
+ url
95
+ test_files: []