vagrant-node 0.0.2
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/.gitignore +4 -0
- data/Gemfile +4 -0
- data/LICENSE +14 -0
- data/README.md +4 -0
- data/Rakefile +1 -0
- data/lib/vagrant-node.rb +21 -0
- data/lib/vagrant-node/actions/snapshot.rb +285 -0
- data/lib/vagrant-node/api.rb +160 -0
- data/lib/vagrant-node/apidesc.rb +220 -0
- data/lib/vagrant-node/clientcontroller.rb +633 -0
- data/lib/vagrant-node/dbmanager.rb +59 -0
- data/lib/vagrant-node/nodeservercommand.rb +78 -0
- data/lib/vagrant-node/nodeserverstart.rb +24 -0
- data/lib/vagrant-node/nodeserverstop.rb +23 -0
- data/lib/vagrant-node/pidfile.rb +49 -0
- data/lib/vagrant-node/server.rb +95 -0
- data/lib/vagrant-node/version.rb +5 -0
- data/vagrant-node.gemspec +33 -0
- metadata +182 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'sqlite3'
|
2
|
+
|
3
|
+
module Vagrant
|
4
|
+
module Node
|
5
|
+
module DB
|
6
|
+
class DBManager
|
7
|
+
|
8
|
+
def initialize(data_dir)
|
9
|
+
@db=check_database(data_dir)
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_backup_log_entries(vmname)
|
13
|
+
sql="SELECT * FROM #{BACKUP_TABLE_NAME}"
|
14
|
+
sql = sql + " WHERE #{BACKUP_VM_NAME_COLUMN} = \"#{vmname}\"" if vmname
|
15
|
+
|
16
|
+
#return rows
|
17
|
+
@db.execute(sql)
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_backup_log_entry(date,vmname,status)
|
22
|
+
sql="INSERT INTO #{BACKUP_TABLE_NAME} VALUES ( ? , ? , ? )"
|
23
|
+
@db.execute(sql,date,vmname,status)
|
24
|
+
end
|
25
|
+
|
26
|
+
def update_backup_log_entry(date,vmname,status)
|
27
|
+
sql="UPDATE #{BACKUP_TABLE_NAME} SET #{BACKUP_STATUS_COLUMN} = ? WHERE #{BACKUP_DATE_COLUMN}= ? AND #{BACKUP_VM_NAME_COLUMN}= ?"
|
28
|
+
@db.execute(sql,status,date,vmname)
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
BACKUP_TABLE_NAME='node_table'
|
35
|
+
BACKUP_DATE_COLUMN = 'date'
|
36
|
+
BACKUP_VM_NAME_COLUMN = 'vm_name'
|
37
|
+
BACKUP_STATUS_COLUMN = 'backup_status'
|
38
|
+
|
39
|
+
def check_database(data_dir)
|
40
|
+
#Creates and/or open the database
|
41
|
+
|
42
|
+
db = SQLite3::Database.new( data_dir.to_s + "/node.db" )
|
43
|
+
|
44
|
+
if db.execute("SELECT name FROM sqlite_master
|
45
|
+
WHERE type='table' AND name='#{BACKUP_TABLE_NAME}';").length==0
|
46
|
+
db.execute( "create table '#{BACKUP_TABLE_NAME}' (#{BACKUP_DATE_COLUMN} TEXT NOT NULL,
|
47
|
+
#{BACKUP_VM_NAME_COLUMN} TEXT PRIMARY_KEY,
|
48
|
+
#{BACKUP_STATUS_COLUMN} TEXT NOT NULL);" )
|
49
|
+
end
|
50
|
+
|
51
|
+
#return db
|
52
|
+
db
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'vagrant/plugin'
|
2
|
+
require 'vagrant-node/api'
|
3
|
+
require 'vagrant-node/server'
|
4
|
+
|
5
|
+
module Vagrant
|
6
|
+
module Node
|
7
|
+
|
8
|
+
class Command < Vagrant.plugin(2, :command)
|
9
|
+
START_COMMAND = "start"
|
10
|
+
STOP_COMMAND = "stop"
|
11
|
+
def initialize(argv, env)
|
12
|
+
super
|
13
|
+
|
14
|
+
@main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
|
15
|
+
@subcommands = Vagrant::Registry.new
|
16
|
+
|
17
|
+
@subcommands.register(:start) do
|
18
|
+
require File.expand_path("../nodeserverstart", __FILE__)
|
19
|
+
NodeServerStart
|
20
|
+
end
|
21
|
+
|
22
|
+
@subcommands.register(:stop) do
|
23
|
+
require File.expand_path("../nodeserverstop", __FILE__)
|
24
|
+
NodeServerStop
|
25
|
+
end
|
26
|
+
|
27
|
+
# puts "MAIN ARGS #{@main_args}"
|
28
|
+
# puts "SUB COMMAND #{@sub_command}"
|
29
|
+
# puts "SUB ARGS #{@sub_args}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def execute
|
33
|
+
if @main_args.include?("-h") || @main_args.include?("--help")
|
34
|
+
# Print help
|
35
|
+
return help
|
36
|
+
end
|
37
|
+
|
38
|
+
command_class = @subcommands.get(@sub_command.to_sym) if @sub_command
|
39
|
+
return help if !command_class || !@sub_command
|
40
|
+
|
41
|
+
@logger.debug("Invoking command class: #{command_class} #{@sub_args.inspect}")
|
42
|
+
|
43
|
+
command_class.new(@sub_args, @env).execute
|
44
|
+
|
45
|
+
# case @sub_command
|
46
|
+
# when START_COMMAND then
|
47
|
+
# @env.lock_path contiene la ruta al fichero de lock
|
48
|
+
#incluyendo el nombre de este, por lo tanto se pasa
|
49
|
+
#únicamente la ruta
|
50
|
+
# ServerAPI::ServerManager.run(File.dirname(@env.lock_path))
|
51
|
+
# when STOP_COMMAND then
|
52
|
+
# ServerAPI::ServerManager.stop(File.dirname(@env.lock_path))
|
53
|
+
# else
|
54
|
+
# return help
|
55
|
+
# end
|
56
|
+
0
|
57
|
+
end
|
58
|
+
|
59
|
+
def help
|
60
|
+
|
61
|
+
opts = OptionParser.new do |opts|
|
62
|
+
opts.banner = "Usage: vagrant nodeserver <command>"
|
63
|
+
opts.separator ""
|
64
|
+
opts.on("-h", "--help", "Print this help.")
|
65
|
+
opts.separator ""
|
66
|
+
opts.separator "Available subcommands:"
|
67
|
+
opts.separator " start"
|
68
|
+
opts.separator " stop"
|
69
|
+
opts.separator ""
|
70
|
+
end
|
71
|
+
|
72
|
+
@env.ui.info(opts.help, :prefix => false)
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'vagrant-node/server'
|
3
|
+
module Vagrant
|
4
|
+
module Node
|
5
|
+
class NodeServerStart < Vagrant.plugin(2, :command)
|
6
|
+
def execute
|
7
|
+
options = {}
|
8
|
+
|
9
|
+
opts = OptionParser.new do |opts|
|
10
|
+
opts.banner = "Usage: vagrant nodeserver start [port=3333]"
|
11
|
+
end
|
12
|
+
|
13
|
+
argv = parse_options(opts)
|
14
|
+
return if !argv
|
15
|
+
raise Vagrant::Errors::CLIInvalidUsage, :help => opts.help.chomp if argv.length > 1
|
16
|
+
|
17
|
+
ServerAPI::ServerManager.run(File.dirname(@env.lock_path),@env.data_dir,argv[0].to_i)
|
18
|
+
|
19
|
+
0
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'vagrant-node/server'
|
3
|
+
module Vagrant
|
4
|
+
module Node
|
5
|
+
class NodeServerStop < Vagrant.plugin(2, :command)
|
6
|
+
def execute
|
7
|
+
options = {}
|
8
|
+
|
9
|
+
opts = OptionParser.new do |opts|
|
10
|
+
opts.banner = "Usage: vagrant nodeserver stop"
|
11
|
+
end
|
12
|
+
|
13
|
+
argv = parse_options(opts)
|
14
|
+
return if !argv
|
15
|
+
raise Vagrant::Errors::CLIInvalidUsage, :help => opts.help.chomp if argv.length > 1
|
16
|
+
|
17
|
+
ServerAPI::ServerManager.stop(File.dirname(@env.lock_path))
|
18
|
+
0
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Vagrant
|
2
|
+
module Node
|
3
|
+
module ServerAPI
|
4
|
+
class PidFile
|
5
|
+
|
6
|
+
#FIXME en realidad no haría falta pasar el pid
|
7
|
+
#ya que se puede coger el del hilo en curso con
|
8
|
+
#el Process.pid
|
9
|
+
def self.create(pid_file,pid)
|
10
|
+
|
11
|
+
#Check first if pid_file exists
|
12
|
+
if File.exists?(pid_file)
|
13
|
+
#Check if the stored pid belongs to a
|
14
|
+
#running process
|
15
|
+
pidold = open(pid_file, 'r').read.to_i
|
16
|
+
if process_exist?(pidold)
|
17
|
+
raise 'Process #{pidold} is still alive and running'
|
18
|
+
else
|
19
|
+
#If it is not alive then remove the file
|
20
|
+
delete(pid_file)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
lock = open(pid_file, "w")
|
25
|
+
lock.flock(File::LOCK_EX | File::LOCK_NB) || raise
|
26
|
+
lock.puts pid
|
27
|
+
lock.flush
|
28
|
+
lock.rewind
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.delete(pid_file)
|
32
|
+
File.delete pid_file
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def self.process_exist?(pid)
|
38
|
+
begin
|
39
|
+
Process.kill(0, pid)
|
40
|
+
true
|
41
|
+
rescue Errno::ESRCH, TypeError
|
42
|
+
false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'vagrant-node/api'
|
3
|
+
require 'vagrant-node/pidfile'
|
4
|
+
require 'webrick'
|
5
|
+
|
6
|
+
|
7
|
+
#FIXME Problema con el logging ya que únicamnete
|
8
|
+
#vuelca al fichero todo cuando se acaba el proceso con el
|
9
|
+
#vagrant server stop
|
10
|
+
module Vagrant
|
11
|
+
module Node
|
12
|
+
module ServerAPI
|
13
|
+
class ServerManager
|
14
|
+
PIDFILENAME = "server.pid"
|
15
|
+
DEFAULT_BIND_PORT = 3333
|
16
|
+
BIND_ADDRESS = "0.0.0.0"
|
17
|
+
LOG_FILE = "webrick.log"
|
18
|
+
def self.run(pid_path,log_path,port=DEFAULT_BIND_PORT)
|
19
|
+
pid_file = File.join(pid_path,PIDFILENAME)
|
20
|
+
|
21
|
+
pid = fork do
|
22
|
+
|
23
|
+
|
24
|
+
log_file = File.open (log_path + LOG_FILE).to_s, 'a+'
|
25
|
+
|
26
|
+
log = WEBrick::Log.new log_file
|
27
|
+
|
28
|
+
access_log = [
|
29
|
+
[log_file, WEBrick::AccessLog::COMBINED_LOG_FORMAT],
|
30
|
+
]
|
31
|
+
|
32
|
+
port = DEFAULT_BIND_PORT if port < 1024
|
33
|
+
|
34
|
+
options = {
|
35
|
+
:Port => port,
|
36
|
+
:BindAddress => BIND_ADDRESS,
|
37
|
+
:Logger => log,
|
38
|
+
:AccessLog => access_log
|
39
|
+
}
|
40
|
+
|
41
|
+
begin
|
42
|
+
server = WEBrick::HTTPServer.new(options)
|
43
|
+
|
44
|
+
server.mount "/", Rack::Handler::WEBrick,ServerAPI::API.new
|
45
|
+
trap("INT") { server.stop }
|
46
|
+
|
47
|
+
PidFile.create(pid_file,Process.pid)
|
48
|
+
|
49
|
+
server.start
|
50
|
+
|
51
|
+
|
52
|
+
rescue Exception => e
|
53
|
+
puts e.message
|
54
|
+
end
|
55
|
+
|
56
|
+
#Alternative running mode
|
57
|
+
# ServerAPI::API.run! :bind => '0.0.0.0', :port => 1234
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.stop(pid_path)
|
63
|
+
begin
|
64
|
+
|
65
|
+
pid_file = File.join(pid_path,PIDFILENAME)
|
66
|
+
|
67
|
+
if !File.exists?(pid_file)
|
68
|
+
return
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
pid = File.read(pid_file).to_i
|
73
|
+
|
74
|
+
#Regardless the pid belongs to a running process or not
|
75
|
+
#first delete the file
|
76
|
+
PidFile.delete(pid_file)
|
77
|
+
#FIXME No sé por qué cuando se crea un environment
|
78
|
+
#en el cliente, el servidor deja de atrapar la señal
|
79
|
+
#de INT
|
80
|
+
#Process.kill('INT', pid)
|
81
|
+
Process.kill('KILL', pid)
|
82
|
+
#Process.kill 9, pid
|
83
|
+
|
84
|
+
rescue Exception => e
|
85
|
+
puts e.message
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'vagrant-node/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "vagrant-node"
|
8
|
+
spec.version = Vagrant::Node::VERSION
|
9
|
+
spec.authors = ["Francisco Javier Lopez de San Pedro"]
|
10
|
+
spec.email = ["fjsanpedro@gmail.com"]
|
11
|
+
spec.description = "This Vagrant plugin allows you to configure a vm environment as a node in a client/server infraestructure. See vagrant-nodemaster"
|
12
|
+
spec.summary = "ESCRIBIR SUMMARY"
|
13
|
+
spec.homepage = "http://www.catedrasaes.org"
|
14
|
+
spec.license = "GNU"
|
15
|
+
|
16
|
+
spec.rubyforge_project = "vagrant-node"
|
17
|
+
|
18
|
+
spec.add_dependency "sinatra"
|
19
|
+
spec.add_dependency "json"
|
20
|
+
spec.add_dependency "rack"
|
21
|
+
spec.add_dependency "rubyzip"
|
22
|
+
spec.add_dependency "sqlite3"
|
23
|
+
#spec.add_dependency "sambal"
|
24
|
+
#spec.add_dependency "rexml"
|
25
|
+
|
26
|
+
spec.files = `git ls-files`.split($/)
|
27
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
28
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
29
|
+
spec.require_paths = ["lib"]
|
30
|
+
|
31
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
32
|
+
spec.add_development_dependency "rake"
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vagrant-node
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Francisco Javier Lopez de San Pedro
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2013-06-25 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: sinatra
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: json
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rack
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
type: :runtime
|
61
|
+
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rubyzip
|
64
|
+
prerelease: false
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
type: :runtime
|
75
|
+
version_requirements: *id004
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: sqlite3
|
78
|
+
prerelease: false
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
type: :runtime
|
89
|
+
version_requirements: *id005
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
name: bundler
|
92
|
+
prerelease: false
|
93
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ~>
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
hash: 9
|
99
|
+
segments:
|
100
|
+
- 1
|
101
|
+
- 3
|
102
|
+
version: "1.3"
|
103
|
+
type: :development
|
104
|
+
version_requirements: *id006
|
105
|
+
- !ruby/object:Gem::Dependency
|
106
|
+
name: rake
|
107
|
+
prerelease: false
|
108
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
109
|
+
none: false
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
hash: 3
|
114
|
+
segments:
|
115
|
+
- 0
|
116
|
+
version: "0"
|
117
|
+
type: :development
|
118
|
+
version_requirements: *id007
|
119
|
+
description: This Vagrant plugin allows you to configure a vm environment as a node in a client/server infraestructure. See vagrant-nodemaster
|
120
|
+
email:
|
121
|
+
- fjsanpedro@gmail.com
|
122
|
+
executables: []
|
123
|
+
|
124
|
+
extensions: []
|
125
|
+
|
126
|
+
extra_rdoc_files: []
|
127
|
+
|
128
|
+
files:
|
129
|
+
- .gitignore
|
130
|
+
- Gemfile
|
131
|
+
- LICENSE
|
132
|
+
- README.md
|
133
|
+
- Rakefile
|
134
|
+
- lib/vagrant-node.rb
|
135
|
+
- lib/vagrant-node/actions/snapshot.rb
|
136
|
+
- lib/vagrant-node/api.rb
|
137
|
+
- lib/vagrant-node/apidesc.rb
|
138
|
+
- lib/vagrant-node/clientcontroller.rb
|
139
|
+
- lib/vagrant-node/dbmanager.rb
|
140
|
+
- lib/vagrant-node/nodeservercommand.rb
|
141
|
+
- lib/vagrant-node/nodeserverstart.rb
|
142
|
+
- lib/vagrant-node/nodeserverstop.rb
|
143
|
+
- lib/vagrant-node/pidfile.rb
|
144
|
+
- lib/vagrant-node/server.rb
|
145
|
+
- lib/vagrant-node/version.rb
|
146
|
+
- vagrant-node.gemspec
|
147
|
+
homepage: http://www.catedrasaes.org
|
148
|
+
licenses:
|
149
|
+
- GNU
|
150
|
+
post_install_message:
|
151
|
+
rdoc_options: []
|
152
|
+
|
153
|
+
require_paths:
|
154
|
+
- lib
|
155
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
156
|
+
none: false
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
hash: 3
|
161
|
+
segments:
|
162
|
+
- 0
|
163
|
+
version: "0"
|
164
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
|
+
none: false
|
166
|
+
requirements:
|
167
|
+
- - ">="
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
hash: 3
|
170
|
+
segments:
|
171
|
+
- 0
|
172
|
+
version: "0"
|
173
|
+
requirements: []
|
174
|
+
|
175
|
+
rubyforge_project: vagrant-node
|
176
|
+
rubygems_version: 1.8.15
|
177
|
+
signing_key:
|
178
|
+
specification_version: 3
|
179
|
+
summary: ESCRIBIR SUMMARY
|
180
|
+
test_files: []
|
181
|
+
|
182
|
+
has_rdoc:
|