avm 0.6.1 → 0.10.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/avm/data/package/dump.rb +3 -3
  3. data/lib/avm/data/rotate.rb +107 -0
  4. data/lib/avm/docker/runner.rb +8 -0
  5. data/lib/avm/instances/application.rb +25 -0
  6. data/lib/avm/instances/base/auto_values/access.rb +40 -0
  7. data/lib/avm/instances/base/auto_values/admin.rb +19 -0
  8. data/lib/avm/instances/base/auto_values/data.rb +26 -0
  9. data/lib/avm/instances/base/auto_values/database.rb +76 -0
  10. data/lib/avm/instances/base/auto_values/filesystem.rb +45 -0
  11. data/lib/avm/instances/base/auto_values/mailer.rb +34 -0
  12. data/lib/avm/instances/base/auto_values/ruby.rb +15 -0
  13. data/lib/avm/instances/base/auto_values/source.rb +15 -0
  14. data/lib/avm/instances/base/auto_values/system.rb +23 -0
  15. data/lib/avm/instances/base/auto_values/web.rb +46 -0
  16. data/lib/avm/instances/base/auto_values.rb +21 -0
  17. data/lib/avm/instances/base/dockerizable.rb +45 -0
  18. data/lib/avm/instances/base/entry_keys.rb +22 -0
  19. data/lib/avm/instances/base.rb +64 -0
  20. data/lib/avm/instances/entries.rb +43 -0
  21. data/lib/avm/instances/entry.rb +54 -0
  22. data/lib/avm/instances/entry_keys.rb +57 -0
  23. data/lib/avm/instances/runner.rb +38 -0
  24. data/lib/avm/instances.rb +8 -0
  25. data/lib/avm/registry/base.rb +12 -10
  26. data/lib/avm/registry.rb +1 -1
  27. data/lib/avm/runners/base.rb +31 -0
  28. data/lib/avm/scms/base.rb +5 -0
  29. data/lib/avm/scms/inflector.rb +22 -0
  30. data/lib/avm/self/docker_image.rb +14 -0
  31. data/lib/avm/self/instance/entry_keys.rb +12 -0
  32. data/lib/avm/self/instance.rb +24 -0
  33. data/lib/avm/sources/base/configuration.rb +37 -0
  34. data/lib/avm/sources/base/testing.rb +21 -0
  35. data/lib/avm/sources/base.rb +9 -25
  36. data/lib/avm/sources/tester.rb +24 -0
  37. data/lib/avm/sources/tests/builder.rb +83 -0
  38. data/lib/avm/sources/tests/performer.rb +35 -0
  39. data/lib/avm/sources/tests/result.rb +15 -0
  40. data/lib/avm/sources/tests/single.rb +56 -0
  41. data/lib/avm/sources/tests.rb +11 -0
  42. data/lib/avm/version.rb +1 -1
  43. metadata +58 -5
  44. data/lib/avm/source_stereotypes/base.rb +0 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a8d74639333b0b7c2b8f8e171c22dd6184ec276653bfe46ac84cbddfdf05d0c
4
- data.tar.gz: f897626773b7aa103b80347a7b41740c6a5c66c3aee68e7834ee80e44263fc3a
3
+ metadata.gz: 38b3cb78a40be49432757cf6da098d59bf73ff4873b19c6797fdba2d7e4d287f
4
+ data.tar.gz: 5fe80c98b3c824af779750f5c1068c963c2ffbe178162dfc13b48d601c6fc966
5
5
  SHA512:
6
- metadata.gz: 9122946512714522606f24e5e3c79f64b773a7f4229ed25cb8c3a7e2e82b62e86a3ec4354230fdb2bce366bb36ad0e27593cd42e3e9380ab5eb82854eafbff55
7
- data.tar.gz: 71b9e84a0416b0bcefccbbd283d78b5da476e1d5e366746e245eb75eb6c5f22752ef3871a4f571363554f0f99354c366823193dd6a84d3f92faa981b82299d52
6
+ metadata.gz: ce0716e32d4450fddd8707145357b4d36aae42a173e0d91e7adbab4087ad833d57917376a3d43cc2bf65fc4bc3a401fc6db8d537e1e9a1a8d158c0702fca3093
7
+ data.tar.gz: e71070a17e331c95aa719131f0e3ffe9af461150cc3ae8b0df05a0e192ecc58fb02f7dee38e8394fafce5ee890b4528c34661a58b44ff4b73cac6c84c7c471a0
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'avm/tools/core_ext'
4
- require 'avm/files/rotate'
3
+ require 'avm/data/rotate'
4
+ require 'eac_ruby_utils/core_ext'
5
5
  require 'minitar'
6
6
 
7
7
  module Avm
@@ -88,7 +88,7 @@ module Avm
88
88
  return unless existing == EXISTING_ROTATE
89
89
 
90
90
  infom "Rotating \"#{data_file_path}\"..."
91
- ::Avm::Files::Rotate.new(data_file_path).run
91
+ ::Avm::Data::Rotate.new(data_file_path).run
92
92
  end
93
93
 
94
94
  def new_build_path
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/object/blank'
4
+ require 'eac_ruby_utils/simple_cache'
5
+
6
+ module Avm
7
+ module Data
8
+ class Rotate
9
+ include ::EacRubyUtils::SimpleCache
10
+
11
+ attr_reader :options, :source_path
12
+
13
+ def initialize(source_path, options = {})
14
+ @source_path = source_path
15
+ @options = options
16
+ end
17
+
18
+ def run
19
+ validate_msg = validate
20
+ return validate_msg if validate_msg.present?
21
+
22
+ ::FileUtils.mv(source_path, target_path)
23
+ check_space_limit
24
+ nil
25
+ end
26
+
27
+ def space_limit
28
+ r = options[:space_limit].try(:to_i)
29
+ return r if r.present? && r.positive?
30
+
31
+ r
32
+ end
33
+
34
+ def space_used
35
+ rotated_files.inject(0) { |a, e| a + ::File.size(e) }
36
+ end
37
+
38
+ def rotated_files
39
+ ::Dir["#{dirname}/#{source_basename_without_extension}*#{source_extension}"]
40
+ end
41
+
42
+ def oldest_rotated_file
43
+ rotated_files.min_by { |file| [::File.mtime(file)] }
44
+ end
45
+
46
+ private
47
+
48
+ def check_space_limit
49
+ return unless space_limit
50
+
51
+ while space_used > space_limit
52
+ file = oldest_rotated_file
53
+ unless file
54
+ raise 'oldest_rotated_file returned nil ' \
55
+ "(Limit: #{space_limit}, used: #{space_used})"
56
+ end
57
+ ::File.delete(file)
58
+ end
59
+ end
60
+
61
+ def validate
62
+ return "Source file \"#{source_path}\" does not exist" unless ::File.exist?(source_path)
63
+ return "File \"#{source_path}\" is already rotated" if source_rotated?
64
+
65
+ nil
66
+ end
67
+
68
+ def source_rotated?
69
+ source_basename_without_extension.match(/[PN]\d{4}\z/)
70
+ end
71
+
72
+ def source_extension_uncached
73
+ file_extension(::File.basename(source_path))
74
+ end
75
+
76
+ def source_basename_without_extension
77
+ ::File.basename(source_path, source_extension)
78
+ end
79
+
80
+ def target_path_uncached
81
+ ::File.join(dirname, target_basename)
82
+ end
83
+
84
+ def dirname
85
+ ::File.dirname(source_path)
86
+ end
87
+
88
+ def target_basename
89
+ source_basename_without_extension + target_suffix + source_extension
90
+ end
91
+
92
+ def target_suffix
93
+ return '_UNKNOWN_MTIME' unless ::File.exist?(source_path)
94
+
95
+ t = ::File.mtime(source_path)
96
+ t.strftime('_%Y-%m-%d_%H-%M-%S_') + t.strftime('%z').gsub(/\A\+/, 'P').gsub(/\A\-/, 'N')
97
+ end
98
+
99
+ def file_extension(basename)
100
+ extension = ::File.extname(basename)
101
+ return '' if extension.blank?
102
+
103
+ file_extension(::File.basename(basename, extension)) + extension
104
+ end
105
+ end
106
+ end
107
+ end
@@ -13,6 +13,7 @@ module Avm
13
13
 
14
14
  runner_with :help do
15
15
  desc 'Manipulate Docker images.'
16
+ bool_opt '-I', '--image-name', 'Output image name.'
16
17
  arg_opt '-n', '--registry-name', 'Docker registry\'s name.'
17
18
  bool_opt '-p', '--push', 'Push the image to Docker registry.'
18
19
  bool_opt '-r', '--run', 'Run or start a container with builded image.'
@@ -27,6 +28,7 @@ module Avm
27
28
  setup
28
29
  banner
29
30
  build
31
+ output_image_name
30
32
  push
31
33
  container_run
32
34
  end
@@ -84,6 +86,12 @@ module Avm
84
86
  )
85
87
  end
86
88
 
89
+ def output_image_name
90
+ return unless parsed.image_name
91
+
92
+ out(docker_image.tag.to_s.strip + "\n")
93
+ end
94
+
87
95
  def registry_uncached
88
96
  registry_from_option || registry_from_instance || registry_from_default ||
89
97
  fatal_error('No registry defined')
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'avm/instances/entries'
4
+
5
+ module Avm
6
+ module Instances
7
+ class Application
8
+ include ::Avm::Instances::Entries
9
+
10
+ attr_reader :id
11
+
12
+ def initialize(id)
13
+ @id = id.to_s
14
+ end
15
+
16
+ def to_s
17
+ id
18
+ end
19
+
20
+ def instance(suffix)
21
+ ::Avm::Instances::Base.new(self, suffix)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Avm
4
+ module Instances
5
+ class Base
6
+ module AutoValues
7
+ module Access
8
+ def auto_access
9
+ read_entry_optional('ssh.url').present? ? 'ssh' : 'local'
10
+ end
11
+
12
+ def auto_ssh_hostname
13
+ inherited_entry_value(::Avm::Instances::EntryKeys::HOST_ID, 'ssh.hostname')
14
+ end
15
+
16
+ def auto_ssh_port
17
+ inherited_entry_value(::Avm::Instances::EntryKeys::HOST_ID, 'ssh.port') || 22
18
+ end
19
+
20
+ def auto_ssh_username
21
+ inherited_entry_value(::Avm::Instances::EntryKeys::HOST_ID, 'ssh.username')
22
+ end
23
+
24
+ def auto_ssh_url
25
+ inherited_entry_value(::Avm::Instances::EntryKeys::HOST_ID, 'ssh.url') ||
26
+ auto_ssh_url_by_parts
27
+ end
28
+
29
+ def auto_ssh_url_by_parts
30
+ read_entry_optional('ssh.hostname').if_present do |a|
31
+ a = read_entry_optional('ssh.username').if_present(a) { |v| "#{v}@#{a}" }
32
+ a = read_entry_optional('ssh.port').if_present(a) { |v| "#{a}:#{v}" }
33
+ "ssh://#{a}"
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Avm
4
+ module Instances
5
+ class Base
6
+ module AutoValues
7
+ module Admin
8
+ def auto_admin_email
9
+ inherited_entry_value(::Avm::Instances::EntryKeys::HOST_ID, 'admin.email')
10
+ end
11
+
12
+ def auto_admin_name
13
+ inherited_entry_value(::Avm::Instances::EntryKeys::HOST_ID, 'admin.name')
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'avm/data/package/dump'
4
+ require 'avm/self/instance'
5
+
6
+ module Avm
7
+ module Instances
8
+ class Base
9
+ module AutoValues
10
+ module Data
11
+ def auto_data_default_dump_path
12
+ ::Avm::Self
13
+ .instance
14
+ .read_entry_optional(::Avm::Self::Instance::EntryKeys::DATA_DEFAULT_PATH)
15
+ .if_present do |v|
16
+ ::File.join(
17
+ v,
18
+ "#{id}#{::Avm::Data::Instance::Package::Dump::DEFAULT_FILE_EXTENSION}"
19
+ )
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'avm/instances/entry_keys'
4
+
5
+ module Avm
6
+ module Instances
7
+ class Base
8
+ module AutoValues
9
+ module Database
10
+ DEFAULT_EXTRA = ''
11
+ DEFAULT_HOSTNAME = '127.0.0.1'
12
+ DEFAULT_LIMIT = 5
13
+ DEFAULT_PORTS = {
14
+ 'postgresql' => 5432,
15
+ 'mysql' => 3306,
16
+ 'oracle' => 1521,
17
+ 'sqlserver' => 1433
18
+ }.freeze
19
+ DEFAULT_SYSTEM = 'postgresql'
20
+ DEFAULT_TIMEOUT = 5000
21
+
22
+ def auto_database_extra
23
+ database_auto_common('hostname') || DEFAULT_EXTRA
24
+ end
25
+
26
+ def auto_database_name
27
+ inherited_entry_value(::Avm::Instances::EntryKeys::DATABASE_ID,
28
+ ::Avm::Instances::EntryKeys::DATABASE_NAME) || id
29
+ end
30
+
31
+ def auto_database_hostname
32
+ database_auto_common('hostname') || DEFAULT_HOSTNAME
33
+ end
34
+
35
+ def auto_database_limit
36
+ database_auto_common('limit') || DEFAULT_LIMIT
37
+ end
38
+
39
+ def auto_database_password
40
+ database_auto_common('password')
41
+ end
42
+
43
+ def auto_database_port
44
+ database_auto_common('port') || database_port_by_system
45
+ end
46
+
47
+ def auto_database_username
48
+ database_auto_common('username')
49
+ end
50
+
51
+ def auto_database_system
52
+ database_auto_common('system') || DEFAULT_SYSTEM
53
+ end
54
+
55
+ def auto_database_timeout
56
+ database_auto_common('timeout') || DEFAULT_TIMEOUT
57
+ end
58
+
59
+ private
60
+
61
+ def database_auto_common(suffix)
62
+ database_key = ::Avm::Instances::EntryKeys.const_get("database_#{suffix}".upcase)
63
+ inherited_entry_value(::Avm::Instances::EntryKeys::DATABASE_ID, database_key) ||
64
+ inherited_entry_value(::Avm::Instances::EntryKeys::HOST_ID, database_key)
65
+ end
66
+
67
+ def database_port_by_system
68
+ read_entry_optional(::Avm::Instances::EntryKeys::DATABASE_SYSTEM).if_present do |v|
69
+ DEFAULT_PORTS.fetch(v)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Avm
4
+ module Instances
5
+ class Base
6
+ module AutoValues
7
+ module Filesystem
8
+ FS_PATH_KEY = :fs_path
9
+
10
+ def auto_fs_path
11
+ inherited_entry_value(::Avm::Instances::EntryKeys::HOST_ID, FS_PATH_KEY) do |v|
12
+ v + '/' + id
13
+ end
14
+ end
15
+
16
+ def auto_data_fs_path
17
+ inherited_entry_value(::Avm::Instances::EntryKeys::HOST_ID, :data_fs_path) do |v|
18
+ v + '/' + id
19
+ end
20
+ end
21
+
22
+ def auto_fs_url
23
+ auto_fs_url_with_ssh || auto_fs_url_without_ssh
24
+ end
25
+
26
+ def auto_fs_url_with_ssh
27
+ read_entry_optional('ssh.url').if_present do |ssh_url|
28
+ read_entry_optional('fs_path').if_present do |fs_path|
29
+ "#{ssh_url}#{fs_path}"
30
+ end
31
+ end
32
+ end
33
+
34
+ def auto_fs_url_without_ssh
35
+ return nil if read_entry_optional('ssh.url').present?
36
+
37
+ read_entry_optional('fs_path').if_present do |fs_path|
38
+ "file://#{fs_path}"
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'avm/instances/entry'
4
+ require 'avm/instances/entry_keys'
5
+
6
+ module Avm
7
+ module Instances
8
+ class Base
9
+ module AutoValues
10
+ module Mailer
11
+ ::Avm::Instances::EntryKeys.all.select { |c| c.to_s.start_with?('mailer.') }
12
+ .reject { |c| c == ::Avm::Instances::EntryKeys::MAILER_ID }
13
+ .each do |mailer_key|
14
+ define_method ::Avm::Instances::Entry.auto_value_method_name(mailer_key) do
15
+ mailer_auto_common(mailer_key)
16
+ end
17
+ end
18
+
19
+ def auto_mailer_id
20
+ inherited_entry_value(::Avm::Instances::EntryKeys::HOST_ID,
21
+ ::Avm::Instances::EntryKeys::MAILER_ID) ||
22
+ read_entry_optional(::Avm::Instances::EntryKeys::HOST_ID)
23
+ end
24
+
25
+ private
26
+
27
+ def mailer_auto_common(mailer_key)
28
+ inherited_entry_value(::Avm::Instances::EntryKeys::MAILER_ID, mailer_key)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Avm
4
+ module Instances
5
+ class Base
6
+ module AutoValues
7
+ module Ruby
8
+ def auto_ruby_version
9
+ inherited_entry_value(::Avm::Instances::EntryKeys::HOST_ID, 'ruby.version')
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Avm
4
+ module Instances
5
+ class Base
6
+ module AutoValues
7
+ module Source
8
+ def auto_source_instance_id
9
+ "#{application.id}_dev"
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'addressable'
4
+
5
+ module Avm
6
+ module Instances
7
+ class Base
8
+ module AutoValues
9
+ module System
10
+ def auto_system_username
11
+ inherited_entry_value(::Avm::Instances::EntryKeys::HOST_ID, 'system.username') ||
12
+ read_entry_optional('ssh.username')
13
+ end
14
+
15
+ def auto_system_groupname
16
+ inherited_entry_value(::Avm::Instances::EntryKeys::HOST_ID, 'system.groupname') ||
17
+ read_entry_optional('system.username')
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'addressable'
4
+ require 'avm/instances/entry_keys'
5
+
6
+ module Avm
7
+ module Instances
8
+ class Base
9
+ module AutoValues
10
+ module Web
11
+ def auto_web_authority
12
+ web_url_as_uri(&:authority)
13
+ end
14
+
15
+ def auto_web_hostname
16
+ web_url_as_uri(&:host)
17
+ end
18
+
19
+ def auto_web_path
20
+ web_url_as_uri(&:path)
21
+ end
22
+
23
+ def auto_web_port
24
+ web_url_as_uri(&:port)
25
+ end
26
+
27
+ def auto_web_scheme
28
+ web_url_as_uri(&:scheme)
29
+ end
30
+
31
+ def auto_web_userinfo
32
+ web_url_as_uri(&:userinfo)
33
+ end
34
+
35
+ private
36
+
37
+ def web_url_as_uri
38
+ read_entry_optional(::Avm::Instances::EntryKeys::WEB_URL).if_present do |v|
39
+ yield(::Addressable::URI.parse(v))
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/require_sub'
4
+ ::EacRubyUtils.require_sub(__FILE__)
5
+
6
+ module Avm
7
+ module Instances
8
+ class Base
9
+ module AutoValues
10
+ extend ::ActiveSupport::Concern
11
+
12
+ included do
13
+ %w[Access Admin Data Database Filesystem Mailer Ruby Source System Web]
14
+ .each do |class_name|
15
+ include const_get(class_name)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_docker/executables'
4
+ require 'eac_ruby_utils/core_ext'
5
+ require 'avm/docker/container'
6
+
7
+ module Avm
8
+ module Instances
9
+ class Base
10
+ module Dockerizable
11
+ enable_simple_cache
12
+ attr_reader :docker_image_options
13
+
14
+ def docker_image_options=(options)
15
+ @docker_image_options = ::ActiveSupport::HashWithIndifferentAccess.new(options)
16
+ reset_cache
17
+ end
18
+
19
+ def docker_container_exist?
20
+ ::EacDocker::Executables.docker.command.append(
21
+ ['ps', '-qaf', "name=#{docker_container_name}"]
22
+ ).execute!.present?
23
+ end
24
+
25
+ def docker_container_name
26
+ id
27
+ end
28
+
29
+ private
30
+
31
+ def docker_container_uncached
32
+ ::Avm::Docker::Container.new(self)
33
+ end
34
+
35
+ def docker_image_uncached
36
+ r = docker_image_class.new(docker_image_options.fetch(:registry))
37
+ r.instance = self if r.respond_to?(:instance)
38
+ r.version = docker_image_options[:version] if docker_image_options.key?(:version)
39
+ r.snapshot = docker_image_options[:snapshot] if docker_image_options.key?(:snapshot)
40
+ r
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'avm/instances/entry_keys'
4
+
5
+ module Avm
6
+ module Instances
7
+ class Base
8
+ module EntryKeys
9
+ ::Avm::Instances::EntryKeys.all.each do |key|
10
+ method_name = key.to_s.variableize
11
+ define_method method_name do
12
+ read_entry(key)
13
+ end
14
+
15
+ define_method "#{method_name}_optional" do
16
+ read_entry(key, required: false)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end