itamae 1.1.26 → 1.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fb27312cdd1e4cbfccca56ee5eb7a85e48188d2a
4
- data.tar.gz: 164226caebc7e74dad4d9584f694b03b07bfd61f
3
+ metadata.gz: 3c531f6aca9ae4e769d8f073077e47c722be40c5
4
+ data.tar.gz: 35844bba50ca0705a464208a49e521ff0525da0b
5
5
  SHA512:
6
- metadata.gz: b6b7ac732a3b58aea5425e075ce7b787be1167cf38dc85a19300ec256bf6af4d9e0dd1e66ed33cc5fb5ba5ece0a76cbcb583a07895269119ad53dea55667a254
7
- data.tar.gz: b510acec0c54fee7d6bfcca40c5fec9129f41b3ffe307dfaa2046f4dcf60f0b9b8e02bdb868a8d54bfab3d81bbf9aebbd6847b762ef5672f54a7d4af5d17d432
6
+ metadata.gz: 84bf522e5530b3b3f11901987098106e33f15674017d1d32eacbf6e2806b62036e7a4394c7c544e46cdfdcadac3082b2179e25f3c344890d2bbe7e805bde0fda
7
+ data.tar.gz: 7588acd8fb22db71c6a261bc47e09233535a24a0de9db260522980b85962b67085ba5394e6b496438c1b53e4c35e86b1952ba95c6ab9edc7e83a7656e78c930a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,31 @@
1
+ ## v1.2.0
2
+
3
+ Feature
4
+
5
+ - Docker backend
6
+ - This backend builds a Docker image.
7
+ - Usage: `itamae docker --image baseimage recipe.rb`
8
+ - NOTE: This feature is experimental.
9
+
10
+ ## v1.1.26
11
+
12
+ Bugfix
13
+
14
+ - Always outdent.
15
+
16
+ ## v1.1.25
17
+
18
+ Improvements
19
+
20
+ - Make logging less verbose by default. (by @eagletmt)
21
+ - Change indent width from 3 to 2.
22
+
23
+ ## v1.1.24
24
+
25
+ Bugfixes
26
+
27
+ - Make `node` accessible from define block.
28
+
1
29
  ## v1.1.23
2
30
 
3
31
  Feature
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.18.2"
21
+ spec.add_runtime_dependency "specinfra", ">= 2.21.1"
22
22
  spec.add_runtime_dependency "hashie"
23
23
  spec.add_runtime_dependency "ansi"
24
24
  spec.add_runtime_dependency "schash", "~> 0.1.0"
@@ -28,4 +28,5 @@ Gem::Specification.new do |spec|
28
28
  spec.add_development_dependency "rspec", "~> 3.0"
29
29
  spec.add_development_dependency "serverspec", "~> 2.1"
30
30
  spec.add_development_dependency "pry-byebug"
31
+ spec.add_development_dependency "docker-api", "~> 1.20"
31
32
  end
@@ -20,102 +20,147 @@ module Specinfra
20
20
  end
21
21
 
22
22
  module Itamae
23
- class Backend
23
+ module Backend
24
24
  UnknownBackendTypeError = Class.new(StandardError)
25
25
  CommandExecutionError = Class.new(StandardError)
26
26
 
27
- include Singleton
28
-
29
- def set_type(type, options = {})
30
- case type
31
- when :local
32
- Specinfra.configuration.backend = :exec
33
- when :ssh
34
- Specinfra.configuration.request_pty = true
35
- Specinfra.configuration.host = options.delete(:host)
36
- Specinfra.configuration.disable_sudo = options.delete(:disable_sudo)
37
- Specinfra.configuration.ssh_options = options
38
-
39
- Specinfra.configuration.backend = :ssh
40
- else
41
- raise UnknownBackendTypeError, "'#{type}' backend is unknown."
27
+ class << self
28
+ def set_type(type, opts = {})
29
+ @instance = self.const_get(type.capitalize).new(opts)
42
30
  end
43
- end
44
31
 
45
- def run_command(commands, options = {})
46
- options = {error: true}.merge(options)
47
-
48
- if commands.is_a?(Array)
49
- command = commands.map do |cmd|
50
- Shellwords.escape(cmd)
51
- end.join(' ')
52
- else
53
- command = commands
54
- end
32
+ def instance
33
+ unless @instance
34
+ raise "Before calling Backend.instance, call Backend.set_type."
35
+ end
55
36
 
56
- cwd = options[:cwd]
57
- if cwd
58
- command = "cd #{Shellwords.escape(cwd)} && #{command}"
37
+ @instance
59
38
  end
39
+ end
60
40
 
61
- user = options[:user]
62
- if user
63
- command = "sudo -u #{Shellwords.escape(user)} -- /bin/sh -c #{Shellwords.escape(command)}"
64
- end
41
+ class Base
42
+ def run_command(commands, options = {})
43
+ options = {error: true}.merge(options)
65
44
 
66
- Logger.debug "Executing `#{command}`..."
45
+ if commands.is_a?(Array)
46
+ command = commands.map do |cmd|
47
+ Shellwords.escape(cmd)
48
+ end.join(' ')
49
+ else
50
+ command = commands
51
+ end
67
52
 
68
- result = Specinfra::Runner.run_command(command)
69
- exit_status = result.exit_status
53
+ cwd = options[:cwd]
54
+ if cwd
55
+ command = "cd #{Shellwords.escape(cwd)} && #{command}"
56
+ end
70
57
 
71
- Logger.formatter.with_indent do
72
- if exit_status == 0 || !options[:error]
73
- method = :debug
74
- message = "exited with #{exit_status}"
75
- else
76
- method = :error
77
- message = "Command `#{command}` failed. (exit status: #{exit_status})"
58
+ user = options[:user]
59
+ if user
60
+ command = "sudo -u #{Shellwords.escape(user)} -- /bin/sh -c #{Shellwords.escape(command)}"
78
61
  end
79
62
 
80
- Logger.public_send(method, message)
63
+ Logger.debug "Executing `#{command}`..."
81
64
 
82
- {"stdout" => result.stdout, "stderr" => result.stderr}.each_pair do |name, value|
83
- next unless value && value != ''
65
+ result = Specinfra::Runner.run_command(command)
66
+ exit_status = result.exit_status
84
67
 
85
- if value.bytesize > 1024 * 1024
86
- Logger.public_send(method, "#{name} is suppressed because it's too large")
87
- next
68
+ Logger.formatter.with_indent do
69
+ if exit_status == 0 || !options[:error]
70
+ method = :debug
71
+ message = "exited with #{exit_status}"
72
+ else
73
+ method = :error
74
+ message = "Command `#{command}` failed. (exit status: #{exit_status})"
88
75
  end
89
76
 
90
- value.each_line do |line|
91
- # remove control chars
92
- case line.encoding
93
- when Encoding::UTF_8
94
- line = line.tr("\u0000-\u001f\u007f\u2028",'')
77
+ Logger.public_send(method, message)
78
+
79
+ {"stdout" => result.stdout, "stderr" => result.stderr}.each_pair do |name, value|
80
+ next unless value && value != ''
81
+
82
+ if value.bytesize > 1024 * 1024
83
+ Logger.public_send(method, "#{name} is suppressed because it's too large")
84
+ next
95
85
  end
96
86
 
97
- Logger.public_send(method, "#{name} | #{line}")
87
+ value.each_line do |line|
88
+ # remove control chars
89
+ case line.encoding
90
+ when Encoding::UTF_8
91
+ line = line.tr("\u0000-\u001f\u007f\u2028",'')
92
+ end
93
+
94
+ Logger.public_send(method, "#{name} | #{line}")
95
+ end
98
96
  end
99
97
  end
98
+
99
+ if options[:error] && exit_status != 0
100
+ raise CommandExecutionError
101
+ end
102
+
103
+ result
104
+ end
105
+
106
+ def get_command(*args)
107
+ Specinfra.command.get(*args)
100
108
  end
101
109
 
102
- if options[:error] && exit_status != 0
103
- raise CommandExecutionError
110
+ def send_file(*args)
111
+ Specinfra::Runner.send_file(*args)
104
112
  end
105
113
 
106
- result
114
+ def send_directory(*args)
115
+ Specinfra::Runner.send_directory(*args)
116
+ end
117
+
118
+ def finalize
119
+ # pass
120
+ end
107
121
  end
108
122
 
109
- def get_command(*args)
110
- Specinfra.command.get(*args)
123
+ # TODO: Make Specinfra's backends instanciatable
124
+ class Local < Base
125
+ def initialize(options)
126
+ Specinfra.configuration.backend = :exec
127
+ end
111
128
  end
112
129
 
113
- def send_file(*args)
114
- Specinfra::Runner.send_file(*args)
130
+ class Ssh < Base
131
+ def initialize(options)
132
+ Specinfra.configuration.request_pty = true
133
+ Specinfra.configuration.host = options.delete(:host)
134
+ Specinfra.configuration.disable_sudo = options.delete(:disable_sudo)
135
+ Specinfra.configuration.ssh_options = options
136
+
137
+ Specinfra.configuration.backend = :ssh
138
+ end
115
139
  end
116
140
 
117
- def send_directory(*args)
118
- Specinfra::Runner.send_directory(*args)
141
+ class Docker < Base
142
+ def initialize(options)
143
+ begin
144
+ require 'docker'
145
+ rescue LoadError
146
+ Logger.fatal "To use docker backend, please install 'docker-api' gem"
147
+ end
148
+
149
+ Specinfra.configuration.docker_image = options[:image]
150
+ Specinfra.configuration.docker_container = options[:container]
151
+
152
+ # TODO: Move to Specinfra?
153
+ Excon.defaults[:ssl_verify_peer] = options[:tls_verify_peer]
154
+
155
+ Specinfra.configuration.backend = :docker
156
+
157
+ ::Docker.logger = Logger
158
+ end
159
+
160
+ def finalize
161
+ image = Specinfra.backend.commit_container
162
+ Logger.info "Image created: #{image.id}"
163
+ end
119
164
  end
120
165
  end
121
166
  end
data/lib/itamae/cli.rb CHANGED
@@ -53,6 +53,17 @@ module Itamae
53
53
  Runner.run(recipe_files, :ssh, options)
54
54
  end
55
55
 
56
+ desc "docker RECIPE [RECIPE...]", "Create Docker image"
57
+ option :image, type: :string, required: true
58
+ option :tls_verify_peer, type: :boolean, default: true
59
+ def docker(*recipe_files)
60
+ if recipe_files.empty?
61
+ raise "Please specify recipe files."
62
+ end
63
+
64
+ Runner.run(recipe_files, :docker, options)
65
+ end
66
+
56
67
  desc "version", "Print version"
57
68
  def version
58
69
  puts "Itamae v#{Itamae::VERSION}"
@@ -8,4 +8,3 @@ Specinfra::Command::Base::User.class_eval do
8
8
  end
9
9
  end
10
10
  end
11
-
data/lib/itamae/runner.rb CHANGED
@@ -58,8 +58,6 @@ module Itamae
58
58
  opts = {}
59
59
 
60
60
  case type
61
- when :local
62
- # do nothing
63
61
  when :ssh
64
62
  opts[:host] = options[:host]
65
63
  opts[:user] = options[:user] || Etc.getlogin
@@ -81,9 +79,11 @@ module Itamae
81
79
  print "\n"
82
80
  opts.merge!(password: password)
83
81
  end
82
+ when :docker
83
+ opts = options
84
84
  end
85
85
 
86
- Backend.instance.set_type(type, opts)
86
+ Backend.set_type(type, opts)
87
87
  end
88
88
  end
89
89
 
@@ -110,6 +110,7 @@ module Itamae
110
110
 
111
111
  def run(options)
112
112
  children.run(options)
113
+ Backend.instance.finalize
113
114
  end
114
115
  end
115
116
  end
@@ -1 +1 @@
1
- 1.1.26
1
+ 1.2.0
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.1.26
4
+ version: 1.2.0
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-21 00:00:00.000000000 Z
11
+ date: 2015-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 2.18.2
33
+ version: 2.21.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 2.18.2
40
+ version: 2.21.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: hashie
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +150,20 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: docker-api
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '1.20'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '1.20'
153
167
  description:
154
168
  email:
155
169
  - ryota.arai@gmail.com
@@ -240,7 +254,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
240
254
  version: '0'
241
255
  requirements: []
242
256
  rubyforge_project:
243
- rubygems_version: 2.4.5
257
+ rubygems_version: 2.2.2
244
258
  signing_key:
245
259
  specification_version: 4
246
260
  summary: Simple Configuration Management Tool