torikago 0.0.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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.ja.md +144 -0
- data/README.md +142 -0
- data/exe/torikago +8 -0
- data/lib/torikago/checker.rb +159 -0
- data/lib/torikago/cli.rb +235 -0
- data/lib/torikago/configuration.rb +45 -0
- data/lib/torikago/current_execution.rb +23 -0
- data/lib/torikago/engine_container.rb +340 -0
- data/lib/torikago/errors.rb +16 -0
- data/lib/torikago/gateway.rb +86 -0
- data/lib/torikago/package_api_updater.rb +101 -0
- data/lib/torikago/registry.rb +34 -0
- data/lib/torikago/version.rb +3 -0
- data/lib/torikago.rb +71 -0
- data/test/test_helper.rb +9 -0
- data/test/torikago/checker.rb +164 -0
- data/test/torikago/cli.rb +143 -0
- data/test/torikago/configuration.rb +74 -0
- data/test/torikago/engine_container.rb +549 -0
- data/test/torikago/gateway.rb +155 -0
- data/test/torikago/package_api_updater.rb +94 -0
- data/test/torikago/registry.rb +83 -0
- data/test/torikago/version.rb +11 -0
- data/test/torikago.rb +110 -0
- metadata +73 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
require_relative "../test_helper"
|
|
2
|
+
require "fileutils"
|
|
3
|
+
require "tmpdir"
|
|
4
|
+
require "yaml"
|
|
5
|
+
|
|
6
|
+
class TorikagoPackageApiUpdaterTest < Minitest::Test
|
|
7
|
+
def test_update_package_api_creates_manifest_from_package_api_files
|
|
8
|
+
Dir.mktmpdir("torikago-package-api-updater") do |module_root|
|
|
9
|
+
package_api_dir = File.join(module_root, "app/package_api/foo")
|
|
10
|
+
FileUtils.mkdir_p(package_api_dir)
|
|
11
|
+
|
|
12
|
+
File.write(File.join(package_api_dir, "user_create_command.rb"), "")
|
|
13
|
+
File.write(File.join(package_api_dir, "user_find_query.rb"), "")
|
|
14
|
+
|
|
15
|
+
configuration = Torikago::Configuration.new
|
|
16
|
+
configuration.register(:foo, root: module_root)
|
|
17
|
+
|
|
18
|
+
updates = Torikago::PackageApiUpdater.new(configuration: configuration).call
|
|
19
|
+
manifest = YAML.safe_load(File.read(File.join(module_root, "package_api.yml")))
|
|
20
|
+
|
|
21
|
+
assert_equal [Pathname(File.join(module_root, "package_api.yml"))], updates.values
|
|
22
|
+
assert_equal(
|
|
23
|
+
{
|
|
24
|
+
"exports" => {
|
|
25
|
+
"Foo::UserCreateCommand" => { "allowed_callers" => [] },
|
|
26
|
+
"Foo::UserFindQuery" => { "allowed_callers" => [] }
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
manifest
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_update_package_api_preserves_existing_allowed_callers
|
|
35
|
+
Dir.mktmpdir("torikago-package-api-updater") do |module_root|
|
|
36
|
+
package_api_dir = File.join(module_root, "app/package_api/foo")
|
|
37
|
+
FileUtils.mkdir_p(package_api_dir)
|
|
38
|
+
|
|
39
|
+
File.write(File.join(package_api_dir, "user_create_command.rb"), "")
|
|
40
|
+
File.write(
|
|
41
|
+
File.join(module_root, "package_api.yml"),
|
|
42
|
+
<<~YAML
|
|
43
|
+
exports:
|
|
44
|
+
Foo::UserCreateCommand:
|
|
45
|
+
allowed_callers:
|
|
46
|
+
- bar
|
|
47
|
+
YAML
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
configuration = Torikago::Configuration.new
|
|
51
|
+
configuration.register(:foo, root: module_root)
|
|
52
|
+
|
|
53
|
+
Torikago::PackageApiUpdater.new(configuration: configuration).call(:foo)
|
|
54
|
+
manifest = YAML.safe_load(File.read(File.join(module_root, "package_api.yml")))
|
|
55
|
+
|
|
56
|
+
assert_equal ["bar"], manifest.dig("exports", "Foo::UserCreateCommand", "allowed_callers")
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def test_update_package_api_uses_a_configured_entrypoint_directory
|
|
61
|
+
Dir.mktmpdir("torikago-package-api-updater") do |module_root|
|
|
62
|
+
package_api_dir = File.join(module_root, "components/public_api/foo")
|
|
63
|
+
FileUtils.mkdir_p(package_api_dir)
|
|
64
|
+
|
|
65
|
+
File.write(File.join(package_api_dir, "user_create_command.rb"), "")
|
|
66
|
+
|
|
67
|
+
configuration = Torikago::Configuration.new
|
|
68
|
+
configuration.register(:foo, root: module_root, entrypoint: "components/public_api")
|
|
69
|
+
|
|
70
|
+
Torikago::PackageApiUpdater.new(configuration: configuration).call(:foo)
|
|
71
|
+
manifest = YAML.safe_load(File.read(File.join(module_root, "package_api.yml")))
|
|
72
|
+
|
|
73
|
+
assert_equal(
|
|
74
|
+
{ "allowed_callers" => [] },
|
|
75
|
+
manifest.dig("exports", "Foo::UserCreateCommand")
|
|
76
|
+
)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def test_update_package_api_does_not_scan_parent_when_configured_entrypoint_directory_is_missing
|
|
81
|
+
Dir.mktmpdir("torikago-package-api-updater") do |module_root|
|
|
82
|
+
FileUtils.mkdir_p(File.join(module_root, "app/models/foo"))
|
|
83
|
+
File.write(File.join(module_root, "app/models/foo/widget.rb"), "")
|
|
84
|
+
|
|
85
|
+
configuration = Torikago::Configuration.new
|
|
86
|
+
configuration.register(:foo, root: module_root, entrypoint: "app/package_api")
|
|
87
|
+
|
|
88
|
+
Torikago::PackageApiUpdater.new(configuration: configuration).call(:foo)
|
|
89
|
+
manifest = YAML.safe_load(File.read(File.join(module_root, "package_api.yml")))
|
|
90
|
+
|
|
91
|
+
assert_equal({ "exports" => {} }, manifest)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require_relative "../test_helper"
|
|
2
|
+
|
|
3
|
+
class TorikagoRegistryTest < Minitest::Test
|
|
4
|
+
def setup
|
|
5
|
+
@configuration = Torikago::Configuration.new
|
|
6
|
+
@configuration.register(
|
|
7
|
+
:foo,
|
|
8
|
+
root: "/modules/foo",
|
|
9
|
+
entrypoint: "lib/foo/box_runtime.rb",
|
|
10
|
+
setup: "config/box_setup.rb",
|
|
11
|
+
gemfile: "Gemfile"
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def test_resolve_returns_a_container_for_a_registered_module
|
|
16
|
+
registry = Torikago::Registry.new(configuration: @configuration) do |definition|
|
|
17
|
+
{
|
|
18
|
+
name: definition.name,
|
|
19
|
+
root: definition.root.to_s,
|
|
20
|
+
entrypoint: definition.entrypoint,
|
|
21
|
+
setup: definition.setup,
|
|
22
|
+
gemfile: definition.gemfile
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
container = registry.resolve(:foo)
|
|
27
|
+
|
|
28
|
+
assert_equal :foo, container[:name]
|
|
29
|
+
assert_equal "/modules/foo", container[:root]
|
|
30
|
+
assert_equal "lib/foo/box_runtime.rb", container[:entrypoint]
|
|
31
|
+
assert_equal "config/box_setup.rb", container[:setup]
|
|
32
|
+
assert_equal "Gemfile", container[:gemfile]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_resolve_reuses_the_same_container_for_the_same_module
|
|
36
|
+
build_count = 0
|
|
37
|
+
|
|
38
|
+
registry = Torikago::Registry.new(configuration: @configuration) do |_definition|
|
|
39
|
+
build_count += 1
|
|
40
|
+
Object.new
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
first = registry.resolve(:foo)
|
|
44
|
+
second = registry.resolve("foo")
|
|
45
|
+
|
|
46
|
+
assert_same first, second
|
|
47
|
+
assert_equal 1, build_count
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def test_resolve_fails_clearly_for_an_unknown_module
|
|
51
|
+
registry = Torikago::Registry.new(configuration: @configuration) do |_definition|
|
|
52
|
+
Object.new
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
error = assert_raises(KeyError) do
|
|
56
|
+
registry.resolve(:missing)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
assert_match(/missing/, error.message)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def test_resolve_uses_the_container_factory_not_the_gateway
|
|
63
|
+
captured_definition = nil
|
|
64
|
+
|
|
65
|
+
registry = Torikago::Registry.new(configuration: @configuration) do |definition|
|
|
66
|
+
captured_definition = definition
|
|
67
|
+
Object.new
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
registry.resolve(:foo)
|
|
71
|
+
|
|
72
|
+
refute_nil captured_definition
|
|
73
|
+
assert_equal :foo, captured_definition.name
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def test_resolve_builds_an_engine_container_by_default
|
|
77
|
+
registry = Torikago::Registry.new(configuration: @configuration)
|
|
78
|
+
|
|
79
|
+
container = registry.resolve(:foo)
|
|
80
|
+
|
|
81
|
+
assert_instance_of Torikago::EngineContainer, container
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require_relative "../test_helper"
|
|
2
|
+
|
|
3
|
+
class TorikagoVersionTest < Minitest::Test
|
|
4
|
+
def test_has_a_version_number
|
|
5
|
+
refute_nil ::Torikago::VERSION
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def test_version_uses_semver_like_format
|
|
9
|
+
assert_match(/\A\d+\.\d+\.\d+\z/, ::Torikago::VERSION)
|
|
10
|
+
end
|
|
11
|
+
end
|
data/test/torikago.rb
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
require_relative "test_helper"
|
|
2
|
+
require "open3"
|
|
3
|
+
require "rbconfig"
|
|
4
|
+
|
|
5
|
+
class TorikagoTest < Minitest::Test
|
|
6
|
+
def test_version_is_available_when_module_is_included
|
|
7
|
+
object = Class.new { include Torikago }.new
|
|
8
|
+
|
|
9
|
+
assert_equal Torikago::VERSION, object.version
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_configure_yields_the_shared_configuration
|
|
13
|
+
original_configuration = Torikago.configuration
|
|
14
|
+
|
|
15
|
+
begin
|
|
16
|
+
yielded_configuration = nil
|
|
17
|
+
|
|
18
|
+
Torikago.configure do |config|
|
|
19
|
+
yielded_configuration = config
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
assert_same Torikago.configuration, yielded_configuration
|
|
23
|
+
ensure
|
|
24
|
+
Torikago.instance_variable_set(:@configuration, original_configuration)
|
|
25
|
+
Torikago.instance_variable_set(:@registry, nil)
|
|
26
|
+
Torikago.instance_variable_set(:@gateway, nil)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_warns_when_loaded_in_rails_without_ruby_box
|
|
31
|
+
script = <<~RUBY
|
|
32
|
+
$LOAD_PATH.unshift(ARGV.fetch(0))
|
|
33
|
+
|
|
34
|
+
module Rails
|
|
35
|
+
class << self
|
|
36
|
+
attr_accessor :application
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
self.application = Object.new
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
require "torikago"
|
|
43
|
+
RUBY
|
|
44
|
+
|
|
45
|
+
_stdout, stderr, status = Open3.capture3(
|
|
46
|
+
{ "RUBY_BOX" => nil },
|
|
47
|
+
RbConfig.ruby,
|
|
48
|
+
"-e",
|
|
49
|
+
script,
|
|
50
|
+
File.expand_path("../lib", __dir__)
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
assert_predicate status, :success?, stderr
|
|
54
|
+
assert_match(/\[warn\].*RUBY_BOX=1/, stderr)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_does_not_warn_when_ruby_box_is_enabled
|
|
58
|
+
with_ruby_box_env("1") do
|
|
59
|
+
with_temporary_rails_constant(application: Object.new) do
|
|
60
|
+
assert_output(nil, "") do
|
|
61
|
+
Torikago.send(:warn_if_ruby_box_is_disabled_in_rails!)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def test_does_not_warn_outside_rails
|
|
68
|
+
with_ruby_box_env(nil) do
|
|
69
|
+
assert_output(nil, "") do
|
|
70
|
+
Torikago.send(:warn_if_ruby_box_is_disabled_in_rails!)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def test_does_not_warn_when_rails_constant_exists_but_no_application_is_booted
|
|
76
|
+
with_ruby_box_env(nil) do
|
|
77
|
+
with_temporary_rails_constant(application: nil) do
|
|
78
|
+
assert_output(nil, "") do
|
|
79
|
+
Torikago.send(:warn_if_ruby_box_is_disabled_in_rails!)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
def with_ruby_box_env(value)
|
|
88
|
+
original = ENV["RUBY_BOX"]
|
|
89
|
+
ENV["RUBY_BOX"] = value
|
|
90
|
+
yield
|
|
91
|
+
ensure
|
|
92
|
+
ENV["RUBY_BOX"] = original
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def with_temporary_rails_constant(application:)
|
|
96
|
+
had_rails = Object.const_defined?(:Rails)
|
|
97
|
+
unless had_rails
|
|
98
|
+
rails_module = Module.new do
|
|
99
|
+
singleton_class.attr_accessor :application
|
|
100
|
+
end
|
|
101
|
+
rails_module.application = application
|
|
102
|
+
Object.const_set(:Rails, rails_module)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
Rails.application = application if Rails.respond_to?(:application=)
|
|
106
|
+
yield
|
|
107
|
+
ensure
|
|
108
|
+
Object.send(:remove_const, :Rails) if !had_rails && Object.const_defined?(:Rails)
|
|
109
|
+
end
|
|
110
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: torikago
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- se4weed
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: |
|
|
13
|
+
torikago is a Ruby gem for modular monolith runtime isolation. It boots
|
|
14
|
+
module-scoped runtimes with Ruby::Box and routes host app and inter-module
|
|
15
|
+
communication through explicit gateway and registry objects.
|
|
16
|
+
email:
|
|
17
|
+
- se4weed@gmail.com
|
|
18
|
+
executables:
|
|
19
|
+
- torikago
|
|
20
|
+
extensions: []
|
|
21
|
+
extra_rdoc_files:
|
|
22
|
+
- README.ja.md
|
|
23
|
+
files:
|
|
24
|
+
- LICENSE.txt
|
|
25
|
+
- README.ja.md
|
|
26
|
+
- README.md
|
|
27
|
+
- exe/torikago
|
|
28
|
+
- lib/torikago.rb
|
|
29
|
+
- lib/torikago/checker.rb
|
|
30
|
+
- lib/torikago/cli.rb
|
|
31
|
+
- lib/torikago/configuration.rb
|
|
32
|
+
- lib/torikago/current_execution.rb
|
|
33
|
+
- lib/torikago/engine_container.rb
|
|
34
|
+
- lib/torikago/errors.rb
|
|
35
|
+
- lib/torikago/gateway.rb
|
|
36
|
+
- lib/torikago/package_api_updater.rb
|
|
37
|
+
- lib/torikago/registry.rb
|
|
38
|
+
- lib/torikago/version.rb
|
|
39
|
+
- test/test_helper.rb
|
|
40
|
+
- test/torikago.rb
|
|
41
|
+
- test/torikago/checker.rb
|
|
42
|
+
- test/torikago/cli.rb
|
|
43
|
+
- test/torikago/configuration.rb
|
|
44
|
+
- test/torikago/engine_container.rb
|
|
45
|
+
- test/torikago/gateway.rb
|
|
46
|
+
- test/torikago/package_api_updater.rb
|
|
47
|
+
- test/torikago/registry.rb
|
|
48
|
+
- test/torikago/version.rb
|
|
49
|
+
homepage: "https://github.com/se4weed/torikago"
|
|
50
|
+
licenses:
|
|
51
|
+
- MIT
|
|
52
|
+
metadata:
|
|
53
|
+
rubygems_mfa_required: "true"
|
|
54
|
+
rdoc_options: []
|
|
55
|
+
require_paths:
|
|
56
|
+
- lib
|
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
-
|
|
60
|
+
- ">="
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: 4.0.3
|
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
-
|
|
66
|
+
- ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: "0"
|
|
69
|
+
requirements: []
|
|
70
|
+
rubygems_version: 4.1.0.dev
|
|
71
|
+
specification_version: 4
|
|
72
|
+
summary: "Runtime isolation for modular monoliths built around Ruby::Box"
|
|
73
|
+
test_files: []
|