rubyang 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8bf6ba0d6403e44658776ca41420c57286cb758d
4
- data.tar.gz: f6443bd567723e7693972f72972c298d1aaf1eb2
3
+ metadata.gz: 000a93a9ac2a85ec169ecbe1c54112b330e026b4
4
+ data.tar.gz: 3e81e19d9247fe5459de45aa57120508371d12fc
5
5
  SHA512:
6
- metadata.gz: e0a78dad49333f4721d9aa13eff55c04acf013ad77733d1c14ded2252e390591bbd59ec3883aa51c70d7cc863f1e4c1bbf6efd37f104380eeb21338c4440561a
7
- data.tar.gz: ca383e240527e026eba7151c05e1c17e5a3bd638c0e6794647b80e5d9f312654addd7d05e70efc96a744d4e61c64e85f5f74d207824977149a6e28673fcde80b
6
+ metadata.gz: 4d5ab6836505d061b019f844893a17fcfc4c4761eb2bf7e1d140670d8aa97970faacb952c8bffd10a337a80efe07d7be26c15ad3b50048f7c6697432d60e8668
7
+ data.tar.gz: ad6e739291421f469746f786755ef8288821af5a30cbda43b3c0fb757434019eddda5668422ff315b587002e23e82324c7251374d3674a2b04ee46450738e2bd
data/.codeclimate.yml CHANGED
@@ -25,3 +25,6 @@ ratings:
25
25
  - "**.rb"
26
26
  exclude_paths:
27
27
  - spec/
28
+ - vendor/
29
+ - lib/rubyang/model/parser/parser.tab.rb
30
+ - lib/rubyang/xpath/parser/parser.tab.rb
data/.gitignore CHANGED
@@ -39,3 +39,4 @@ Gemfile.lock
39
39
  .DS_Store
40
40
  *~
41
41
  *.swp
42
+ /yang/
data/README.md CHANGED
@@ -1,9 +1,10 @@
1
1
  # rubyang
2
2
 
3
3
  [![Build Status](https://travis-ci.org/hirura/rubyang.svg?branch=master)](https://travis-ci.org/hirura/rubyang)
4
- [![Coverage Status](https://coveralls.io/repos/github/hirura/rubyang/badge.svg?branch=master)](https://coveralls.io/github/hirura/rubyang?branch=master)
5
4
  [![Code Climate](https://codeclimate.com/github/hirura/rubyang/badges/gpa.svg)](https://codeclimate.com/github/hirura/rubyang)
5
+ [![Test Coverage](https://codeclimate.com/github/hirura/rubyang/badges/coverage.svg)](https://codeclimate.com/github/hirura/rubyang/coverage)
6
6
  [![Issue Count](https://codeclimate.com/github/hirura/rubyang/badges/issue_count.svg)](https://codeclimate.com/github/hirura/rubyang)
7
+ [![Gem Version](https://badge.fury.io/rb/rubyang.svg)](https://badge.fury.io/rb/rubyang)
7
8
 
8
9
  YANG parser and tree structure data store
9
10
 
@@ -25,7 +26,110 @@ Or install it yourself as:
25
26
 
26
27
  ## Usage
27
28
 
28
- TODO: Write usage instructions here
29
+ ### Core
30
+
31
+ You can use Rubyang as yang database or as server
32
+
33
+ To use rubyang as database, add this line to head of your code:
34
+
35
+ ```ruby
36
+ require 'rubyang'
37
+ ```
38
+
39
+ You can specify YANG model as String:
40
+
41
+ ```ruby
42
+ yang = <<EOB
43
+ module rubyang-example {
44
+ namespace 'http://rubyang/example';
45
+ prefix 'rubyang-example';
46
+ container container1 {
47
+ leaf leaf1 {
48
+ type string;
49
+ }
50
+ }
51
+ }
52
+ EOB
53
+ ```
54
+
55
+ And prepare DB for configurations:
56
+
57
+ ```ruby
58
+ db = Rubyang::Database.new
59
+ ```
60
+
61
+ You can load YANG model to DB:
62
+
63
+ ```ruby
64
+ db.load_model Rubyang::Model::Parser.parse( yang )
65
+ ```
66
+
67
+ Then configurations can be set with YANG model:
68
+
69
+ ```ruby
70
+ db.configure.edit( "container1" ).edit( "leaf1" ).set( "hoge" )
71
+ ```
72
+
73
+ And you can see configured data in XML format:
74
+
75
+ ```ruby
76
+ puts db.configure.to_xml( pretty: true )
77
+ # => <config xmlns='http://rubyang/config/0.1'>
78
+ # <container1 xmlns='http://rubyang/example'>
79
+ # <leaf1>hoge</leaf1>
80
+ # </container1>
81
+ # </config>
82
+ ```
83
+
84
+ And also JSON format:
85
+
86
+ ```ruby
87
+ puts db.configure.to_json( pretty: true )
88
+ # => {
89
+ # "config": {
90
+ # "container1": {
91
+ # "leaf1": "hoge"
92
+ # }
93
+ # }
94
+ # }
95
+ ```
96
+
97
+ And to use rubyang as server
98
+
99
+ ```ruby
100
+ require 'rubyang/server/base'
101
+ ```
102
+
103
+ and create some class inheriting Rubyang::Server::Base class
104
+
105
+ ```ruby
106
+ class Example < Rubyang::Server::Base
107
+ end
108
+ ```
109
+
110
+ now you can run server
111
+
112
+ ```ruby
113
+ example = Example.new
114
+ example.run
115
+ ```
116
+
117
+ you can connect to this server with cli.rb
118
+
119
+ ```ruby
120
+ require 'rubyang/cli'
121
+
122
+ cli = Rubyang::Cli.new
123
+ cli.run
124
+ ```
125
+
126
+ ### Additional Component
127
+
128
+ Rubyang provides component mechanism to develop some component for users.
129
+ Users can develop some components and load those components.
130
+ The components which is defined as "hook commit" in configuraion are called when commit is executed.
131
+
132
+ Example component is stored in "/path/to/rubyang/component/example.rb"
29
133
 
30
134
  ## Development
31
135
 
data/lib/rubyang/cli.rb CHANGED
@@ -1,120 +1,131 @@
1
1
  # coding: utf-8
2
2
 
3
+ require 'drb/drb'
3
4
  require 'readline'
4
5
 
5
- require_relative 'cli/parser'
6
-
7
6
  require_relative '../rubyang'
7
+ require_relative 'cli/parser'
8
8
 
9
9
  module Rubyang
10
- module Cli
11
- end
12
- end
10
+ class Cli
11
+ def initialize
12
+ @sock_file = "/tmp/rubyang/server/Example.sock"
13
+ @db = DRbObject.new_with_uri( "drbunix:#{@sock_file}" )
13
14
 
14
- target_yang = File.expand_path( File.dirname( __FILE__ ) ) + '/cli/target.yang'
15
- model = Rubyang::Model::Parser.parse( File.open( target_yang, 'r' ).read )
16
- db = Rubyang::Database.new
17
- db.load_model model
18
- $config_tree = db.configure
15
+ @config_tree = @db.configure
19
16
 
20
- $fo = File.open('./cli/log.txt', 'w')
21
- $fo.sync = true
22
-
23
- def set config_tree, tokens
24
- set_recursive config_tree, tokens
25
- end
26
-
27
- def set_recursive config_tree, tokens
28
- return config_tree if tokens.size == 0
29
- token = tokens[0]
30
- case tokens[1..-1].size
31
- when 0
32
- config_tree.set token
33
- else
34
- child_tree = config_tree.edit token
35
- set_recursive child_tree, tokens[1..-1]
36
- end
37
- end
17
+ @fo = File.open("#{File.dirname(__FILE__)}/cli/log.txt", 'w')
18
+ @fo.sync = true
38
19
 
39
- def get_candidates config_tree, tokens
40
- $fo.puts config_tree.class
41
- $fo.puts tokens.inspect
42
- token = tokens[0].to_s
43
- case config_tree
44
- when Rubyang::Database::DataTree::Leaf
45
- if tokens.size == 1
46
- [config_tree.value]
47
- else
48
- []
20
+ #Readline.basic_word_break_characters = ""
21
+ #Readline.completer_word_break_characters = ""
22
+ Readline.completion_append_character = " "
23
+ Readline.completion_proc = proc { |buf|
24
+ @fo.puts "line_buffer: #{Readline.line_buffer}"
25
+ begin
26
+ tokens = Rubyang::Cli::Parser.parse( Readline.line_buffer )
27
+ rescue
28
+ next
29
+ end
30
+ command_type = tokens.shift
31
+ case command_type
32
+ when /^set$/
33
+ if tokens.size == 0
34
+ all_candidates = ['set']
35
+ candidates = all_candidates
36
+ else
37
+ value = tokens.last.to_s
38
+ all_candidates = get_candidates( @config_tree, tokens )
39
+ candidates = all_candidates.grep(/^#{Regexp.escape(value.to_s)}/)
40
+ end
41
+ when /^show$/
42
+ format = tokens[0].to_s
43
+ all_candidates = ['xml', 'json']
44
+ candidates = all_candidates.grep(/^#{Regexp.escape(format.to_s)}/)
45
+ candidates
46
+ else
47
+ all_candidates = ['set', 'show']
48
+ candidates = all_candidates.grep(/^#{Regexp.escape(command_type.to_s)}/)
49
+ candidates
50
+ end
51
+ @fo.puts "tokens = #{tokens.inspect}"
52
+ @fo.puts "all_candidates = #{all_candidates.inspect}"
53
+ @fo.puts "candidates = #{candidates.inspect}"
54
+ @fo.puts
55
+ @fo.puts
56
+ candidates
57
+ }
49
58
  end
50
- else
51
- if tokens.size > 1 and config_tree.schema.children.map{ |c| c.arg }.include? token
52
- child_tree = config_tree.edit token
53
- get_candidates child_tree, tokens[1..-1]
54
- else
55
- config_tree.schema.children.map{ |c| c.arg }
56
- end
57
- end
58
- end
59
59
 
60
+ def set config_tree, tokens
61
+ set_recursive config_tree, tokens
62
+ end
60
63
 
61
- #Readline.basic_word_break_characters = ""
62
- #Readline.completer_word_break_characters = ""
63
- Readline.completion_append_character = " "
64
- Readline.completion_proc = proc { |buf|
65
- $fo.puts "line_buffer: #{Readline.line_buffer}"
66
- begin
67
- tokens = Rubyang::Cli::Parser.parse( Readline.line_buffer )
68
- rescue
69
- next
70
- end
71
- command_type = tokens.shift
72
- case command_type
73
- when /^set$/
74
- if tokens.size == 0
75
- all_candidates = ['set']
76
- candidates = all_candidates
77
- else
78
- value = tokens.last.to_s
79
- all_candidates = get_candidates( $config_tree, tokens )
80
- candidates = all_candidates.grep(/^#{Regexp.escape(value.to_s)}/)
64
+ def set_recursive config_tree, tokens
65
+ return config_tree if tokens.size == 0
66
+ token = tokens[0]
67
+ case tokens[1..-1].size
68
+ when 0
69
+ config_tree.set token
70
+ else
71
+ child_tree = config_tree.edit token
72
+ set_recursive child_tree, tokens[1..-1]
73
+ end
81
74
  end
82
- when /^show$/
83
- format = tokens[0].to_s
84
- all_candidates = ['xml', 'json']
85
- candidates = all_candidates.grep(/^#{Regexp.escape(format.to_s)}/)
86
- candidates
87
- else
88
- all_candidates = ['set', 'show']
89
- candidates = all_candidates.grep(/^#{Regexp.escape(command_type.to_s)}/)
90
- candidates
91
- end
92
- $fo.puts "tokens = #{tokens.inspect}"
93
- $fo.puts "all_candidates = #{all_candidates.inspect}"
94
- $fo.puts "candidates = #{candidates.inspect}"
95
- $fo.puts
96
- $fo.puts
97
- candidates
98
- }
99
75
 
100
- while buf = Readline.readline("> ", true)
101
- tokens = Rubyang::Cli::Parser.parse( buf )
102
- command_type = tokens.shift
103
- case command_type
104
- when /^set$/
105
- begin
106
- set $config_tree, tokens
107
- $config_tree.commit
108
- rescue => e
109
- puts e
76
+ def get_candidates config_tree, tokens
77
+ @fo.puts config_tree.class
78
+ @fo.puts tokens.inspect
79
+ token = tokens[0].to_s
80
+ case config_tree
81
+ when Rubyang::Database::DataTree::Leaf
82
+ if tokens.size == 1
83
+ [config_tree.value]
84
+ else
85
+ []
86
+ end
87
+ else
88
+ if tokens.size > 1 and config_tree.schema.children.map{ |c| c.arg }.include? token
89
+ child_tree = config_tree.edit token
90
+ get_candidates child_tree, tokens[1..-1]
91
+ else
92
+ config_tree.schema.children.map{ |c| c.arg }
93
+ end
94
+ end
110
95
  end
111
- when /^show$/
112
- show_type = tokens.shift
113
- case show_type
114
- when /^xml$/
115
- puts $config_tree.to_xml( pretty: true )
116
- when /^json$/
117
- puts $config_tree.to_json( pretty: true )
96
+
97
+ def run
98
+ while buf = Readline.readline("> ", true)
99
+ tokens = Rubyang::Cli::Parser.parse( buf )
100
+ command_type = tokens.shift
101
+ case command_type
102
+ when /^set$/
103
+ begin
104
+ set @config_tree, tokens
105
+ rescue => e
106
+ puts "Error: #{e}"
107
+ end
108
+ when /^show$/
109
+ show_type = tokens.shift
110
+ case show_type
111
+ when /^xml$/
112
+ puts @config_tree.to_xml( pretty: true )
113
+ when /^json$/
114
+ puts @config_tree.to_json( pretty: true )
115
+ end
116
+ when /^commit$/
117
+ begin
118
+ @config_tree.commit
119
+ rescue => e
120
+ puts "Error: #{e}"
121
+ end
122
+ end
123
+ end
118
124
  end
119
125
  end
120
126
  end
127
+
128
+ if __FILE__ == $0
129
+ cli = Rubyang::Cli.new
130
+ cli.run
131
+ end
@@ -5,7 +5,7 @@ require 'strscan'
5
5
  #require_relative 'parser/parser.tab.rb'
6
6
 
7
7
  module Rubyang
8
- module Cli
8
+ class Cli
9
9
  class Parser
10
10
  def self.parse( str )
11
11
  parser = self.new
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+
3
+ require 'bundler/setup'
4
+
5
+ require 'fileutils'
6
+ require 'drb/drb'
7
+
8
+ module Rubyang
9
+ module Component
10
+ class Base
11
+ include DRb::DRbUndumped
12
+
13
+ def initialize
14
+ @rubyang_sock_file = "/tmp/rubyang/server/Example.sock"
15
+ @db = DRbObject.new_with_uri( "drbunix:#{@rubyang_sock_file}" )
16
+
17
+ #@pid = Process.pid
18
+ @sock_dir = "/tmp/rubyang/component"
19
+ #@sock_file = "#{@sock_dir}/#{self.class}.#{pid}.sock"
20
+ @sock_file = "#{@sock_dir}/#{self.class}.sock"
21
+
22
+ FileUtils.mkdir_p @sock_dir
23
+
24
+ DRb.start_service( "drbunix:#{@sock_file}", self )
25
+ DRb.thread.join
26
+ end
27
+
28
+ def run
29
+ end
30
+
31
+ def finish
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,15 @@
1
+ # coding: utf-8
2
+
3
+ require_relative 'base'
4
+
5
+ class Example < Rubyang::Component::Base
6
+ def run
7
+ config = @db.configure
8
+ File.open( '/tmp/rubyang_component_example.txt', 'w' ){ |fo|
9
+ fo.puts config.to_xml( pretty: true )
10
+ }
11
+ end
12
+ end
13
+
14
+ example = Example.new
15
+ example.run
@@ -0,0 +1,77 @@
1
+ # coding: utf-8
2
+
3
+ require 'open3'
4
+ require 'drb/drb'
5
+
6
+ require_relative '../../rubyang'
7
+
8
+ module Rubyang
9
+ class Database
10
+ class ComponentManager
11
+ class Component
12
+ attr_reader :name, :hook, :path, :sock, :thread, :instance
13
+
14
+ def initialize name, hook, path
15
+ @name = name
16
+ @hook = hook
17
+ @path = path
18
+ @sock = "/tmp/rubyang/component/#{@name}.sock"
19
+ end
20
+
21
+ def start
22
+ begin
23
+ @thread = Thread.new( @path ) do |path|
24
+ stdout, stderr, status = Open3.capture3( "#{RUBY_ENGINE} #{path}" )
25
+ end
26
+ 10.times{ |i|
27
+ break if File.socket? @sock
28
+ sleep 1
29
+ raise "Load failed: #{@name} : #{@path}" if i == 9
30
+ }
31
+ @instance = DRbObject.new_with_uri( "drbunix:#{@sock}" )
32
+ rescue => e
33
+ puts "Error: #{e}"
34
+ end
35
+ end
36
+
37
+ def run
38
+ begin
39
+ @instance.run
40
+ rescue => e
41
+ puts "Error: #{e}"
42
+ end
43
+ end
44
+ end
45
+
46
+ def initialize
47
+ @components = Array.new
48
+ end
49
+
50
+ def update components
51
+ current_component_names = @components.map{ |c| c.name }
52
+ new_component_names = components.map{ |c| c[0] }
53
+ unloading_component_names = current_component_names - new_component_names
54
+ loading_component_names = new_component_names - current_component_names
55
+ puts "Load: #{loading_component_names}"
56
+ puts "Unload: #{unloading_component_names}"
57
+ unloading_component_names.each{ |n|
58
+ component = @components.find{ |c| c.name == n }
59
+ component.thread.kill
60
+ @components.delete_if{ |c| c.name == n }
61
+ }
62
+ loading_component_names.each{ |n|
63
+ name, hook, path = components.find{ |c| c[0] == n }
64
+ component = Component.new name, hook, path
65
+ component.start
66
+ @components.push component
67
+ }
68
+ end
69
+
70
+ def run hook
71
+ @components.select{ |c| c.hook == hook }.each{ |c|
72
+ c.run
73
+ }
74
+ end
75
+ end
76
+ end
77
+ end