liri 0.1.0
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 +7 -0
- data/.gitignore +9 -0
- data/.rakeTasks +7 -0
- data/.rspec +8 -0
- data/.rubocop.yml +15 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +32 -0
- data/Gemfile.lock +76 -0
- data/LICENSE.txt +21 -0
- data/README.md +161 -0
- data/Rakefile +61 -0
- data/bin/bundle +114 -0
- data/bin/coderay +29 -0
- data/bin/commander +29 -0
- data/bin/htmldiff +29 -0
- data/bin/ldiff +29 -0
- data/bin/liri +29 -0
- data/bin/rake +29 -0
- data/bin/rspec +29 -0
- data/bin/rubocop +29 -0
- data/bin/ruby-parse +29 -0
- data/bin/ruby-rewrite +29 -0
- data/bin/yard +29 -0
- data/bin/yardoc +29 -0
- data/bin/yri +29 -0
- data/config/locales/to_duration_es.yml +25 -0
- data/exe/liri +73 -0
- data/lib/agent/agent.rb +235 -0
- data/lib/agent/runner.rb +19 -0
- data/lib/all_libraries.rb +30 -0
- data/lib/common/benchmarking.rb +36 -0
- data/lib/common/compressor/zip.rb +70 -0
- data/lib/common/log.rb +121 -0
- data/lib/common/source_code.rb +53 -0
- data/lib/common/unit_test/rspec.rb +91 -0
- data/lib/exe/agent.rb +5 -0
- data/lib/exe/manager.rb +5 -0
- data/lib/hash_extend.rb +57 -0
- data/lib/liri.rb +129 -0
- data/lib/manager/credential.rb +47 -0
- data/lib/manager/manager.rb +258 -0
- data/lib/manager/setup.rb +70 -0
- data/lib/manager/test_result.rb +38 -0
- data/lib/task.rb +15 -0
- data/liri.gemspec +58 -0
- data/template/liri-config.yml +28 -0
- metadata +182 -0
data/bin/htmldiff
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'htmldiff' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("diff-lcs", "htmldiff")
|
data/bin/ldiff
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'ldiff' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("diff-lcs", "ldiff")
|
data/bin/liri
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'liri' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("liri", "liri")
|
data/bin/rake
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rake' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rake", "rake")
|
data/bin/rspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rspec' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rspec-core", "rspec")
|
data/bin/rubocop
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rubocop' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rubocop", "rubocop")
|
data/bin/ruby-parse
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'ruby-parse' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("parser", "ruby-parse")
|
data/bin/ruby-rewrite
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'ruby-rewrite' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("parser", "ruby-rewrite")
|
data/bin/yard
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'yard' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("yard", "yard")
|
data/bin/yardoc
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'yardoc' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("yard", "yardoc")
|
data/bin/yri
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'yri' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("yard", "yri")
|
@@ -0,0 +1,25 @@
|
|
1
|
+
es:
|
2
|
+
to_duration:
|
3
|
+
and: y
|
4
|
+
less_than_one_second: Menos de un segundo
|
5
|
+
year:
|
6
|
+
one: año
|
7
|
+
other: años
|
8
|
+
month:
|
9
|
+
one: mes
|
10
|
+
other: meses
|
11
|
+
week:
|
12
|
+
one: semana
|
13
|
+
other: semanas
|
14
|
+
day:
|
15
|
+
one: día
|
16
|
+
other: dias
|
17
|
+
hour:
|
18
|
+
one: hora
|
19
|
+
other: horas
|
20
|
+
minute:
|
21
|
+
one: minuto
|
22
|
+
other: minutos
|
23
|
+
second:
|
24
|
+
one: segundo
|
25
|
+
other: segundos
|
data/exe/liri
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Este script de ruby permite ejecutar el comando liri en CLI (interface de línea de comandos)
|
3
|
+
# From:
|
4
|
+
# - https://robdodson.me/how-to-write-a-command-line-ruby-gem/
|
5
|
+
# - https://medium.com/@stephenagrice/making-a-command-line-ruby-gem-write-build-and-push-aec24c6c49eb
|
6
|
+
# - https://www.sitepoint.com/ruby-command-line-interface-gems/
|
7
|
+
require 'rubygems'
|
8
|
+
require 'commander/import'
|
9
|
+
require 'liri'
|
10
|
+
require 'manager/manager'
|
11
|
+
require 'agent/agent'
|
12
|
+
|
13
|
+
program :name, Liri::NAME
|
14
|
+
program :version, Liri::VERSION
|
15
|
+
program :description, 'Ejecuta pruebas unitarias usando un sistema distribuido'
|
16
|
+
|
17
|
+
# Define el comando y los parámetros para el programa principal
|
18
|
+
command :manager do |c|
|
19
|
+
c.syntax = 'liri manager [options]'
|
20
|
+
c.summary = 'Ejecuta pruebas unitarias'
|
21
|
+
c.description = 'Ejecuta el programa principal que se conecta con uno o más programas agentes para organizar la ejecución de pruebas unitarias'
|
22
|
+
c.example 'Ejecuta el programa principal mostrando el resultado en línea de comandos', 'liri'
|
23
|
+
c.example 'Ejecuta el programa principal mostrando el resultado en línea de comandos', 'liri m'
|
24
|
+
c.example 'Ejecuta el programa principal mostrando el resultado en línea de comandos', 'liri manager'
|
25
|
+
c.example 'Ejecuta el programa principal guardando los resultados en un archivo .html', 'liri -o result.html'
|
26
|
+
c.option '-o', '--output [filename]', String, 'Especifica donde guardar los resultados de la ejecución de pruebas unitarias'
|
27
|
+
c.action do |args, options|
|
28
|
+
Liri::Common::Benchmarking.start(end_msg: "\nFinalizado en: ") do
|
29
|
+
# Metodo que se ejecuta al llamar al comando manager
|
30
|
+
Liri::Manager.run
|
31
|
+
end
|
32
|
+
puts ''
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Define el alias m para el comando manager
|
37
|
+
alias_command :m, :manager
|
38
|
+
# Define un texto vacío como alias lo que permite ejecutar el programa principal solamente usando el comando liri
|
39
|
+
#alias_command '', :manager
|
40
|
+
|
41
|
+
# Define el comando y los parámetros para el programa agente
|
42
|
+
command :agent do |c|
|
43
|
+
c.syntax = 'Liri agent [options]'
|
44
|
+
c.summary = 'Ejecuta el programa agente'
|
45
|
+
c.description = 'Espera las ordenes del programa principal para ejecutar pruebas unitarias'
|
46
|
+
c.example 'Ejecuta el programa agente', 'liri a'
|
47
|
+
c.example 'Ejecuta el programa agente', 'liri agent'
|
48
|
+
c.action do |args, options|
|
49
|
+
# Método que se ejecuta al llamar al comando agent
|
50
|
+
Liri::Agent.run
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Define el alias m para el comando agent
|
55
|
+
alias_command :a, :agent
|
56
|
+
|
57
|
+
# Define el comando y los parámetros para obtener la cantidad de tests
|
58
|
+
command :tests do |c|
|
59
|
+
c.syntax = 'Liri tests [options]'
|
60
|
+
c.summary = 'Retorna la cantidad total de tests'
|
61
|
+
c.description = 'Ejecuta el comando para obtener la cantidad total de tests del proyecto'
|
62
|
+
c.example 'Ejecuta el comando tests', 'liri t'
|
63
|
+
c.example 'Ejecuta el comando tests', 'liri tests'
|
64
|
+
c.action do |args, options|
|
65
|
+
# Método que se ejecuta al llamar al comando tests
|
66
|
+
tests_count = Liri::Task.tests_count
|
67
|
+
puts tests_count
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Define el alias t para el comando tests
|
72
|
+
alias_command :t, :tests
|
73
|
+
|
data/lib/agent/agent.rb
ADDED
@@ -0,0 +1,235 @@
|
|
1
|
+
=begin
|
2
|
+
Este módulo es el punto de entrada del programa agente
|
3
|
+
=end
|
4
|
+
require 'net/scp'
|
5
|
+
require 'all_libraries'
|
6
|
+
|
7
|
+
module Liri
|
8
|
+
class Agent
|
9
|
+
attr_reader :managers
|
10
|
+
|
11
|
+
class << self
|
12
|
+
# Inicia la ejecución del Agent
|
13
|
+
# @param stop [Boolean] el valor true es para que no se ejecute infinitamente el método en el test unitario.
|
14
|
+
def run(stop = false)
|
15
|
+
Liri.create_folders('agent')
|
16
|
+
|
17
|
+
Liri.set_logger(Liri::AGENT_LOGS_FOLDER_PATH, 'liri-agent.log')
|
18
|
+
Liri.logger.info("Proceso Agent iniciado")
|
19
|
+
puts "Presione Ctrl + c para terminar el proceso Agent manualmente\n\n"
|
20
|
+
|
21
|
+
source_code = Liri::Common::SourceCode.new(Liri::AGENT_FOLDER_PATH, Liri.compression_class, Liri.unit_test_class)
|
22
|
+
runner = Liri::Agent::Runner.new(Liri.unit_test_class, source_code.decompressed_file_folder_path)
|
23
|
+
agent = Agent.new(Liri.udp_port, Liri.tcp_port, source_code, runner)
|
24
|
+
threads = []
|
25
|
+
threads << agent.start_server_socket_to_process_manager_connection_request # Esperar y procesar la petición de conexión del Manager
|
26
|
+
|
27
|
+
Liri.init_exit(stop, threads, 'Agent')
|
28
|
+
Liri.logger.info("Proceso Agent terminado")
|
29
|
+
rescue SignalException => e
|
30
|
+
Liri.logger.info("Exception(#{e}) Proceso Agent terminado manualmente")
|
31
|
+
Liri.kill(threads)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(udp_port, tcp_port, source_code, runner)
|
36
|
+
@udp_port = udp_port
|
37
|
+
@udp_socket = UDPSocket.new
|
38
|
+
@tcp_port = tcp_port
|
39
|
+
|
40
|
+
@source_code = source_code
|
41
|
+
@runner = runner
|
42
|
+
|
43
|
+
@managers = {}
|
44
|
+
end
|
45
|
+
|
46
|
+
# Inicia un servidor udp que se mantiene en espera de la primera petición de conexión del Manager
|
47
|
+
def start_server_socket_to_process_manager_connection_request
|
48
|
+
# El servidor udp se ejecuta en bucle dentro de un hilo, esto permite realizar otras tareas mientras este hilo sigue esperando
|
49
|
+
# que un Manager se conecte, cuando se conecta un Manager, se guarda la ip de este manager y se vuelve a esperar otra petición
|
50
|
+
Thread.new do
|
51
|
+
BasicSocket.do_not_reverse_lookup = true
|
52
|
+
begin
|
53
|
+
@udp_socket.bind('0.0.0.0', @udp_port)
|
54
|
+
rescue Errno::EADDRINUSE => e
|
55
|
+
Liri.logger.error("Exception(#{e}) Puerto UDP #{@udp_port} ocupado")
|
56
|
+
Thread.exit
|
57
|
+
end
|
58
|
+
Liri.logger.info("En espera de peticiones de Managers en el puerto UDP #{@udp_port}
|
59
|
+
(Se espera que algún Manager se contacte por primera vez para establecer una conexión TCP)
|
60
|
+
")
|
61
|
+
|
62
|
+
loop do
|
63
|
+
@manager_request = @udp_socket.recvfrom(1024)
|
64
|
+
manager_ip_address = @manager_request.last.last
|
65
|
+
user, pass, dir = @manager_request.first.split(";")
|
66
|
+
process_manager_connection_request(manager_ip_address, user, pass, dir)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Inicia un cliente tcp para responder a la petición broadcast del Manager para que éste sepa donde enviar las pruebas
|
72
|
+
def start_client_socket_to_process_tests(manager_ip_address)
|
73
|
+
tcp_socket = TCPSocket.open(manager_ip_address, @tcp_port)
|
74
|
+
|
75
|
+
Liri.logger.info("Se inicia una conexión con el Manager: #{manager_ip_address} en el puerto TCP: #{@tcp_port}
|
76
|
+
(Se establece una conexión para procesar la ejecución de las pruebas)
|
77
|
+
")
|
78
|
+
|
79
|
+
tcp_socket.print("Listo para ejecutar pruebas") # Se envía un mensaje inicial al Manager
|
80
|
+
puts "\nConexión iniciada con el Manager: #{manager_ip_address}"
|
81
|
+
|
82
|
+
# Se procesan las pruebas enviadds por el Manager
|
83
|
+
while line = tcp_socket.gets
|
84
|
+
response = line.chop
|
85
|
+
break if response == 'exit'
|
86
|
+
|
87
|
+
tests = JSON.parse(response)
|
88
|
+
Liri.logger.debug("Pruebas recibidas del Manager #{manager_ip_address}:")
|
89
|
+
Liri.logger.debug(tests)
|
90
|
+
|
91
|
+
tests_result = @runner.run_tests(tests)
|
92
|
+
|
93
|
+
json_tests_result = tests_result.to_json
|
94
|
+
Liri.logger.debug("Resultados de la ejecución de las pruebas recibidas del Manager #{manager_ip_address}:")
|
95
|
+
Liri.logger.debug(json_tests_result)
|
96
|
+
|
97
|
+
Liri.logger.info("
|
98
|
+
#{tests.size} pruebas recibidas, #{tests_result[:example_quantity]} pruebas ejecutadas
|
99
|
+
")
|
100
|
+
tcp_socket.print(json_tests_result) # Este no logra enviar toda la información, porque? en cambio el cliente recibe un json grande sin problemas
|
101
|
+
end
|
102
|
+
|
103
|
+
tcp_socket.close
|
104
|
+
Liri.logger.info("Se termina la conexión con el Manager #{manager_ip_address}")
|
105
|
+
|
106
|
+
Liri.clean_folder(Liri::AGENT_FOLDER_PATH)
|
107
|
+
|
108
|
+
start_client_to_close_manager_server(manager_ip_address, 'Conexión Terminada')
|
109
|
+
unregister_manager(manager_ip_address)
|
110
|
+
rescue Errno::EADDRINUSE => e
|
111
|
+
Liri.logger.error("Exception(#{e}) Puerto TCP #{@tcp_port} ocupado")
|
112
|
+
rescue Errno::ECONNRESET => e
|
113
|
+
tcp_socket.close
|
114
|
+
Liri.logger.error("Exception(#{e}) Conexión cerrada en el puerto TCP #{@tcp_port}")
|
115
|
+
Liri.logger.info("Se termina la conexión con el Manager #{manager_ip_address}")
|
116
|
+
unregister_manager(manager_ip_address)
|
117
|
+
rescue Errno::ECONNREFUSED => e
|
118
|
+
Liri.logger.error("Exception(#{e}) Conexión rechazada en el puerto TCP #{@tcp_port}")
|
119
|
+
Liri.logger.info("Se termina la conexión con el Manager #{manager_ip_address}")
|
120
|
+
unregister_manager(manager_ip_address)
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
# Inserta el ip recibido dentro del hash si es que ya no existe en el hash
|
126
|
+
# Nota: Se requieren imprimir datos para saber el estado de la aplicación, sería muy útil usar algo para logear
|
127
|
+
# estas cosas en los diferentes niveles, debug, info, etc.
|
128
|
+
def process_manager_connection_request(manager_ip_address, user, pass, dir)
|
129
|
+
unless registered_manager?(manager_ip_address)
|
130
|
+
register_manager(manager_ip_address)
|
131
|
+
Liri.logger.info("Petición broadcast UDP recibida del Manager: #{manager_ip_address} en el puerto UDP: #{@udp_port}")
|
132
|
+
if process_manager_connection_scp(manager_ip_address, user, pass, dir)
|
133
|
+
start_client_socket_to_process_tests(manager_ip_address)
|
134
|
+
else
|
135
|
+
unregister_manager(manager_ip_address)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Se establece una nueva comunicación con el servidor TCP del Manager con el único objetivo de cerrar el servidor
|
141
|
+
# Esta conexión permitirá al Manager cerrar sus hilos pendientes con servidores TCP en espera y terminar el proceso
|
142
|
+
def start_client_to_close_manager_server(manager_ip_address, msg)
|
143
|
+
tcp_socket = TCPSocket.open(manager_ip_address, @tcp_port)
|
144
|
+
Liri.logger.info("Se termina cualquier proceso pendiente con el Manager #{manager_ip_address}")
|
145
|
+
tcp_socket.print({msg: msg}.to_json)
|
146
|
+
tcp_socket.close
|
147
|
+
end
|
148
|
+
|
149
|
+
def process_manager_connection_scp(manager_ip_address, user, password, dir)
|
150
|
+
# puts "User: #{user} Password: #{password}"
|
151
|
+
puts ''
|
152
|
+
Liri::Common::Benchmarking.start(start_msg: "Obteniendo código fuente. Espere... ") do
|
153
|
+
puts ''
|
154
|
+
Net::SCP.start(manager_ip_address, user, :password => password) do |scp|
|
155
|
+
scp.download!(dir, @source_code.compressed_file_folder_path)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
puts ''
|
159
|
+
|
160
|
+
downloaded_file_name = dir.split('/').last
|
161
|
+
downloaded_file_path = File.join(@source_code.compressed_file_folder_path, '/', downloaded_file_name)
|
162
|
+
|
163
|
+
Liri::Common::Benchmarking.start(start_msg: "Descomprimiendo código fuente. Espere... ") do
|
164
|
+
@source_code.decompress_file(downloaded_file_path)
|
165
|
+
end
|
166
|
+
puts ''
|
167
|
+
|
168
|
+
# Se cambia temporalmente la carpeta de trabajo a la carpeta de código fuente descomprimida
|
169
|
+
Dir.chdir(@source_code.decompressed_file_folder_path) do
|
170
|
+
# Se borra el directorio .git para evitar el siguiente error al ejecutar las pruebas: fatal: not a git repository (or any of the parent directories): .git
|
171
|
+
# Una mejor alternativa es no traer siquiera esa carpeta junto al código fuente excluyendo la carpeta .git al comprimir el código fuente.
|
172
|
+
# Por cuestiones de tiempo se procede a borrar la carpeta .git por ahora, aunque al parecer el error mostrado no afecta la ejecución del Agent
|
173
|
+
# Al realizar pruebas, el error mencionado se sigue viendo en producción así que no es seguro que este borrado de la carpeta .git solucione el problema
|
174
|
+
git_folder_path = File.join(Dir.pwd, '/.git')
|
175
|
+
FileUtils.rm_rf(git_folder_path) if Dir.exist?(git_folder_path)
|
176
|
+
|
177
|
+
# Descomentar para la depuración en entorno de desarrollo (Creo que aún así no se puede depurar)
|
178
|
+
# system("bundle install")
|
179
|
+
# Descomentar para el entorno de producción
|
180
|
+
# Se setea la versión de ruby y el gemset para el código fuente descomprimido
|
181
|
+
# Se especifica el Gemfile del cual se van a instalar los requerimientos
|
182
|
+
# Esto se hace porque por defecto se usa la versión de Ruby de Liri y su Gemset y por ello hay que cambiarlos explicitamente aquí
|
183
|
+
Liri::Common::Benchmarking.start(start_msg: "Ejecutando bundle install. Espere... ", end_msg: "Ejecución de bundle install. Duración: ") do
|
184
|
+
puts ''
|
185
|
+
system("bash -lc 'rvm use #{Liri.current_folder_ruby_and_gemset}; BUNDLE_GEMFILE=Gemfile bundle install'")
|
186
|
+
end
|
187
|
+
puts ''
|
188
|
+
|
189
|
+
Liri::Common::Benchmarking.start(start_msg: "Ejecutando rake db:migrate RAILS_ENV=test. Espere... ", end_msg: "Ejecución de rake db:migrate RAILS_ENV=test. Duración: ") do
|
190
|
+
puts ''
|
191
|
+
system("bash -lc 'rvm use #{Liri.current_folder_ruby_and_gemset}; rake db:migrate RAILS_ENV=test'")
|
192
|
+
end
|
193
|
+
puts ''
|
194
|
+
|
195
|
+
#Liri::Common::Benchmarking.start(start_msg: "Ejecutando rake db:migrate:reset RAILS_ENV=test. Espere... ", end_msg: "Ejecución de rake db:migrate:reset RAILS_ENV=test. Duración: ") do
|
196
|
+
# puts ''
|
197
|
+
# system("bash -lc 'rvm use #{Liri.current_folder_ruby_and_gemset}; rake db:migrate:reset RAILS_ENV=test'")
|
198
|
+
#end
|
199
|
+
#puts ''
|
200
|
+
end
|
201
|
+
true
|
202
|
+
rescue Errno::ECONNREFUSED => e
|
203
|
+
Liri.logger.error("Exception(#{e}) Conexión rechazada por #{manager_ip_address}. Posiblemente ssh no esté ejecutandose en #{manager_ip_address}")
|
204
|
+
false
|
205
|
+
rescue Errno::ENOTTY => e
|
206
|
+
# Este rescue es temporal, hay que ver una mejor manera de detectar si la contraseña es incorrecta
|
207
|
+
Liri.logger.error("Exception(#{e}) Contraseña incorrecta recibida de #{manager_ip_address} para la conexión ssh")
|
208
|
+
start_client_to_close_manager_server(manager_ip_address, "No se puede obtener el archivo de código fuente. Posiblemente se envío una contraseña incorrencta desde #{manager_ip_address}")
|
209
|
+
false
|
210
|
+
rescue Net::SSH::AuthenticationFailed => e
|
211
|
+
# Este rescue es temporal, hay que ver una mejor manera de detectar si la contraseña es incorrecta
|
212
|
+
Liri.logger.error("Exception(#{e}) Contraseña incorrecta recibida de #{manager_ip_address} para la conexión ssh")
|
213
|
+
start_client_to_close_manager_server(manager_ip_address, "No se puede obtener el archivo de código fuente. Posiblemente se envío una contraseña incorrencta desde #{manager_ip_address}")
|
214
|
+
false
|
215
|
+
rescue Net::SCP::Error => e
|
216
|
+
Liri.logger.warn("Exception(#{e}) Archivo no encontrado en #{manager_ip_address} a través de scp")
|
217
|
+
false
|
218
|
+
rescue TypeError => e
|
219
|
+
Liri.logger.warn("Exception(#{e}) Error indeterminado")
|
220
|
+
false
|
221
|
+
end
|
222
|
+
|
223
|
+
def registered_manager?(manager_ip_address)
|
224
|
+
@managers[manager_ip_address]
|
225
|
+
end
|
226
|
+
|
227
|
+
def register_manager(manager_ip_address)
|
228
|
+
@managers[manager_ip_address] = manager_ip_address
|
229
|
+
end
|
230
|
+
|
231
|
+
def unregister_manager(manager_ip_address)
|
232
|
+
@managers.remove!(manager_ip_address)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|