itamae-mitsurin 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +7 -0
  5. data/LICENSE.txt +26 -0
  6. data/README.md +44 -0
  7. data/Rakefile +55 -0
  8. data/bin/itamae +5 -0
  9. data/bin/itamae-mitsurin +5 -0
  10. data/itamae-mitsurin.gemspec +35 -0
  11. data/lib/itamae.rb +18 -0
  12. data/lib/itamae/backend.rb +293 -0
  13. data/lib/itamae/cli.rb +86 -0
  14. data/lib/itamae/definition.rb +40 -0
  15. data/lib/itamae/ext.rb +1 -0
  16. data/lib/itamae/ext/specinfra.rb +39 -0
  17. data/lib/itamae/generators.rb +20 -0
  18. data/lib/itamae/generators/cookbook.rb +22 -0
  19. data/lib/itamae/generators/project.rb +22 -0
  20. data/lib/itamae/generators/role.rb +22 -0
  21. data/lib/itamae/generators/templates/cookbook/default.rb +0 -0
  22. data/lib/itamae/generators/templates/cookbook/files/.keep +0 -0
  23. data/lib/itamae/generators/templates/cookbook/templates/.keep +0 -0
  24. data/lib/itamae/generators/templates/project/Gemfile +4 -0
  25. data/lib/itamae/generators/templates/project/cookbooks/.keep +0 -0
  26. data/lib/itamae/generators/templates/project/roles/.keep +0 -0
  27. data/lib/itamae/generators/templates/role/default.rb +0 -0
  28. data/lib/itamae/generators/templates/role/files/.keep +0 -0
  29. data/lib/itamae/generators/templates/role/templates/.keep +0 -0
  30. data/lib/itamae/handler.rb +21 -0
  31. data/lib/itamae/handler/base.rb +40 -0
  32. data/lib/itamae/handler/debug.rb +10 -0
  33. data/lib/itamae/handler/fluentd.rb +44 -0
  34. data/lib/itamae/handler/json.rb +22 -0
  35. data/lib/itamae/handler_proxy.rb +38 -0
  36. data/lib/itamae/logger.rb +124 -0
  37. data/lib/itamae/mitsurin.rb +13 -0
  38. data/lib/itamae/mitsurin/cli.rb +56 -0
  39. data/lib/itamae/mitsurin/creators.rb +19 -0
  40. data/lib/itamae/mitsurin/creators/cookbook.rb +24 -0
  41. data/lib/itamae/mitsurin/creators/project.rb +24 -0
  42. data/lib/itamae/mitsurin/creators/templates/project/.rspec +2 -0
  43. data/lib/itamae/mitsurin/creators/templates/project/Gemfile +3 -0
  44. data/lib/itamae/mitsurin/creators/templates/project/Rakefile +2 -0
  45. data/lib/itamae/mitsurin/creators/templates/project/environments/.keep +0 -0
  46. data/lib/itamae/mitsurin/creators/templates/project/environments/sample.json +7 -0
  47. data/lib/itamae/mitsurin/creators/templates/project/nodes/.keep +0 -0
  48. data/lib/itamae/mitsurin/creators/templates/project/nodes/sample01.json +8 -0
  49. data/lib/itamae/mitsurin/creators/templates/project/roles/.keep +0 -0
  50. data/lib/itamae/mitsurin/creators/templates/project/site-cookbooks/_base/_base/attributes/.keep +0 -0
  51. data/lib/itamae/mitsurin/creators/templates/project/site-cookbooks/_base/_base/files/.keep +0 -0
  52. data/lib/itamae/mitsurin/creators/templates/project/site-cookbooks/_base/_base/recipes/default.rb +0 -0
  53. data/lib/itamae/mitsurin/creators/templates/project/site-cookbooks/_base/_base/spec/default_spec.rb +2 -0
  54. data/lib/itamae/mitsurin/creators/templates/project/site-cookbooks/_base/_base/templates/.keep +0 -0
  55. data/lib/itamae/mitsurin/creators/templates/project/spec/spec_helper.rb +32 -0
  56. data/lib/itamae/mitsurin/creators/templates/project/tmp-nodes/.keep +0 -0
  57. data/lib/itamae/mitsurin/creators/templates/site-cookbooks/attributes/.keep +0 -0
  58. data/lib/itamae/mitsurin/creators/templates/site-cookbooks/files/.keep +0 -0
  59. data/lib/itamae/mitsurin/creators/templates/site-cookbooks/recipes/default.rb +0 -0
  60. data/lib/itamae/mitsurin/creators/templates/site-cookbooks/spec/.keep +0 -0
  61. data/lib/itamae/mitsurin/creators/templates/site-cookbooks/templates/.keep +0 -0
  62. data/lib/itamae/mitsurin/itamae_task.rb +199 -0
  63. data/lib/itamae/mitsurin/serverspec_task.rb +110 -0
  64. data/lib/itamae/mitsurin/version.rb +5 -0
  65. data/lib/itamae/mitsurin/version.txt +1 -0
  66. data/lib/itamae/node.rb +74 -0
  67. data/lib/itamae/notification.rb +46 -0
  68. data/lib/itamae/recipe.rb +171 -0
  69. data/lib/itamae/recipe_children.rb +86 -0
  70. data/lib/itamae/resource.rb +73 -0
  71. data/lib/itamae/resource/aws_ebs_volume.rb +84 -0
  72. data/lib/itamae/resource/base.rb +374 -0
  73. data/lib/itamae/resource/directory.rb +63 -0
  74. data/lib/itamae/resource/execute.rb +26 -0
  75. data/lib/itamae/resource/file.rb +176 -0
  76. data/lib/itamae/resource/gem_package.rb +81 -0
  77. data/lib/itamae/resource/git.rb +94 -0
  78. data/lib/itamae/resource/group.rb +42 -0
  79. data/lib/itamae/resource/http_request.rb +71 -0
  80. data/lib/itamae/resource/link.rb +33 -0
  81. data/lib/itamae/resource/local_ruby_block.rb +15 -0
  82. data/lib/itamae/resource/package.rb +44 -0
  83. data/lib/itamae/resource/remote_directory.rb +84 -0
  84. data/lib/itamae/resource/remote_file.rb +54 -0
  85. data/lib/itamae/resource/service.rb +69 -0
  86. data/lib/itamae/resource/template.rb +53 -0
  87. data/lib/itamae/resource/user.rb +93 -0
  88. data/lib/itamae/runner.rb +124 -0
  89. data/spec/integration/Vagrantfile +35 -0
  90. data/spec/integration/default_spec.rb +226 -0
  91. data/spec/integration/recipes/default.rb +423 -0
  92. data/spec/integration/recipes/default2.rb +6 -0
  93. data/spec/integration/recipes/define/default.rb +6 -0
  94. data/spec/integration/recipes/define/files/remote_file_in_definition +1 -0
  95. data/spec/integration/recipes/dry_run.rb +6 -0
  96. data/spec/integration/recipes/files/remote_file_auto +1 -0
  97. data/spec/integration/recipes/hello.erb +6 -0
  98. data/spec/integration/recipes/hello.txt +1 -0
  99. data/spec/integration/recipes/included.rb +9 -0
  100. data/spec/integration/recipes/node.json +3 -0
  101. data/spec/integration/recipes/redefine.rb +20 -0
  102. data/spec/integration/recipes/templates/template_auto.erb +6 -0
  103. data/spec/integration/spec_helper.rb +42 -0
  104. data/spec/unit/lib/itamae/backend_spec.rb +95 -0
  105. data/spec/unit/lib/itamae/handler/base_spec.rb +34 -0
  106. data/spec/unit/lib/itamae/handler/fluentd_spec.rb +19 -0
  107. data/spec/unit/lib/itamae/handler_proxy_spec.rb +38 -0
  108. data/spec/unit/lib/itamae/handler_spec.rb +11 -0
  109. data/spec/unit/lib/itamae/node_spec.rb +14 -0
  110. data/spec/unit/lib/itamae/recipe_spec.rb +6 -0
  111. data/spec/unit/lib/itamae/resource/base_spec.rb +127 -0
  112. data/spec/unit/lib/itamae/resource_spec.rb +23 -0
  113. data/spec/unit/lib/itamae/runner_spec.rb +32 -0
  114. data/spec/unit/spec_helper.rb +23 -0
  115. metadata +393 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ebdf4efc9c889e355f3e693436b1dac36b24f313
4
+ data.tar.gz: b9494d2c5291046feb71801dde6582fc20137020
5
+ SHA512:
6
+ metadata.gz: 26ca1bc353e49f4bba91aace86ec64faf2444f08236f12fff5d5c5fa302c44eb49f424c850b5f00b9fcbb5f14cef448513f0bafdf5076f49861d4334c99bc179
7
+ data.tar.gz: e5cd9b57cd29db325d8a7ef4739664a2913008d53a35c01bf0e1eac48675a8c486ec85fb57412103f36954c278e5931edcb572ee57c72717635cef9d0992f251
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .vagrant
19
+ Gemfile.local
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ -fd
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in itamae-mitsurin.gemspec
4
+ gemspec
5
+
6
+ path = Pathname.new("Gemfile.local")
7
+ eval(path.read) if path.exist?
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2016 Akihiro Kamiyama
2
+
3
+ Ripped out of Itamae 1.9.3, Itamae-plugin-resource-aws 0.1 and modified.
4
+ Copyright (c) 2013-2015 Ryota Arai
5
+ Copyright (c) 2015 Gosuke Miyashita
6
+
7
+ MIT License
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining
10
+ a copy of this software and associated documentation files (the
11
+ "Software"), to deal in the Software without restriction, including
12
+ without limitation the rights to use, copy, modify, merge, publish,
13
+ distribute, sublicense, and/or sell copies of the Software, and to
14
+ permit persons to whom the Software is furnished to do so, subject to
15
+ the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be
18
+ included in all copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,44 @@
1
+ [![Gem Version](https://badge.fury.io/rb/itamae-mitsurin.svg)](http://badge.fury.io/rb/itamae-mitsurin)
2
+
3
+ Customized version of Itamae and plugin
4
+
5
+ ## Concept
6
+
7
+ - More like Chef
8
+ - Minimum attributes
9
+ - Support AWS Resource
10
+ - Require Rake
11
+
12
+ ## Installation
13
+
14
+ ```
15
+ $ gem install itamae-mitsurin
16
+ $ itamae-mitsurin init [project_name]
17
+ ```
18
+
19
+ ## Usage AWS Resource
20
+
21
+ ```ruby
22
+ # recipe
23
+
24
+ Aws.config[:region] = 'ap-northeast-1'
25
+
26
+ aws_ebs_volume 'db_ebs_volume' do
27
+ action [:create, :attach]
28
+ availability_zone 'ap-northeast-1b'
29
+ device '/dev/xvdf'
30
+ volume_type 'standard'
31
+ size 30
32
+ instance_id node['ec2']['instance-id']
33
+ end
34
+ ```
35
+
36
+ ## Contributing
37
+
38
+ If you have a problem, please [create an issue](https://github.com/kammy1231/itamae-mitsurin) or a pull request.
39
+
40
+ 1. Fork it
41
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
42
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
43
+ 4. Push to the branch (`git push origin my-new-feature`)
44
+ 5. Create new Pull Request
@@ -0,0 +1,55 @@
1
+ # coding: utf-8
2
+ require "bundler/gem_tasks"
3
+ require 'rspec/core/rake_task'
4
+
5
+ require 'rake/testtask'
6
+ require 'rake/extensiontask'
7
+ require 'rake/packagetask'
8
+ begin
9
+ require 'bundler/gem_tasks'
10
+ rescue LoadError
11
+ puts 'If you want to create gem, You must install Bundler'
12
+ end
13
+
14
+ require './lib/itamae/mitsurin/version.rb'
15
+ def version
16
+ Itamae::Mitsurin::VERSION
17
+ end
18
+
19
+ task :default => :test
20
+ task :test => :compile
21
+ Rake::TestTask.new do |t|
22
+ t.libs << 'lib' << 'test'
23
+ t.test_files = FileList['test/test_*.rb'].exclude('test/test_assoccoords.rb')
24
+ end
25
+
26
+ Rake::ExtensionTask.new do |ext|
27
+ ext.name = 'itamae-mitsurin'
28
+ ext.ext_dir = 'ext/'
29
+ ext.lib_dir = 'lib/'
30
+ end
31
+
32
+ Rake::PackageTask.new('itamae-mitsurin', "#{version}") do |t|
33
+ t.need_tar_gz = true
34
+ t.package_files.include `git ls-files`.split("\n")
35
+ end
36
+
37
+ namespace :release do
38
+ desc "Bump up version and commit"
39
+ task :version_up do
40
+ version_file = File.expand_path("lib/itamae/mitsurin/version.txt")
41
+ current_version = File.read(version_file).strip
42
+
43
+ if /\A(.+?)(\d+)\z/ =~ current_version
44
+ next_version = "#{$1}#{$2.to_i + 1}"
45
+ else
46
+ raise "Invalid version"
47
+ end
48
+
49
+ open(version_file, "w") do |f|
50
+ f.write next_version
51
+ end
52
+ system "git add #{version_file}"
53
+ system "git commit -m 'Bump up version'"
54
+ end
55
+ end
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'itamae/cli'
4
+ Itamae::CLI.start
5
+
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'itamae/mitsurin/cli'
4
+ Itamae::Mitsurin::CLI.start
5
+
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'itamae/mitsurin/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "itamae-mitsurin"
8
+ spec.version = Itamae::Mitsurin::VERSION
9
+ spec.authors = ["Akihiro Kamiyama"]
10
+ spec.email = ["kamiyama@qualitia.co.jp"]
11
+ spec.summary = %q{Customized version of Itamae and Itamae plugin}
12
+ spec.homepage = "https://github.com/kammy1231/itamae-mitsurin"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_runtime_dependency "thor"
21
+ spec.add_runtime_dependency "specinfra", [">= 2.51.2", "< 3.0.0"]
22
+ spec.add_runtime_dependency "hashie"
23
+ spec.add_runtime_dependency "ansi"
24
+ spec.add_runtime_dependency "schash", "~> 0.1.0"
25
+ spec.add_runtime_dependency "aws-sdk", "~> 2"
26
+ spec.add_runtime_dependency "serverspec", [">= 2.30", "< 3.0.0"]
27
+
28
+ spec.add_development_dependency "bundler", "~> 1.10"
29
+ spec.add_development_dependency "rake"
30
+ spec.add_development_dependency "rspec", "~> 3.0"
31
+ spec.add_development_dependency "pry-byebug"
32
+ spec.add_development_dependency "docker-api", "~> 1.20"
33
+ spec.add_development_dependency "fakefs"
34
+ spec.add_development_dependency "fluent-logger"
35
+ end
@@ -0,0 +1,18 @@
1
+ require "itamae/runner"
2
+ require "itamae/cli"
3
+ require "itamae/recipe"
4
+ require "itamae/resource"
5
+ require "itamae/handler"
6
+ require "itamae/handler_proxy"
7
+ require "itamae/recipe_children"
8
+ require "itamae/logger"
9
+ require "itamae/node"
10
+ require "itamae/backend"
11
+ require "itamae/notification"
12
+ require "itamae/definition"
13
+ require "itamae/ext"
14
+ require "itamae/generators"
15
+
16
+ module Itamae
17
+ # Your code goes here...
18
+ end
@@ -0,0 +1,293 @@
1
+ require 'specinfra/core'
2
+ require 'singleton'
3
+ require 'io/console'
4
+ require 'net/ssh'
5
+
6
+ Specinfra::Configuration.error_on_missing_backend_type = true
7
+
8
+ module Specinfra
9
+ module Configuration
10
+ def self.sudo_password
11
+ return ENV['SUDO_PASSWORD'] if ENV['SUDO_PASSWORD']
12
+ return @sudo_password if @sudo_password
13
+
14
+ # TODO: Fix this dirty hack
15
+ return nil unless caller.any? {|call| call.include?('channel_data') }
16
+
17
+ print "sudo password: "
18
+ @sudo_password = STDIN.noecho(&:gets).strip
19
+ print "\n"
20
+ @sudo_password
21
+ end
22
+ end
23
+ end
24
+
25
+ module Itamae
26
+ module Backend
27
+ UnknownBackendTypeError = Class.new(StandardError)
28
+ CommandExecutionError = Class.new(StandardError)
29
+ SourceNotExistError = Class.new(StandardError)
30
+
31
+ class << self
32
+ def create(type, opts = {})
33
+ self.const_get(type.capitalize).new(opts)
34
+ end
35
+ end
36
+
37
+ class Base
38
+ attr_reader :executed_commands
39
+
40
+ def initialize(options)
41
+ @options = options
42
+ @backend = create_specinfra_backend
43
+ @executed_commands = []
44
+ end
45
+
46
+ def run_command(commands, options = {})
47
+ options = {error: true}.merge(options)
48
+
49
+ command = build_command(commands, options)
50
+ Itamae.logger.debug "Executing `#{command}`..."
51
+
52
+ result = nil
53
+
54
+ Itamae.logger.with_indent do
55
+ reset_output_handler
56
+
57
+ result = run_command_with_profiling(command)
58
+
59
+ flush_output_handler_buffer
60
+
61
+ if result.exit_status == 0 || !options[:error]
62
+ method = :debug
63
+ message = "exited with #{result.exit_status}"
64
+ else
65
+ method = :error
66
+ message = "Command `#{command}` failed. (exit status: #{result.exit_status})"
67
+
68
+ unless Itamae.logger.level == ::Logger::DEBUG
69
+ result.stdout.each_line do |l|
70
+ log_output_line("stdout", l, :error)
71
+ end
72
+ result.stderr.each_line do |l|
73
+ log_output_line("stderr", l, :error)
74
+ end
75
+ end
76
+ end
77
+
78
+ Itamae.logger.public_send(method, message)
79
+ end
80
+
81
+ if options[:error] && result.exit_status != 0
82
+ raise CommandExecutionError
83
+ end
84
+
85
+ result
86
+ end
87
+
88
+ def get_command(*args)
89
+ @backend.command.get(*args)
90
+ end
91
+
92
+ def receive_file(src, dst = nil)
93
+ if dst
94
+ Itamae.logger.debug "Receiving a file from '#{src}' to '#{dst}'..."
95
+ else
96
+ Itamae.logger.debug "Receiving a file from '#{src}'..."
97
+ end
98
+ @backend.receive_file(src, dst)
99
+ end
100
+
101
+ def send_file(src, dst)
102
+ Itamae.logger.debug "Sending a file from '#{src}' to '#{dst}'..."
103
+ unless ::File.exist?(src)
104
+ raise SourceNotExistError, "The file '#{src}' doesn't exist."
105
+ end
106
+ unless ::File.file?(src)
107
+ raise SourceNotExistError, "'#{src}' is not a file."
108
+ end
109
+ @backend.send_file(src, dst)
110
+ end
111
+
112
+ def send_directory(src, dst)
113
+ Itamae.logger.debug "Sending a directory from '#{src}' to '#{dst}'..."
114
+ unless ::File.exist?(src)
115
+ raise SourceNotExistError, "The directory '#{src}' doesn't exist."
116
+ end
117
+ unless ::File.directory?(src)
118
+ raise SourceNotExistError, "'#{src}' is not a directory."
119
+ end
120
+ @backend.send_directory(src, dst)
121
+ end
122
+
123
+ def host_inventory
124
+ @backend.host_inventory
125
+ end
126
+
127
+ def finalize
128
+ # pass
129
+ end
130
+
131
+ private
132
+
133
+ def create_specinfra_backend
134
+ raise NotImplementedError
135
+ end
136
+
137
+ def reset_output_handler
138
+ @buf = {}
139
+ %w!stdout stderr!.each do |output_name|
140
+ @buf[output_name] = ""
141
+ handler = lambda do |str|
142
+ lines = str.split(/\r?\n/, -1)
143
+ @buf[output_name] += lines.pop
144
+ unless lines.empty?
145
+ lines[0] = @buf[output_name] + lines[0]
146
+ @buf[output_name] = ""
147
+ lines.each do |l|
148
+ log_output_line(output_name, l)
149
+ end
150
+ end
151
+ end
152
+ @backend.public_send("#{output_name}_handler=", handler)
153
+ end
154
+ end
155
+
156
+ def flush_output_handler_buffer
157
+ @buf.each do |output_name, line|
158
+ next if line.empty?
159
+ log_output_line(output_name, line)
160
+ end
161
+ end
162
+
163
+ def log_output_line(output_name, line, severity = :debug)
164
+ line = line.gsub(/[[:cntrl:]]/, '')
165
+ Itamae.logger.public_send(severity, "#{output_name} | #{line}")
166
+ end
167
+
168
+ def build_command(commands, options)
169
+ if commands.is_a?(Array)
170
+ command = commands.map do |cmd|
171
+ cmd.shellescape
172
+ end.join(' ')
173
+ else
174
+ command = commands
175
+ end
176
+
177
+ cwd = options[:cwd]
178
+ if cwd
179
+ command = "cd #{cwd.shellescape} && #{command}"
180
+ end
181
+
182
+ user = options[:user]
183
+ if user
184
+ command = "cd ~#{user.shellescape} ; #{command}"
185
+ command = "sudo -H -u #{user.shellescape} -- #{shell.shellescape} -c #{command.shellescape}"
186
+ end
187
+
188
+ command
189
+ end
190
+
191
+ def shell
192
+ @options[:shell] || '/bin/sh'
193
+ end
194
+
195
+ def run_command_with_profiling(command)
196
+ start_at = Time.now
197
+ result = @backend.run_command(command)
198
+ duration = Time.now.to_f - start_at.to_f
199
+
200
+ @executed_commands << {command: command, duration: duration}
201
+
202
+ result
203
+ end
204
+ end
205
+
206
+ class Local < Base
207
+ private
208
+ def create_specinfra_backend
209
+ Specinfra::Backend::Exec.new(
210
+ shell: @options[:shell],
211
+ )
212
+ end
213
+ end
214
+
215
+ class Ssh < Base
216
+ private
217
+ def create_specinfra_backend
218
+ Specinfra::Backend::Ssh.new(
219
+ request_pty: true,
220
+ host: ssh_options[:host_name],
221
+ disable_sudo: disable_sudo?,
222
+ ssh_options: ssh_options,
223
+ shell: @options[:shell],
224
+ )
225
+ end
226
+
227
+ def ssh_options
228
+ opts = {}
229
+
230
+ opts[:host_name] = @options[:host]
231
+
232
+ # from ssh-config
233
+ opts.merge!(Net::SSH::Config.for(@options[:host]))
234
+ opts[:user] = @options[:user] || opts[:user] || Etc.getlogin
235
+ opts[:keys] = [@options[:key]] if @options[:key]
236
+ opts[:port] = @options[:port] if @options[:port]
237
+
238
+ if @options[:vagrant]
239
+ config = Tempfile.new('', Dir.tmpdir)
240
+ hostname = opts[:host_name] || 'default'
241
+ vagrant_cmd = "vagrant ssh-config #{hostname} > #{config.path}"
242
+ if defined?(Bundler)
243
+ Bundler.with_clean_env do
244
+ `#{vagrant_cmd}`
245
+ end
246
+ else
247
+ `#{vagrant_cmd}`
248
+ end
249
+ opts.merge!(Net::SSH::Config.for(hostname, [config.path]))
250
+ end
251
+
252
+ if @options[:ask_password]
253
+ print "password: "
254
+ password = STDIN.noecho(&:gets).strip
255
+ print "#{ENV['SSH_PASSWORD']}\n"
256
+ opts.merge!(password: password)
257
+ end
258
+
259
+ opts
260
+ end
261
+
262
+ def disable_sudo?
263
+ !@options[:sudo]
264
+ end
265
+ end
266
+
267
+ class Docker < Base
268
+ def finalize
269
+ image = @backend.commit_container
270
+ Itamae.logger.info "Image created: #{image.id}"
271
+ end
272
+
273
+ private
274
+ def create_specinfra_backend
275
+ begin
276
+ require 'docker'
277
+ rescue LoadError
278
+ Itamae.logger.fatal "To use docker backend, please install 'docker-api' gem"
279
+ end
280
+
281
+ # TODO: Move to Specinfra?
282
+ Excon.defaults[:ssl_verify_peer] = @options[:tls_verify_peer]
283
+ ::Docker.logger = Itamae.logger
284
+
285
+ Specinfra::Backend::Docker.new(
286
+ docker_image: @options[:image],
287
+ docker_container: @options[:container],
288
+ shell: @options[:shell],
289
+ )
290
+ end
291
+ end
292
+ end
293
+ end