container_broker 1.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.
Files changed (126) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +98 -0
  3. data/Rakefile +8 -0
  4. data/app/controllers/application_controller.rb +5 -0
  5. data/app/controllers/healthcheck_controller.rb +21 -0
  6. data/app/controllers/nodes_controller.rb +70 -0
  7. data/app/controllers/nodes_healthcheck_controller.rb +28 -0
  8. data/app/controllers/status_controller.rb +48 -0
  9. data/app/controllers/tasks_controller.rb +83 -0
  10. data/app/controllers/tasks_healthcheck_controller.rb +28 -0
  11. data/app/jobs/add_task_tags_job.rb +13 -0
  12. data/app/jobs/adjust_node_slots_job.rb +27 -0
  13. data/app/jobs/application_job.rb +9 -0
  14. data/app/jobs/collect_load_metrics_job.rb +9 -0
  15. data/app/jobs/container_broker_base_job.rb +32 -0
  16. data/app/jobs/migrate_tasks_from_dead_node_job.rb +32 -0
  17. data/app/jobs/monitor_unresponsive_node_job.rb +21 -0
  18. data/app/jobs/monitor_unresponsive_nodes_job.rb +9 -0
  19. data/app/jobs/release_slot_job.rb +47 -0
  20. data/app/jobs/remove_runner_job.rb +11 -0
  21. data/app/jobs/remove_unused_tags_job.rb +25 -0
  22. data/app/jobs/request_id_from_task.rb +7 -0
  23. data/app/jobs/run_task_job.rb +64 -0
  24. data/app/jobs/run_tasks_for_all_execution_types_job.rb +11 -0
  25. data/app/jobs/run_tasks_job.rb +42 -0
  26. data/app/jobs/timeout_failed_tasks_job.rb +31 -0
  27. data/app/jobs/update_all_nodes_status_job.rb +9 -0
  28. data/app/jobs/update_node_status_job.rb +24 -0
  29. data/app/jobs/update_task_status_job.rb +71 -0
  30. data/app/models/mongoid_serializable_model.rb +14 -0
  31. data/app/models/node.rb +101 -0
  32. data/app/models/slot.rb +42 -0
  33. data/app/models/task.rb +148 -0
  34. data/app/models/task_tag.rb +11 -0
  35. data/app/observers/observable.rb +23 -0
  36. data/app/observers/task_observer.rb +11 -0
  37. data/app/serializers/node_healthcheck_serializer.rb +5 -0
  38. data/app/serializers/node_serializer.rb +5 -0
  39. data/app/serializers/status_panel_node_serializer.rb +9 -0
  40. data/app/serializers/status_panel_slot_serializer.rb +5 -0
  41. data/app/serializers/status_panel_task_serializer.rb +16 -0
  42. data/app/serializers/task_healthcheck_serializer.rb +5 -0
  43. data/app/serializers/task_serializer.rb +7 -0
  44. data/app/services/adjust_execution_type_slots.rb +51 -0
  45. data/app/services/check_for_slot_removal.rb +28 -0
  46. data/app/services/collect_load_metrics.rb +40 -0
  47. data/app/services/delete_node.rb +25 -0
  48. data/app/services/friendly_name_nodes.rb +10 -0
  49. data/app/services/friendly_name_slots.rb +15 -0
  50. data/app/services/kill_node_runners.rb +17 -0
  51. data/app/services/kill_task_container.rb +29 -0
  52. data/app/services/kubernetes_client.rb +136 -0
  53. data/app/services/least_used_node.rb +44 -0
  54. data/app/services/lock_manager.rb +74 -0
  55. data/app/services/lock_slot.rb +37 -0
  56. data/app/services/lock_task.rb +45 -0
  57. data/app/services/metrics.rb +43 -0
  58. data/app/services/migrate_runner.rb +26 -0
  59. data/app/services/node_task_acceptance.rb +18 -0
  60. data/app/services/node_usage_percentage_per_execution_type.rb +22 -0
  61. data/app/services/reschedule_tasks_for_missing_runners.rb +70 -0
  62. data/app/services/runners.rb +4 -0
  63. data/app/services/runners/docker/create_connection.rb +18 -0
  64. data/app/services/runners/docker/create_execution_info.rb +87 -0
  65. data/app/services/runners/docker/fetch_execution_info.rb +17 -0
  66. data/app/services/runners/docker/fetch_logs.rb +18 -0
  67. data/app/services/runners/docker/fetch_task_container.rb +15 -0
  68. data/app/services/runners/docker/filer.rb +19 -0
  69. data/app/services/runners/docker/kill_slot_runner.rb +19 -0
  70. data/app/services/runners/docker/node_availability.rb +11 -0
  71. data/app/services/runners/docker/remove_runner.rb +18 -0
  72. data/app/services/runners/docker/run_task.rb +63 -0
  73. data/app/services/runners/docker/update_node_status.rb +62 -0
  74. data/app/services/runners/execution_info.rb +49 -0
  75. data/app/services/runners/invalid_config.rb +5 -0
  76. data/app/services/runners/invalid_runner.rb +5 -0
  77. data/app/services/runners/kubernetes/create_client.rb +29 -0
  78. data/app/services/runners/kubernetes/create_execution_info.rb +103 -0
  79. data/app/services/runners/kubernetes/fetch_execution_info.rb +15 -0
  80. data/app/services/runners/kubernetes/fetch_logs.rb +17 -0
  81. data/app/services/runners/kubernetes/filer.rb +41 -0
  82. data/app/services/runners/kubernetes/kill_slot_runner.rb +11 -0
  83. data/app/services/runners/kubernetes/node_availability.rb +11 -0
  84. data/app/services/runners/kubernetes/remove_runner.rb +19 -0
  85. data/app/services/runners/kubernetes/run_task.rb +54 -0
  86. data/app/services/runners/kubernetes/update_node_status.rb +64 -0
  87. data/app/services/runners/runner_id_not_found_error.rb +5 -0
  88. data/app/services/runners/services_factory.rb +38 -0
  89. data/app/services/runners/update_node_status_helper.rb +43 -0
  90. data/app/services/slots_usage_percentage.rb +18 -0
  91. data/config/application.rb +34 -0
  92. data/config/boot.rb +5 -0
  93. data/config/environment.rb +7 -0
  94. data/config/environments/test.rb +44 -0
  95. data/config/initializers/application_controller_renderer.rb +10 -0
  96. data/config/initializers/backtrace_silencers.rb +9 -0
  97. data/config/initializers/config.rb +51 -0
  98. data/config/initializers/cookies_serializer.rb +7 -0
  99. data/config/initializers/docker_config.rb +3 -0
  100. data/config/initializers/filter_parameter_logging.rb +6 -0
  101. data/config/initializers/idempotent_request.rb +12 -0
  102. data/config/initializers/inflections.rb +18 -0
  103. data/config/initializers/mime_types.rb +6 -0
  104. data/config/initializers/mongoid.rb +3 -0
  105. data/config/initializers/new_framework_defaults_6_0.rb +47 -0
  106. data/config/initializers/raven.rb +10 -0
  107. data/config/initializers/sidekiq.rb +24 -0
  108. data/config/initializers/wrap_parameters.rb +16 -0
  109. data/config/locales/en.yml +33 -0
  110. data/config/mongoid.yml +10 -0
  111. data/config/routes.rb +43 -0
  112. data/config/secrets.yml +35 -0
  113. data/config/settings.yml +34 -0
  114. data/config/settings/test.yml +27 -0
  115. data/config/sidekiq_scheduler.yml +18 -0
  116. data/config/spring.rb +8 -0
  117. data/lib/constants.rb +12 -0
  118. data/lib/container_broker.rb +30 -0
  119. data/lib/container_broker/engine.rb +6 -0
  120. data/lib/container_broker/version.rb +5 -0
  121. data/lib/current_thread_request_id.rb +19 -0
  122. data/lib/idempotent_request/callback.rb +25 -0
  123. data/lib/idempotent_request/policy.rb +15 -0
  124. data/lib/redis_url_parser.rb +25 -0
  125. data/lib/tasks/task.rake +34 -0
  126. metadata +590 -0
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ ::Docker.logger = Logger.new(STDOUT)
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Be sure to restart your server when you modify this file.
4
+
5
+ # Configure sensitive parameters which will be filtered from the log file.
6
+ Rails.application.config.filter_parameters += [:password]
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.config.middleware.use(
4
+ IdempotentRequest::Middleware,
5
+ storage: IdempotentRequest::RedisStorage.new(
6
+ Redis.new(RedisUrlParser.call(Settings.redis_url)),
7
+ expire_time: 1.day
8
+ ),
9
+ header_key: "X-Idempotency-Key",
10
+ policy: IdempotentRequest::Policy,
11
+ callback: IdempotentRequest::Callback
12
+ )
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Be sure to restart your server when you modify this file.
4
+
5
+ # Add new inflection rules using the following format. Inflections
6
+ # are locale specific, and you may define rules for as many different
7
+ # locales as you wish. All of these examples are active by default:
8
+ # ActiveSupport::Inflector.inflections(:en) do |inflect|
9
+ # inflect.plural /^(ox)$/i, '\1en'
10
+ # inflect.singular /^(ox)en/i, '\1'
11
+ # inflect.irregular 'person', 'people'
12
+ # inflect.uncountable %w( fish sheep )
13
+ # end
14
+
15
+ # These inflection rules are supported but not enabled by default:
16
+ # ActiveSupport::Inflector.inflections(:en) do |inflect|
17
+ # inflect.acronym 'RESTful'
18
+ # end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Be sure to restart your server when you modify this file.
4
+
5
+ # Add new mime types for use in respond_to blocks:
6
+ # Mime::Type.register "text/richtext", :rtf
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ Mongoid.raise_not_found_error = false
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Be sure to restart your server when you modify this file.
4
+ #
5
+ # This file contains migration options to ease your Rails 6.0 upgrade.
6
+ #
7
+ # Once upgraded flip defaults one by one to migrate to the new default.
8
+ #
9
+ # Read the Guide for Upgrading Ruby on Rails for more info on each option.
10
+
11
+ # Don't force requests from old versions of IE to be UTF-8 encoded.
12
+ Rails.application.config.action_view.default_enforce_utf8 = false
13
+
14
+ # Embed purpose and expiry metadata inside signed and encrypted
15
+ # cookies for increased security.
16
+ #
17
+ # This option is not backwards compatible with earlier Rails versions.
18
+ # It's best enabled when your entire app is migrated and stable on 6.0.
19
+ Rails.application.config.action_dispatch.use_cookies_with_metadata = true
20
+
21
+ # Change the return value of `ActionDispatch::Response#content_type` to Content-Type header without modification.
22
+ Rails.application.config.action_dispatch.return_only_media_type_on_content_type = false
23
+
24
+ # Return false instead of self when enqueuing is aborted from a callback.
25
+ Rails.application.config.active_job.return_false_on_aborted_enqueue = true
26
+
27
+ # Send Active Storage analysis and purge jobs to dedicated queues.
28
+ # Rails.application.config.active_storage.queues.analysis = :active_storage_analysis
29
+ # Rails.application.config.active_storage.queues.purge = :active_storage_purge
30
+
31
+ # When assigning to a collection of attachments declared via `has_many_attached`, replace existing
32
+ # attachments instead of appending. Use #attach to add new attachments without replacing existing ones.
33
+ # Rails.application.config.active_storage.replace_on_assign_to_many = true
34
+
35
+ # Use ActionMailer::MailDeliveryJob for sending parameterized and normal mail.
36
+ #
37
+ # The default delivery jobs (ActionMailer::Parameterized::DeliveryJob, ActionMailer::DeliveryJob),
38
+ # will be removed in Rails 6.1. This setting is not backwards compatible with earlier Rails versions.
39
+ # If you send mail in the background, job workers need to have a copy of
40
+ # MailDeliveryJob to ensure all delivery jobs are processed properly.
41
+ # Make sure your entire app is migrated and stable on 6.0 before using this setting.
42
+ # Rails.application.config.action_mailer.delivery_job = "ActionMailer::MailDeliveryJob"
43
+
44
+ # Enable the same cache key to be reused when the object being cached of type
45
+ # `ActiveRecord::Relation` changes by moving the volatile information (max updated at and count)
46
+ # of the relation's cache key into the cache version to support recycling cache key.
47
+ # Rails.application.config.active_record.collection_cache_versioning = true
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ if Settings.sentry.enabled
4
+ require "raven"
5
+
6
+ Raven.configure do |config|
7
+ config.dsn = "https://#{Settings.sentry.app.public_key}:#{Settings.sentry.app.private_key}@#{Settings.sentry.host}/#{Settings.sentry.app.project_id}"
8
+ config.ssl_verification = false
9
+ end
10
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.config.active_job.queue_adapter = Rails.env.test? ? :test : :sidekiq
4
+
5
+ Sidekiq.default_worker_options = { backtrace: true }
6
+
7
+ connection = proc {
8
+ Redis.new(RedisUrlParser.call(Settings.redis_url))
9
+ }
10
+
11
+ Sidekiq.configure_server do |config|
12
+ config.redis = ConnectionPool.new(size: 50, &connection)
13
+ config.logger.level = Logger::DEBUG
14
+
15
+ config.on(:startup) do
16
+ Sidekiq.schedule = YAML.load_file(File.expand_path("../sidekiq_scheduler.yml", __dir__))
17
+ SidekiqScheduler::Scheduler.instance.reload_schedule!
18
+ end
19
+ end
20
+
21
+ Sidekiq.configure_client do |config|
22
+ config.redis = ConnectionPool.new(size: 50, &connection)
23
+ config.logger.level = Logger::DEBUG
24
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Be sure to restart your server when you modify this file.
4
+
5
+ # This file contains settings for ActionController::ParamsWrapper which
6
+ # is enabled by default.
7
+
8
+ # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
9
+ ActiveSupport.on_load(:action_controller) do
10
+ wrap_parameters format: [:json]
11
+ end
12
+
13
+ # To enable root element in JSON for ActiveRecord objects.
14
+ # ActiveSupport.on_load(:active_record) do
15
+ # self.include_root_in_json = true
16
+ # end
@@ -0,0 +1,33 @@
1
+ # Files in the config/locales directory are used for internationalization
2
+ # and are automatically loaded by Rails. If you want to use locales other
3
+ # than English, add the necessary files in this directory.
4
+ #
5
+ # To use the locales, use `I18n.t`:
6
+ #
7
+ # I18n.t 'hello'
8
+ #
9
+ # In views, this is aliased to just `t`:
10
+ #
11
+ # <%= t('hello') %>
12
+ #
13
+ # To use a different locale, set it with `I18n.locale`:
14
+ #
15
+ # I18n.locale = :es
16
+ #
17
+ # This would use the information in config/locales/es.yml.
18
+ #
19
+ # The following keys must be escaped otherwise they will not be retrieved by
20
+ # the default I18n backend:
21
+ #
22
+ # true, false, on, off, yes, no
23
+ #
24
+ # Instead, surround them with single quotes.
25
+ #
26
+ # en:
27
+ # 'true': 'foo'
28
+ #
29
+ # To learn more, please read the Rails Internationalization guide
30
+ # available at http://guides.rubyonrails.org/i18n.html.
31
+
32
+ en:
33
+ hello: "Hello world"
@@ -0,0 +1,10 @@
1
+ test:
2
+ clients:
3
+ default:
4
+ database: container-broker_test
5
+ hosts:
6
+ - <%= ENV["MONGODB_URL"] || "localhost:27017" %>
7
+ options:
8
+ read:
9
+ mode: :primary
10
+ max_pool_size: 1
data/config/routes.rb ADDED
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ ContainerBroker::Engine.routes.draw do
4
+ resources :status, only: :index do
5
+ collection do
6
+ get :nodes
7
+ get :tasks
8
+ get :tags
9
+ get :tag_values
10
+ get :task_statuses
11
+ post "retry_task/:uuid", action: :retry_task
12
+ end
13
+ end
14
+
15
+ resources :tasks, only: %i[create show], param: :uuid do
16
+ get :logs, on: :member
17
+
18
+ member do
19
+ put :mark_as_error
20
+ post :kill_container
21
+ end
22
+
23
+ collection do
24
+ delete :errors, action: :clear_errors
25
+ get :healthcheck, controller: :tasks_healthcheck, action: :index
26
+ end
27
+ end
28
+
29
+ resources :nodes, except: %i[edit new], param: :uuid do
30
+ member do
31
+ post :accept_new_tasks, :reject_new_tasks, :kill_containers
32
+ end
33
+
34
+ collection do
35
+ get :healthcheck, controller: :nodes_healthcheck, action: :index
36
+ end
37
+ end
38
+ # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
39
+
40
+ # root to: redirect(Settings.backstage_admin.url)
41
+
42
+ get "/healthcheck" => "healthcheck#index"
43
+ end
@@ -0,0 +1,35 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Your secret key is used for verifying the integrity of signed cookies.
4
+ # If you change this key, all old signed cookies will become invalid!
5
+
6
+ # Make sure the secret is at least 30 characters and all random,
7
+ # no regular words or you'll be exposed to dictionary attacks.
8
+ # You can use `rails secret` to generate a secure secret key.
9
+
10
+ # Make sure the secrets in this file are kept private
11
+ # if you're sharing your code publicly.
12
+
13
+ # Shared secrets are available across all environments.
14
+
15
+ # shared:
16
+ # api_key: a1B2c3D4e5F6
17
+
18
+ # Environmental secrets are only available for that specific environment.
19
+
20
+ development:
21
+ secret_key_base: 41b8e60baf81a74ce740ca7115ea449c4b25bed764ed32f6a8453a2ced129cf229ee87e674b8aaad5a6f652129b3a29aabb6324df1f53ccde60b2cef665204a1
22
+
23
+ test:
24
+ secret_key_base: 187f05efcc897d1d81fe968e825825053ff28fa492e352febc7e7957320c32b7a5359ec0c8aecb46b34ebb909c6809ef8fb133dd3844e1d0f699333972295e42
25
+
26
+ # Do not keep production secrets in the unencrypted secrets file.
27
+ # Instead, either read values from the environment.
28
+ # Or, use `bin/rails secrets:setup` to configure encrypted secrets
29
+ # and move the `production:` environment over there.
30
+
31
+ dev:
32
+ secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
33
+
34
+ production:
35
+ secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
@@ -0,0 +1,34 @@
1
+ ignore_containers: []
2
+ cors_origins: []
3
+ kubernetes:
4
+ liveness_probe_seconds_interval: 30
5
+ requests:
6
+ memory: <%= ENV.fetch("KUBERNETES_REQUESTS_MEMORY", "4G") %>
7
+ cpu: <%= ENV.fetch("KUBERNETES_REQUESTS_CPU", 4) %>
8
+ limits:
9
+ memory: <%= ENV.fetch("KUBERNETES_LIMITS_MEMORY", "8G") %>
10
+ cpu: <%= ENV.fetch("KUBERNETES_LIMITS_CPU", 8) %>
11
+ sentry:
12
+ enabled: false
13
+ measures:
14
+ enabled: false
15
+ run_container_as:
16
+ user_id: root
17
+ group_id: root
18
+ timeout_tasks_after_hours: <%= 20.hours %>
19
+ task_retry_count: 3
20
+ redis_url: <%= ENV["DBAAS_SENTINEL_ENDPOINT"] %>
21
+ delete_container_after_run: <%= ENV.fetch("DELETE_CONTAINER_AFTER_RUN", true) %>
22
+ node_unavailable_after_seconds: <%= 2.minutes %>
23
+ storage_mounts:
24
+ docker:
25
+ shared: "/opt/shared"
26
+ tmp: "/tmp"
27
+ kubernetes:
28
+ shared:
29
+ nfs:
30
+ server: "nfs-server.test"
31
+ path: "/shared"
32
+ tmp:
33
+ local:
34
+ path: "/tmp"
@@ -0,0 +1,27 @@
1
+ task_retry_count: 3
2
+ redis_url: <%= ENV["REDIS_URL"] || "redis://localhost:6379/0" %>
3
+ delete_container_after_run: true
4
+ node_unavailable_after_seconds: <%= 5.minutes %>
5
+ timeout_tasks_after_hours: <%= 20.hours %>
6
+ sentry:
7
+ enabled: false
8
+ measures:
9
+ enabled: false
10
+ backstage_admin:
11
+ url: admin.test
12
+ run_container_as:
13
+ user_id: 1001
14
+ group_id: 1002
15
+ storage_mounts:
16
+ docker:
17
+ shared_nfs: /mnt/nfs/node
18
+ temp: /tmp/node
19
+ ingest-nfs: /tmp/ingest_nfs
20
+ kubernetes:
21
+ shared_nfs:
22
+ nfs:
23
+ server: nfs.test
24
+ path: /mnt/nfs/node
25
+ temp:
26
+ local:
27
+ path: /mnt/local/node
@@ -0,0 +1,18 @@
1
+ update_nodes_status:
2
+ cron: '*/5 * * * * *'
3
+ class: UpdateAllNodesStatusJob
4
+ run_tasks:
5
+ in: '10s'
6
+ class: RunTasksForAllExecutionTypesJob
7
+ monitor_unresponsive_nodes:
8
+ cron: '*/30 * * * * *'
9
+ class: MonitorUnresponsiveNodesJob
10
+ remove_unreferenced_tags:
11
+ cron: '0 30 4 * * *'
12
+ class: RemoveUnusedTagsJob
13
+ timeout_failed_tasks:
14
+ cron: '0 */15 * * * *'
15
+ class: TimeoutFailedTasksJob
16
+ collect_load_metrics:
17
+ cron: '*/5 * * * * *'
18
+ class: CollectLoadMetricsJob
data/config/spring.rb ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ %w[
4
+ .ruby-version
5
+ .rbenv-vars
6
+ tmp/restart.txt
7
+ tmp/caching-dev.txt
8
+ ].each { |path| Spring.watch(path) }
data/lib/constants.rb ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Constants
4
+ class ExecutionType
5
+ FORMAT = /\A([a-z0-9])+(\-[a-z0-9]+)*\z/.freeze
6
+ INVALID_FORMAT_MESSAGE = "only allows lowercase letters, numbers and hyphen symbol"
7
+ end
8
+
9
+ class Runner
10
+ MAX_NAME_SIZE = 63
11
+ end
12
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "container_broker/engine"
4
+
5
+ require "redis_url_parser"
6
+ require "idempotent_request/callback"
7
+ require "idempotent_request/policy"
8
+ require "constants"
9
+ require "current_thread_request_id"
10
+
11
+ # Gems
12
+ require "config"
13
+ require "docker-api"
14
+ require "active_model_serializers"
15
+ require "config"
16
+ require "idempotent-request"
17
+ require "kubeclient"
18
+ require "mongoid/uuid"
19
+ require "mongoid_enumerable"
20
+ require "redis-namespace"
21
+ require "sentry-raven"
22
+ require "sidekiq"
23
+ require "sidekiq-failures"
24
+ require "sidekiq-scheduler"
25
+ require "docker-api"
26
+ require "measures"
27
+
28
+ module ContainerBroker
29
+ # Your code goes here...
30
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ContainerBroker
4
+ class Engine < ::Rails::Engine
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ContainerBroker
4
+ VERSION = "1.0.1"
5
+ end