script_executor 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -100,4 +100,8 @@
100
100
 
101
101
  == Version 1.6.0
102
102
 
103
- * Upgrade net:ssh, small bug fix.
103
+ * Upgrade net:ssh, small bug fix.
104
+
105
+ == Version 1.7.0
106
+
107
+ * Replace simple parsing with parslet-based parsing.
data/Gemfile CHANGED
@@ -3,18 +3,20 @@ source "https://rubygems.org"
3
3
  group :default do
4
4
  gem "highline", "~>1.6"
5
5
  gem "net-ssh", "~>2.9"
6
- gem "text-interpolator", "~>1.0"
6
+ gem "text-interpolator", "~>1.1"
7
7
  gem "json_pure", "~>1.8"
8
+ gem "parslet"
9
+ gem 'thor'
8
10
  end
9
11
 
10
12
  group :development do
11
13
  gem "gemspec_deps_gen", "~>1.1"
12
14
  gem "gemcutter", "~>0.7"
15
+ gem 'awesome_print'
13
16
  end
14
17
 
15
18
  group :test do
16
- gem "rspec"
17
- gem "mocha"
19
+ gem "rspec", "~>3.0"
18
20
  end
19
21
 
20
22
  # group :debug do
data/Gemfile.lock CHANGED
@@ -1,7 +1,9 @@
1
1
  GEM
2
2
  remote: https://rubygems.org/
3
3
  specs:
4
- diff-lcs (1.1.3)
4
+ awesome_print (1.6.1)
5
+ blankslate (3.1.3)
6
+ diff-lcs (1.2.5)
5
7
  file_utils (1.0.7)
6
8
  gemcutter (0.7.1)
7
9
  gemspec_deps_gen (1.1.2)
@@ -9,32 +11,39 @@ GEM
9
11
  file_utils
10
12
  highline (1.6.15)
11
13
  json_pure (1.8.1)
12
- metaclass (0.0.1)
13
- mocha (0.13.1)
14
- metaclass (~> 0.0.1)
15
14
  net-ssh (2.9.2)
16
- rspec (2.12.0)
17
- rspec-core (~> 2.12.0)
18
- rspec-expectations (~> 2.12.0)
19
- rspec-mocks (~> 2.12.0)
20
- rspec-core (2.12.2)
21
- rspec-expectations (2.12.1)
22
- diff-lcs (~> 1.1.3)
23
- rspec-mocks (2.12.0)
24
- text-interpolator (1.0.0)
15
+ parslet (1.7.1)
16
+ blankslate (>= 2.0, <= 4.0)
17
+ rspec (3.3.0)
18
+ rspec-core (~> 3.3.0)
19
+ rspec-expectations (~> 3.3.0)
20
+ rspec-mocks (~> 3.3.0)
21
+ rspec-core (3.3.2)
22
+ rspec-support (~> 3.3.0)
23
+ rspec-expectations (3.3.1)
24
+ diff-lcs (>= 1.2.0, < 2.0)
25
+ rspec-support (~> 3.3.0)
26
+ rspec-mocks (3.3.2)
27
+ diff-lcs (>= 1.2.0, < 2.0)
28
+ rspec-support (~> 3.3.0)
29
+ rspec-support (3.3.0)
30
+ text-interpolator (1.1.6)
31
+ thor (0.19.1)
25
32
 
26
33
  PLATFORMS
27
34
  ruby
28
35
 
29
36
  DEPENDENCIES
37
+ awesome_print
30
38
  gemcutter (~> 0.7)
31
39
  gemspec_deps_gen (~> 1.1)
32
40
  highline (~> 1.6)
33
41
  json_pure (~> 1.8)
34
- mocha
35
42
  net-ssh (~> 2.9)
36
- rspec
37
- text-interpolator (~> 1.0)
43
+ parslet
44
+ rspec (~> 3.0)
45
+ text-interpolator (~> 1.1)
46
+ thor
38
47
 
39
48
  BUNDLED WITH
40
49
  1.10.6
@@ -42,7 +42,7 @@ class BaseProvision
42
42
  provision = self
43
43
 
44
44
  provision.script_list.each do |name, value|
45
- title = provision.script_title(value)
45
+ title = value[:comment]
46
46
 
47
47
  title = title.nil? ? name : title
48
48
 
@@ -73,7 +73,7 @@ class BaseProvision
73
73
  end
74
74
 
75
75
  def run server_info, script_name, params
76
- execute(server_info) { evaluate_script_body(script_list[script_name], params, :string) }
76
+ execute(server_info) { evaluate_script_body(script_list[script_name][:codeLines], params, :string) }
77
77
  end
78
78
 
79
79
  def run_command server_info, command
@@ -1,44 +1,45 @@
1
1
  require 'erb'
2
2
  require 'text_interpolator'
3
+ require 'script_executor/scripts_parser'
3
4
 
4
5
  module ScriptLocator
5
6
 
6
7
  def scripts file
7
8
  data = extract_data file
8
9
 
9
- locate_scripts(data)
10
+ scripts_parser = ScriptsParser.new
11
+
12
+ scripts_parser.parse data
10
13
  end
11
14
 
12
15
  def evaluate_script_body content, env, type=:erb
13
- case type
14
- when :erb
15
- template = ERB.new content
16
- template.result(env).strip
16
+ if content.class == Array
17
+ content.each_with_index do |el, index|
18
+ content[index] = evaluate_script_body el, env, type
19
+ end
20
+ else
21
+ case type
22
+ when :erb
23
+ template = ERB.new content
24
+ template.result(env).strip
17
25
 
18
- when :string
19
- interpolator = TextInterpolator.new
26
+ when :string
27
+ interpolator = TextInterpolator.new
20
28
 
21
- result = interpolator.interpolate content, env
29
+ result = interpolator.interpolate content, env
22
30
 
23
- puts interpolator.errors if interpolator.errors.size > 0
31
+ puts interpolator.errors if interpolator.errors.size > 0
24
32
 
25
- result
26
- else
27
- interpolator = TextInterpolator.new
33
+ result
34
+ else
35
+ interpolator = TextInterpolator.new
28
36
 
29
- result = interpolator.interpolate content, env
37
+ result = interpolator.interpolate content, env
30
38
 
31
- puts interpolator.errors if interpolator.errors.size > 0
39
+ puts interpolator.errors if interpolator.errors.size > 0
32
40
 
33
- result
34
- end
35
- end
36
-
37
- def script_title script
38
- if script[0] == '#'
39
- StringIO.new(script[1..-1]).readline.strip
40
- else
41
- nil
41
+ result
42
+ end
42
43
  end
43
44
  end
44
45
 
@@ -52,29 +53,4 @@ module ScriptLocator
52
53
  index.nil? ? content : content[index+9..-1]
53
54
  end
54
55
 
55
- def locate_scripts data
56
- scripts = {}
57
-
58
- current_key = nil
59
-
60
- stream = StringIO.new data
61
-
62
- stream.each_line do |line|
63
- if line =~ /^(\s)*\[[\w\d\s\-\_]*\](\s)*$/
64
- marker = line.strip.gsub(/\[[\w\d\s\-\_]*\]/).first
65
-
66
- if !marker.nil? and marker.strip.length > 0
67
- key = marker[1..marker.length-2]
68
-
69
- scripts[key] = ""
70
- current_key = key
71
- end
72
- else
73
- scripts[current_key] += line if current_key
74
- end
75
- end
76
-
77
- scripts
78
- end
79
-
80
56
  end
@@ -0,0 +1,44 @@
1
+ require 'parslet'
2
+
3
+ require 'script_executor/scripts_transformer'
4
+
5
+ class ScriptsParser < Parslet::Parser
6
+ root :language
7
+
8
+ # language
9
+ rule(:language) { (shebang.as(:shebang).maybe >> ignored.as(:ignored).maybe >> scripts.as(:scripts)).as(:language) }
10
+
11
+ rule(:shebang) { str('#') >> str('!') >> match['\w\d_/\s'].repeat(1) }
12
+ rule(:ignored) { comment.repeat }
13
+ rule(:scripts) { script.repeat }
14
+
15
+ rule(:script) { emptyLines >> (name >> comment.maybe >> codeLines).as(:script) }
16
+ rule(:comment) { emptyLines >> spaces >> (str('#') >> spaces >> (newline.absent? >> any).repeat.as(:comment)) >> newline }
17
+ rule(:name) { spaces >> str('[') >> spaces >> spaces >> nameChars.as(:name) >> spaces >> str(']') >> spaces >> newline }
18
+
19
+ rule(:codeLines) { (emptyLines >> codeLine.repeat.maybe >> emptyLines).as(:codeLines) }
20
+ rule(:codeLine) { emptyLines >> codeChars.as(:codeLine) >> newline }
21
+
22
+ rule(:nameChars) { match['\w\d_'].repeat(1) }
23
+ rule(:codeChars) { match['(.*)\w\d $_#"<>{}\'\/\.%=!\-+/\*|:'].repeat(1) }
24
+
25
+ rule(:emptyLines) { emptyLine.repeat }
26
+ rule(:emptyLine) { spaces >> newline }
27
+ rule(:newline) { str("\n") >> str("\r").maybe }
28
+
29
+ rule(:spaces) { str(' ').repeat }
30
+
31
+ def parse content
32
+ begin
33
+ parsed_content = super content + "\n"
34
+
35
+ # ap parsed_content
36
+
37
+ transformer = ScriptsTransformer.new
38
+
39
+ transformer.apply(parsed_content)[:scripts]
40
+ rescue Parslet::ParseFailed => failure
41
+ puts failure.cause.ascii_tree
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,25 @@
1
+ require 'parslet'
2
+
3
+ class ScriptsTransformer < Parslet::Transform
4
+ rule(:language => subtree(:language)) do
5
+ language.delete(:ignored)
6
+
7
+ new_scripts = {}
8
+
9
+ language[:scripts].each do |script|
10
+ name = script[:script][:name].to_sym
11
+ comment = script[:script][:comment].to_s
12
+ code_lines = script[:script][:codeLines]
13
+
14
+ code_lines.each_with_index do |codeLine, index|
15
+ code_lines[index] = codeLine[:codeLine].to_s
16
+ end
17
+
18
+ new_scripts[name] = {comment: comment, codeLines: code_lines}
19
+ end
20
+
21
+ language[:scripts] = new_scripts
22
+
23
+ language
24
+ end
25
+ end
@@ -1,3 +1,3 @@
1
1
  class ScriptExecutor
2
- VERSION = "1.6.0"
2
+ VERSION = "1.7.0"
3
3
  end
@@ -19,10 +19,13 @@ Gem::Specification.new do |spec|
19
19
 
20
20
  spec.add_runtime_dependency "highline", ["~> 1.6"]
21
21
  spec.add_runtime_dependency "net-ssh", ["~> 2.9"]
22
- spec.add_runtime_dependency "text-interpolator", ["~> 1.0"]
22
+ spec.add_runtime_dependency "text-interpolator", ["~> 1.1"]
23
23
  spec.add_runtime_dependency "json_pure", ["~> 1.8"]
24
+ spec.add_runtime_dependency "parslet", [">= 0"]
25
+ spec.add_runtime_dependency "thor", [">= 0"]
24
26
  spec.add_development_dependency "gemspec_deps_gen", ["~> 1.1"]
25
27
  spec.add_development_dependency "gemcutter", ["~> 0.7"]
28
+ spec.add_development_dependency "awesome_print", [">= 0"]
26
29
 
27
30
  end
28
31
 
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ require 'thor'
4
+ require 'script_executor/base_provision'
5
+
6
+ class ThorClass < Thor
7
+
8
+ end
9
+
10
+ describe BaseProvision do
11
+ describe "#parse" do
12
+ it "parses content from file" do
13
+ provision = BaseProvision.new ThorClass, 'spec/support/base.conf.json', ['spec/support/big_script.sh']
14
+
15
+ ap provision.script_list
16
+ end
17
+ end
18
+ end
@@ -1,14 +1,10 @@
1
- require File.expand_path('spec_helper', File.dirname(__FILE__))
1
+ require 'spec_helper'
2
+ require 'rspec/mocks'
2
3
 
3
4
  require 'executable'
4
5
 
5
- class MyExecutable
6
- include Executable
7
- end
8
-
9
- describe MyExecutable do
10
-
11
- subject { MyExecutable.new }
6
+ describe Executable do
7
+ subject { Object.new.extend Executable }
12
8
 
13
9
  before :all do
14
10
  @password ||= HighLine.new.ask("Enter password for #{ENV['USER']}: ") { |q| q.echo = '*' }
@@ -114,6 +110,8 @@ describe MyExecutable do
114
110
  end
115
111
 
116
112
  it "should execute commands from :script parameter" do
113
+ expect_any_instance_of(RemoteCommand).to receive(:execute).and_return 'vagrant'
114
+
117
115
  result = subject.execute @remote_info.merge(:script => "whoami")
118
116
 
119
117
  expect(result).to eq "vagrant"
@@ -1,14 +1,10 @@
1
- require File.expand_path('spec_helper', File.dirname(__FILE__))
1
+ require 'spec_helper'
2
2
 
3
3
  require 'script_locator'
4
4
 
5
- class MyScriptLocator
6
- include ScriptLocator
7
- end
8
-
9
- describe MyScriptLocator do
5
+ describe ScriptLocator do
10
6
 
11
- subject { MyScriptLocator.new }
7
+ subject { Object.new.extend ScriptLocator }
12
8
 
13
9
  describe "#scripts" do
14
10
  it "reads after __END__" do
@@ -20,7 +16,7 @@ describe MyScriptLocator do
20
16
  end
21
17
 
22
18
  it "reads from file completely if it does not have __END__ tag" do
23
- file = File.expand_path('test.conf', File.dirname(__FILE__))
19
+ file = File.expand_path('support/test.conf', File.dirname(__FILE__))
24
20
 
25
21
  scripts = subject.scripts(file)
26
22
 
@@ -34,22 +30,23 @@ describe MyScriptLocator do
34
30
 
35
31
  name = "alisa"
36
32
 
37
- result = subject.evaluate_script_body(scripts['test1'], binding)
33
+ result = subject.evaluate_script_body(scripts[:test1][:codeLines], binding)
34
+
35
+ expect(result.first).to match /#{name}/
38
36
 
39
- expect(result).to match /#{name}/
40
- expect(subject.script_title(scripts['test1'])).to eq "Some description"
37
+ expect(scripts[:test1][:comment]).to eq "Some description"
41
38
  end
42
39
 
43
40
  it "locates script inside external file and evaluates it as string" do
44
- file = File.expand_path('test.conf', File.dirname(__FILE__))
41
+ file = File.expand_path('support/test.conf', File.dirname(__FILE__))
45
42
 
46
43
  scripts = subject.scripts(file)
47
44
 
48
45
  env = {:name => "alisa"}
49
46
 
50
- result = subject.evaluate_script_body(scripts['test1'], env, :string)
47
+ result = subject.evaluate_script_body(scripts[:test1][:codeLines], env, :string)
51
48
 
52
- expect(result).to match /#{env[:name]}/
49
+ expect(result.first).to match /#{env[:name]}/
53
50
  end
54
51
  end
55
52
 
@@ -64,4 +61,4 @@ echo "<%= name %>"
64
61
 
65
62
  [test2]
66
63
 
67
- echo "test2"
64
+ echo "test2"
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ require 'script_executor/scripts_parser'
4
+ require 'script_executor/scripts_transformer'
5
+
6
+ describe ScriptsParser do
7
+ describe "#parse" do
8
+ it "parses content from file" do
9
+ content = File.read('spec/support/big_script.sh')
10
+ #content = File.read('spec/support/test.conf')
11
+
12
+ parsed_content = subject.parse(content)
13
+
14
+ ap parsed_content
15
+ end
16
+ end
17
+ end
data/spec/spec_helper.rb CHANGED
@@ -1 +1,2 @@
1
- $: << File.expand_path('../lib', File.dirname(__FILE__))
1
+ require 'bundler/setup'
2
+ require 'ap'
@@ -0,0 +1,16 @@
1
+ {
2
+ "node": {
3
+ "domain": "22.22.22.22", // remote host, see "config.vm.synced_folder"
4
+ "port": "22", // default ssh port
5
+ "user": "vagrant", // vagrant user name
6
+ "password": "vagrant", // vagrant user password
7
+ "home": "/home/vagrant",
8
+ "remote": true
9
+ },
10
+
11
+ "project": {
12
+ "home": "#{node.home}/acceptance_demo",
13
+ "ruby_version": "2.2.3",
14
+ "gemset": "acceptance_demo"
15
+ }
16
+ }
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env bash
2
+
3
+ [test1]
4
+ # Some description
5
+
6
+ echo "<%= name %>"
7
+
8
+ [test2]
9
+
10
+ echo "test2"
11
+
12
+ #######################################
13
+ [echo]
14
+
15
+ echo "Hello world!"
16
+
17
+
18
+ #######################################
19
+ [ubuntu_update]
20
+
21
+ sudo apt-get update
22
+
23
+
24
+ #######################################
25
+ [prepare_linux]
26
+ # Updates linux core packages
27
+
28
+ sudo apt-get update
29
+
30
+ sudo apt-get install -y curl
31
+ sudo apt-get install -y g++
32
+ sudo apt-get install -y subversion
33
+ sudo apt-get install -y git
34
+
35
+ # to support rvm
36
+
37
+ sudo apt-get install -y libreadline6-dev
38
+ sudo apt-get install -y zlib1g-dev
39
+ sudo apt-get install -y libssl-dev
40
+ sudo apt-get install -y libyaml-dev
41
+ sudo apt-get install -y libsqlite3-dev
42
+ sudo apt-get install -y sqlite3
43
+ sudo apt-get install -y autoconf
44
+ sudo apt-get install -y libgdbm-dev
45
+ sudo apt-get install -y libncurses5-dev
46
+ sudo apt-get install -y automake
47
+ sudo apt-get install -y libtool
48
+ sudo apt-get install -y bison
49
+ sudo apt-get install -y pkg-config
50
+ sudo apt-get install -y libffi-dev
51
+
52
+
53
+ #######################################
54
+ [rvm]
55
+ # Installs rvm
56
+
57
+ curl -L https://get.rvm.io | bash
58
+
59
+ #sudo chown -R vagrant /opt/vagrant_ruby
60
+
61
+
62
+ #######################################
63
+ [ruby]
64
+ # Installs ruby
65
+
66
+ source /usr/local/rvm/scripts/rvm
67
+
68
+ rvm install ruby-2.2.3
69
+
70
+
71
+ #######################################
72
+ [node]
73
+ # Installs node
74
+
75
+ sudo apt-get install -y node
76
+
77
+
78
+ #######################################
79
+ [rbenv]
80
+ # Installs node
81
+
82
+ sudo apt-get install -y rbenv
83
+ git clone git://github.com/jf/rbenv-gemset.git $HOME/.rbenv/plugins/rbenv-gemset
84
+
85
+
86
+ #######################################
87
+ [prepare]
88
+ # to support nokogiri
89
+ sudo apt-get install -y libgmp-dev
90
+
91
+ # to support capybara-webkit
92
+ sudo apt-get install -y libqt4-dev
93
+ sudo apt-get install -y libqtwebkit-dev
94
+
95
+ # to support headless
96
+ sudo apt-get install -y xvfb
File without changes
@@ -0,0 +1,8 @@
1
+ [test1]
2
+ # Some description
3
+
4
+ echo "<%= name %>"
5
+
6
+ [test2]
7
+
8
+ echo "test2"