knife-hitori 0.0.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.
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +0 -0
- data/Rakefile +7 -0
- data/knife-hitori.gemspec +28 -0
- data/lib/chef/knife/hitori/version.rb +7 -0
- data/lib/chef/knife/hitori_base.rb +11 -0
- data/lib/chef/knife/hitori_config.rb +70 -0
- data/lib/chef/knife/hitori_cook.rb +291 -0
- data/lib/chef/knife/hitori_hello.rb +25 -0
- data/lib/chef/knife/hitori_prepare.rb +47 -0
- data/lib/knife-hitori/interactive_configure.rb +35 -0
- data/lib/knife-hitori/resources/centos_bootstrap.erb +47 -0
- data/lib/knife-hitori/resources/do_cook.sh +37 -0
- data/lib/knife-hitori/resources/knife.erb +34 -0
- data/lib/knife-hitori/resources/knife_ec2.erb +14 -0
- data/lib/knife-hitori.rb +7 -0
- data/refs/Rakefile +272 -0
- data/refs/Vagrantfile +54 -0
- data/refs/run_chef_solo.sh +41 -0
- data/refs/util/create_encrypt_databag.rb +57 -0
- data/refs/util/crypt_file.rb +45 -0
- data/spec/knife/hitori_config_spec.rb +106 -0
- data/spec/knife/hitori_cook_spec.rb +67 -0
- data/spec/knife/hitori_hello_spec.rb +13 -0
- data/spec/knife/hitori_prepare_spec.rb +44 -0
- data/spec/spec_helper.rb +4 -0
- metadata +175 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
current_dir = File.dirname(__FILE__)
|
2
|
+
parent_dir = File.realdirpath(current_dir + '/..')
|
3
|
+
chef_env_file = "#{parent_dir}/.chef_env"
|
4
|
+
|
5
|
+
|
6
|
+
chef_env = (ENV['CHEF_ENV'] || (File.exists?(chef_env_file) && File.read(chef_env_file)) || 'dev').strip
|
7
|
+
|
8
|
+
solo_environment chef_env
|
9
|
+
chef_solo_base_dir parent_dir
|
10
|
+
file_cache_path "#{chef_solo_base_dir}/.solo_cache"
|
11
|
+
cookbook_path "#{chef_solo_base_dir}/cookbooks"
|
12
|
+
|
13
|
+
data_bag_path_tpl "#{chef_solo_base_dir}/data_bags/%s"
|
14
|
+
data_bag_path sprintf(data_bag_path_tpl, chef_env)
|
15
|
+
|
16
|
+
role_path "#{chef_solo_base_dir}/roles"
|
17
|
+
|
18
|
+
encrypted_data_bag_secret_tpl "#{data_bag_path_tpl}/crypt.key"
|
19
|
+
encrypted_data_bag_secret sprintf(encrypted_data_bag_secret_tpl, chef_env)
|
20
|
+
|
21
|
+
settings_path_tpl "#{chef_solo_base_dir}/environments/%s/settings.json"
|
22
|
+
settings_path sprintf(settings_path_tpl, chef_env)
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
Chef::Config[:solo] = true
|
27
|
+
# load extra config
|
28
|
+
config_files = %w(ec2.rb)
|
29
|
+
|
30
|
+
config_files.each do |name|
|
31
|
+
filename = "#{current_dir}/#{name}"
|
32
|
+
Chef::Config.from_file(filename) if File.exists?(filename)
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
knife[:availability_zone] = "<%= config[:availability_zone] %>"
|
2
|
+
knife[:aws_access_key_id] = "<%= config[:aws_access_key_id] %>"
|
3
|
+
knife[:aws_secret_access_key] = "<%= config[:aws_secret_access_key] %>"
|
4
|
+
knife[:image] = "<%= config[:image] %>"
|
5
|
+
knife[:flavor] = "<%= config[:flavor] %>"
|
6
|
+
knife[:aws_ssh_key_id] = "<%= config[:aws_ssh_key_id] %>"
|
7
|
+
knife[:ssh_port] = <%= config[:ssh_port] %>
|
8
|
+
knife[:ssh_user] = "<%= config[:ssh_user] %>"
|
9
|
+
knife[:identity_file] = "<%= config[:identity_file] %>"
|
10
|
+
knife[:region] = "<%= config[:region] %>"
|
11
|
+
knife[:template_file] = "<%= config[:template_file] %>"
|
12
|
+
knife[:security_groups] = "<%= config[:security_groups] %>"
|
13
|
+
knife[:remote_chef_dir] = "/tmp/chef-solo"
|
14
|
+
|
data/lib/knife-hitori.rb
ADDED
data/refs/Rakefile
ADDED
@@ -0,0 +1,272 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rake'
|
4
|
+
require 'erb'
|
5
|
+
require 'digest/md5'
|
6
|
+
|
7
|
+
DEFAULT_AZ = 'ap-northeast-1c'
|
8
|
+
DEFAULT_AMI = 'ami-5d7dfa5c'
|
9
|
+
DEFAULT_FLAVOR = 'm1.small'
|
10
|
+
DEFAULT_REGION = 'ap-northeast-1'
|
11
|
+
DEFAULT_BOOTSTRAP = 'centos_bootstrap.erb'
|
12
|
+
|
13
|
+
|
14
|
+
THIS_DIR = File.absolute_path(File.dirname(__FILE__))
|
15
|
+
CHEF_SOLO_DIR = "#{THIS_DIR}/chef-solo"
|
16
|
+
TMPL_DIR = "#{THIS_DIR}/templates"
|
17
|
+
|
18
|
+
KNIFE = "#{CHEF_SOLO_DIR}/.chef/knife.rb"
|
19
|
+
EC2_CONFIG = "#{CHEF_SOLO_DIR}/.chef/ec2.rb"
|
20
|
+
|
21
|
+
|
22
|
+
desc 'EC2関連の設定をknife.rbに追加する'
|
23
|
+
task :ec2_config do
|
24
|
+
require 'chef/config'
|
25
|
+
template_ec2 = "#{TMPL_DIR}/knife_ec2.erb"
|
26
|
+
tmpl_ec2 = ERB.new(File.read(template_ec2))
|
27
|
+
|
28
|
+
Chef::Config.from_file(EC2_CONFIG) if File.exists?(EC2_CONFIG)
|
29
|
+
config = ask_ec2_config_all(Chef::Config.knife)
|
30
|
+
|
31
|
+
Dir.mkdir(File.dirname(EC2_CONFIG)) unless File.exists?(File.dirname(EC2_CONFIG))
|
32
|
+
|
33
|
+
open(EC2_CONFIG, 'w') do |f|
|
34
|
+
f.puts(tmpl_ec2.result(binding))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
desc 'ec2.rb を削除する'
|
39
|
+
task :clear_config do |t, args|
|
40
|
+
rm [EC2_CONFIG], :force => true
|
41
|
+
end
|
42
|
+
|
43
|
+
desc 'EC2サーバを新規に作成し、Chefを実行する'
|
44
|
+
task :ec2_create_server do
|
45
|
+
tag_id = ec2_create_server_only
|
46
|
+
options = {RUN_TAG_KEY => "#{CHEF_EC2_TAG_ID}=#{tag_id}"}
|
47
|
+
ec2_provision(options)
|
48
|
+
info = fetch_server_info(options)
|
49
|
+
puts "Done! please access by 'ssh #{info.public_ip_address}'"
|
50
|
+
end
|
51
|
+
|
52
|
+
desc 'EC2サーバのリストを表示する'
|
53
|
+
task :ec2_server_list do
|
54
|
+
cd CHEF_SOLO_DIR
|
55
|
+
sh "knife ec2 server list -c '#{KNIFE}'"
|
56
|
+
end
|
57
|
+
|
58
|
+
desc 'EC2サーバを起動する'
|
59
|
+
task :ec2_create_server_only do |t, args|
|
60
|
+
ec2_create_server_only
|
61
|
+
end
|
62
|
+
|
63
|
+
desc 'EC2サーバ上でchefを実行する'
|
64
|
+
task :ec2_provision do |t, _|
|
65
|
+
options = [RUN_GROUPS_KEY, RUN_TAG_KEY, RUN_IP_KEY, RUN_NAME_KEY].inject({}) {|t,x| t[x] = ENV[x].to_s if ENV[x]; t}
|
66
|
+
|
67
|
+
if options.size == 1
|
68
|
+
ec2_provision(options)
|
69
|
+
else
|
70
|
+
puts <<-EOM
|
71
|
+
Usage: rake #{t.name} [#{RUN_GROUPS_KEY}=<group>] [#{RUN_NAME_KEY}=<name>] [#{RUN_IP_KEY}=<public ip>] [#{RUN_TAG_KEY}=<tag-key>=<tag-value>]
|
72
|
+
please specify GROUP or NAME or IP or TAG
|
73
|
+
|
74
|
+
|
75
|
+
EOM
|
76
|
+
Rake::Task['ec2_server_list'].execute
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
#######################################################################################
|
81
|
+
#######################################################################################
|
82
|
+
#######################################################################################
|
83
|
+
|
84
|
+
CHEF_EC2_TAG_ID = 'chefec2_id'
|
85
|
+
RUN_GROUPS_KEY = 'GROUP'
|
86
|
+
RUN_TAG_KEY = 'TAG'
|
87
|
+
RUN_IP_KEY = 'IP'
|
88
|
+
RUN_NAME_KEY = 'NAME'
|
89
|
+
|
90
|
+
|
91
|
+
def ask_ec2_config_all(knife, runtime=false)
|
92
|
+
config = {}
|
93
|
+
config[:availability_zone] = input_arg('availability_zone', knife[:availability_zone], ENV['EC2_AVAILABILITY_ZONE'], DEFAULT_AZ)
|
94
|
+
config[:aws_access_key_id] = input_arg('aws_access_key_id', knife[:aws_access_key_id], ENV['AWS_ACCESS_KEY_ID']) unless runtime
|
95
|
+
config[:aws_secret_access_key] = input_arg('aws_secret_access_key', knife[:aws_secret_access_key], ENV['AWS_SECRET_ACCESS_KEY']) unless runtime
|
96
|
+
config[:image] = input_arg('ami image', knife[:image], ENV['EC2_AMI_IMAGE'], DEFAULT_AMI)
|
97
|
+
config[:flavor] = input_arg('flavor', knife[:flavor], ENV['EC2_FLAVOR'], DEFAULT_FLAVOR)
|
98
|
+
config[:groups] = input_arg('Security Group', knife[:groups], ENV['EC2_SECURITY_GROUP'], 'default')
|
99
|
+
config[:ssh_user] = input_arg('ssh_user', knife[:ssh_user], ENV['EC2_SSH_USER'], 'ec2-user')
|
100
|
+
config[:identity_file] = k = input_arg('identity_file(*.pem)', knife[:identity_file], ENV['EC2_PRIVATE_KEY'])
|
101
|
+
config[:ssh_key] = input_arg('ssh_key_name', knife[:ssh_key], ENV['EC2_SSH_KEY'], File.basename(k || '').sub(/\.pem$/, ''))
|
102
|
+
config[:region] = input_arg('region', knife[:region], ENV['EC2_REGION'], DEFAULT_REGION)
|
103
|
+
config[:template_file] = input_arg('bootstrap template', knife[:template_file], "#{TMPL_DIR}/#{DEFAULT_BOOTSTRAP}")
|
104
|
+
config[:identity_file] = File.absolute_path(config[:identity_file]) if config[:identity_file]
|
105
|
+
config
|
106
|
+
end
|
107
|
+
|
108
|
+
def input_arg(message, *defaults)
|
109
|
+
default = defaults.select { |x| !x.to_s.empty? }.first
|
110
|
+
while true
|
111
|
+
print "#{message} [#{default}] ? "
|
112
|
+
input = STDIN.gets.chomp
|
113
|
+
input = input.empty? ? default : input
|
114
|
+
break if not block_given? or yield(input)
|
115
|
+
end
|
116
|
+
input
|
117
|
+
end
|
118
|
+
|
119
|
+
def create_random_id
|
120
|
+
Digest::MD5.hexdigest(Time.new.to_i.to_s + rand.to_s)
|
121
|
+
end
|
122
|
+
|
123
|
+
def configure_chef
|
124
|
+
require 'chef/config'
|
125
|
+
Chef::Config.from_file(KNIFE)
|
126
|
+
end
|
127
|
+
|
128
|
+
def server_info_list
|
129
|
+
require 'fog'
|
130
|
+
configure_chef
|
131
|
+
connection = Fog::Compute.new(
|
132
|
+
:provider => 'AWS',
|
133
|
+
:aws_access_key_id => Chef::Config[:knife][:aws_access_key_id],
|
134
|
+
:aws_secret_access_key => Chef::Config[:knife][:aws_secret_access_key],
|
135
|
+
:region => Chef::Config[:knife][:region]
|
136
|
+
)
|
137
|
+
connection.servers.all.to_a
|
138
|
+
end
|
139
|
+
|
140
|
+
def ec2_create_server_only
|
141
|
+
configure_chef
|
142
|
+
knife = Chef::Config.knife
|
143
|
+
config = ask_ec2_config_all(knife, true)
|
144
|
+
tag_id = create_random_id
|
145
|
+
|
146
|
+
cd CHEF_SOLO_DIR
|
147
|
+
cmd_list = %w(knife ec2 server create)
|
148
|
+
cmd_list << "-c '#{KNIFE}'"
|
149
|
+
cmd_list << "-T #{CHEF_EC2_TAG_ID}=#{tag_id}"
|
150
|
+
add_args(cmd_list, '--groups=', :groups, knife, config)
|
151
|
+
add_args(cmd_list, '--availability-zone=', :availability_zone, knife, config)
|
152
|
+
add_args(cmd_list, '--image=', :image, knife, config, true)
|
153
|
+
add_args(cmd_list, '--flavor=', :flavor, knife, config)
|
154
|
+
add_args(cmd_list, '--ssh-user=', :ssh_user, knife, config, true)
|
155
|
+
add_args(cmd_list, '--identity-file=', :identity_file, knife, config, true)
|
156
|
+
add_args(cmd_list, '--ssh-key=', :ssh_key, knife, config, true)
|
157
|
+
add_args(cmd_list, '--region=', :region, knife, config)
|
158
|
+
add_args(cmd_list, '--template-file=', :template_file, knife, config, true)
|
159
|
+
sh cmd_list.join(' ')
|
160
|
+
return tag_id
|
161
|
+
end
|
162
|
+
|
163
|
+
def add_args(cmd_list, tmpl, key, orig, update, force=false)
|
164
|
+
cmd_list << (tmpl + update[key]) if force or orig[key] != update[key]
|
165
|
+
end
|
166
|
+
|
167
|
+
def fetch_server_info(options)
|
168
|
+
require 'set'
|
169
|
+
servers = server_info_list
|
170
|
+
|
171
|
+
if options[RUN_TAG_KEY]
|
172
|
+
tag_key, tag_value = options[RUN_TAG_KEY].to_s.split(/=/, 2)
|
173
|
+
servers.select {|x| x.tags[tag_key] == tag_value.to_s}
|
174
|
+
elsif options[RUN_GROUPS_KEY]
|
175
|
+
g = Set.new(options[RUN_GROUPS_KEY].split(/,/))
|
176
|
+
servers.select {|x| (Set.new(x.groups) & g).size > 0}
|
177
|
+
elsif options[RUN_NAME_KEY]
|
178
|
+
servers.select {|x| x.tags['Name'] == options[RUN_NAME_KEY]}
|
179
|
+
elsif options[RUN_IP_KEY]
|
180
|
+
servers.select {|x| x.public_ip_address == options[RUN_IP_KEY]}
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def console_log(text, color=nil)
|
185
|
+
#Background colors
|
186
|
+
#40 Black
|
187
|
+
#41 Red
|
188
|
+
#42 Green
|
189
|
+
#43 Yellow
|
190
|
+
#44 Blue
|
191
|
+
#45 Magenta
|
192
|
+
#46 Cyan
|
193
|
+
#47 White
|
194
|
+
c = 47 - ((color.to_i + 3) % 7)
|
195
|
+
print "\e[#{c}m#{text}\e[0m"
|
196
|
+
end
|
197
|
+
|
198
|
+
def exec_remote(server, knife, command, options)
|
199
|
+
require 'net/ssh'
|
200
|
+
Net::SSH.start(server.public_ip_address, knife[:ssh_user], :keys => [knife[:identity_file]]) do |ssh|
|
201
|
+
ssh.open_channel do |ch|
|
202
|
+
ch.request_pty do |pty, success|
|
203
|
+
raise 'Could not obtain pty' unless success
|
204
|
+
end
|
205
|
+
ch.exec(command) do |c, success|
|
206
|
+
abort 'could not execute command' unless success
|
207
|
+
ch.on_data do |c, data|
|
208
|
+
console_log(data, options[:idx])
|
209
|
+
end
|
210
|
+
|
211
|
+
ch.on_extended_data do |c, type, data|
|
212
|
+
console_log(data, options[:idx])
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def run_ec2_provision(knife, server, options)
|
220
|
+
require 'net/scp'
|
221
|
+
mkdir_cmd = <<-EOS
|
222
|
+
[ -e #{knife[:remote_chef_dir]} ] && sudo rm -rf #{knife[:remote_chef_dir]}
|
223
|
+
sudo mkdir -p #{knife[:remote_chef_dir]}
|
224
|
+
sudo chmod 777 #{knife[:remote_chef_dir]}
|
225
|
+
EOS
|
226
|
+
exec_remote(server, knife, mkdir_cmd, options)
|
227
|
+
|
228
|
+
console_log "Uploading Chef Cookbooks to #{server.public_ip_address}\n", options[:idx]
|
229
|
+
Net::SCP.start(server.public_ip_address, knife[:ssh_user], :keys => [knife[:identity_file]], :compression => true) do |scp|
|
230
|
+
scp.upload!(CHEF_SOLO_DIR, knife[:remote_chef_dir], :recursive => true, :verbose => true)
|
231
|
+
end
|
232
|
+
console_log "Upload is done #{server.public_ip_address}\n", options[:idx]
|
233
|
+
|
234
|
+
remote_dir = "#{knife[:remote_chef_dir]}/#{File.basename(CHEF_SOLO_DIR)}"
|
235
|
+
chef_solo = 'do_cook.sh'
|
236
|
+
script = <<-EOS
|
237
|
+
tr -d '\\r' < #{remote_dir}/#{chef_solo} > #{remote_dir}/.a; mv #{remote_dir}/.a #{remote_dir}/#{chef_solo}
|
238
|
+
sudo CHEF_ENV=#{ENV['CHEF_ENV']} CHEF_ROLE=#{ENV['CHEF_ROLE']} sh #{remote_dir}/#{chef_solo} #{ENV['chef_option']}
|
239
|
+
EOS
|
240
|
+
exec_remote(server, knife, script, options)
|
241
|
+
end
|
242
|
+
|
243
|
+
def find_ec2_servers(options)
|
244
|
+
server = nil
|
245
|
+
3.times do
|
246
|
+
server = fetch_server_info(options)
|
247
|
+
break if server && !server.empty?
|
248
|
+
sleep 5
|
249
|
+
end
|
250
|
+
server
|
251
|
+
end
|
252
|
+
|
253
|
+
def ec2_provision(options)
|
254
|
+
configure_chef
|
255
|
+
servers = find_ec2_servers(options)
|
256
|
+
unless servers && !servers.empty?
|
257
|
+
puts "no server found(#{options})"
|
258
|
+
return
|
259
|
+
end
|
260
|
+
|
261
|
+
threads = []
|
262
|
+
servers.each_with_index do |server, idx|
|
263
|
+
threads << Thread.new {
|
264
|
+
# p server.public_ip_address
|
265
|
+
run_ec2_provision(Chef::Config.knife, server, :idx => idx)
|
266
|
+
}
|
267
|
+
end
|
268
|
+
threads.each do |t|
|
269
|
+
t.join
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
data/refs/Vagrantfile
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
CHEF_ENV = (ENV['CHEF_ENV'] || (File.exists?(chef_env_file) && File.read(chef_env_file)) || 'dev').strip
|
7
|
+
|
8
|
+
Vagrant::Config.run do |config|
|
9
|
+
config.vm.define :sample do |c| # CHANGE_THIS! :sample は vagrant up sample のときの名前になります。
|
10
|
+
# box_urlと紐付けられる名前を付けましょう
|
11
|
+
c.vm.box = "cent64-chef11" # CHANGE_THIS!
|
12
|
+
|
13
|
+
# ImageのURLを指定しましょう。一旦関連付けられるとLocalにCacheされます。
|
14
|
+
c.vm.box_url = 'http://developer.nrel.gov/downloads/vagrant-boxes/CentOS-6.4-x86_64-v20130309.box' # CHANGE_THIS!
|
15
|
+
|
16
|
+
# VirtualBoxのホストOSからゲストOSへアクセスするときのIPアドレス。重複するようなら変更してください。 # CHANGE_THIS!
|
17
|
+
c.vm.network :hostonly, '192.168.33.10'
|
18
|
+
|
19
|
+
# NAT の設定をするならば設定してください
|
20
|
+
# c.vm.forward_port 80, 8080
|
21
|
+
|
22
|
+
# 共有フォルダ設定
|
23
|
+
# Share-Name Guest-PATH Host-Path
|
24
|
+
config.vm.share_folder 'sprocket', '/var/lib/sprocket', '..'
|
25
|
+
end
|
26
|
+
|
27
|
+
config.vm.provision :chef_solo do |chef|
|
28
|
+
chef.cookbooks_path = './chef-solo/cookbooks'
|
29
|
+
chef.roles_path = './chef-solo/roles'
|
30
|
+
chef.data_bags_path = "./chef-solo/data_bags/#{CHEF_ENV}"
|
31
|
+
# node.json を読み込んで設定
|
32
|
+
settings_json = "./chef-solo/environments/#{CHEF_ENV}/settings.json"
|
33
|
+
if File.exists?(settings_json)
|
34
|
+
json_data = JSON.parse(File.read(settings_json))
|
35
|
+
if json_data['run_list']
|
36
|
+
json_data['run_list'].each do |cmd|
|
37
|
+
if cmd =~ /^role\[(.+)\]/
|
38
|
+
chef.add_role $1
|
39
|
+
elsif cmd =~ /^recipe\[(.+)\]/
|
40
|
+
chef.add_recipe $1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
if ENV['CHEF_ROLE']
|
46
|
+
chef.add_role ENV['CHEF_ROLE']
|
47
|
+
json_data['run_list'] << "role[#{ENV['CHEF_ROLE']}]"
|
48
|
+
end
|
49
|
+
|
50
|
+
chef.json = json_data
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
# run_chef_solo.sh
|
3
|
+
|
4
|
+
set -e -a
|
5
|
+
|
6
|
+
THIS_DIR=$(cd $(dirname $0); pwd)
|
7
|
+
|
8
|
+
if [ -z "$CHEF_ENV" -a -e ${THIS_DIR}/.chef_env ]; then
|
9
|
+
CHEF_ENV=$(cat ${THIS_DIR}/.chef_env)
|
10
|
+
else
|
11
|
+
CHEF_ENV=${CHEF_ENV:-dev}
|
12
|
+
fi
|
13
|
+
|
14
|
+
cd $THIS_DIR
|
15
|
+
|
16
|
+
CHEF_SOLO_DIR=$THIS_DIR
|
17
|
+
SOLO=${CHEF_SOLO_DIR}/.chef/knife.rb
|
18
|
+
RBENV_FILE=${RBENV_FILE:-/usr/local/share/rbenv.sh}
|
19
|
+
RUNLIST_FILE=${CHEF_SOLO_DIR}/run_list/${CHEF_ENV}/`hostname`
|
20
|
+
SERVER_JSON=${CHEF_SOLO_DIR}/environments/${CHEF_ENV}/settings.json
|
21
|
+
|
22
|
+
if [ ! -e $SERVER_JSON -a -e ${CHEF_SOLO_DIR}/node.json ]; then
|
23
|
+
SERVER_JSON=${CHEF_SOLO_DIR}/node.json
|
24
|
+
fi
|
25
|
+
|
26
|
+
OPTIONS=""
|
27
|
+
if [ "$#" -gt 0 ]; then
|
28
|
+
OPTIONS="$@"
|
29
|
+
elif [ -e $RUNLIST_FILE ]; then
|
30
|
+
OPTIONS="-o $(cat $RUNLIST_FILE)"
|
31
|
+
elif [ -n "$CHEF_ROLE" ]; then
|
32
|
+
OPTIONS="-o role[${CHEF_ROLE}]"
|
33
|
+
fi
|
34
|
+
|
35
|
+
# enable rbenv and chef
|
36
|
+
if [ -e $RBENV_FILE ]; then
|
37
|
+
. $RBENV_FILE
|
38
|
+
fi
|
39
|
+
|
40
|
+
echo chef-solo -c $SOLO -j $SERVER_JSON $OPTIONS
|
41
|
+
chef-solo -c $SOLO -j $SERVER_JSON $OPTIONS
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'chef'
|
5
|
+
require 'chef/knife'
|
6
|
+
require 'chef/encrypted_data_bag_item'
|
7
|
+
require 'json'
|
8
|
+
require 'fileutils'
|
9
|
+
require 'optparse'
|
10
|
+
|
11
|
+
|
12
|
+
options = {}
|
13
|
+
opt = OptionParser.new
|
14
|
+
# opt.on("-k SecretKey") {|v| options[:key] = v}
|
15
|
+
opt.on('-j JSON') {|v| options[:data] = v}
|
16
|
+
opt.on('-b BagName') {|v| options[:bag] = v}
|
17
|
+
opt.on('-i ItemName') {|v| options[:item] = v}
|
18
|
+
opt.on('--show') {|_| options[:show] = true}
|
19
|
+
opt.permute!(ARGV)
|
20
|
+
|
21
|
+
unless (options[:data] or options[:show]) and options[:bag] and options[:item]
|
22
|
+
puts opt.help
|
23
|
+
exit
|
24
|
+
end
|
25
|
+
|
26
|
+
class Fixnum
|
27
|
+
def to_json(options = nil)
|
28
|
+
to_s
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
knife = Chef::Knife.new
|
33
|
+
knife.configure_chef
|
34
|
+
|
35
|
+
# http://lists.opscode.com/sympa/arc/chef/2012-11/msg00402.html
|
36
|
+
|
37
|
+
Chef::Config[:solo] = true
|
38
|
+
data_bag_path = Chef::Config[:data_bag_path]
|
39
|
+
secret = Chef::EncryptedDataBagItem.load_secret(Chef::Config[:encrypted_data_bag_secret])
|
40
|
+
|
41
|
+
if options[:show]
|
42
|
+
spr_creds = Chef::EncryptedDataBagItem.load(options[:bag], options[:item], secret)
|
43
|
+
puts JSON.pretty_generate(spr_creds.to_hash)
|
44
|
+
else
|
45
|
+
data = nil
|
46
|
+
File.open(options[:data], "r") do |f|
|
47
|
+
data = JSON.parse(f.read)
|
48
|
+
end
|
49
|
+
|
50
|
+
encrypted_data = Chef::EncryptedDataBagItem.encrypt_data_bag_item(data, secret)
|
51
|
+
|
52
|
+
bag_dir = "#{data_bag_path}/#{options[:bag]}"
|
53
|
+
FileUtils.mkpath(bag_dir)
|
54
|
+
File.open("#{bag_dir}/#{options[:item]}.json", 'w') do |f|
|
55
|
+
f.print encrypted_data.to_json
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'chef'
|
4
|
+
require 'chef/knife'
|
5
|
+
require 'chef/encrypted_data_bag_item'
|
6
|
+
require 'json'
|
7
|
+
require 'optparse'
|
8
|
+
require_relative '../cookbooks/cryptfile/libraries/crypt_util'
|
9
|
+
|
10
|
+
|
11
|
+
options = {}
|
12
|
+
opt = OptionParser.new
|
13
|
+
opt.on('-i input_file') {|v| options[:input_file] = v}
|
14
|
+
opt.on('-d') {|_| options[:mode] = :decrypt}
|
15
|
+
opt.on('-e') {|_| options[:mode] = :encrypt}
|
16
|
+
opt.on('-k secret_file') {|v| options[:secret_file] = v}
|
17
|
+
opt.permute!(ARGV)
|
18
|
+
|
19
|
+
unless options[:input_file] and options[:mode]
|
20
|
+
puts opt.help
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
|
24
|
+
class Fixnum
|
25
|
+
def to_json(options = nil)
|
26
|
+
to_s
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
knife = Chef::Knife.new
|
31
|
+
knife.configure_chef
|
32
|
+
Chef::Config[:solo] = true
|
33
|
+
|
34
|
+
# http://lists.opscode.com/sympa/arc/chef/2012-11/msg00402.html
|
35
|
+
|
36
|
+
secret_file = options[:secret_file] || Chef::Config[:encrypted_data_bag_secret]
|
37
|
+
secret = File.read(secret_file)
|
38
|
+
data = File.read(options[:input_file])
|
39
|
+
|
40
|
+
case options[:mode]
|
41
|
+
when :encrypt
|
42
|
+
print JSON.dump(encrypt(data, secret))
|
43
|
+
when :decrypt
|
44
|
+
print decrypt(JSON.parse(data), secret)
|
45
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
require 'spec_helper'
|
6
|
+
|
7
|
+
require 'chef/knife/hitori_config'
|
8
|
+
|
9
|
+
|
10
|
+
describe 'hitori_config' do
|
11
|
+
before do
|
12
|
+
Chef::Knife::HitoriConfig.load_deps
|
13
|
+
@obj = Chef::Knife::HitoriConfig.new
|
14
|
+
setup_interactive_response
|
15
|
+
end
|
16
|
+
|
17
|
+
def setup_interactive_response
|
18
|
+
@obj.stub(:input_arg) { |message, args|
|
19
|
+
case message
|
20
|
+
when /availability_zone/ then
|
21
|
+
'MY_AZ'
|
22
|
+
when /aws_access_key_id/ then
|
23
|
+
'MY_access_key'
|
24
|
+
when /aws_secret_access_key/ then
|
25
|
+
'MY_secret'
|
26
|
+
when /ami image/ then
|
27
|
+
'MY_ami'
|
28
|
+
when /flavor/ then
|
29
|
+
'MY_flavor'
|
30
|
+
when /Security Group/ then
|
31
|
+
'MY_group'
|
32
|
+
when /ssh_user/ then
|
33
|
+
'MY_user'
|
34
|
+
when /identity_file/ then
|
35
|
+
'MY_identity.pem'
|
36
|
+
when /ssh_key_name/ then
|
37
|
+
'MY_ssh_key_name'
|
38
|
+
when /region/ then
|
39
|
+
'MY_region'
|
40
|
+
when /overwrite knife/ then
|
41
|
+
(@obj.config[:yes] || 'Y')
|
42
|
+
end
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
describe :run do
|
47
|
+
def knife_ruby_path
|
48
|
+
"#{@temp_dir}/.chef/knife.rb"
|
49
|
+
end
|
50
|
+
|
51
|
+
def knife_ec2_ruby_path
|
52
|
+
"#{@temp_dir}/.chef/ec2.rb"
|
53
|
+
end
|
54
|
+
|
55
|
+
before do
|
56
|
+
@temp_dir = Dir.mktmpdir
|
57
|
+
@obj.config[:base_dir] = @temp_dir
|
58
|
+
end
|
59
|
+
|
60
|
+
after do
|
61
|
+
FileUtils.remove_entry_secure(@temp_dir)
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'brand new' do
|
65
|
+
it 'should not call input_arg for overwrite knife.rb' do
|
66
|
+
@obj.should_not_receive(:input_arg).with(/overwrite knife.rb/, 'N')
|
67
|
+
@obj.run
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should create knife.rb' do
|
71
|
+
@obj.run
|
72
|
+
::File.exists?(knife_ruby_path).should be_true
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should create ec2.rb' do
|
76
|
+
@obj.run
|
77
|
+
::File.exists?(knife_ec2_ruby_path).should be_true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'knife.rb exists already' do
|
82
|
+
before do
|
83
|
+
@content = 'knife[:fruit] = "apple"'
|
84
|
+
FileUtils.makedirs(::File.dirname(knife_ruby_path))
|
85
|
+
::File.write(knife_ruby_path, @content)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should call input_arg for overwrite knife.rb' do
|
89
|
+
@obj.should_receive(:input_arg).with(/overwrite knife.rb/, 'N')
|
90
|
+
@obj.run
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should overwrite if user input y' do
|
94
|
+
@obj.config[:yes] = 'y'
|
95
|
+
@obj.run
|
96
|
+
::File.read(knife_ruby_path).should_not == @content
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should not overwrite if user input n' do
|
100
|
+
@obj.config[:yes] = 'n'
|
101
|
+
@obj.run
|
102
|
+
::File.read(knife_ruby_path).should == @content
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|