config_o_mat 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +1 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +26 -0
  7. data/Gemfile.lock +56 -0
  8. data/LICENSE +202 -0
  9. data/NOTICE +2 -0
  10. data/README.md +15 -0
  11. data/Rakefile +35 -0
  12. data/bin/config_o_mat-configurator +49 -0
  13. data/bin/config_o_mat-meta_configurator +49 -0
  14. data/config_o_mat.gemspec +49 -0
  15. data/design/configurator_lifecycle_test.dot +91 -0
  16. data/design/original_design.md +45 -0
  17. data/lib/config_o_mat/configurator/cond/first_run.rb +29 -0
  18. data/lib/config_o_mat/configurator/cond/next_state.rb +29 -0
  19. data/lib/config_o_mat/configurator/cond/profiles_to_apply.rb +29 -0
  20. data/lib/config_o_mat/configurator/cond/retries_left.rb +37 -0
  21. data/lib/config_o_mat/configurator/cond/services_to_reload.rb +29 -0
  22. data/lib/config_o_mat/configurator/cond.rb +17 -0
  23. data/lib/config_o_mat/configurator/memory.rb +93 -0
  24. data/lib/config_o_mat/configurator/op/apply_all_profiles.rb +35 -0
  25. data/lib/config_o_mat/configurator/op/commit_staged_profile.rb +35 -0
  26. data/lib/config_o_mat/configurator/op/compile_templates.rb +41 -0
  27. data/lib/config_o_mat/configurator/op/connect_to_appconfig.rb +35 -0
  28. data/lib/config_o_mat/configurator/op/generate_all_templates.rb +66 -0
  29. data/lib/config_o_mat/configurator/op/next_tick.rb +48 -0
  30. data/lib/config_o_mat/configurator/op/notify_systemd_start.rb +29 -0
  31. data/lib/config_o_mat/configurator/op/parse_cli.rb +93 -0
  32. data/lib/config_o_mat/configurator/op/refresh_all_profiles.rb +63 -0
  33. data/lib/config_o_mat/configurator/op/refresh_profile.rb +65 -0
  34. data/lib/config_o_mat/configurator/op/reload_one_service.rb +73 -0
  35. data/lib/config_o_mat/configurator/op/stage_one_profile.rb +33 -0
  36. data/lib/config_o_mat/configurator/op/wait_retry.rb +41 -0
  37. data/lib/config_o_mat/configurator/op.rb +17 -0
  38. data/lib/config_o_mat/configurator.rb +122 -0
  39. data/lib/config_o_mat/flip_flopper/cond/service_status.rb +29 -0
  40. data/lib/config_o_mat/flip_flopper/cond.rb +17 -0
  41. data/lib/config_o_mat/flip_flopper/memory.rb +51 -0
  42. data/lib/config_o_mat/flip_flopper/op/check_service_status.rb +72 -0
  43. data/lib/config_o_mat/flip_flopper/op/determine_running_instance.rb +56 -0
  44. data/lib/config_o_mat/flip_flopper/op/report_failure.rb +36 -0
  45. data/lib/config_o_mat/flip_flopper/op/start_activating_instance.rb +34 -0
  46. data/lib/config_o_mat/flip_flopper/op/stop_activating_instance.rb +34 -0
  47. data/lib/config_o_mat/flip_flopper/op/stop_initial_instance.rb +34 -0
  48. data/lib/config_o_mat/flip_flopper/op.rb +17 -0
  49. data/lib/config_o_mat/flip_flopper.rb +46 -0
  50. data/lib/config_o_mat/meta_configurator/memory.rb +73 -0
  51. data/lib/config_o_mat/meta_configurator/op/generate_systemd_config.rb +80 -0
  52. data/lib/config_o_mat/meta_configurator/op/parse_meta_cli.rb +103 -0
  53. data/lib/config_o_mat/meta_configurator/op.rb +17 -0
  54. data/lib/config_o_mat/meta_configurator.rb +44 -0
  55. data/lib/config_o_mat/shared/cond/early_exit.rb +29 -0
  56. data/lib/config_o_mat/shared/cond.rb +17 -0
  57. data/lib/config_o_mat/shared/op/load_meta_config.rb +188 -0
  58. data/lib/config_o_mat/shared/op.rb +17 -0
  59. data/lib/config_o_mat/shared/systemd_interface.rb +93 -0
  60. data/lib/config_o_mat/shared/types.rb +248 -0
  61. data/lib/config_o_mat/version.rb +19 -0
  62. data/lib/version.rb +19 -0
  63. data/systemd/teak-configurator-restart-service@.path +27 -0
  64. data/systemd/teak-configurator-restart-service@.service +21 -0
  65. data/systemd/teak-configurator-start-service@.path +27 -0
  66. data/systemd/teak-configurator-start-service@.service +21 -0
  67. data/systemd/teak-configurator-stop-service@.path +27 -0
  68. data/systemd/teak-configurator-stop-service@.service +21 -0
  69. data/systemd/teak-configurator.service +68 -0
  70. data/systemd/teak-metaconfigurator.service +57 -0
  71. metadata +213 -0
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Teak.io, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'lifecycle_vm/op_base'
18
+
19
+ module ConfigOMat
20
+ module Op
21
+ class StartActivatingInstance < LifecycleVM::OpBase
22
+ reads :service, :activating_instance, :runtime_directory
23
+
24
+ def call
25
+ instance_name = "#{service}#{activating_instance}"
26
+ file_path = File.join(runtime_directory, "#{instance_name}.start")
27
+
28
+ logger&.notice(:service_start, name: instance_name)
29
+
30
+ FileUtils.touch(file_path)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Teak.io, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'lifecycle_vm/op_base'
18
+
19
+ module ConfigOMat
20
+ module Op
21
+ class StopActivatingInstance < LifecycleVM::OpBase
22
+ reads :service, :activating_instance, :runtime_directory
23
+
24
+ def call
25
+ instance_name = "#{service}#{activating_instance}"
26
+ file_path = File.join(runtime_directory, "#{instance_name}.stop")
27
+
28
+ logger&.notice(:service_stop, name: instance_name)
29
+
30
+ FileUtils.touch(file_path)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Teak.io, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'lifecycle_vm/op_base'
18
+
19
+ module ConfigOMat
20
+ module Op
21
+ class StopInitialInstance < LifecycleVM::OpBase
22
+ reads :service, :running_instance, :runtime_directory
23
+
24
+ def call
25
+ instance_name = "#{service}#{running_instance}"
26
+ file_path = File.join(runtime_directory, "#{instance_name}.stop")
27
+
28
+ logger&.notice(:service_stop, name: instance_name)
29
+
30
+ FileUtils.touch(file_path)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Teak.io, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ Dir[File.join(__dir__, 'op', '*')].sort.each { |file| require file }
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Teak.io, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'lifecycle_vm'
18
+
19
+ require 'config_o_mat/flip_flopper/op'
20
+ require 'config_o_mat/flip_flopper/cond'
21
+ require 'config_o_mat/flip_flopper/memory'
22
+
23
+ module ConfigOMat
24
+ module FlipFlopper
25
+ class VM < LifecycleVM::VM
26
+ memory_class ConfigOMat::FlipFlopper::Memory
27
+
28
+ on :start, do: Op::DetermineRunningInstance, then: :start_activating_instance
29
+ on :start_activating_instance, do: Op::StartActivatingInstance, then: :wait_for_service_start
30
+ on :wait_for_service_start, do: Op::CheckServiceStatus, then: {
31
+ case: Cond::ServiceStatus,
32
+ when: {
33
+ starting: :wait_for_service_start,
34
+ started: :stop_initial_service,
35
+ failed: :fail,
36
+ timed_out: :abort
37
+ }
38
+ }
39
+
40
+ on :stop_initial_service, do: Op::StopInitialInstance, then: :exit
41
+ on :fail, do: Op::ReportFailure, then: :exit
42
+
43
+ on :abort, do: Op::StopActivatingInstance, then: :fail
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Teak.io, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'lifecycle_vm/memory'
18
+
19
+ module ConfigOMat
20
+ module MetaConfigurator
21
+ class Memory < LifecycleVM::Memory
22
+ attr_accessor :argv, :env, :early_exit, :configuration_directory, :runtime_directory,
23
+ :systemd_directory, :logs_directory, :profile_defs,
24
+ :template_defs, :service_defs, :dependencies, :refresh_interval,
25
+ :client_id, :retry_count, :retries_left, :retry_wait,
26
+ :region, :systemd_interface
27
+
28
+ def initialize(
29
+ argv: [],
30
+ env: {},
31
+ early_exit: false,
32
+ configuration_directory: nil,
33
+ runtime_directory: nil,
34
+ logs_directory: nil,
35
+ systemd_directory: nil,
36
+ profile_defs: {},
37
+ template_defs: {},
38
+ service_defs: {},
39
+ dependencies: {},
40
+ refresh_interval: 5,
41
+ client_id: '',
42
+ logger: nil,
43
+ retry_count: 3,
44
+ retries_left: 3,
45
+ retry_wait: 2,
46
+ region: nil,
47
+ systemd_interface: nil
48
+ )
49
+ super()
50
+
51
+ @argv = argv
52
+ @env = env
53
+ @early_exit = early_exit
54
+ @configuration_directory = configuration_directory
55
+ @runtime_directory = runtime_directory
56
+ @logs_directory = logs_directory
57
+ @systemd_directory = systemd_directory
58
+ @profile_defs = profile_defs
59
+ @template_defs = template_defs
60
+ @service_defs = service_defs
61
+ @dependencies = dependencies
62
+ @refresh_interval = refresh_interval
63
+ @client_id = client_id
64
+ @logger = logger
65
+ @retry_count = retry_count
66
+ @retries_left = retries_left
67
+ @retry_wait = retry_wait
68
+ @region = region
69
+ @systemd_interface = systemd_interface
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Teak.io, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'lifecycle_vm/op_base'
18
+
19
+ require 'fileutils'
20
+
21
+ module ConfigOMat
22
+ module Op
23
+ class GenerateSystemdConfig < LifecycleVM::OpBase
24
+ DROPIN_FILE_NAME = '99_teak_configurator.conf'
25
+
26
+ reads :template_defs, :service_defs, :runtime_directory, :systemd_directory, :systemd_interface
27
+
28
+ def call
29
+ grouped_restart_modes = service_defs.values.group_by(&:restart_mode)
30
+ restarts = grouped_restart_modes[:restart]
31
+ flip_flops = grouped_restart_modes[:flip_flop]
32
+
33
+ enable_restarts(restarts) if restarts
34
+ enable_flip_flops(flip_flops) if flip_flops
35
+
36
+ systemd_interface.daemon_reload
37
+ end
38
+
39
+ private
40
+
41
+ def write_dropin(unit, service)
42
+ dropin = %([Service]\n)
43
+ service.templates.each do |tmpl|
44
+ template = template_defs[tmpl.to_sym]
45
+ dropin += %(LoadCredential=#{template.dst}:#{File.join(runtime_directory, template.dst)}\n)
46
+ end
47
+
48
+ dropin_dir = File.join(systemd_directory, "#{unit}.service.d")
49
+
50
+ FileUtils.mkdir_p(dropin_dir)
51
+ File.open(File.join(dropin_dir, DROPIN_FILE_NAME), 'w') { |f| f.write(dropin) }
52
+ end
53
+
54
+ def enable_restarts(services)
55
+ units = []
56
+ services.each do |service|
57
+ unit = service.systemd_unit
58
+ units << unit
59
+
60
+ write_dropin(unit, service)
61
+ end
62
+
63
+ systemd_interface.enable_restart_paths(units)
64
+ end
65
+
66
+ def enable_flip_flops(services)
67
+ units = []
68
+ services.each do |service|
69
+ unit = service.systemd_unit
70
+ units << "#{unit}1"
71
+ units << "#{unit}2"
72
+
73
+ write_dropin(unit, service)
74
+ end
75
+
76
+ systemd_interface.enable_start_stop_paths(units)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Teak.io, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'lifecycle_vm/op_base'
18
+
19
+ require 'optparse'
20
+
21
+ module ConfigOMat
22
+ module Op
23
+ class ParseMetaCli < LifecycleVM::OpBase
24
+ DEFAULT_SYSTEMD_DIRECTORY = '/run/systemd/system'
25
+
26
+ reads :argv, :env
27
+ writes :configuration_directory, :runtime_directory, :logs_directory, :systemd_directory, :early_exit
28
+
29
+ # Add expand_path to string because the safe accessor is nice to use.
30
+ module CoreExt
31
+ refine String do
32
+ def expand_path
33
+ File.expand_path(self)
34
+ end
35
+ end
36
+ end
37
+
38
+ using CoreExt
39
+
40
+ def call
41
+ self.early_exit = false
42
+
43
+ parser = OptionParser.new do |opts|
44
+ opts.on('-v', '--version', 'Display the version') do
45
+ self.early_exit = true
46
+ end
47
+
48
+ opts.on('-h', '--help', 'Prints this help') do
49
+ puts opts
50
+ self.early_exit = true
51
+ end
52
+
53
+ opts.on(
54
+ '-c', '--configuration-directory directory',
55
+ 'Read configuration from the given directory instead of from $CONFIGURATION_DIRECTORY'
56
+ ) do |dir|
57
+ self.configuration_directory = dir
58
+ end
59
+
60
+ opts.on(
61
+ '-r', '--runtime-directory directory',
62
+ 'Use the given directory for writing templates instead of $RUNTIME_DIRECTORY'
63
+ ) do |dir|
64
+ self.runtime_directory = dir
65
+ end
66
+
67
+ opts.on(
68
+ '-l', '--logs-directory directory',
69
+ 'Use the given directory for writing log files instead of $LOGS_DIRECTORY'
70
+ ) do |dir|
71
+ self.logs_directory = dir
72
+ end
73
+
74
+ opts.on(
75
+ '-s', '--systemd-directory directory',
76
+ "Write out systemd configuration to the given directory instead of #{DEFAULT_SYSTEMD_DIRECTORY}"
77
+ ) do |dir|
78
+ self.systemd_directory = dir
79
+ end
80
+ end
81
+
82
+ parser.parse(argv)
83
+
84
+ self.configuration_directory ||= env['CONFIGURATION_DIRECTORY']
85
+ self.runtime_directory ||= env['RUNTIME_DIRECTORY']
86
+ self.logs_directory ||= env['LOGS_DIRECTORY']
87
+ self.systemd_directory ||= DEFAULT_SYSTEMD_DIRECTORY
88
+
89
+ self.configuration_directory = configuration_directory&.expand_path
90
+ end
91
+
92
+ def validate
93
+ return if early_exit
94
+
95
+ if configuration_directory.nil? || configuration_directory.empty?
96
+ error :configuration_directory, 'must be present'
97
+ end
98
+
99
+ error :runtime_directory, 'must be present' if runtime_directory.nil? || runtime_directory.empty?
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Teak.io, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ Dir[File.join(__dir__, 'op', '*')].sort.each { |file| require file }
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Teak.io, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'lifecycle_vm'
18
+
19
+ require 'config_o_mat/shared/op'
20
+ require 'config_o_mat/shared/cond'
21
+ require 'config_o_mat/meta_configurator/op'
22
+ require 'config_o_mat/meta_configurator/memory'
23
+
24
+ module ConfigOMat
25
+ module MetaConfigurator
26
+ class VM < LifecycleVM::VM
27
+ VERSION = "0.0.1"
28
+
29
+ memory_class ConfigOMat::MetaConfigurator::Memory
30
+
31
+ on :start, do: Op::ParseMetaCli, then: {
32
+ case: Cond::EarlyExit,
33
+ when: {
34
+ true => :exit,
35
+ false => :reading_meta_config
36
+ }
37
+ }
38
+
39
+ on :reading_meta_config, do: Op::LoadMetaConfig, then: :generating_systemd_config
40
+
41
+ on :generating_systemd_config, do: Op::GenerateSystemdConfig, then: :exit
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Teak.io, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'lifecycle_vm/cond_base'
18
+
19
+ module ConfigOMat
20
+ module Cond
21
+ class EarlyExit < LifecycleVM::CondBase
22
+ reads :early_exit
23
+
24
+ def call
25
+ early_exit
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Teak.io, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ Dir[File.join(__dir__, 'cond', '*')].sort.each { |file| require file }