junoser 0.1.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/exe/junoser ADDED
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'pathname'
5
+
6
+ $: << File.expand_path('../../lib', Pathname.new(__FILE__).realpath)
7
+
8
+ require 'junoser/cli'
9
+
10
+
11
+ command = nil
12
+ opts = OptionParser.new do |opts|
13
+ opts.banner = 'junoser: an juniper configuration parser'
14
+ opts.define_head 'Usage: junoser [options] [path]'
15
+ opts.separator ''
16
+ opts.separator 'Options:'
17
+
18
+ opts.on '-c', '--check', 'Verify syntax' do
19
+ command = :check
20
+ end
21
+
22
+ opts.on '-d', '--display-set', 'Translate to "display set" form' do
23
+ command = :display_set
24
+ end
25
+
26
+ opts.on '-s', '--structured', 'Translate to structured form' do
27
+ command = :struct
28
+ end
29
+
30
+ opts.on_tail '-h', '--help', 'Show this message' do
31
+ puts opts
32
+ exit
33
+ end
34
+
35
+ opts.on_tail '-v', '--version', 'Show version' do
36
+ puts Junoser::VERSION
37
+ end
38
+ end
39
+ opts.parse!
40
+
41
+ case command
42
+ when :check
43
+ Junoser::Cli.commit_check $<
44
+ when :display_set
45
+ Junoser::Cli.display_set $<
46
+ when :struct
47
+ Junoser::Cli.struct $<
48
+ else
49
+ puts opts
50
+ abort
51
+ end
data/junoser.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'junoser/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "junoser"
8
+ spec.version = Junoser::VERSION
9
+ spec.authors = ["Shintaro Kojima"]
10
+ spec.email = ["goodies@codeout.net"]
11
+
12
+ spec.summary = %q{PEG parser for JUNOS configuration.}
13
+ spec.description = %q{PEG parser to vefiry and translate into different formats for JUNOS configuration.}
14
+ spec.homepage = "https://github.com/codeout/sakura-cli"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "parslet"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.9"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "activesupport"
26
+ spec.add_development_dependency "nokogiri"
27
+ end
@@ -0,0 +1,55 @@
1
+ require 'parslet'
2
+ require 'junoser/display'
3
+ require 'junoser/parser'
4
+
5
+
6
+ module Junoser
7
+ module Cli
8
+ class << self
9
+ def commit_check(io_or_string)
10
+ config = if io_or_string.respond_to?(:read)
11
+ $<.read
12
+ else
13
+ io_or_string.to_s
14
+ end
15
+
16
+ if Junoser::Display.display_set?(config)
17
+ commit_check_display_set config
18
+ else
19
+ commit_check_structured config
20
+ end
21
+ end
22
+
23
+ def display_set(io_or_string)
24
+ Junoser::Display::Set.new(io_or_string).transform
25
+ end
26
+
27
+ def struct(io_or_string)
28
+ Junoser::Display::Structure.new(io_or_string).transform
29
+ end
30
+
31
+
32
+ private
33
+
34
+ def commit_check_structured(config)
35
+ Junoser::Display::Set.new(config).commit_check
36
+ end
37
+
38
+ def commit_check_display_set(config)
39
+ parser = Junoser::Parser.new
40
+ failed = false
41
+
42
+ config.split("\n").each do |line|
43
+ begin
44
+ parser.parse line
45
+ rescue Parslet::ParseFailed
46
+ $stderr.puts "Invalid syntax: #{line}"
47
+ failed = true
48
+ end
49
+ end
50
+
51
+ abort if failed
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,2 @@
1
+ require 'junoser/xsd/parsable'
2
+ require 'junoser/ruler'
@@ -0,0 +1,40 @@
1
+ module Junoser
2
+ module Display
3
+ module Base
4
+ attr_accessor :output
5
+
6
+ def initialize(io_or_string)
7
+ @input = io_or_string
8
+ @output = $stdout
9
+ end
10
+
11
+
12
+ private
13
+
14
+ def read_io_or_string
15
+ return @read_io_or_string if @read_io_or_string
16
+
17
+ config = if @input.respond_to?(:read)
18
+ @input.read
19
+ else
20
+ @input.to_s
21
+ end
22
+
23
+ @read_io_or_string = remove_blank_and_comment(config)
24
+ @read_io_or_string = unify_carriage_return(@read_io_or_string)
25
+ end
26
+
27
+ def remove_blank_and_comment(str)
28
+ str.gsub! /#.*/, ''
29
+ str.gsub! /\/\*((?!\*\/).)*\*\//m, ''
30
+ str.gsub! /\n\s*/, "\n"
31
+ str.strip
32
+ end
33
+
34
+ def unify_carriage_return(str)
35
+ str.gsub! /\r\n?/, "\n"
36
+ str
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,52 @@
1
+ require 'forwardable'
2
+
3
+ module Junoser
4
+ module Display
5
+ class ConfigStore
6
+ extend Forwardable
7
+
8
+ OFFSET = ' '
9
+
10
+ def initialize(depth=0)
11
+ @hash = {}
12
+ @depth = depth
13
+ end
14
+
15
+ def push(str)
16
+ store = self
17
+
18
+ join_arg(str).split("\n").each_with_index do |element, index|
19
+ store[element] ||= self.class.new(index+1)
20
+ store = store[element]
21
+ end
22
+ end
23
+ alias << push
24
+
25
+ def to_s
26
+ str = ''
27
+
28
+ each do |k, v|
29
+ if v.empty?
30
+ str << OFFSET*@depth << "#{k};\n"
31
+ else
32
+ str << OFFSET*@depth << "#{k} {\n"
33
+ str << v.to_s.chop << "\n"
34
+ str << OFFSET*@depth << "}\n"
35
+ end
36
+ end
37
+
38
+ str
39
+ end
40
+
41
+ def_delegators :@hash, :[], :[]=, :each, :empty?
42
+
43
+ private
44
+
45
+ def join_arg(str)
46
+ str.gsub!(/\narg\((.*)\)$/) { " #$1" }
47
+ str.gsub!(/arg\((.*)\)/) { "#$1" }
48
+ str
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,82 @@
1
+ require 'junoser/display/base'
2
+
3
+ module Junoser
4
+ module Display
5
+ class Set
6
+ include Base
7
+
8
+ def transform
9
+ process do |current_stack, str|
10
+ @output.puts transform_line(current_stack, str)
11
+ end
12
+ end
13
+
14
+ def commit_check(&block)
15
+ parser = Junoser::Parser.new
16
+ failed = false
17
+
18
+ process do |current_stack, str|
19
+ config = transform_line(current_stack, str)
20
+
21
+ begin
22
+ parser.parse config
23
+ rescue Parslet::ParseFailed
24
+ $stderr.puts "Invalid syntax:\n#{struct(current_stack.dup, str)}"
25
+ failed = true
26
+ end
27
+ end
28
+
29
+ abort if failed
30
+ end
31
+
32
+
33
+ private
34
+
35
+ def process(&block)
36
+ stack = []
37
+
38
+ read_io_or_string.split("\n").each do |line|
39
+ case line
40
+ when /(.*){/
41
+ stack.push $1.strip
42
+ when '}'
43
+ stack.pop
44
+ when /((?!\[).*)\[(.*)\];/
45
+ $2.split("\s").each do |i|
46
+ yield stack, "#{$1.strip} #{i}"
47
+ end
48
+ when /(.*);/
49
+ yield stack, $1
50
+ else
51
+ raise "ERROR* unknown statement: #{line}"
52
+ end
53
+ end
54
+ end
55
+
56
+ def transform_line(current_stack, str)
57
+ statement = if current_stack.empty?
58
+ str
59
+ else
60
+ statement = "#{current_stack.join(' ')} #{str}"
61
+ end
62
+
63
+ if statement.gsub!('inactive: ', '')
64
+ "deactivate #{statement}"
65
+ else
66
+ "set #{statement}"
67
+ end
68
+ end
69
+
70
+ def struct(stack, statement, offset=2)
71
+ width = 2
72
+ if label = stack.shift
73
+ %[#{" "*offset}#{label} {
74
+ #{struct(stack, statement, width+offset)}
75
+ #{" "*offset}}]
76
+ else
77
+ %[#{" "*offset}#{statement};]
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,29 @@
1
+ require 'junoser/display/config_store'
2
+ require 'junoser/parser'
3
+ require 'junoser/transformer'
4
+
5
+ module Junoser
6
+ module Display
7
+ class Structure
8
+ include Base
9
+
10
+ def initialize(io_or_string)
11
+ super
12
+ @config = Junoser::Display::ConfigStore.new
13
+ end
14
+
15
+ def transform
16
+ parser = Junoser::Parser.new
17
+ transform = Junoser::Transformer.new
18
+
19
+ read_io_or_string.split("\n").each do |line|
20
+ transformed = transform.apply(parser.parse(line))
21
+ raise "ERROR: parse failed" unless transformed.is_a?(String)
22
+ @config << transformed
23
+ end
24
+
25
+ @output.puts @config.to_s
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,16 @@
1
+ require 'junoser/display/set'
2
+ require 'junoser/display/structure'
3
+
4
+ module Junoser
5
+ module Display
6
+ class << self
7
+ def display_set?(str)
8
+ str =~ /\Aset|deactivate/
9
+ end
10
+
11
+ def structured?(str)
12
+ !display_set?(str)
13
+ end
14
+ end
15
+ end
16
+ end