rundock 0.2.0 → 0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0491b048401872650ce67684e7e23556866b43e3
4
- data.tar.gz: 6bd121b04391da55428ba012f7ed550427a7d0cd
3
+ metadata.gz: eef77dde29974f83d4bef90d7ac82886ebfc46d5
4
+ data.tar.gz: 484b9c3e7f4f4f557a3ecb1d3d5ce506566bc45d
5
5
  SHA512:
6
- metadata.gz: b218e32fb3145065062a7d8c7d869e948898361c38a0b63af2c692d6987d2373a20d8fd04187c3f58700b87f6d4cd63411a2292e41311c429570f9bdbb953308
7
- data.tar.gz: 1e327e599076b186c71d67e260b2195d3f19c1b5103b01d5940ad90641b29db8974e726b507895d6eebc0a9dcba0723c919ed4313471fc024d8ff182cd39f35d
6
+ metadata.gz: adf8f0dc23a9a4f38db95b77eb804ac336dae9aba7d0a8d671572221c635c8ec8fc6fd3b71ef0cc8979162f22253b603345a85b33578e413bbe30005037622be
7
+ data.tar.gz: a8b0d0a20eb279a2ae8f46cbe800a38fe266736d4087a0eccb15546cea74d7e13525245e72706a999376e64fd622cad4198b8f4245a6b9408a8b397ab781f5da
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## v0.2.2
2
+
3
+ Fix
4
+
5
+ - Fix ssh options conflict bugs
6
+ - Support docker 1.6.2 for Circle CI environtment
7
+
8
+ ## v0.2.1
9
+
10
+ Improvements
11
+
12
+ - Support error-exit options.(like shellscript set -e/+e)
13
+ - Change file path option name from '*_yaml' to '*'
14
+ - Add a option that stdout can no-header
15
+
1
16
  ## v0.2.0
2
17
 
3
18
  Refactoring
data/README.md CHANGED
@@ -12,6 +12,28 @@ $ gem install rundock
12
12
 
13
13
  ## Usage
14
14
 
15
+ Edit your hostgroup to "hostgroup.yml" like this sample.
16
+
17
+ ```
18
+ # node section
19
+ - node: 192.168.1.11
20
+ - node: host-alias-01
21
+ ---
22
+ # host information section
23
+ host-alias-01:
24
+ host: 192.168.1.12
25
+ ssh_opts:
26
+ port: 2222
27
+ user: anyuser
28
+ keys: ["~/.ssh/id_rsa_anyuser"]
29
+ ```
30
+
31
+ and execute rundock.
32
+
33
+ $ rundock ssh -g /path/to/your-dir/hostgroup.yml -c 'your-gread-command'
34
+
35
+ or
36
+
15
37
  Edit your operation scenario to "[scenario.yml](https://github.com/hiracy/rundock/blob/master/scenario_sample.yml)" like this sample.
16
38
 
17
39
  ```
@@ -37,19 +59,26 @@ host-alias-01:
37
59
  ---
38
60
  # task information section
39
61
  update_gem:
40
- - "sudo gem update --system"
41
- - "sudo gem update"
62
+ command:
63
+ - "sudo gem update --system"
64
+ - "sudo gem update"
42
65
  install_bundler:
43
- - "sudo gem install bundler --no-ri --no-rdoc"
66
+ command:
67
+ - "sudo gem install bundler --no-ri --no-rdoc"
44
68
  ```
45
69
 
46
- and do rundock.
70
+ and execute rundock.
47
71
 
48
- $ rundock do -s /path/to/your-dir/scenario.yml
72
+ $ rundock do /path/to/your-dir/scenario.yml
49
73
 
50
- You can also specify [ssh_options.yml](http://net-ssh.github.io/net-ssh/classes/Net/SSH.html)(Net::SSH options) file contents that you specified "-d" option to the default ssh options.
74
+ You can also specify [default_ssh_options.yml](https://github.com/hiracy/rundock/blob/master/default_ssh.yml) [(Net::SSH options)](http://net-ssh.github.io/net-ssh/classes/Net/SSH.html) file contents that you specified "-d" option to the default ssh options.
51
75
 
52
- $ rundock do -s /path/to/your-dir/scenario.yml -d /path/to/your-dir/ssh_options.yml
76
+ ```
77
+ $ rundock ssh -g /path/to/your-dir/hostgroup.yml -c 'your-gread-command' -d /path/to/your-dir/default_ssh_options.yml
78
+ ```
79
+ ```
80
+ $ rundock do -s /path/to/your-dir/scenario.yml -d /path/to/your-dir/default_ssh_options.yml
81
+ ```
53
82
 
54
83
  For more detail. You can see from `rundock -h` command.
55
84
 
data/Rakefile CHANGED
@@ -6,15 +6,6 @@ run_commands = [
6
6
  'echo \'Hello Rundock.\' > /var/tmp/hello_rundock'
7
7
  ]
8
8
 
9
- run_scenarios = %w(
10
- use_default_ssh_scenario
11
- simple_echo_scenario
12
- )
13
-
14
- run_groups = %w(
15
- simple_host_group
16
- )
17
-
18
9
  def execute(command, clean_env)
19
10
  puts "[EXECUTE:] #{command}"
20
11
 
@@ -42,8 +33,9 @@ def setup_docker(platform, timeout, interval)
42
33
  raise 'Docker Error.' unless found
43
34
  end
44
35
 
45
- def do_rundock_ssh(commands, platform, groups)
36
+ def do_rundock_ssh(commands, platform)
46
37
  base_dir = "#{ENV['HOME']}/.rundock/#{platform}"
38
+ groups_files_pattern = ["#{base_dir}/groups/*.yml"]
47
39
 
48
40
  if platform == 'localhost'
49
41
  commands.each do |cmd|
@@ -52,38 +44,42 @@ def do_rundock_ssh(commands, platform, groups)
52
44
  else
53
45
  commands.each do |cmd|
54
46
  execute('bundle exec exe/rundock' \
55
- " ssh -c \"#{cmd}\" -h 127.0.0.1 -p 22222 -u tester" \
47
+ " ssh -c \"#{cmd}\" -h 172.17.42.1 -p 22222 -u tester" \
56
48
  " -i #{ENV['HOME']}/.ssh/id_rsa_rundock_spec_#{platform}_tmp -l debug", true)
57
- groups.each do |g|
49
+ Dir.glob(groups_files_pattern).each do |g|
58
50
  execute('bundle exec exe/rundock' \
59
- " ssh -c \"#{cmd}\" -g #{base_dir}/scenarios/#{g}.yml -p 22222 -u tester" \
51
+ " ssh -c \"#{cmd}\" -g #{g} -p 22222 -u tester" \
60
52
  " -i #{ENV['HOME']}/.ssh/id_rsa_rundock_spec_#{platform}_tmp -l debug", true)
61
53
  end
62
54
  end
63
55
  end
64
56
  end
65
57
 
66
- def do_rundock_scenarios(scenarios, platform)
58
+ def do_rundock_scenarios(platform)
67
59
  if platform == 'localhost'
68
60
  base_dir = './spec/integration/platforms/localhost'
61
+ scenario_files_pattern = ['./spec/integration/platforms/localhost/scenarios/*.yml']
69
62
  else
70
63
  base_dir = "#{ENV['HOME']}/.rundock/#{platform}"
64
+ scenario_files_pattern = ["#{base_dir}/scenarios/*.yml"]
71
65
  end
72
66
 
73
- scenarios.each do |scenario|
74
- default_ssh_opt = ''
67
+ Dir.glob(scenario_files_pattern).each do |scenario|
75
68
  if scenario =~ /use_default_ssh/ && platform != 'localhost'
76
69
  default_ssh_opt = " -d #{base_dir}/integration_default_ssh.yml"
70
+ else
71
+ default_ssh_opt = ''
77
72
  end
78
73
 
79
74
  execute('bundle exec exe/rundock' \
80
- " do -s #{base_dir}/scenarios/#{scenario}.yml#{default_ssh_opt} -l debug", true)
75
+ " do #{scenario}#{default_ssh_opt} -l debug", true)
81
76
  end
82
77
  end
83
78
 
84
79
  desc 'Cleaning environments'
85
80
 
86
81
  task :clean do
82
+ execute('rm -f /var/tmp/hello_rundock*', false)
87
83
  Dir.glob('./spec/integration/platforms/*').each do |platform|
88
84
  next if platform =~ /localhost$/
89
85
  execute("#{platform}/setup.sh --clean", false)
@@ -132,8 +128,8 @@ namespace :spec do
132
128
  desc "Run rundock for #{target}"
133
129
 
134
130
  task :rundock do
135
- do_rundock_ssh(run_commands, target, run_groups)
136
- do_rundock_scenarios(run_scenarios, target)
131
+ do_rundock_ssh(run_commands, target)
132
+ do_rundock_scenarios(target)
137
133
  end
138
134
 
139
135
  desc "Run serverspec tests for #{target}"
@@ -141,7 +137,7 @@ namespace :spec do
141
137
  RSpec::Core::RakeTask.new(:serverspec) do |t|
142
138
  ENV['TARGET_HOST'] = target
143
139
  t.ruby_opts = '-I ./spec/integration'
144
- t.pattern = './spec/integration/recipes/*_spec.rb'
140
+ t.pattern = ['./spec/integration/recipes/*_spec.rb']
145
141
  end
146
142
  end
147
143
  end
@@ -25,18 +25,18 @@ module Rundock
25
25
  @backend = create_specinfra_backend
26
26
  end
27
27
 
28
- def run_commands(cmd, options = {})
28
+ def run_commands(cmd, exec_options = {})
29
29
  Array(cmd).each do |c|
30
- run_command(c)
30
+ run_command(c, exec_options)
31
31
  end
32
32
  end
33
33
 
34
34
  private
35
35
 
36
- def run_command(cmd, options = {})
36
+ def run_command(cmd, exec_options = {})
37
37
  command = cmd.strip
38
- command = "cd #{Shellwords.escape(options[:cwd])} && #{command}" if options[:cwd]
39
- command = "sudo -H -u #{Shellwords.escape(user)} -- /bin/sh -c #{command}" if options[:user]
38
+ command = "cd #{Shellwords.escape(exec_options[:cwd])} && #{command}" if exec_options[:cwd]
39
+ command = "sudo -H -u #{Shellwords.escape(user)} -- /bin/sh -c #{command}" if exec_options[:user]
40
40
 
41
41
  Logger.debug(%(Start executing: "#{command}"))
42
42
 
@@ -46,11 +46,12 @@ module Rundock
46
46
  Logger.formatter.indent do
47
47
  Logger.error("#{result.stderr}") unless result.stderr.blank?
48
48
  Logger.info("#{result.stdout.strip}") unless result.stdout.strip.blank?
49
+ Logger.debug("errexit: #{exec_options[:errexit]}")
49
50
  Logger.debug("exit status: #{exit_status}")
50
51
  end
51
52
 
52
- if options[:no_continue_if_error] && exit_status != 0
53
- raise CommandResultStatucError
53
+ if exec_options[:errexit] && exit_status != 0
54
+ raise CommandResultStatusError
54
55
  end
55
56
 
56
57
  result
@@ -81,19 +82,15 @@ module Rundock
81
82
  private
82
83
 
83
84
  def parse(options)
84
- if options['ssh_config'] && FileTest.exists?(options['ssh_config'])
85
- ssh_opts = Net::SSH::Config.for(options['host'], [options['ssh_config']])
85
+ if options[:ssh_config] && FileTest.exists?(options[:ssh_config])
86
+ ssh_opts = Net::SSH::Config.for(options[:host], [options[:ssh_config]])
86
87
  else
87
- ssh_opts = Net::SSH::Config.for(options['host'])
88
+ ssh_opts = Net::SSH::Config.for(options[:host])
88
89
  end
89
90
 
90
- ssh_opts[:host_name] = options['host']
91
- ssh_opts[:user] = options['user']
92
- ssh_opts[:keys] = options['keys']
93
- ssh_opts[:keys] = Array(options['key']) if !ssh_opts[:keys] && options['key']
94
- ssh_opts[:port] = options['port']
95
- ssh_opts[:password] = parse_password_from_stdin if options['ask_password']
96
-
91
+ ssh_opts[:host_name] = options[:host]
92
+ ssh_opts[:keys] = Array(options[:key]) if options[:key]
93
+ ssh_opts[:password] = parse_password_from_stdin if options[:ask_password]
97
94
  ssh_opts.merge!(filter_net_ssh_options(options))
98
95
 
99
96
  Logger.debug(%(Net::SSH Options: "#{ssh_opts}"))
@@ -111,7 +108,7 @@ module Rundock
111
108
  def filter_net_ssh_options(options)
112
109
  opts = {}
113
110
  options.each do |k, v|
114
- opts[k.to_sym] = v if Net::SSH::VALID_OPTIONS.include?(k.to_sym)
111
+ opts[k] = v if Net::SSH::VALID_OPTIONS.include?(k)
115
112
  end
116
113
 
117
114
  opts
@@ -15,12 +15,14 @@ module Rundock
15
15
  opts.merge!(@options)
16
16
 
17
17
  # update ssh options for node from node_info
18
- opts.merge!(@node_info[@nodename]['ssh_opts'])
18
+ opts.merge!(@node_info[@nodename.to_sym][:ssh_opts])
19
+
19
20
  # delete trash ssh_options(node[host::ssh_options])
20
- @node_info[@nodename].delete('ssh_opts')
21
+ @node_info[@nodename.to_sym].delete(:ssh_opts)
21
22
 
22
23
  # add any attributes for host from node_info
23
- opts.merge!(@node_info[@nodename])
24
+ opts.merge!(@node_info[@nodename.to_sym])
25
+
24
26
  Backend.create(backend_type, opts)
25
27
  end
26
28
 
@@ -30,35 +32,34 @@ module Rundock
30
32
  opts = {}
31
33
 
32
34
  if !@node_info ||
33
- !@node_info[@nodename]
34
- @node_info = { @nodename => {} }
35
+ !@node_info[@nodename.to_sym]
36
+ @node_info = { @nodename.to_sym => {} }
35
37
  end
36
- @node_info[@nodename]['ssh_opts'] = {} unless @node_info[@nodename]['ssh_opts']
37
- is_local = @nodename =~ /localhost|127\.0\.0\.1/
38
+ @node_info[@nodename.to_sym][:ssh_opts] = {} unless @node_info[@nodename.to_sym][:ssh_opts]
38
39
 
39
40
  # replace default ssh options if exists
40
- @options.keys.select { |o| o =~ /(\w+)_ssh_default$/ }.each do |oo|
41
- opt = oo.gsub(/_ssh_default/, '')
41
+ @options.keys.select { |o| o.to_s =~ /(\w+)_ssh_default$/ }.each do |oo|
42
42
  # no use default ssh options if local
43
- # (like docker or localhost with port access host should not use default ssh options)
44
- @node_info[@nodename]['ssh_opts'][opt] = @options[oo] if !is_local && !@node_info[@nodename]['ssh_opts'][opt]
43
+ # set unless scenario file and cli options specified and not localhost
44
+ next if @nodename =~ /localhost|127\.0\.0\.1/
45
+ opt = oo.to_s.gsub(/_ssh_default/, '').to_sym
46
+ if !@node_info[@nodename.to_sym][:ssh_opts][opt] && !@options[opt]
47
+ @node_info[@nodename.to_sym][:ssh_opts][opt] = @options[oo]
48
+ end
45
49
  end
46
50
 
47
51
  # replace cli ssh options if exists
48
- %w(user key port ssh_config ask_password sudo).each { |o| @node_info[@nodename]['ssh_opts'][o] = @options[o] if @options[o] }
49
-
50
- opts['host'] = @nodename
52
+ %w(:user :key :port :ssh_config :ask_password :sudo).each { |o| @node_info[@nodename.to_sym][:ssh_opts][o] = @options[o] if @options[o] }
51
53
 
54
+ opts[:host] = @nodename
52
55
  opts
53
56
  end
54
57
 
55
58
  def parse_backend_type
56
- is_local = @nodename =~ /localhost|127\.0\.0\.1/
57
-
58
- if is_local &&
59
- !@node_info[@nodename]['ssh_opts']['port'] &&
60
- !@node_info[@nodename]['ssh_opts']['user'] &&
61
- !@node_info[@nodename]['ssh_opts']['ssh_config']
59
+ if @nodename =~ /localhost|127\.0\.0\.1/ &&
60
+ !@node_info[@nodename.to_sym][:ssh_opts][:port] &&
61
+ !@node_info[@nodename.to_sym][:ssh_opts][:user] &&
62
+ !@node_info[@nodename.to_sym][:ssh_opts][:ssh_config]
62
63
  backend_type = :local
63
64
  else
64
65
  backend_type = :ssh
@@ -12,8 +12,8 @@ module Rundock
12
12
  def build
13
13
  opts = {}
14
14
 
15
- if @options['default_ssh_opts_yaml'] && FileTest.exist?(@options['default_ssh_opts_yaml'])
16
- def_ssh_file = @options['default_ssh_opts_yaml']
15
+ if @options[:default_ssh_opts] && FileTest.exist?(@options[:default_ssh_opts])
16
+ def_ssh_file = @options[:default_ssh_opts]
17
17
  else
18
18
  def_ssh_file = PRESET_SSH_OPTIONS_DEFAULT_FILE_PATH
19
19
  end
@@ -21,7 +21,7 @@ module Rundock
21
21
  File.open(def_ssh_file) do |f|
22
22
  YAML.load_documents(f) do |y|
23
23
  y.each do |k, v|
24
- opts["#{k}_ssh_default"] = v
24
+ opts["#{k}_ssh_default".to_sym] = v
25
25
  end
26
26
  end
27
27
  end
@@ -0,0 +1,88 @@
1
+ module Rundock
2
+ module Builder
3
+ class OperationBuilder < Base
4
+ def build_first(scenario, node_info, tasks)
5
+ if @options[:hostgroup] && !@options[:command]
6
+ raise CommandArgNotFoundError, %("--command or -c" option is required if hostgroup specified.)
7
+ end
8
+
9
+ node = nil
10
+ scen = Scenario.new
11
+ node_attributes = { :task => {} }
12
+ tasks.each { |k, v| node_attributes[:task][k] = v } if tasks
13
+ scen.node_info = node_info
14
+ scen.tasks = tasks
15
+
16
+ # use scenario file
17
+ scenario.each do |n|
18
+ scen.nodes.push(node) if node
19
+
20
+ n.deep_symbolize_keys.each do |k, v|
21
+ if k == :node
22
+ backend = BackendBuilder.new(@options, v, node_info).build
23
+ node = Node.new(v, backend)
24
+ node_attributes[:nodename] = v
25
+
26
+ if @options[:command]
27
+ node.add_operation(build_cli_command_operation(@options[:command], @options))
28
+ end
29
+ else
30
+ if @options[:command] && (k == :command || k == :task)
31
+ Logger.debug(%("--command or -c" option is specified and ignore scenario file.))
32
+ next
33
+ end
34
+
35
+ next unless node
36
+
37
+ ope = build_operations(k, Array(v), node_attributes, @options)
38
+ node.add_operation(ope)
39
+ end
40
+ end
41
+ end
42
+
43
+ scen.nodes.push(node) if node
44
+ scen
45
+ end
46
+
47
+ def build_task(tasks, backend, node_attributes)
48
+ node = Node.new(node_attributes[:nodename], backend)
49
+ scen = Scenario.new
50
+
51
+ tasks.each do |k, v|
52
+ ope = build_operations(k, Array(v), node_attributes, nil)
53
+ node.add_operation(ope)
54
+ end
55
+
56
+ scen.nodes.push(node) if node
57
+ scen
58
+ end
59
+
60
+ def build_cli
61
+ scen = Scenario.new
62
+
63
+ @options[:host].split(',').each do |host|
64
+ backend = BackendBuilder.new(@options, host, nil).build
65
+ node = Node.new(host, backend)
66
+ node.add_operation(build_cli_command_operation(@options[:command], @options))
67
+ scen.nodes.push(node)
68
+ end
69
+
70
+ scen
71
+ end
72
+
73
+ private
74
+
75
+ def build_cli_command_operation(command, cli_options)
76
+ node_attributes = {}
77
+ node_attributes[:errexit] = !cli_options[:run_anyway]
78
+ Rundock::OperationFactory.instance(:command).create(Array(command), nil)
79
+ end
80
+
81
+ def build_operations(ope_type, ope_content, node_attributes, cli_options)
82
+ node_attributes[:errexit] = !cli_options[:run_anyway] if cli_options
83
+ node_attributes[:errexit] = true if cli_options.nil?
84
+ Rundock::OperationFactory.instance(ope_type).create(Array(ope_content), node_attributes)
85
+ end
86
+ end
87
+ end
88
+ end
@@ -13,82 +13,45 @@ module Rundock
13
13
 
14
14
  def build
15
15
  # parse default ssh file
16
- opts = @default_ssh_builder.build
17
- opts.merge!(@options)
16
+ @options.merge!(@default_ssh_builder.build)
18
17
 
19
18
  # use host specified
20
- return build_scenario_with_host(opts) if opts['host']
19
+ return build_scenario_with_cli if @options[:host]
21
20
 
22
21
  # use scenario file
23
- build_scenario(opts)
22
+ build_scenario_with_file
24
23
  end
25
24
 
26
- private
27
-
28
- def build_scenario_with_host(options)
29
- raise CommandArgNotFoundError, %("--command or -c" option is not specified.) unless options['command']
30
-
31
- scen = Scenario.new
32
-
33
- options['host'].split(',').each do |host|
34
- backend = BackendBuilder.new(options, host, nil).build
35
- node = Node.new(host, backend)
36
- node.add_operation(Rundock::OperationFactory.instance(:command).create(Array(options['command']), nil))
37
- scen << node
38
- end
39
-
40
- scen
25
+ def build_task(tasks, backend, node_attributes)
26
+ OperationBuilder.new(@options).build_task(tasks, backend, node_attributes)
41
27
  end
42
28
 
43
- def build_scenario(options)
44
- if options['hostgroup_yaml'] && !options['command']
45
- raise CommandArgNotFoundError, %("--command or -c" option is required if hostgroup specified.)
46
- end
29
+ private
47
30
 
48
- type = [:main, :node_info, :tasks]
49
- scenario_data = {}
31
+ def build_scenario_with_cli
32
+ raise CommandArgNotFoundError, %("--command or -c" option is not specified.) unless @options[:command]
33
+ ope = OperationBuilder.new(@options)
34
+ ope.build_cli
35
+ end
50
36
 
37
+ def build_scenario_with_file
51
38
  if @scenario_file
52
- YAML.load_documents(@scenario_file).each_with_index do |data, idx|
53
- scenario_data[type[idx]] = data
54
- end
55
- end
56
-
57
- node = nil
58
- scen = Scenario.new
59
-
60
- # use scenario file
61
- scenario_data[:main].each do |n|
62
- scen << node if node
63
39
 
64
- n.each do |k, v|
65
- if k == 'node'
66
- backend = BackendBuilder.new(options, v, scenario_data[:node_info]).build
67
- node = Node.new(v, backend)
40
+ type = [:main, :node_info, :tasks]
41
+ scenario_data = {}
68
42
 
69
- if options['command']
70
- node.add_operation(
71
- Rundock::OperationFactory.instance(:command).create(Array(options['command']), nil))
72
- end
43
+ YAML.load_documents(@scenario_file).each_with_index do |data, idx|
44
+ if idx == 0
45
+ scenario_data[type[idx]] = data
73
46
  else
74
-
75
- if options['command'] && (k == 'command' || k == 'task')
76
- Logger.debug(%("--command or -c" option is specified and ignore scenario file.))
77
- next
78
- end
79
-
80
- ope = build_operations(k, v, scenario_data[:tasks], options)
81
- node.add_operation(ope) if node
47
+ scenario_data[type[idx]] = data.deep_symbolize_keys unless data.nil?
82
48
  end
83
49
  end
84
50
  end
85
51
 
86
- scen << node if node
87
- scen
88
- end
89
-
90
- def build_operations(ope_type, ope_content, tasks, options)
91
- Rundock::OperationFactory.instance(ope_type.to_sym).create(Array(ope_content), tasks)
52
+ ope = OperationBuilder.new(@options)
53
+ ope.build_first(
54
+ scenario_data[:main], scenario_data[:node_info], scenario_data[:tasks])
92
55
  end
93
56
  end
94
57
  end
data/lib/rundock/cli.rb CHANGED
@@ -9,12 +9,14 @@ module Rundock
9
9
 
10
10
  class_option :log_level, type: :string, aliases: ['-l'], default: 'info'
11
11
  class_option :color, type: :boolean, default: true
12
+ class_option :header, type: :boolean, default: true
12
13
 
13
14
  def initialize(args, opts, config)
14
15
  super(args, opts, config)
15
16
 
16
17
  Rundock::Logger.level = ::Logger.const_get(options[:log_level].upcase)
17
18
  Rundock::Logger.formatter.colored = options[:color]
19
+ Rundock::Logger.formatter.show_header = options[:header]
18
20
  end
19
21
 
20
22
  desc 'version', 'Print version'
@@ -24,30 +26,31 @@ module Rundock
24
26
 
25
27
  desc 'do [SCENARIO] [options]', 'Run rundock from scenario file'
26
28
  option :sudo, type: :boolean, default: false
27
- option :scenario_yaml, type: :string, aliases: ['-s'], default: DEFAULT_SCENARIO_FILE_PATH
28
- option :default_ssh_opts_yaml, type: :string, aliases: ['-d'], default: DEFAULT_SSH_OPTIONS_DEFAULT_FILE_PATH
29
+ option :default_ssh_opts, type: :string, aliases: ['-d'], default: DEFAULT_SSH_OPTIONS_DEFAULT_FILE_PATH
30
+ option :run_anyway, type: :boolean, default: false
29
31
  def do(*scenario_file_path)
30
32
  scenario_file_path = [DEFAULT_SCENARIO_FILE_PATH] if scenario_file_path.empty?
31
- opts = { :scenario_yaml => scenario_file_path[0] }
33
+ opts = { :scenario => scenario_file_path[0] }
32
34
 
33
- Runner.run(opts.merge(options))
35
+ Runner.run(opts.merge(options.deep_symbolize_keys))
34
36
  end
35
37
 
36
38
  desc 'ssh [options]', 'Run rundock ssh with various options'
37
39
  option :command, type: :string, aliases: ['-c']
38
- option :default_ssh_opts_yaml, type: :string, aliases: ['-d'], default: DEFAULT_SSH_OPTIONS_DEFAULT_FILE_PATH
40
+ option :default_ssh_opts, type: :string, aliases: ['-d'], default: DEFAULT_SSH_OPTIONS_DEFAULT_FILE_PATH
39
41
  option :host, type: :string, aliases: ['-h'], banner: 'You can specify comma separated hosts.[ex: host1,host2,..]'
40
- option :hostgroup_yaml, type: :string, aliases: ['-g']
42
+ option :hostgroup, type: :string, aliases: ['-g']
41
43
  option :user, type: :string, aliases: ['-u']
42
44
  option :key, type: :string, aliases: ['-i']
43
45
  option :port, type: :numeric, aliases: ['-p']
44
46
  option :ssh_config, type: :string, aliases: ['-F']
45
47
  option :ask_password, type: :boolean, default: false
46
48
  option :sudo, type: :boolean, default: false
49
+ option :run_anyway, type: :boolean, default: false
47
50
  def ssh
48
51
  opts = {}
49
52
 
50
- Runner.run(opts.merge(options))
53
+ Runner.run(opts.merge(options.deep_symbolize_keys))
51
54
  end
52
55
  end
53
56
  end
@@ -8,6 +8,7 @@ module Rundock
8
8
  attr_accessor :colored
9
9
  attr_accessor :indent_depth
10
10
  attr_accessor :color
11
+ attr_accessor :show_header
11
12
 
12
13
  def initialize(*args)
13
14
  super
@@ -15,7 +16,12 @@ module Rundock
15
16
  end
16
17
 
17
18
  def call(severity, datetime, progname, msg)
18
- out = "[%5s:] %s%s\n" % [severity, ' ' * 2 * indent_depth, msg2str(msg)]
19
+ if @show_header
20
+ out = "[\%5s:] %s%s\n" % [severity, ' ' * 2 * indent_depth, msg2str(msg)]
21
+ else
22
+ out = "%s\n" % [msg2str(msg)]
23
+ end
24
+
19
25
  if colored
20
26
  colorize(out, severity)
21
27
  else
data/lib/rundock/node.rb CHANGED
@@ -18,6 +18,10 @@ module Rundock
18
18
 
19
19
  def run
20
20
  Logger.debug("run name: #{@name}")
21
+ if @operations.blank?
22
+ Logger.warn("no operation running: #{@name}")
23
+ return
24
+ end
21
25
  @operations.each do |ope|
22
26
  Logger.debug("operation type: #{ope.class}")
23
27
  ope.run(@backend, ope.attributes)
@@ -3,6 +3,11 @@ module Rundock
3
3
  class Command < Base
4
4
  def run(backend, attributes = {})
5
5
  @instruction.each do |i|
6
+ if i.is_a?(Hash)
7
+ attributes.merge!(i)
8
+ next
9
+ end
10
+
6
11
  backend.run_commands(i, attributes)
7
12
  end
8
13
  end
@@ -3,12 +3,15 @@ module Rundock
3
3
  class Task < Base
4
4
  def run(backend, attributes = {})
5
5
  @instruction.each do |i|
6
- unless attributes.key?(i)
7
- Logger.warn("[WARN]task not found and ignored: #{i}")
6
+ unless attributes[:task].key?(i.to_sym)
7
+ Logger.warn("task not found and ignored: #{i}")
8
8
  next
9
9
  end
10
10
 
11
- backend.run_commands(attributes[i])
11
+ scenario = Rundock::Builder::ScenarioBuilder.new(nil, nil).build_task(
12
+ attributes[:task][i.to_sym], backend, attributes)
13
+
14
+ scenario.run
12
15
  end
13
16
  end
14
17
  end
@@ -7,7 +7,7 @@ module Rundock
7
7
 
8
8
  class << self
9
9
  def run(options)
10
- Logger.info 'Starting Rundoc:'
10
+ Logger.debug 'Starting Rundoc:'
11
11
 
12
12
  runner = self.new(options)
13
13
  runner.build(options)
@@ -25,24 +25,28 @@ module Rundock
25
25
  @scenario.run
26
26
  end
27
27
 
28
+ def run_tasks
29
+ @scenario.run
30
+ end
31
+
28
32
  def build(options)
29
- if options['scenario_yaml'] || options['hostgroup_yaml']
30
- if options['scenario_yaml'] && !FileTest.exist?(options['scenario_yaml'])
31
- raise ScenarioNotFoundError, "'#{options['scenario_yaml']}' scenario file is not found."
32
- elsif options['hostgroup_yaml'] && !FileTest.exist?(options['hostgroup_yaml'])
33
- raise ScenarioNotFoundError, "'#{options['hostgroup_yaml']}' hostgroup file is not found."
33
+ if options[:scenario] || options[:hostgroup]
34
+ if options[:scenario] && !FileTest.exist?(options[:scenario])
35
+ raise ScenarioNotFoundError, "'#{options[:scenario]}' scenario file is not found."
36
+ elsif options[:hostgroup] && !FileTest.exist?(options[:hostgroup])
37
+ raise ScenarioNotFoundError, "'#{options[:hostgroup]}' hostgroup file is not found."
34
38
  end
35
39
 
36
- options['scenario_yaml'] = options['hostgroup_yaml'] if options['hostgroup_yaml']
40
+ options[:scenario] = options[:hostgroup] if options[:hostgroup]
37
41
 
38
42
  # parse scenario
39
- if options['scenario_yaml'] =~ %r{^(http|https)://}
43
+ if options[:scenario] =~ %r{^(http|https)://}
40
44
  # read from http/https
41
- open(options['scenario_yaml']) do |f|
45
+ open(options[:scenario]) do |f|
42
46
  @scenario = Rundock::Builder::ScenarioBuilder.new(options, f).build
43
47
  end
44
48
  else
45
- File.open(options['scenario_yaml']) do |f|
49
+ File.open(options[:scenario]) do |f|
46
50
  @scenario = Rundock::Builder::ScenarioBuilder.new(options, f).build
47
51
  end
48
52
  end
@@ -1,7 +1,15 @@
1
1
  module Rundock
2
- class Scenario < Array
2
+ class Scenario
3
+ attr_accessor :nodes
4
+ attr_accessor :node_info
5
+ attr_accessor :tasks
6
+
7
+ def initialize
8
+ @nodes = []
9
+ end
10
+
3
11
  def run
4
- self.each(&:run)
12
+ @nodes.each(&:run)
5
13
  end
6
14
  end
7
15
  end
@@ -1,3 +1,3 @@
1
1
  module Rundock
2
- VERSION = '0.2.0'
2
+ VERSION = '0.2.2'
3
3
  end
data/lib/rundock.rb CHANGED
@@ -12,6 +12,7 @@ require 'rundock/backend'
12
12
  require 'rundock/builder/base'
13
13
  require 'rundock/builder/default_ssh_builder'
14
14
  require 'rundock/builder/backend_builder'
15
+ require 'rundock/builder/operation_builder'
15
16
  require 'rundock/builder/scenario_builder'
16
17
  require 'rundock/runner'
17
18
  require 'rundock/cli'
data/rundock.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ['hiracy']
10
10
  spec.email = ['leizhen@mbr.nifty.com']
11
11
 
12
- spec.summary = 'Simple Execution framework for various servers'
12
+ spec.summary = 'Simple and extensible server operation framework'
13
13
  spec.homepage = 'https://github.com/hiracy/rundock'
14
14
  spec.license = 'MIT'
15
15
 
data/scenario_sample.yml CHANGED
@@ -38,16 +38,26 @@
38
38
  task:
39
39
  - echo_platform
40
40
  - echo_users
41
+ command:
42
+ - errexit: true
43
+ - "rm /tmp/riskyfile"
44
+ - errexit: false
45
+ - "rm /tmp/safetyfile"
46
+ - "ls -1 /tmp"
41
47
  ---
42
- anyhost-01:
48
+ - anyhost-01:
43
49
  host: 192.168.1.11
44
50
  ssh_opts:
45
51
  port: 22
46
52
  user: anyuser
53
+ - anyhost-02:
54
+ host: 192.168.1.12
47
55
  ---
48
56
  echo_platform:
49
- - "hostname"
50
- - "uname -a"
57
+ command:
58
+ - "hostname"
59
+ - "uname -a"
51
60
  echo_users:
52
- - "whoami"
53
- - "w"
61
+ command:
62
+ - "whoami"
63
+ - "w"
@@ -4,7 +4,7 @@
4
4
  - node: anyhost-01
5
5
  ---
6
6
  anyhost-01:
7
- host: 127.0.0.1
7
+ host: 172.17.42.1
8
8
  ssh_opts:
9
9
  port: 22222
10
10
  user: tester
@@ -6,6 +6,7 @@ PROJECT_NAME=rundock_spec
6
6
  PLATFORM_NAME=centos6
7
7
  PLATFORM_DIR="${PROJECT_ROOT}/platforms/${PLATFORM_NAME}"
8
8
  DOCKER_IMAGE_NAME="${PROJECT_NAME}/${PLATFORM_NAME}"
9
+ DOCKER_ADDRESS="172.17.42.1"
9
10
  DOCKER_CACHE_DIR="${HOME}/docker"
10
11
  DOCKER_CACHE_IMAGE_PATH="${DOCKER_CACHE_DIR}/${PLATFORM_NAME}.tar"
11
12
  DOCKER_SSH_PORT=22222
@@ -15,12 +16,17 @@ DOCKER_SSH_KEY_PUBLIC_LOCAL="${HOME}/.ssh/id_rsa_${PROJECT_NAME}_${PLATFORM_NAME
15
16
  DOCKER_SSH_KEY_PUBLIC_REMOTE="${PLATFORM_DIR}/authorized_keys"
16
17
  DOCKER_SSH_CONFIG="${HOME}/.ssh/config_${PROJECT_NAME}_${PLATFORM_NAME}"
17
18
  RUNDOCK_SCENARIO_DIR="${PROJECT_ROOT}/scenarios"
19
+ RUNDOCK_GROUP_DIR="${PROJECT_ROOT}/groups"
18
20
  RUNDOCK_CACHE_DIR="${HOME}/.rundock/${PLATFORM_NAME}"
19
21
  RUNDOCK_DEFAULT_SSH_YML="${RUNDOCK_CACHE_DIR}/integration_default_ssh.yml"
20
22
  RUNDOCK_SCENARIO_CACHE_DIR="${RUNDOCK_CACHE_DIR}/scenarios"
23
+ RUNDOCK_GROUP_CACHE_DIR="${RUNDOCK_CACHE_DIR}/groups"
21
24
 
22
25
  if [ "${1}x" = "--cleanx" ];then
23
26
  if sudo docker ps | grep "${DOCKER_IMAGE_NAME}" > /dev/null; then
27
+ rm -f "/var/tmp/hello_rundock*"
28
+ rm -f "${RUNDOCK_SCENARIO_CACHE_DIR}/*.yml"
29
+ rm -f "${RUNDOCK_GROUP_CACHE_DIR}/*.yml"
24
30
  rm -f "${DOCKER_CACHE_IMAGE_PATH}"
25
31
  rm -f "${DOCKER_SSH_KEY_PRIVATE}"
26
32
  rm -f "${DOCKER_SSH_KEY_PUBLIC_LOCAL}"
@@ -34,6 +40,7 @@ if [ "${1}x" = "--cleanx" ];then
34
40
  fi
35
41
 
36
42
  mkdir -p "${RUNDOCK_SCENARIO_CACHE_DIR}"
43
+ mkdir -p "${RUNDOCK_GROUP_CACHE_DIR}"
37
44
 
38
45
  if [ ! -f ${RUNDOCK_DEFAULT_SSH_YML} ]; then
39
46
  (
@@ -47,8 +54,11 @@ EOP
47
54
  fi
48
55
 
49
56
  cp ${RUNDOCK_SCENARIO_DIR}/* ${RUNDOCK_SCENARIO_CACHE_DIR}
57
+ cp ${RUNDOCK_GROUP_DIR}/* ${RUNDOCK_GROUP_CACHE_DIR}
50
58
 
51
- find ${RUNDOCK_SCENARIO_CACHE_DIR} -type f -name "*_scenario.yml" -or -name "*_group.yml" | \
59
+ find ${RUNDOCK_SCENARIO_CACHE_DIR} -type f -name "*_scenario.yml" | \
60
+ xargs sed -i -e "s#<replaced_by_platforms>#${DOCKER_SSH_KEY_PRIVATE}#g"
61
+ find ${RUNDOCK_GROUP_CACHE_DIR} -type f -name "*_group.yml" | \
52
62
  xargs sed -i -e "s#<replaced_by_platforms>#${DOCKER_SSH_KEY_PRIVATE}#g"
53
63
 
54
64
  sudo docker ps | grep "${DOCKER_IMAGE_NAME}" && { echo "docker image is already standing."; exit 0; }
@@ -68,10 +78,10 @@ sudo docker build -t "${DOCKER_IMAGE_NAME}" ${PLATFORM_DIR}
68
78
  rm -f ${DOCKER_SSH_KEY_PUBLIC_REMOTE}
69
79
  mkdir -p ${DOCKER_CACHE_DIR}
70
80
  sudo docker save "${DOCKER_IMAGE_NAME}" > ${DOCKER_CACHE_IMAGE_PATH}
71
- sudo docker run -d --privileged -p ${DOCKER_SSH_PORT}:22 "${DOCKER_IMAGE_NAME}"
81
+ sudo docker run -d --privileged -p ${DOCKER_ADDRESS}:${DOCKER_SSH_PORT}:22 "${DOCKER_IMAGE_NAME}"
72
82
 
73
83
  echo "Host ${PLATFORM_NAME}" > $DOCKER_SSH_CONFIG
74
- echo " HostName 127.0.0.1" >> $DOCKER_SSH_CONFIG
84
+ echo " HostName ${DOCKER_ADDRESS}" >> $DOCKER_SSH_CONFIG
75
85
  echo " User ${DOCKER_SSH_USER}" >> $DOCKER_SSH_CONFIG
76
86
  echo " Port ${DOCKER_SSH_PORT}" >> $DOCKER_SSH_CONFIG
77
87
  echo " IdentityFile ${DOCKER_SSH_KEY_PRIVATE}" >> $DOCKER_SSH_CONFIG
@@ -0,0 +1,14 @@
1
+ - node: localhost
2
+ command:
3
+ - errexit: false
4
+ - "rm /noexistdir/noexistfile1"
5
+ - "rm /noexistdir/noexistfile2"
6
+ task:
7
+ - err_task
8
+ ---
9
+ ---
10
+ err_task:
11
+ command:
12
+ - "uname -a"
13
+ - errexit: false
14
+ - "rm /noexistdir/noexistfile2"
@@ -6,4 +6,5 @@
6
6
  ---
7
7
  ---
8
8
  write_echo:
9
- - "echo 'Hello Rundock from Scenario.' > /var/tmp/hello_rundock_from_scenario"
9
+ command:
10
+ - "echo 'Hello Rundock from Scenario.' > /var/tmp/hello_rundock_from_scenario"
@@ -14,20 +14,22 @@
14
14
  - write_echo
15
15
  ---
16
16
  anyhost-01:
17
- host: 127.0.0.1
17
+ host: 172.17.42.1
18
18
  ssh_opts:
19
19
  port: 22222
20
20
  user: tester
21
21
  key: "<replaced_by_platforms>"
22
22
  anyhost-02:
23
- host: "127.0.0.1"
23
+ host: "172.17.42.1"
24
24
  ssh_opts:
25
25
  port: 22222
26
26
  user: tester
27
27
  keys: ["<replaced_by_platforms>"]
28
28
  ---
29
29
  echo_platform:
30
- - "hostname"
31
- - "uname -a"
30
+ command:
31
+ - "hostname"
32
+ - "uname -a"
32
33
  write_echo:
33
- - "echo 'Hello Rundock from Scenario.' > /var/tmp/hello_rundock_from_scenario"
34
+ command:
35
+ - "echo 'Hello Rundock from Scenario.' > /var/tmp/hello_rundock_from_scenario"
@@ -9,6 +9,7 @@ if ENV['TARGET_HOST'] != 'localhost'
9
9
  options = Net::SSH::Config.for(host, ["#{ENV['HOME']}/.ssh/config_rundock_spec_#{ENV['TARGET_HOST']}"])
10
10
 
11
11
  options[:user] ||= Etc.getlogin
12
+ options[:paranoid] = false
12
13
 
13
14
  set :host, options[:host_name] || host
14
15
  set :ssh_options, options
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rundock
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - hiracy
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-07-14 00:00:00.000000000 Z
11
+ date: 2015-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -155,6 +155,7 @@ files:
155
155
  - lib/rundock/builder/backend_builder.rb
156
156
  - lib/rundock/builder/base.rb
157
157
  - lib/rundock/builder/default_ssh_builder.rb
158
+ - lib/rundock/builder/operation_builder.rb
158
159
  - lib/rundock/builder/scenario_builder.rb
159
160
  - lib/rundock/cli.rb
160
161
  - lib/rundock/ext/hash.rb
@@ -170,14 +171,15 @@ files:
170
171
  - lib/rundock/version.rb
171
172
  - rundock.gemspec
172
173
  - scenario_sample.yml
174
+ - spec/integration/groups/simple_host_group.yml
173
175
  - spec/integration/platforms/centos6/Dockerfile
174
176
  - spec/integration/platforms/centos6/setup.sh
177
+ - spec/integration/platforms/localhost/scenarios/run_anyway_scenario.yml
175
178
  - spec/integration/platforms/localhost/scenarios/simple_echo_scenario.yml
176
179
  - spec/integration/platforms/localhost/scenarios/use_default_ssh_scenario.yml
177
180
  - spec/integration/recipes/simple_echo_scenario_spec.rb
178
181
  - spec/integration/recipes/simple_echo_spec.rb
179
182
  - spec/integration/scenarios/simple_echo_scenario.yml
180
- - spec/integration/scenarios/simple_host_group.yml
181
183
  - spec/integration/scenarios/use_default_ssh_scenario.yml
182
184
  - spec/integration/spec_helper.rb
183
185
  homepage: https://github.com/hiracy/rundock
@@ -203,5 +205,5 @@ rubyforge_project:
203
205
  rubygems_version: 2.4.5
204
206
  signing_key:
205
207
  specification_version: 4
206
- summary: Simple Execution framework for various servers
208
+ summary: Simple and extensible server operation framework
207
209
  test_files: []