test-kitchen 1.0.0.alpha.7 → 1.0.0.beta.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.
@@ -1,177 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
- #
5
- # Copyright (C) 2012, Fletcher Nichol
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
- require 'fileutils'
20
- require 'json'
21
- require 'net/scp'
22
- require 'stringio'
23
-
24
- module Kitchen
25
-
26
- # Uploads Chef asset files such as dna.json, data bags, and cookbooks to an
27
- # instance over SSH.
28
- #
29
- # @author Fletcher Nichol <fnichol@nichol.ca>
30
- class ChefDataUploader
31
-
32
- include ShellOut
33
- include Logging
34
-
35
- def initialize(instance, ssh_args, kitchen_root, chef_home)
36
- @instance = instance
37
- @ssh_args = ssh_args
38
- @kitchen_root = kitchen_root
39
- @chef_home = chef_home
40
- end
41
-
42
- def upload
43
- Net::SCP.start(*ssh_args) do |scp|
44
- upload_json scp
45
- upload_solo_rb scp
46
- upload_cookbooks scp
47
- upload_data_bags scp if instance.suite.data_bags_path
48
- upload_roles scp if instance.suite.roles_path
49
- upload_secret scp if instance.suite.encrypted_data_bag_secret_key_path
50
- end
51
- end
52
-
53
- private
54
-
55
- attr_reader :instance, :ssh_args, :kitchen_root, :chef_home
56
-
57
- def logger
58
- instance.logger
59
- end
60
-
61
- def upload_json(scp)
62
- json_file = StringIO.new(instance.dna.to_json)
63
- scp.upload!(json_file, "#{chef_home}/dna.json")
64
- end
65
-
66
- def upload_solo_rb(scp)
67
- solo_rb_file = StringIO.new(solo_rb_contents)
68
- scp.upload!(solo_rb_file, "#{chef_home}/solo.rb")
69
- end
70
-
71
- def upload_cookbooks(scp)
72
- cookbooks_dir = local_cookbooks
73
- upload_path(scp, cookbooks_dir, "cookbooks")
74
- ensure
75
- FileUtils.rmtree(cookbooks_dir) unless cookbooks_dir.nil?
76
- end
77
-
78
- def upload_data_bags(scp)
79
- upload_path(scp, instance.suite.data_bags_path)
80
- end
81
-
82
- def upload_roles(scp)
83
- upload_path(scp, instance.suite.roles_path)
84
- end
85
-
86
- def upload_secret(scp)
87
- scp.upload!(instance.suite.encrypted_data_bag_secret_key_path,
88
- "#{chef_home}/encrypted_data_bag_secret")
89
- end
90
-
91
- def upload_path(scp, path, dir = File.basename(path))
92
- dest = "#{chef_home}/#{dir}"
93
-
94
- scp.upload!(path, dest, :recursive => true) do |ch, name, sent, total|
95
- if sent == total
96
- info("Uploaded #{name.sub(%r{^#{path}/}, '')} (#{total} bytes)")
97
- end
98
- end
99
- end
100
-
101
- def solo_rb_contents
102
- solo = []
103
- solo << %{node_name "#{instance.name}"}
104
- solo << %{file_cache_path "#{chef_home}/cache"}
105
- solo << %{cookbook_path "#{chef_home}/cookbooks"}
106
- solo << %{role_path "#{chef_home}/roles"}
107
- if instance.suite.data_bags_path
108
- solo << %{data_bag_path "#{chef_home}/data_bags"}
109
- end
110
- if instance.suite.encrypted_data_bag_secret_key_path
111
- secret = "#{chef_home}/encrypted_data_bag_secret"
112
- solo << %{encrypted_data_bag_secret "#{secret}"}
113
- end
114
- solo.join("\n")
115
- end
116
-
117
- def local_cookbooks
118
- tmpdir = Dir.mktmpdir("#{instance.name}-cookbooks")
119
- prepare_tmpdir(tmpdir)
120
- tmpdir
121
- end
122
-
123
- def prepare_tmpdir(tmpdir)
124
- if File.exists?(File.join(kitchen_root, "Berksfile"))
125
- run_resolver("Berkshelf", "berks", tmpdir)
126
- elsif File.exists?(File.join(kitchen_root, "Cheffile"))
127
- run_resolver("Librarian", "librarian-chef", tmpdir)
128
- elsif File.directory?(File.join(kitchen_root, "cookbooks"))
129
- cp_cookbooks(tmpdir)
130
- elsif File.exists?(File.join(kitchen_root, "metadata.rb"))
131
- cp_this_cookbook(tmpdir)
132
- else
133
- FileUtils.rmtree(tmpdir)
134
- fatal("Berksfile, Cheffile, cookbooks/, or metadata.rb" +
135
- " must exist in #{kitchen_root}")
136
- raise UserError, "Cookbooks could not be found"
137
- end
138
- end
139
-
140
- def run_resolver(name, bin, tmpdir)
141
- # Just going to have to take your chances on Windows - no way to
142
- # check for a command without running it, and looking for an
143
- # exit code. Good times.
144
- if RUBY_PLATFORM !~ /mswin|mingw/
145
- begin
146
- run_command "if ! command -v #{bin} >/dev/null; then exit 1; fi"
147
- rescue Kitchen::ShellOut::ShellCommandFailed
148
- fatal("#{name} must be installed, add it to your Gemfile.")
149
- raise UserError, "#{bin} command not found"
150
- end
151
- end
152
-
153
- Kitchen.mutex.synchronize do
154
- run_command "#{bin} install --path #{tmpdir}"
155
- end
156
- end
157
-
158
- def cp_cookbooks(tmpdir)
159
- FileUtils.cp_r(File.join(kitchen_root, "cookbooks", "."), tmpdir)
160
- cp_this_cookbook(tmpdir) if File.exists?(File.expand_path('metadata.rb'))
161
- end
162
-
163
- def cp_this_cookbook(tmpdir)
164
- metadata_rb = File.join(kitchen_root, "metadata.rb")
165
- cb_name = MetadataChopper.extract(metadata_rb).first or raise(UserError,
166
- "The metadata.rb does not define the 'name' key." +
167
- " Please add: `name '<cookbook_name>'` to metadata.rb and try again")
168
-
169
- cb_path = File.join(tmpdir, cb_name)
170
- glob = Dir.glob("#{kitchen_root}/{metadata.rb,README.*," +
171
- "attributes,files,libraries,providers,recipes,resources,templates}")
172
-
173
- FileUtils.mkdir_p(cb_path)
174
- FileUtils.cp_r(glob, cb_path)
175
- end
176
- end
177
- end