script_executor 1.6.0 → 1.7.0

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.
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"