From d6b120b1761c9c0c046719dc0433e9a1ce27c086 Mon Sep 17 00:00:00 2001 From: shogosanz Date: Sun, 21 Jan 2018 16:18:28 +0900 Subject: [PATCH] implement junoser-squash --- exe/junoser-squash | 25 +++++++++++ lib/junoser/squash.rb | 90 +++++++++++++++++++++++++++++++++++++ test/test_junoser-squash.rb | 48 ++++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100755 exe/junoser-squash create mode 100644 lib/junoser/squash.rb create mode 100644 test/test_junoser-squash.rb diff --git a/exe/junoser-squash b/exe/junoser-squash new file mode 100755 index 0000000..a45b080 --- /dev/null +++ b/exe/junoser-squash @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require 'optparse' +require 'pathname' + +$: << File.expand_path('../../lib', Pathname.new(__FILE__).realpath) +require 'junoser/squash' + +command = :squash +opts = OptionParser.new do |opts| + opts.banner = 'junoser-squash: squash config file.' + opts.define_head 'Usage: junoser-squash [path]' + + opts.on_tail '-h', '--help', 'Show this message' do + puts opts + exit + end +end +opts.parse! +case command + when :squash + puts Junoser::Squash.new($<).transform + else + puts opts + abort +end diff --git a/lib/junoser/squash.rb b/lib/junoser/squash.rb new file mode 100644 index 0000000..b0ba518 --- /dev/null +++ b/lib/junoser/squash.rb @@ -0,0 +1,90 @@ +require 'junoser' +require 'parslet' + +module Junoser + class DeleteTransformer < Parslet::Transform + rule(config: simple(:config)) do + "(#{config.to_s} .*" + end + + rule(config: sequence(:configs)) do + configs.join("\n") + end + + rule(arg: simple(:arg)) do + arg + end + + rule(label: simple(:label)) do + ")#{Regexp.escape(label.to_s)}" + end + + rule(label: simple(:label), child: simple(:child)) do + "#{Regexp.escape(label.to_s)} #{child}" + end + + rule(label: simple(:label), child: sequence(:children)) do + %[#{Regexp.escape(label.to_s)} #{children.join(' ')}] + end + + rule(statement: simple(:statement), argument: simple(:argument)) do + "#{statement} #{argument}" + end + + rule(statement: simple(:statement), argument: sequence(:arguments)) do + %[#{statement} #{arguments.join(' ')}] + end + + rule(oneline: simple(:str)) do + str + end + + rule(oneline: sequence(:strs)) do + strs.join(' ') + end + end + + class Squash + def initialize(io_or_string) + @input = io_or_string + @lines = [] + @parser = Junoser::Parser.new + @transformer = DeleteTransformer.new + end + + def transform + config = Junoser::Input.new(@input).read.split("\n") + config.each do |l| + l.strip! + case l + when /^set / + @lines << l + when /^delete / + to_delete = @parser.parse(l.gsub(/^delete /, 'set ')) + delete_lines @transformer.apply(to_delete) + end + end + + @lines.uniq! + remove_subcommand(@lines).map(&:strip).join("\n") + end + + private + + def remove_subcommand(lines) + lines.each_with_index do |l,i| + lines[i..-1].each do |l2| + if l.include?(l2) and l != l2 + lines.delete(l2) + end + end + end + end + + def delete_lines(pattern) + @lines.each do |l| + l.sub!(/#{pattern}/) { $1 } + end + end + end +end \ No newline at end of file diff --git a/test/test_junoser-squash.rb b/test/test_junoser-squash.rb new file mode 100644 index 0000000..1158451 --- /dev/null +++ b/test/test_junoser-squash.rb @@ -0,0 +1,48 @@ +require 'pathname' + +$: << File.expand_path('../', Pathname.new(__FILE__).realpath) +require 'helper' + +$: << File.expand_path('../../lib', Pathname.new(__FILE__).realpath) +require 'junoser/squash' + + +class TestCommentLine < Test::Unit::TestCase + config_subcommand = <<-EOS +set interfaces em0 unit 0 family inet address 192.0.2.1/32 +set interfaces em0 unit 0 family inet +set interfaces em100 unit 0 family inet +set interfaces em100 unit 0 family inet address 192.0.2.1/32 +EOS + + config_delete = <<-EOS +set interfaces em0 unit 0 family inet address 192.0.2.0/32 +set interfaces em10 unit 10 family inet address 192.0.2.0/32 +set interfaces em10 unit 10 family inet mtu 1500 +set interfaces em10 unit 20 +set interfaces em100 unit 100 family inet address 192.0.2.0/32 +set interfaces em100 unit 200 family inet6 +delete interfaces em0 unit 0 family inet address 192.0.2.0/32 +delete interfaces em10 unit 10 +delete interfaces em100 unit 200 +EOS + + # config_insert + # ... + # config_squash + + test 'check subcommand function' do + assert_equal('set interfaces em0 unit 0 family inet address 192.0.2.1/32 +set interfaces em100 unit 0 family inet +set interfaces em100 unit 0 family inet address 192.0.2.1/32',Junoser::Squash.new(config_subcommand).transform) + + end + + test 'check delete function' do + assert_equal('set interfaces em0 unit 0 family inet address 192.0.2.0/32 +set interfaces em10 +set interfaces em10 unit 20 +set interfaces em100 unit 100 family inet address 192.0.2.0/32',Junoser::Squash.new(config_delete).transform) + + end +end