rubyang 0.1.0 → 0.1.1

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