itamae 1.2.0 → 1.2.2
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 +2 -0
- data/Rakefile +0 -2
- data/itamae.gemspec +1 -1
- data/lib/itamae/backend.rb +67 -31
- data/lib/itamae/ext/specinfra.rb +0 -8
- data/lib/itamae/node.rb +6 -1
- data/lib/itamae/resource/base.rb +1 -1
- data/lib/itamae/runner.rb +44 -73
- data/lib/itamae/version.txt +1 -1
- data/spec/unit/lib/itamae/node_spec.rb +3 -2
- metadata +11 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bee2953f7e53e6c977a24568b6f1ef50b2209f40
|
4
|
+
data.tar.gz: 2b8e4200cbcbf4f2106185355e240ba2c9798863
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73481813d9a2e6d6ed1033e787dc8e0392a6b47c1e68de5df4af6b43e76b6bd0a67e9095c826aa51b9cd74e62cbb08767f41210f55ddfa8e088996f58c339963
|
7
|
+
data.tar.gz: a1627a795d970cbfb2eba039bb13a5d33141c5209a1a75d967b549937e1db0bba7b03199e02f5758d0326be534d1758ee7673a4516e3f652c12a34742c2623a8
|
data/README.md
CHANGED
data/Rakefile
CHANGED
data/itamae.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
20
|
spec.add_runtime_dependency "thor"
|
21
|
-
spec.add_runtime_dependency "specinfra", ">= 2.
|
21
|
+
spec.add_runtime_dependency "specinfra", [">= 2.24.1", "< 3.0.0"]
|
22
22
|
spec.add_runtime_dependency "hashie"
|
23
23
|
spec.add_runtime_dependency "ansi"
|
24
24
|
spec.add_runtime_dependency "schash", "~> 0.1.0"
|
data/lib/itamae/backend.rb
CHANGED
@@ -25,20 +25,17 @@ module Itamae
|
|
25
25
|
CommandExecutionError = Class.new(StandardError)
|
26
26
|
|
27
27
|
class << self
|
28
|
-
def
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
def instance
|
33
|
-
unless @instance
|
34
|
-
raise "Before calling Backend.instance, call Backend.set_type."
|
35
|
-
end
|
36
|
-
|
37
|
-
@instance
|
28
|
+
def create(type, opts = {})
|
29
|
+
self.const_get(type.capitalize).new(opts)
|
38
30
|
end
|
39
31
|
end
|
40
32
|
|
41
33
|
class Base
|
34
|
+
def initialize(options)
|
35
|
+
@options = options
|
36
|
+
@backend = create_specinfra_backend
|
37
|
+
end
|
38
|
+
|
42
39
|
def run_command(commands, options = {})
|
43
40
|
options = {error: true}.merge(options)
|
44
41
|
|
@@ -62,7 +59,7 @@ module Itamae
|
|
62
59
|
|
63
60
|
Logger.debug "Executing `#{command}`..."
|
64
61
|
|
65
|
-
result =
|
62
|
+
result = @backend.run_command(command)
|
66
63
|
exit_status = result.exit_status
|
67
64
|
|
68
65
|
Logger.formatter.with_indent do
|
@@ -104,61 +101,100 @@ module Itamae
|
|
104
101
|
end
|
105
102
|
|
106
103
|
def get_command(*args)
|
107
|
-
|
104
|
+
@backend.command.get(*args)
|
108
105
|
end
|
109
106
|
|
110
107
|
def send_file(*args)
|
111
|
-
|
108
|
+
@backend.send_file(*args)
|
112
109
|
end
|
113
110
|
|
114
111
|
def send_directory(*args)
|
115
|
-
|
112
|
+
@backend.send_directory(*args)
|
113
|
+
end
|
114
|
+
|
115
|
+
def host_inventory
|
116
|
+
@backend.host_inventory
|
116
117
|
end
|
117
118
|
|
118
119
|
def finalize
|
119
120
|
# pass
|
120
121
|
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
def create_specinfra_backend
|
126
|
+
raise NotImplementedError
|
127
|
+
end
|
121
128
|
end
|
122
129
|
|
123
130
|
# TODO: Make Specinfra's backends instanciatable
|
124
131
|
class Local < Base
|
125
|
-
|
126
|
-
|
132
|
+
private
|
133
|
+
def create_specinfra_backend
|
134
|
+
Specinfra::Backend::Exec.new()
|
127
135
|
end
|
128
136
|
end
|
129
137
|
|
130
138
|
class Ssh < Base
|
131
|
-
|
132
|
-
|
133
|
-
Specinfra.
|
134
|
-
|
135
|
-
|
139
|
+
private
|
140
|
+
def create_specinfra_backend
|
141
|
+
Specinfra::Backend::Ssh.new(
|
142
|
+
request_pty: true,
|
143
|
+
host: ssh_options[:host_name],
|
144
|
+
disable_sudo: ssh_options[:disable_sudo],
|
145
|
+
ssh_options: ssh_options,
|
146
|
+
)
|
147
|
+
end
|
148
|
+
|
149
|
+
def ssh_options
|
150
|
+
opts = {}
|
151
|
+
|
152
|
+
opts[:host_name] = @options[:host]
|
153
|
+
opts[:user] = @options[:user] || Etc.getlogin
|
154
|
+
opts[:keys] = [@options[:key]] if @options[:key]
|
155
|
+
opts[:port] = @options[:port] if @options[:port]
|
156
|
+
opts[:disable_sudo] = true unless @options[:sudo]
|
157
|
+
|
158
|
+
if @options[:vagrant]
|
159
|
+
config = Tempfile.new('', Dir.tmpdir)
|
160
|
+
hostname = opts[:host] || 'default'
|
161
|
+
`vagrant ssh-config #{hostname} > #{config.path}`
|
162
|
+
opts.merge!(Net::SSH::Config.for(hostname, [config.path]))
|
163
|
+
opts[:host] = opts.delete(:host_name)
|
164
|
+
end
|
165
|
+
|
166
|
+
if @options[:ask_password]
|
167
|
+
print "password: "
|
168
|
+
password = STDIN.noecho(&:gets).strip
|
169
|
+
print "\n"
|
170
|
+
opts.merge!(password: password)
|
171
|
+
end
|
136
172
|
|
137
|
-
|
173
|
+
opts
|
138
174
|
end
|
139
175
|
end
|
140
176
|
|
141
177
|
class Docker < Base
|
142
|
-
|
178
|
+
private
|
179
|
+
def create_specinfra_backend
|
143
180
|
begin
|
144
181
|
require 'docker'
|
145
182
|
rescue LoadError
|
146
183
|
Logger.fatal "To use docker backend, please install 'docker-api' gem"
|
147
184
|
end
|
148
185
|
|
149
|
-
Specinfra.configuration.docker_image = options[:image]
|
150
|
-
Specinfra.configuration.docker_container = options[:container]
|
151
|
-
|
152
186
|
# TODO: Move to Specinfra?
|
153
|
-
Excon.defaults[:ssl_verify_peer] = options[:tls_verify_peer]
|
154
|
-
|
155
|
-
Specinfra.configuration.backend = :docker
|
156
|
-
|
187
|
+
Excon.defaults[:ssl_verify_peer] = @options[:tls_verify_peer]
|
157
188
|
::Docker.logger = Logger
|
189
|
+
|
190
|
+
Specinfra::Backend::Docker.new(
|
191
|
+
docker_image: @options[:image],
|
192
|
+
docker_container: @options[:container],
|
193
|
+
)
|
158
194
|
end
|
159
195
|
|
160
196
|
def finalize
|
161
|
-
image =
|
197
|
+
image = @backend.commit_container
|
162
198
|
Logger.info "Image created: #{image.id}"
|
163
199
|
end
|
164
200
|
end
|
data/lib/itamae/ext/specinfra.rb
CHANGED
@@ -1,10 +1,2 @@
|
|
1
1
|
# TODO: Send patches to Specinfra
|
2
2
|
|
3
|
-
Specinfra::Command::Base::User.class_eval do
|
4
|
-
class << self
|
5
|
-
def update_home_directory(user, directory)
|
6
|
-
# -m: Move the content of the user's home directory to the new location.
|
7
|
-
"usermod -m -d #{escape(directory)} #{escape(user)}"
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
data/lib/itamae/node.rb
CHANGED
@@ -7,6 +7,11 @@ module Itamae
|
|
7
7
|
class Node < Hashie::Mash
|
8
8
|
ValidationError = Class.new(StandardError)
|
9
9
|
|
10
|
+
def initialize(initial_hash, backend = nil)
|
11
|
+
super(initial_hash)
|
12
|
+
@backend = backend
|
13
|
+
end
|
14
|
+
|
10
15
|
def reverse_merge(other_hash)
|
11
16
|
Hashie::Mash.new(other_hash).merge(self)
|
12
17
|
end
|
@@ -19,7 +24,7 @@ module Itamae
|
|
19
24
|
val = super(key)
|
20
25
|
if val.nil?
|
21
26
|
begin
|
22
|
-
val = host_inventory[key]
|
27
|
+
val = @backend.host_inventory[key]
|
23
28
|
rescue NotImplementedError, NameError
|
24
29
|
val = nil
|
25
30
|
end
|
data/lib/itamae/resource/base.rb
CHANGED
data/lib/itamae/runner.rb
CHANGED
@@ -8,9 +8,8 @@ module Itamae
|
|
8
8
|
def run(recipe_files, backend_type, options)
|
9
9
|
Logger.info "Starting Itamae..."
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
runner = self.new(node_from_options(options))
|
11
|
+
backend = Backend.create(backend_type, options)
|
12
|
+
runner = self.new(backend, options)
|
14
13
|
runner.load_recipes(recipe_files)
|
15
14
|
|
16
15
|
if dot_file = options[:dot]
|
@@ -23,81 +22,23 @@ module Itamae
|
|
23
22
|
|
24
23
|
runner.run(dry_run: options[:dry_run])
|
25
24
|
end
|
26
|
-
|
27
|
-
private
|
28
|
-
def node_from_options(options)
|
29
|
-
hash = {}
|
30
|
-
|
31
|
-
if options[:ohai]
|
32
|
-
unless Backend.instance.run_command("which ohai", error: false).exit_status == 0
|
33
|
-
# install Ohai
|
34
|
-
Logger.info "Installing Chef package... (to use Ohai)"
|
35
|
-
Backend.instance.run_command("curl -L https://www.opscode.com/chef/install.sh | bash")
|
36
|
-
end
|
37
|
-
|
38
|
-
Logger.info "Loading node data via ohai..."
|
39
|
-
hash.merge!(JSON.parse(Backend.instance.run_command("ohai").stdout))
|
40
|
-
end
|
41
|
-
|
42
|
-
if options[:node_json]
|
43
|
-
path = File.expand_path(options[:node_json])
|
44
|
-
Logger.info "Loading node data from #{path}..."
|
45
|
-
hash.merge!(JSON.load(open(path)))
|
46
|
-
end
|
47
|
-
|
48
|
-
if options[:node_yaml]
|
49
|
-
path = File.expand_path(options[:node_yaml])
|
50
|
-
Logger.info "Loading node data from #{path}..."
|
51
|
-
hash.merge!(YAML.load(open(path)))
|
52
|
-
end
|
53
|
-
|
54
|
-
Node.new(hash)
|
55
|
-
end
|
56
|
-
|
57
|
-
def set_backend_from_options(type, options)
|
58
|
-
opts = {}
|
59
|
-
|
60
|
-
case type
|
61
|
-
when :ssh
|
62
|
-
opts[:host] = options[:host]
|
63
|
-
opts[:user] = options[:user] || Etc.getlogin
|
64
|
-
opts[:keys] = [options[:key]] if options[:key]
|
65
|
-
opts[:port] = options[:port] if options[:port]
|
66
|
-
opts[:disable_sudo] = true unless options[:sudo]
|
67
|
-
|
68
|
-
if options[:vagrant]
|
69
|
-
config = Tempfile.new('', Dir.tmpdir)
|
70
|
-
hostname = opts[:host] || 'default'
|
71
|
-
`vagrant ssh-config #{hostname} > #{config.path}`
|
72
|
-
opts.merge!(Net::SSH::Config.for(hostname, [config.path]))
|
73
|
-
opts[:host] = opts.delete(:host_name)
|
74
|
-
end
|
75
|
-
|
76
|
-
if options[:ask_password]
|
77
|
-
print "password: "
|
78
|
-
password = STDIN.noecho(&:gets).strip
|
79
|
-
print "\n"
|
80
|
-
opts.merge!(password: password)
|
81
|
-
end
|
82
|
-
when :docker
|
83
|
-
opts = options
|
84
|
-
end
|
85
|
-
|
86
|
-
Backend.set_type(type, opts)
|
87
|
-
end
|
88
25
|
end
|
89
26
|
|
90
|
-
|
91
|
-
|
92
|
-
|
27
|
+
attr_reader :backend
|
28
|
+
attr_reader :node
|
29
|
+
attr_reader :tmpdir
|
30
|
+
attr_reader :children
|
31
|
+
|
32
|
+
def initialize(backend, options)
|
33
|
+
@backend = backend
|
34
|
+
@options = options
|
93
35
|
|
94
|
-
|
95
|
-
@node = node
|
36
|
+
@node = create_node
|
96
37
|
@tmpdir = "/tmp/itamae_tmp"
|
97
38
|
@children = RecipeChildren.new
|
98
39
|
|
99
|
-
|
100
|
-
|
40
|
+
@backend.run_command(["mkdir", "-p", @tmpdir])
|
41
|
+
@backend.run_command(["chmod", "777", @tmpdir])
|
101
42
|
end
|
102
43
|
|
103
44
|
def load_recipes(paths)
|
@@ -110,7 +51,37 @@ module Itamae
|
|
110
51
|
|
111
52
|
def run(options)
|
112
53
|
children.run(options)
|
113
|
-
|
54
|
+
@backend.finalize
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def create_node
|
59
|
+
hash = {}
|
60
|
+
|
61
|
+
if @options[:ohai]
|
62
|
+
unless @backend.run_command("which ohai", error: false).exit_status == 0
|
63
|
+
# install Ohai
|
64
|
+
Logger.info "Installing Chef package... (to use Ohai)"
|
65
|
+
@backend.run_command("curl -L https://www.opscode.com/chef/install.sh | bash")
|
66
|
+
end
|
67
|
+
|
68
|
+
Logger.info "Loading node data via ohai..."
|
69
|
+
hash.merge!(JSON.parse(@backend.run_command("ohai").stdout))
|
70
|
+
end
|
71
|
+
|
72
|
+
if @options[:node_json]
|
73
|
+
path = File.expand_path(@options[:node_json])
|
74
|
+
Logger.info "Loading node data from #{path}..."
|
75
|
+
hash.merge!(JSON.load(open(path)))
|
76
|
+
end
|
77
|
+
|
78
|
+
if @options[:node_yaml]
|
79
|
+
path = File.expand_path(@options[:node_yaml])
|
80
|
+
Logger.info "Loading node data from #{path}..."
|
81
|
+
hash.merge!(YAML.load(open(path)))
|
82
|
+
end
|
83
|
+
|
84
|
+
Node.new(hash, @backend)
|
114
85
|
end
|
115
86
|
end
|
116
87
|
end
|
data/lib/itamae/version.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.2.
|
1
|
+
1.2.2
|
@@ -2,10 +2,11 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Itamae
|
4
4
|
describe Node do
|
5
|
+
let(:backend) { nil }
|
5
6
|
describe "#reverse_merge" do
|
6
7
|
it "merges a hash but the method receiver's value will be preferred" do
|
7
|
-
a = described_class.new(a: :b, c: :d)
|
8
|
-
expected = described_class.new(a: :b, c: :d, e: :f)
|
8
|
+
a = described_class.new({a: :b, c: :d}, backend)
|
9
|
+
expected = described_class.new({a: :b, c: :d, e: :f}, backend)
|
9
10
|
expect(a.reverse_merge(a: :c, e: :f)).to eq(expected)
|
10
11
|
end
|
11
12
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: itamae
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryota Arai
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -30,14 +30,20 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 2.
|
33
|
+
version: 2.24.1
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 3.0.0
|
34
37
|
type: :runtime
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
37
40
|
requirements:
|
38
41
|
- - ">="
|
39
42
|
- !ruby/object:Gem::Version
|
40
|
-
version: 2.
|
43
|
+
version: 2.24.1
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 3.0.0
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
48
|
name: hashie
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -254,7 +260,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
254
260
|
version: '0'
|
255
261
|
requirements: []
|
256
262
|
rubyforge_project:
|
257
|
-
rubygems_version: 2.
|
263
|
+
rubygems_version: 2.4.5
|
258
264
|
signing_key:
|
259
265
|
specification_version: 4
|
260
266
|
summary: Simple Configuration Management Tool
|