larrow-runner 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/larrow/runner.rb CHANGED
@@ -1,5 +1,5 @@
1
- require 'active_support/deprecation'
2
1
  require 'active_support/core_ext/hash'
2
+ require 'active_support/core_ext/string'
3
3
 
4
4
  require "larrow/runner/version"
5
5
  require 'larrow/runner/logger'
@@ -18,8 +18,8 @@ module Larrow
18
18
  end
19
19
  # global options
20
20
  RunOption = {}.with_indifferent_access
21
- # cloud wrapper
22
- Cloud = Session.load_cloud
21
+ # default resource file path
22
+ ResourcePath = '.larrow.resource'
23
23
  end
24
24
  end
25
25
 
@@ -8,7 +8,11 @@ You can save it as .larrow.yml on the project root folder.
8
8
  EOF
9
9
  def dump url
10
10
  vcs = Vcs.detect url
11
- configuration = vcs.configuration false
11
+ configuration = Manifest.configuration(
12
+ vcs,
13
+ ignore_base_scripts: true,
14
+ ignore_larrow: true
15
+ )
12
16
  puts configuration.dump
13
17
  end
14
18
 
@@ -1 +1,2 @@
1
- ExecutionError = Class.new StandardError
1
+ ExecutionError = Class.new StandardError
2
+ InvalidConfigFile = Class.new StandardError
@@ -7,7 +7,7 @@ module Larrow::Runner
7
7
  # logger.level(3).title 'hello'
8
8
  # logger.level(3).detail 'hello'
9
9
  class Logger
10
- def initialize logger, level:nil, color:'magenta'
10
+ def initialize logger, level:nil, color:'green'
11
11
  @inner_logger = if logger.is_a? ::Logger
12
12
  logger
13
13
  else
@@ -44,7 +44,7 @@ module Larrow::Runner
44
44
  end
45
45
 
46
46
  def detail msg
47
- color('green').info msg
47
+ color('magenta').info msg
48
48
  end
49
49
 
50
50
  def err msg
@@ -45,6 +45,11 @@ module Larrow::Runner
45
45
 
46
46
  def handle_exception
47
47
  yield
48
+ rescue InvalidConfigFile => e
49
+ data = eval(e.message)
50
+ url = "https://github.com/fsword/larrow-runner/wiki/#{data[:wiki]}"
51
+ RunLogger.err "invalid config file: #{data[:file]}"
52
+ RunLogger.level(1).err "see: #{url}"
48
53
  rescue => e
49
54
  RunOption[:keep] = true if e.is_a?(ExecutionError)
50
55
  if e.is_a?(ExecutionError) && !debug?
@@ -88,7 +93,7 @@ module Larrow::Runner
88
93
 
89
94
  def self.resource
90
95
  resource_iterator do |clazz, array|
91
- RunLogger.detail clazz.name.split("::").last
96
+ RunLogger.info clazz.name.split("::").last
92
97
  clazz.show array, 1
93
98
  end
94
99
  end
@@ -101,14 +106,16 @@ module Larrow::Runner
101
106
  end
102
107
 
103
108
  def self.resource_iterator
104
- resource = YAML.load(File.read '.larrow.resource') rescue nil
105
- return if resource.nil?
109
+ RunLogger.title "load resource from #{ResourcePath}"
110
+ resource = YAML.load(File.read ResourcePath) rescue {}
111
+
106
112
  resource.each_pair do |k,array|
107
113
  case k
108
114
  when :nodes
109
115
  yield Model::Node, array
110
116
  end
111
117
  end
118
+ RunLogger.detail "no resource on the file" if resource.empty?
112
119
  end
113
120
  end
114
121
  end
@@ -13,11 +13,22 @@ module Larrow
13
13
 
14
14
  extend self
15
15
 
16
- def configuration source_accessor
17
- [ Larrow, Travis, Blank ].each do |clazz|
18
- configuration = clazz.new(source_accessor).load
19
- return configuration if configuration
16
+ # options:
17
+ # :ignore_larrow : do not try to use larrow adapter
18
+ # :ignore_base_scripts : do not merge base scripts
19
+ def configuration source_accessor, options={}
20
+ adapters = [Travis, Blank]
21
+ adapters.unshift Larrow unless options[:ignore_larrow]
22
+
23
+ configuration = adapters.each do |clazz|
24
+ c = clazz.new(source_accessor).load
25
+ break c if c
26
+ end
27
+
28
+ unless options[:ignore_base_scripts]
29
+ add_base_scripts(configuration, source_accessor)
20
30
  end
31
+ configuration
21
32
  end
22
33
 
23
34
  def add_base_scripts configuration,source_accessor
@@ -1,31 +1,33 @@
1
- module Larrow::Runner::Manifest
2
- class Larrow < BaseLoader
3
- def config_file
4
- source_accessor.larrow_file || '.larrow.yml'
5
- end
6
-
7
- # TODO manifest validation
8
- def parse content
9
- data = YAML.load(content).with_indifferent_access
10
- if data.is_a? Array # stages as a Array
11
- # TODO
12
- elsif data.is_a? Hash # steps as a Hash
13
- configuration.image = data[:image]
14
- Configuration::DEFINED_GROUPS[:custom].each do |title|
15
- v = data[title]
16
- build_step title,v if v
1
+ module Larrow::Runner
2
+ module Manifest
3
+ class Larrow < BaseLoader
4
+ def config_file
5
+ source_accessor.larrow_file || '.larrow.yml'
6
+ end
7
+
8
+ # TODO manifest validation
9
+ def parse content
10
+ data = YAML.load(content).with_indifferent_access
11
+ if data.is_a? Array # stages as a Array
12
+ # TODO
13
+ elsif data.is_a? Hash # steps as a Hash
14
+ configuration.image = data[:image]
15
+ Configuration::DEFINED_GROUPS[:custom].each do |title|
16
+ v = data[title]
17
+ build_step title,v if v
18
+ end
17
19
  end
18
20
  end
19
- end
20
-
21
- def build_step title, lines
22
- source_dir = if title == :init
23
- nil
24
- else
25
- configuration.source_dir
26
- end
27
- scripts = lines.map{|s| Script.new s, base_dir: source_dir}
28
- configuration.put_to_step title, scripts
21
+
22
+ def build_step title, lines
23
+ source_dir = if title == :init
24
+ nil
25
+ else
26
+ configuration.source_dir
27
+ end
28
+ scripts = lines.map{|s| Script.new s, base_dir: source_dir}
29
+ configuration.put_to_step title, scripts
30
+ end
29
31
  end
30
32
  end
31
33
  end
@@ -1,43 +1,44 @@
1
1
  require 'yaml'
2
2
 
3
- module Larrow::Runner::Manifest
4
- class Travis < BaseLoader
5
- CONFIG_FILE='.travis.yml'
6
- attr_accessor :data
7
-
8
- def parse content
9
- self.data = YAML.load(content).with_indifferent_access
10
- build_language
11
- map_step :prepare, :before_script
12
- map_step :functional_test, :script
13
- end
14
-
15
- def map_step title, travis_title
16
- source_dir = configuration.source_dir
17
- scripts = (data[travis_title] || []).map do |cmd|
18
- Script.new cmd, base_dir: source_dir
3
+ module Larrow::Runner
4
+ module Manifest
5
+ class Travis < BaseLoader
6
+ CONFIG_FILE='.travis.yml'
7
+ attr_accessor :data
8
+
9
+ def parse content
10
+ self.data = YAML.load(content).with_indifferent_access
11
+ build_language
12
+ map_step :prepare, :before_script
13
+ map_step :functional_test, :script
14
+ end
15
+
16
+ def map_step title, travis_title
17
+ source_dir = configuration.source_dir
18
+ scripts = (data[travis_title] || []).map do |cmd|
19
+ Script.new cmd, base_dir: source_dir
20
+ end
21
+ return nil if scripts.empty?
22
+
23
+ configuration.put_to_step title, scripts
24
+ end
25
+
26
+ def build_language
27
+ return if data[:language].nil?
28
+ clazz = eval data[:language].camelize
29
+ clazz.fulfill(data,configuration)
19
30
  end
20
- return nil if scripts.empty?
21
-
22
- configuration.put_to_step title, scripts
23
- end
24
-
25
- def build_language
26
- return if data[:language].nil?
27
- clazz = eval data[:language].camelize
28
- clazz.fulfill(data,configuration)
29
31
  end
30
- end
31
- class Erlang
32
- TEMPLATE_PATH='/opt/install/erlang/%s'
33
- def self.fulfill data, configuration
34
- revision = case data[:otp_release].last
35
- when /R15/ then 'R15B03'
36
- when /R16/ then 'R16B03'
37
- when /17/ then '17.1'
38
- end rescue '17'
39
- install_dir = sprintf(TEMPLATE_PATH,revision.downcase)
40
- lines = <<-EOF
32
+ class Erlang
33
+ TEMPLATE_PATH='/opt/install/erlang/%s'
34
+ def self.fulfill data, configuration
35
+ revision = case data[:otp_release].last
36
+ when /R15/ then 'R15B03'
37
+ when /R16/ then 'R16B03'
38
+ when /17/ then '17.1'
39
+ end rescue '17'
40
+ install_dir = sprintf(TEMPLATE_PATH,revision.downcase)
41
+ lines = <<-EOF
41
42
  echo '-s' >> .curlrc
42
43
  curl https://raw.githubusercontent.com/spawngrid/kerl/master/kerl -o /usr/local/bin/kerl
43
44
  chmod a+x /usr/local/bin/kerl
@@ -45,29 +46,29 @@ kerl update releases
45
46
  kerl build #{revision} #{revision}
46
47
  kerl install #{revision} #{install_dir}
47
48
  echo 'source #{install_dir}/activate' >> $HOME/.bashrc
48
- EOF
49
- lines.split(/\n/).each do |line|
50
- s = Script.new line
51
- configuration.put_to_step :init, s
49
+ EOF
50
+ lines.split(/\n/).each do |line|
51
+ s = Script.new line
52
+ configuration.put_to_step :init, s
53
+ end
52
54
  end
53
55
  end
54
- end
55
-
56
- class Ruby
57
- def self.fulfill data, configuration
58
- return unless data[:rvm] # only rvm is supported for ruby
59
- version = data[:rvm].last
60
- lines = <<-EOF
56
+
57
+ class Ruby
58
+ def self.fulfill data, configuration
59
+ return unless data[:rvm] # only rvm is supported for ruby
60
+ version = data[:rvm].last
61
+ lines = <<-EOF
61
62
  echo '-s' >> .curlrc
62
63
  curl -sSL https://get.rvm.io | bash -s stable
63
64
  echo 'source /etc/profile.d/rvm.sh' >> .bashrc
64
65
  rvm install #{version}
65
- EOF
66
- lines.split(/\n/).each do |line|
67
- s = Script.new line
68
- configuration.put_to_step :init, s
66
+ EOF
67
+ lines.split(/\n/).each do |line|
68
+ s = Script.new line
69
+ configuration.put_to_step :init, s
70
+ end
69
71
  end
70
72
  end
71
73
  end
72
74
  end
73
-
@@ -1,21 +1,23 @@
1
- module Larrow::Runner::Manifest
2
- class BaseLoader
3
- attr_accessor :source_accessor,:configuration
4
- def initialize source_accessor
5
- self.source_accessor = source_accessor
6
- end
1
+ module Larrow::Runner
2
+ module Manifest
3
+ class BaseLoader
4
+ attr_accessor :source_accessor,:configuration
5
+ def initialize source_accessor
6
+ self.source_accessor = source_accessor
7
+ end
7
8
 
8
- def load
9
- content = source_accessor.get config_file
10
- return nil if content.nil?
9
+ def load
10
+ content = source_accessor.get config_file
11
+ return nil if content.nil?
11
12
 
12
- self.configuration = Configuration.new
13
- parse content
14
- self.configuration
15
- end
16
-
17
- def config_file
18
- self.class.const_get('CONFIG_FILE')
13
+ self.configuration = Configuration.new
14
+ parse content
15
+ self.configuration
16
+ end
17
+
18
+ def config_file
19
+ self.class.const_get('CONFIG_FILE')
20
+ end
19
21
  end
20
22
  end
21
23
  end
@@ -1,126 +1,128 @@
1
- module Larrow::Runner::Manifest
2
- # The top of manifest model which store Steps information
3
- class Configuration
4
- DEFINED_GROUPS = {
5
- all:[
6
- :init,
7
- :source_sync, #inner step
8
- :prepare,
9
- :compile, :unit_test,
10
- :before_install, #inner_step
11
- :install, :functional_test,
12
- :before_start, #inner_step
13
- :start, :integration_test,
14
- :after_start, :complete #inner_step
15
- ],
16
- custom: [
17
- :init,
18
- :prepare,
19
- :compile, :unit_test,
20
- :install, :functional_test,
21
- :start, :integration_test,
22
- ],
23
- deploy: [
24
- :init,:source_sync,:prepare,
25
- :compile,:before_install,:install,
26
- :before_start,:start,:after_start,
27
- :complete
28
- ],
29
- image: [:init]
30
- }
31
-
32
- attr_accessor :steps, :image, :source_dir
33
- def initialize
34
- self.steps = {}
35
- self.source_dir = '$HOME/source'
36
- end
37
-
38
- def put_to_step title, *scripts
39
- steps[title] ||= CmdStep.new(nil, title)
40
- steps[title].scripts += scripts.flatten
41
- self
42
- end
43
-
44
- def insert_to_step title, *scripts
45
- steps[title] ||= CmdStep.new(nil, title)
46
- steps[title].scripts.unshift *scripts.flatten
47
- self
48
- end
49
-
50
- def add_source_sync source_accessor
51
- steps[:source_sync] = FunctionStep.new(:source_sync) do |node|
52
- source_accessor.update_source node,source_dir
1
+ module Larrow::Runner
2
+ module Manifest
3
+ # The top of manifest model which store Steps information
4
+ class Configuration
5
+ DEFINED_GROUPS = {
6
+ all:[
7
+ :init,
8
+ :source_sync, #inner step
9
+ :prepare,
10
+ :compile, :unit_test,
11
+ :before_install, #inner_step
12
+ :install, :functional_test,
13
+ :before_start, #inner_step
14
+ :start, :integration_test,
15
+ :after_start, :complete #inner_step
16
+ ],
17
+ custom: [
18
+ :init,
19
+ :prepare,
20
+ :compile, :unit_test,
21
+ :install, :functional_test,
22
+ :start, :integration_test,
23
+ ],
24
+ deploy: [
25
+ :init,:source_sync,:prepare,
26
+ :compile,:before_install,:install,
27
+ :before_start,:start,:after_start,
28
+ :complete
29
+ ],
30
+ image: [:init]
31
+ }
32
+
33
+ attr_accessor :steps, :image, :source_dir
34
+ def initialize
35
+ self.steps = {}
36
+ self.source_dir = '$HOME/source'
53
37
  end
54
- end
55
-
56
- def steps_for type
57
- groups = DEFINED_GROUPS[type]
58
- # ignore init when image id is specified
59
- groups = groups - [:init] if image
60
- groups.each do |title|
61
- yield steps[title] if steps[title]
38
+
39
+ def put_to_step title, *scripts
40
+ steps[title] ||= CmdStep.new(nil, title)
41
+ steps[title].scripts += scripts.flatten
42
+ self
62
43
  end
63
- end
64
-
65
- def dump
66
- data = DEFINED_GROUPS[:all].reduce({}) do |sum,title|
67
- next sum if steps[title].nil?
68
- scripts_data = steps[title].scripts.map(&:dump).compact
69
- sum.update title.to_s => scripts_data
44
+
45
+ def insert_to_step title, *scripts
46
+ steps[title] ||= CmdStep.new(nil, title)
47
+ steps[title].scripts.unshift *scripts.flatten
48
+ self
70
49
  end
71
- YAML.dump data
72
- end
73
- end
74
-
75
- # Describe a set of scripts to accomplish a specific goal
76
- class CmdStep
77
- attr_accessor :scripts, :title
78
- def initialize scripts, title
79
- self.scripts = scripts || []
80
- self.title = title
81
- end
82
-
83
- def run_on node
84
- scripts.each do |script|
85
- node.execute script.actual_command, base_dir: script.base_dir
50
+
51
+ def add_source_sync source_accessor
52
+ steps[:source_sync] = FunctionStep.new(:source_sync) do |node|
53
+ source_accessor.update_source node,source_dir
54
+ end
55
+ end
56
+
57
+ def steps_for type
58
+ groups = DEFINED_GROUPS[type]
59
+ # ignore init when image id is specified
60
+ groups = groups - [:init] if image
61
+ groups.each do |title|
62
+ yield steps[title] if steps[title]
63
+ end
64
+ end
65
+
66
+ def dump
67
+ data = DEFINED_GROUPS[:all].reduce({}) do |sum,title|
68
+ next sum if steps[title].nil?
69
+ scripts_data = steps[title].scripts.map(&:dump).compact
70
+ sum.update title.to_s => scripts_data
71
+ end
72
+ YAML.dump data
86
73
  end
87
74
  end
88
- end
89
-
90
- # An abstract step which bind business logic with block
91
- # This class designed for some typically service,eg:
92
- # * local file folder sync
93
- # * some service invoke
94
- class FunctionStep
95
- attr_accessor :block, :title
96
- def initialize title, &block
97
- self.title = title
98
- self.block = block
99
- end
100
-
101
- def run_on node
102
- block.call node
103
- end
104
- end
105
-
106
- # store the real command line
107
- # :cannt_fail used to declare `non-zero retcode of current script will be fail`
108
- class Script
109
- attr_accessor :cmd, :base_dir, :args, :cannt_fail
110
- def initialize cmd, base_dir:nil, args:{}, cannt_fail: true
111
- self.cmd = cmd
112
- self.args = args
113
- self.cannt_fail = cannt_fail
114
- self.base_dir = base_dir
75
+
76
+ # Describe a set of scripts to accomplish a specific goal
77
+ class CmdStep
78
+ attr_accessor :scripts, :title
79
+ def initialize scripts, title
80
+ self.scripts = scripts || []
81
+ self.title = title
82
+ end
83
+
84
+ def run_on node
85
+ scripts.each do |script|
86
+ node.execute script.actual_command, base_dir: script.base_dir
87
+ end
88
+ end
115
89
  end
116
-
117
- def actual_command
118
- sprintf(cmd, args)
90
+
91
+ # An abstract step which bind business logic with block
92
+ # This class designed for some typically service,eg:
93
+ # * local file folder sync
94
+ # * some service invoke
95
+ class FunctionStep
96
+ attr_accessor :block, :title
97
+ def initialize title, &block
98
+ self.title = title
99
+ self.block = block
100
+ end
101
+
102
+ def run_on node
103
+ block.call node
104
+ end
119
105
  end
120
-
121
- def dump
122
- return nil if cmd.empty?
123
- cmd
106
+
107
+ # store the real command line
108
+ # :cannt_fail used to declare `non-zero retcode of current script will be fail`
109
+ class Script
110
+ attr_accessor :cmd, :base_dir, :args, :cannt_fail
111
+ def initialize cmd, base_dir:nil, args:{}, cannt_fail: true
112
+ self.cmd = cmd
113
+ self.args = args
114
+ self.cannt_fail = cannt_fail
115
+ self.base_dir = base_dir
116
+ end
117
+
118
+ def actual_command
119
+ sprintf(cmd, args)
120
+ end
121
+
122
+ def dump
123
+ return nil if cmd.empty?
124
+ cmd
125
+ end
124
126
  end
125
127
  end
126
128
  end