itamae-mitsurin 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +26 -0
- data/README.md +44 -0
- data/Rakefile +55 -0
- data/bin/itamae +5 -0
- data/bin/itamae-mitsurin +5 -0
- data/itamae-mitsurin.gemspec +35 -0
- data/lib/itamae.rb +18 -0
- data/lib/itamae/backend.rb +293 -0
- data/lib/itamae/cli.rb +86 -0
- data/lib/itamae/definition.rb +40 -0
- data/lib/itamae/ext.rb +1 -0
- data/lib/itamae/ext/specinfra.rb +39 -0
- data/lib/itamae/generators.rb +20 -0
- data/lib/itamae/generators/cookbook.rb +22 -0
- data/lib/itamae/generators/project.rb +22 -0
- data/lib/itamae/generators/role.rb +22 -0
- data/lib/itamae/generators/templates/cookbook/default.rb +0 -0
- data/lib/itamae/generators/templates/cookbook/files/.keep +0 -0
- data/lib/itamae/generators/templates/cookbook/templates/.keep +0 -0
- data/lib/itamae/generators/templates/project/Gemfile +4 -0
- data/lib/itamae/generators/templates/project/cookbooks/.keep +0 -0
- data/lib/itamae/generators/templates/project/roles/.keep +0 -0
- data/lib/itamae/generators/templates/role/default.rb +0 -0
- data/lib/itamae/generators/templates/role/files/.keep +0 -0
- data/lib/itamae/generators/templates/role/templates/.keep +0 -0
- data/lib/itamae/handler.rb +21 -0
- data/lib/itamae/handler/base.rb +40 -0
- data/lib/itamae/handler/debug.rb +10 -0
- data/lib/itamae/handler/fluentd.rb +44 -0
- data/lib/itamae/handler/json.rb +22 -0
- data/lib/itamae/handler_proxy.rb +38 -0
- data/lib/itamae/logger.rb +124 -0
- data/lib/itamae/mitsurin.rb +13 -0
- data/lib/itamae/mitsurin/cli.rb +56 -0
- data/lib/itamae/mitsurin/creators.rb +19 -0
- data/lib/itamae/mitsurin/creators/cookbook.rb +24 -0
- data/lib/itamae/mitsurin/creators/project.rb +24 -0
- data/lib/itamae/mitsurin/creators/templates/project/.rspec +2 -0
- data/lib/itamae/mitsurin/creators/templates/project/Gemfile +3 -0
- data/lib/itamae/mitsurin/creators/templates/project/Rakefile +2 -0
- data/lib/itamae/mitsurin/creators/templates/project/environments/.keep +0 -0
- data/lib/itamae/mitsurin/creators/templates/project/environments/sample.json +7 -0
- data/lib/itamae/mitsurin/creators/templates/project/nodes/.keep +0 -0
- data/lib/itamae/mitsurin/creators/templates/project/nodes/sample01.json +8 -0
- data/lib/itamae/mitsurin/creators/templates/project/roles/.keep +0 -0
- data/lib/itamae/mitsurin/creators/templates/project/site-cookbooks/_base/_base/attributes/.keep +0 -0
- data/lib/itamae/mitsurin/creators/templates/project/site-cookbooks/_base/_base/files/.keep +0 -0
- data/lib/itamae/mitsurin/creators/templates/project/site-cookbooks/_base/_base/recipes/default.rb +0 -0
- data/lib/itamae/mitsurin/creators/templates/project/site-cookbooks/_base/_base/spec/default_spec.rb +2 -0
- data/lib/itamae/mitsurin/creators/templates/project/site-cookbooks/_base/_base/templates/.keep +0 -0
- data/lib/itamae/mitsurin/creators/templates/project/spec/spec_helper.rb +32 -0
- data/lib/itamae/mitsurin/creators/templates/project/tmp-nodes/.keep +0 -0
- data/lib/itamae/mitsurin/creators/templates/site-cookbooks/attributes/.keep +0 -0
- data/lib/itamae/mitsurin/creators/templates/site-cookbooks/files/.keep +0 -0
- data/lib/itamae/mitsurin/creators/templates/site-cookbooks/recipes/default.rb +0 -0
- data/lib/itamae/mitsurin/creators/templates/site-cookbooks/spec/.keep +0 -0
- data/lib/itamae/mitsurin/creators/templates/site-cookbooks/templates/.keep +0 -0
- data/lib/itamae/mitsurin/itamae_task.rb +199 -0
- data/lib/itamae/mitsurin/serverspec_task.rb +110 -0
- data/lib/itamae/mitsurin/version.rb +5 -0
- data/lib/itamae/mitsurin/version.txt +1 -0
- data/lib/itamae/node.rb +74 -0
- data/lib/itamae/notification.rb +46 -0
- data/lib/itamae/recipe.rb +171 -0
- data/lib/itamae/recipe_children.rb +86 -0
- data/lib/itamae/resource.rb +73 -0
- data/lib/itamae/resource/aws_ebs_volume.rb +84 -0
- data/lib/itamae/resource/base.rb +374 -0
- data/lib/itamae/resource/directory.rb +63 -0
- data/lib/itamae/resource/execute.rb +26 -0
- data/lib/itamae/resource/file.rb +176 -0
- data/lib/itamae/resource/gem_package.rb +81 -0
- data/lib/itamae/resource/git.rb +94 -0
- data/lib/itamae/resource/group.rb +42 -0
- data/lib/itamae/resource/http_request.rb +71 -0
- data/lib/itamae/resource/link.rb +33 -0
- data/lib/itamae/resource/local_ruby_block.rb +15 -0
- data/lib/itamae/resource/package.rb +44 -0
- data/lib/itamae/resource/remote_directory.rb +84 -0
- data/lib/itamae/resource/remote_file.rb +54 -0
- data/lib/itamae/resource/service.rb +69 -0
- data/lib/itamae/resource/template.rb +53 -0
- data/lib/itamae/resource/user.rb +93 -0
- data/lib/itamae/runner.rb +124 -0
- data/spec/integration/Vagrantfile +35 -0
- data/spec/integration/default_spec.rb +226 -0
- data/spec/integration/recipes/default.rb +423 -0
- data/spec/integration/recipes/default2.rb +6 -0
- data/spec/integration/recipes/define/default.rb +6 -0
- data/spec/integration/recipes/define/files/remote_file_in_definition +1 -0
- data/spec/integration/recipes/dry_run.rb +6 -0
- data/spec/integration/recipes/files/remote_file_auto +1 -0
- data/spec/integration/recipes/hello.erb +6 -0
- data/spec/integration/recipes/hello.txt +1 -0
- data/spec/integration/recipes/included.rb +9 -0
- data/spec/integration/recipes/node.json +3 -0
- data/spec/integration/recipes/redefine.rb +20 -0
- data/spec/integration/recipes/templates/template_auto.erb +6 -0
- data/spec/integration/spec_helper.rb +42 -0
- data/spec/unit/lib/itamae/backend_spec.rb +95 -0
- data/spec/unit/lib/itamae/handler/base_spec.rb +34 -0
- data/spec/unit/lib/itamae/handler/fluentd_spec.rb +19 -0
- data/spec/unit/lib/itamae/handler_proxy_spec.rb +38 -0
- data/spec/unit/lib/itamae/handler_spec.rb +11 -0
- data/spec/unit/lib/itamae/node_spec.rb +14 -0
- data/spec/unit/lib/itamae/recipe_spec.rb +6 -0
- data/spec/unit/lib/itamae/resource/base_spec.rb +127 -0
- data/spec/unit/lib/itamae/resource_spec.rb +23 -0
- data/spec/unit/lib/itamae/runner_spec.rb +32 -0
- data/spec/unit/spec_helper.rb +23 -0
- metadata +393 -0
checksums.yaml
ADDED
@@ -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
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -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
|
data/Rakefile
ADDED
@@ -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
|
data/bin/itamae
ADDED
data/bin/itamae-mitsurin
ADDED
@@ -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
|
data/lib/itamae.rb
ADDED
@@ -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
|