test-kitchen 1.0.0.alpha.7 → 1.0.0.beta.1

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