junoser 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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