avm-tools 0.59.0 → 0.62.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/lib/avm/cached_download.rb +39 -0
  3. data/lib/avm/eac_redmine_base0/core_update.rb +110 -0
  4. data/lib/avm/eac_redmine_base0/data_unit.rb +27 -0
  5. data/lib/avm/eac_redmine_base0/deploy.rb +36 -0
  6. data/lib/avm/eac_redmine_base0/instance.rb +38 -0
  7. data/lib/avm/launcher/context/instance_manager.rb +76 -0
  8. data/lib/avm/launcher/context/instance_manager/cached_instance.rb +37 -0
  9. data/lib/avm/launcher/context/instance_manager/cached_instances.rb +35 -0
  10. data/lib/avm/launcher/errors/base.rb +10 -0
  11. data/lib/avm/launcher/errors/non_project.rb +15 -0
  12. data/lib/avm/launcher/instances/base.rb +94 -0
  13. data/lib/avm/launcher/instances/base/cache.rb +43 -0
  14. data/lib/avm/local_projects/instance.rb +8 -1
  15. data/lib/avm/local_projects/jobs/update.rb +29 -0
  16. data/lib/avm/projects/stereotype.rb +17 -10
  17. data/lib/avm/projects/stereotypes/git/local_project_mixin.rb +19 -0
  18. data/lib/avm/projects/stereotypes/git_subrepo/warp.rb +5 -4
  19. data/lib/avm/projects/stereotypes/ruby_gem/local_project_mixin.rb +19 -0
  20. data/lib/avm/projects/stereotypes/ruby_gem/update.rb +59 -0
  21. data/lib/avm/stereotypes/eac_webapp_base0/runner/deploy.rb +3 -1
  22. data/lib/avm/sync.rb +94 -0
  23. data/lib/avm/tools/runner/eac_redmine_base0.rb +2 -2
  24. data/lib/avm/tools/runner/eac_redmine_base0/core_update.rb +67 -0
  25. data/lib/avm/tools/runner/eac_redmine_base0/deploy.rb +1 -1
  26. data/lib/avm/tools/runner/git/issue.rb +43 -4
  27. data/lib/avm/tools/runner/local_project.rb +1 -1
  28. data/lib/avm/tools/runner/local_project/update.rb +26 -0
  29. data/lib/avm/tools/version.rb +1 -1
  30. data/lib/eac_launcher/context.rb +2 -2
  31. data/lib/eac_launcher/context/instance_discovery.rb +2 -2
  32. data/lib/eac_launcher/git/base/dirty_files.rb +5 -14
  33. data/lib/eac_launcher/git/sub_warp_base.rb +3 -2
  34. data/lib/eac_launcher/instances.rb +2 -2
  35. data/lib/eac_launcher/instances/error.rb +7 -3
  36. data/lib/eac_launcher/paths/logical.rb +2 -2
  37. data/lib/eac_launcher/publish/base.rb +2 -2
  38. data/template/avm/{stereotypes/eac_redmine_base0 → eac_redmine_base0}/deploy/config/install.sh.template +0 -0
  39. data/template/avm/{stereotypes/eac_redmine_base0 → eac_redmine_base0}/deploy/config/secrets.yml +0 -0
  40. data/vendor/eac_git/lib/eac_git/local.rb +1 -1
  41. data/vendor/eac_git/lib/eac_git/local/dirty_files.rb +38 -0
  42. data/vendor/eac_git/lib/eac_git/version.rb +1 -1
  43. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/docopt_runner/_class_methods.rb +1 -1
  44. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/ssh_env/identity_file.rb +2 -0
  45. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/ssh_env/quiet.rb +2 -0
  46. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/ssh_env/terminal.rb +2 -0
  47. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable/list.rb +5 -0
  48. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/require_sub.rb +8 -8
  49. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/version.rb +1 -1
  50. metadata +25 -11
  51. data/lib/avm/stereotypes/eac_redmine_base0/data_unit.rb +0 -29
  52. data/lib/avm/stereotypes/eac_redmine_base0/deploy.rb +0 -38
  53. data/lib/avm/stereotypes/eac_redmine_base0/instance.rb +0 -40
  54. data/lib/eac_launcher/context/instance_manager.rb +0 -94
  55. data/lib/eac_launcher/instances/base.rb +0 -91
  56. data/lib/eac_launcher/instances/base/cache.rb +0 -41
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'active_support/concern'
4
4
  require 'eac_ruby_utils/boolean'
5
+ require 'eac_ruby_utils/envs/ssh_env/dasho_options'
5
6
 
6
7
  module EacRubyUtils
7
8
  module Envs
@@ -10,6 +11,7 @@ module EacRubyUtils
10
11
  extend ::ActiveSupport::Concern
11
12
 
12
13
  included do
14
+ include ::EacRubyUtils::Envs::SshEnv::DashoOptions
13
15
  add_nodasho_option('Quiet')
14
16
  end
15
17
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_support/concern'
4
+ require 'eac_ruby_utils/envs/ssh_env/dasho_options'
4
5
  require 'eac_ruby_utils/listable'
5
6
  require 'eac_ruby_utils/patches/object/if_present'
6
7
 
@@ -11,6 +12,7 @@ module EacRubyUtils
11
12
  extend ::ActiveSupport::Concern
12
13
 
13
14
  included do
15
+ include ::EacRubyUtils::Envs::SshEnv::DashoOptions
14
16
  add_nodasho_option('Terminal')
15
17
  include ::EacRubyUtils::Listable
16
18
  lists.add_string :terminal_option, :auto, :disable, :enable, :force
@@ -33,6 +33,11 @@ module EacRubyUtils
33
33
  find_list_by_method(name) || super
34
34
  end
35
35
 
36
+ def hash_keys_validate!(hash, error_class = ::StandardError)
37
+ hash.keys.each { |key| value_validate!(key, error_class) }
38
+ hash
39
+ end
40
+
36
41
  def i18n_key
37
42
  "eac_ruby_utils.listable.#{class_i18n_key}.#{item}"
38
43
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_support/inflector'
4
+ require 'eac_ruby_utils/listable'
4
5
 
5
6
  module EacRubyUtils
6
7
  class << self
@@ -10,15 +11,14 @@ module EacRubyUtils
10
11
  end
11
12
 
12
13
  class RequireSub
13
- BASE_OPTION_KEY = :base
14
- INCLUDE_MODULES_OPTION_KEY = :include_modules
15
- REQUIRE_DEPENDENCY_OPTION_KEY = :require_dependency
14
+ include ::EacRubyUtils::Listable
15
+ lists.add_symbol :option, :base, :include_modules, :require_dependency
16
16
 
17
17
  attr_reader :file, :options
18
18
 
19
19
  def initialize(file, options = {})
20
20
  @file = file
21
- @options = options
21
+ @options = self.class.lists.option.hash_keys_validate!(options)
22
22
  end
23
23
 
24
24
  def apply
@@ -29,7 +29,7 @@ module EacRubyUtils
29
29
  private
30
30
 
31
31
  def active_support_require(path)
32
- return false unless options[REQUIRE_DEPENDENCY_OPTION_KEY]
32
+ return false unless options[OPTION_REQUIRE_DEPENDENCY]
33
33
 
34
34
  ::Kernel.require_dependency(path)
35
35
  true
@@ -46,7 +46,7 @@ module EacRubyUtils
46
46
  end
47
47
 
48
48
  def include_modules
49
- return unless options[INCLUDE_MODULES_OPTION_KEY]
49
+ return unless options[OPTION_INCLUDE_MODULES]
50
50
 
51
51
  base.constants.each do |constant_name|
52
52
  constant = base.const_get(constant_name)
@@ -57,11 +57,11 @@ module EacRubyUtils
57
57
  end
58
58
 
59
59
  def base
60
- options[BASE_OPTION_KEY] || raise('Option :base not setted')
60
+ options[OPTION_BASE] || raise('Option :base not setted')
61
61
  end
62
62
 
63
63
  def base?
64
- options[BASE_OPTION_KEY] ? true : false
64
+ options[OPTION_BASE] ? true : false
65
65
  end
66
66
 
67
67
  def kernel_require(path)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EacRubyUtils
4
- VERSION = '0.42.0'
4
+ VERSION = '0.43.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: avm-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.59.0
4
+ version: 0.62.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esquilo Azul Company
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-25 00:00:00.000000000 Z
11
+ date: 2020-08-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aranha-parsers
@@ -274,6 +274,7 @@ files:
274
274
  - Gemfile
275
275
  - exe/avm
276
276
  - lib/avm.rb
277
+ - lib/avm/cached_download.rb
277
278
  - lib/avm/configs.rb
278
279
  - lib/avm/data.rb
279
280
  - lib/avm/data/instance.rb
@@ -289,6 +290,10 @@ files:
289
290
  - lib/avm/docker/image.rb
290
291
  - lib/avm/docker/registry.rb
291
292
  - lib/avm/docker/runner.rb
293
+ - lib/avm/eac_redmine_base0/core_update.rb
294
+ - lib/avm/eac_redmine_base0/data_unit.rb
295
+ - lib/avm/eac_redmine_base0/deploy.rb
296
+ - lib/avm/eac_redmine_base0/instance.rb
292
297
  - lib/avm/executables.rb
293
298
  - lib/avm/files.rb
294
299
  - lib/avm/files/formatter.rb
@@ -358,8 +363,16 @@ files:
358
363
  - lib/avm/instances/entries.rb
359
364
  - lib/avm/instances/entries/entry_reader.rb
360
365
  - lib/avm/instances/entry_keys.rb
366
+ - lib/avm/launcher/context/instance_manager.rb
367
+ - lib/avm/launcher/context/instance_manager/cached_instance.rb
368
+ - lib/avm/launcher/context/instance_manager/cached_instances.rb
369
+ - lib/avm/launcher/errors/base.rb
370
+ - lib/avm/launcher/errors/non_project.rb
371
+ - lib/avm/launcher/instances/base.rb
372
+ - lib/avm/launcher/instances/base/cache.rb
361
373
  - lib/avm/local_projects.rb
362
374
  - lib/avm/local_projects/instance.rb
375
+ - lib/avm/local_projects/jobs/update.rb
363
376
  - lib/avm/patches.rb
364
377
  - lib/avm/patches/object/template.rb
365
378
  - lib/avm/path_string.rb
@@ -367,6 +380,7 @@ files:
367
380
  - lib/avm/projects/stereotype.rb
368
381
  - lib/avm/projects/stereotypes.rb
369
382
  - lib/avm/projects/stereotypes/git.rb
383
+ - lib/avm/projects/stereotypes/git/local_project_mixin.rb
370
384
  - lib/avm/projects/stereotypes/git/publish.rb
371
385
  - lib/avm/projects/stereotypes/git/warp.rb
372
386
  - lib/avm/projects/stereotypes/git_subrepo.rb
@@ -378,7 +392,9 @@ files:
378
392
  - lib/avm/projects/stereotypes/rails_application.rb
379
393
  - lib/avm/projects/stereotypes/redmine_plugin.rb
380
394
  - lib/avm/projects/stereotypes/ruby_gem.rb
395
+ - lib/avm/projects/stereotypes/ruby_gem/local_project_mixin.rb
381
396
  - lib/avm/projects/stereotypes/ruby_gem/publish.rb
397
+ - lib/avm/projects/stereotypes/ruby_gem/update.rb
382
398
  - lib/avm/rails.rb
383
399
  - lib/avm/rails/runners.rb
384
400
  - lib/avm/rails/runners/bundle.rb
@@ -401,9 +417,6 @@ files:
401
417
  - lib/avm/stereotypes/eac_rails_base0/deploy.rb
402
418
  - lib/avm/stereotypes/eac_rails_base0/instance.rb
403
419
  - lib/avm/stereotypes/eac_redmine_base0.rb
404
- - lib/avm/stereotypes/eac_redmine_base0/data_unit.rb
405
- - lib/avm/stereotypes/eac_redmine_base0/deploy.rb
406
- - lib/avm/stereotypes/eac_redmine_base0/instance.rb
407
420
  - lib/avm/stereotypes/eac_ubuntu_base0.rb
408
421
  - lib/avm/stereotypes/eac_ubuntu_base0/apache.rb
409
422
  - lib/avm/stereotypes/eac_ubuntu_base0/apache/site.rb
@@ -429,6 +442,7 @@ files:
429
442
  - lib/avm/stereotypes/postgresql/instance_with.rb
430
443
  - lib/avm/stereotypes/rails.rb
431
444
  - lib/avm/stereotypes/rails/instance.rb
445
+ - lib/avm/sync.rb
432
446
  - lib/avm/tools.rb
433
447
  - lib/avm/tools/runner.rb
434
448
  - lib/avm/tools/runner/eac_rails_base0.rb
@@ -439,6 +453,7 @@ files:
439
453
  - lib/avm/tools/runner/eac_rails_base0/runner.rb
440
454
  - lib/avm/tools/runner/eac_redmine_base0.rb
441
455
  - lib/avm/tools/runner/eac_redmine_base0/bundle.rb
456
+ - lib/avm/tools/runner/eac_redmine_base0/core_update.rb
442
457
  - lib/avm/tools/runner/eac_redmine_base0/data.rb
443
458
  - lib/avm/tools/runner/eac_redmine_base0/data/dump.rb
444
459
  - lib/avm/tools/runner/eac_redmine_base0/deploy.rb
@@ -468,6 +483,7 @@ files:
468
483
  - lib/avm/tools/runner/launcher/publish.rb
469
484
  - lib/avm/tools/runner/local_project.rb
470
485
  - lib/avm/tools/runner/local_project/info.rb
486
+ - lib/avm/tools/runner/local_project/update.rb
471
487
  - lib/avm/tools/runner/ruby.rb
472
488
  - lib/avm/tools/runner/ruby/gems.rb
473
489
  - lib/avm/tools/runner/ruby/gems/generate.rb
@@ -478,7 +494,6 @@ files:
478
494
  - lib/eac_launcher.rb
479
495
  - lib/eac_launcher/context.rb
480
496
  - lib/eac_launcher/context/instance_discovery.rb
481
- - lib/eac_launcher/context/instance_manager.rb
482
497
  - lib/eac_launcher/context/settings.rb
483
498
  - lib/eac_launcher/git.rb
484
499
  - lib/eac_launcher/git/base.rb
@@ -494,8 +509,6 @@ files:
494
509
  - lib/eac_launcher/git/sub_warp_base.rb
495
510
  - lib/eac_launcher/git/warp_base.rb
496
511
  - lib/eac_launcher/instances.rb
497
- - lib/eac_launcher/instances/base.rb
498
- - lib/eac_launcher/instances/base/cache.rb
499
512
  - lib/eac_launcher/instances/error.rb
500
513
  - lib/eac_launcher/instances/runner_helper.rb
501
514
  - lib/eac_launcher/instances/settings.rb
@@ -513,6 +526,8 @@ files:
513
526
  - lib/eac_launcher/vendor.rb
514
527
  - lib/eac_launcher/vendor/github.rb
515
528
  - lib/eac_launcher/version.rb
529
+ - template/avm/eac_redmine_base0/deploy/config/install.sh.template
530
+ - template/avm/eac_redmine_base0/deploy/config/secrets.yml
516
531
  - template/avm/ruby/gems/generator/gemspec.template
517
532
  - template/avm/ruby/gems/generator/root_lib.template
518
533
  - template/avm/ruby/gems/generator/static/Gemfile
@@ -522,8 +537,6 @@ files:
522
537
  - template/avm/self/docker_image/Dockerfile
523
538
  - template/avm/self/docker_image/entrypoint.sh
524
539
  - template/avm/stereotypes/eac_rails_base0/deploy/config/database.yml.template
525
- - template/avm/stereotypes/eac_redmine_base0/deploy/config/install.sh.template
526
- - template/avm/stereotypes/eac_redmine_base0/deploy/config/secrets.yml
527
540
  - template/avm/stereotypes/eac_ubuntu_base0/docker_image/Dockerfile
528
541
  - template/avm/stereotypes/eac_webapp_base0/apache_host/no_ssl.conf
529
542
  - template/avm/stereotypes/eac_wordpress_base0/deploy/wp-config.php.template
@@ -552,6 +565,7 @@ files:
552
565
  - vendor/eac_git/lib/eac_git.rb
553
566
  - vendor/eac_git/lib/eac_git/executables.rb
554
567
  - vendor/eac_git/lib/eac_git/local.rb
568
+ - vendor/eac_git/lib/eac_git/local/dirty_files.rb
555
569
  - vendor/eac_git/lib/eac_git/local/subrepo.rb
556
570
  - vendor/eac_git/lib/eac_git/local/subrepo/config.rb
557
571
  - vendor/eac_git/lib/eac_git/remote.rb
@@ -960,7 +974,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
960
974
  - !ruby/object:Gem::Version
961
975
  version: '0'
962
976
  requirements: []
963
- rubygems_version: 3.0.6
977
+ rubygems_version: 3.0.8
964
978
  signing_key:
965
979
  specification_version: 4
966
980
  summary: Tools for AVM.
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'avm/data/instance/unit'
4
- require 'eac_ruby_utils/core_ext'
5
- require 'open-uri'
6
-
7
- module Avm
8
- module Stereotypes
9
- module EacRedmineBase0
10
- class DataUnit < ::Avm::Data::Instance::Unit
11
- common_constructor :instance
12
-
13
- EXTENSION = '.tar'
14
-
15
- def do_dump(data_path)
16
- ::File.open(data_path, 'wb') do |file|
17
- file << URI.parse(export_url).read
18
- end
19
- end
20
-
21
- def export_url
22
- uri = ::Addressable::URI.parse(instance.read_entry('web.url')) + '/backup/export'
23
- uri.query_values = { key: instance.read_entry('admin.api_key') }
24
- uri.to_s
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'avm/stereotypes/eac_webapp_base0/deploy'
4
- require 'eac_ruby_utils/ruby'
5
-
6
- module Avm
7
- module Stereotypes
8
- module EacRedmineBase0
9
- class Deploy < ::Avm::Stereotypes::EacWebappBase0::Deploy
10
- set_callback :assert_instance_branch, :after, :run_installer
11
-
12
- def run_installer
13
- infom 'Running installer'
14
- ::EacRubyUtils::Ruby.on_clean_environment do
15
- installer_command.system!
16
- end
17
- end
18
-
19
- def installer_command
20
- instance.host_env.command(installer_path, install_task)
21
- end
22
-
23
- def installer_path
24
- ::File.join(instance.read_entry(:fs_path), 'plugins', 'redmine_installer', 'installer',
25
- 'run.sh')
26
- end
27
-
28
- def install_task
29
- if instance.read_entry_optional('web.path').present?
30
- 'redmine_as_apache_path'
31
- else
32
- 'redmine_as_apache_base'
33
- end
34
- end
35
- end
36
- end
37
- end
38
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'avm/stereotypes/eac_redmine_base0/data_unit'
4
- require 'avm/stereotypes/eac_ubuntu_base0/docker_image'
5
- require 'avm/stereotypes/eac_webapp_base0/instance'
6
- require 'avm/stereotypes/rails/instance'
7
-
8
- module Avm
9
- module Stereotypes
10
- module EacRedmineBase0
11
- class Instance < ::Avm::Stereotypes::EacWebappBase0::Instance
12
- include ::Avm::Stereotypes::Rails::Instance
13
-
14
- FILES_UNITS = { files: 'files' }.freeze
15
-
16
- def docker_image_class
17
- ::Avm::Stereotypes::EacUbuntuBase0::DockerImage
18
- end
19
-
20
- def docker_run_arguments
21
- [
22
- '--volume', "#{read_entry(:fs_path)}:/home/myuser/eac_redmine_base0",
23
- '--publish', "#{read_entry(:ssh_port)}:22",
24
- '--publish', "#{read_entry(:http_port)}:80",
25
- '--publish', "#{read_entry(:https_port)}:443"
26
- ]
27
- end
28
-
29
- def data_package
30
- @data_package ||= ::Avm::Data::Instance::Package.new(
31
- self,
32
- units: {
33
- all: ::Avm::Stereotypes::EacRedmineBase0::DataUnit.new(self)
34
- }
35
- )
36
- end
37
- end
38
- end
39
- end
40
- end
@@ -1,94 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require('yaml')
4
-
5
- module EacLauncher
6
- class Context
7
- class InstanceManager
8
- include ::EacRubyUtils::SimpleCache
9
-
10
- def initialize(context)
11
- @context = context
12
- end
13
-
14
- def publish_state_set(instance, stereotype_name, check_status)
15
- data = cached_instances_file_content_uncached
16
- data[instance.logical] ||= {}
17
- data[instance.logical][:publish_state] ||= {}
18
- data[instance.logical][:publish_state][stereotype_name] = check_status
19
- write_cache_file(data)
20
- end
21
-
22
- def pending_instances
23
- instances.select { |instance| pending_instance?(instance) }
24
- end
25
-
26
- private
27
-
28
- def instances_uncached
29
- (cached_instances || search_instances).select(&:included?)
30
- end
31
-
32
- def search_instances
33
- cache_instances(::EacLauncher::Context::InstanceDiscovery.new(@context).instances)
34
- end
35
-
36
- def cached_instances
37
- return nil if @context.recache
38
- return nil unless cached_instances_file_content
39
-
40
- CachedInstances.new(cached_instances_file_content).instances
41
- end
42
-
43
- def cached_instances_file_content_uncached
44
- r = YAML.load_file(cache_file_path)
45
- r.is_a?(::Hash) ? r : nil
46
- rescue Errno::ENOENT
47
- nil
48
- end
49
-
50
- def cache_instances(instances)
51
- write_cache_file(Hash[instances.map { |i| [i.logical, i.to_h] }])
52
- instances
53
- end
54
-
55
- def write_cache_file(data)
56
- ::File.write(cache_file_path, data.to_yaml)
57
- end
58
-
59
- def cache_file_path
60
- ::File.join(@context.cache_root, 'instances.yml')
61
- end
62
-
63
- def pending_instance?(instance)
64
- data = cached_instances_file_content
65
- return false unless data[instance.logical]
66
- return false unless data[instance.logical][:publish_state].is_a?(Hash)
67
-
68
- data[instance.logical][:publish_state].any? do |_k, v|
69
- ::EacLauncher::Publish::CheckResult.pending_status?(v)
70
- end
71
- end
72
-
73
- class CachedInstances
74
- def initialize(content)
75
- @content = content
76
- @instances = {}
77
- end
78
-
79
- def instances
80
- @content.keys.map { |k| by_logical_path(k) }
81
- end
82
-
83
- def by_logical_path(key)
84
- return @instances[key] if @instances.key?(key)
85
-
86
- h = @content[key]
87
- parent_instance = h[:parent] ? by_logical_path(h[:parent]) : nil
88
- path = ::EacLauncher::Paths::Logical.from_h(@context, h)
89
- @instances[key] = ::EacLauncher::Instances::Base.instanciate(path, parent_instance)
90
- end
91
- end
92
- end
93
- end
94
- end