indocker 0.0.0 → 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 +4 -4
- data/.gitignore +2 -1
- data/.rspec +1 -0
- data/Gemfile.lock +12 -0
- data/bin/indocker +9 -0
- data/indocker.gemspec +7 -2
- data/lib/indocker/application_initializer.rb +30 -0
- data/lib/indocker/cli.rb +17 -0
- data/lib/indocker/configs/config.rb +76 -0
- data/lib/indocker/configs/config_factory.rb +36 -0
- data/lib/indocker/configs/locator.rb +23 -0
- data/lib/indocker/container/container_dsl.rb +60 -0
- data/lib/indocker/container/container_evaluator.rb +13 -0
- data/lib/indocker/container/container_manager.rb +111 -0
- data/lib/indocker/container/container_metadata.rb +107 -0
- data/lib/indocker/container/container_metadata_factory.rb +27 -0
- data/lib/indocker/container/container_metadata_repository.rb +27 -0
- data/lib/indocker/directives/base.rb +21 -0
- data/lib/indocker/directives/container_directives/base.rb +19 -0
- data/lib/indocker/directives/container_directives/depends_on.rb +7 -0
- data/lib/indocker/directives/container_directives/env_file.rb +7 -0
- data/lib/indocker/directives/container_directives/expose.rb +7 -0
- data/lib/indocker/directives/container_directives/from.rb +12 -0
- data/lib/indocker/directives/container_directives/network.rb +12 -0
- data/lib/indocker/directives/container_directives/ports.rb +8 -0
- data/lib/indocker/directives/container_directives/ready.rb +16 -0
- data/lib/indocker/directives/container_directives_runner.rb +46 -0
- data/lib/indocker/directives/docker_directives/base.rb +15 -0
- data/lib/indocker/directives/docker_directives/cmd.rb +15 -0
- data/lib/indocker/directives/docker_directives/copy.rb +27 -0
- data/lib/indocker/directives/docker_directives/entrypoint.rb +15 -0
- data/lib/indocker/directives/docker_directives/env.rb +5 -0
- data/lib/indocker/directives/docker_directives/from.rb +30 -0
- data/lib/indocker/directives/docker_directives/run.rb +5 -0
- data/lib/indocker/directives/docker_directives/workdir.rb +5 -0
- data/lib/indocker/directives/image_directives_runner.rb +120 -0
- data/lib/indocker/directives/partial.rb +13 -0
- data/lib/indocker/directives/prepare_directives/base.rb +6 -0
- data/lib/indocker/directives/prepare_directives/docker_cp.rb +16 -0
- data/lib/indocker/docker_api.rb +180 -0
- data/lib/indocker/dsl_context.rb +17 -0
- data/lib/indocker/envs/env_metadata.rb +35 -0
- data/lib/indocker/envs/loader.rb +19 -0
- data/lib/indocker/envs/manager.rb +30 -0
- data/lib/indocker/errors.rb +17 -0
- data/lib/indocker/handlers/base.rb +13 -0
- data/lib/indocker/handlers/run_container.rb +29 -0
- data/lib/indocker/image/image_builder.rb +39 -0
- data/lib/indocker/image/image_dependencies_manager.rb +43 -0
- data/lib/indocker/image/image_dsl.rb +69 -0
- data/lib/indocker/image/image_evaluator.rb +21 -0
- data/lib/indocker/image/image_metadata.rb +50 -0
- data/lib/indocker/image/image_metadata_factory.rb +30 -0
- data/lib/indocker/image/image_metadata_repository.rb +30 -0
- data/lib/indocker/networks/network_metadata.rb +9 -0
- data/lib/indocker/networks/network_metadata_factory.rb +9 -0
- data/lib/indocker/networks/network_metadata_repository.rb +34 -0
- data/lib/indocker/partial/partial_metadata.rb +8 -0
- data/lib/indocker/partial/partial_metadata_repository.rb +26 -0
- data/lib/indocker/utils/ioc_container.rb +17 -0
- data/lib/indocker/utils/logger.rb +62 -0
- data/lib/indocker/utils/logger_factory.rb +12 -0
- data/lib/indocker/utils/registry_authenticator.rb +19 -0
- data/lib/indocker/utils/render_namespace.rb +11 -0
- data/lib/indocker/utils/render_util.rb +15 -0
- data/lib/indocker/utils/string_utils.rb +11 -0
- data/lib/indocker/utils/tar_helper.rb +40 -0
- data/lib/indocker/utils/test_logger_factory.rb +9 -0
- data/lib/indocker/version.rb +2 -2
- data/lib/indocker.rb +123 -1
- data/spec/example/.indocker/config.rb +23 -0
- data/spec/example/.indocker/images_and_containers.rb +25 -0
- data/spec/example/assets/index.css +1 -0
- data/spec/example/assets/index.js +1 -0
- data/spec/indocker/configs/config_factory_spec.rb +18 -0
- data/spec/indocker/configs/config_spec.rb +37 -0
- data/spec/indocker/container/container_manager_spec.rb +230 -0
- data/spec/indocker/directives/image_directives_runner_spec.rb +121 -0
- data/spec/indocker/handlers/run_container_spec.rb +107 -0
- data/spec/indocker/image/image_builder_spec.rb +115 -0
- data/spec/indocker/image/image_evaluator_spec.rb +65 -0
- data/spec/indocker/utils/docker_api_spec.rb +87 -0
- data/spec/spec_helper.rb +46 -0
- data/spec/tmp/indocker_list_container_files/deeper/example3.txt +1 -0
- data/spec/tmp/indocker_list_container_files/deeper/example4.txt +1 -0
- data/spec/tmp/indocker_list_container_files/example1.txt +1 -0
- data/spec/tmp/indocker_list_container_files/example2.txt +1 -0
- metadata +159 -6
- data/spec/.gitkeep +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7df51bb131afb666d9ca1348d33e322f3d37d327
|
|
4
|
+
data.tar.gz: 685f173290c9de44e22d15afec6203f2d2bbb94f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 71e13fe051887fe13b7675e26ac06441ae9318165c1ef98949ebe2e43fda8562b8a7d4d839789ba844d62e565b0e480f5e2165399d50f4e38e42f2d808acd31c
|
|
7
|
+
data.tar.gz: 01a359422b06ef1f4246a2b0fc20eb49699413a4cd45b907663d8e568a8243a98a2d39c0bd0fce86b93e309e918b38e0d241f0b3adbab0642b07978ea6b1eac4
|
data/.gitignore
CHANGED
data/.rspec
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--require spec_helper
|
data/Gemfile.lock
CHANGED
|
@@ -2,11 +2,23 @@ PATH
|
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
4
|
indocker (0.0.0)
|
|
5
|
+
colorize
|
|
6
|
+
docker-api
|
|
7
|
+
smart_ioc
|
|
8
|
+
thor
|
|
5
9
|
|
|
6
10
|
GEM
|
|
7
11
|
remote: https://rubygems.org/
|
|
8
12
|
specs:
|
|
9
13
|
byebug (9.1.0)
|
|
14
|
+
colorize (0.8.1)
|
|
15
|
+
docker-api (1.33.6)
|
|
16
|
+
excon (>= 0.38.0)
|
|
17
|
+
json
|
|
18
|
+
excon (0.59.0)
|
|
19
|
+
json (2.1.0)
|
|
20
|
+
smart_ioc (0.2.1)
|
|
21
|
+
thor (0.20.0)
|
|
10
22
|
|
|
11
23
|
PLATFORMS
|
|
12
24
|
ruby
|
data/bin/indocker
ADDED
data/indocker.gemspec
CHANGED
|
@@ -2,8 +2,8 @@ require_relative 'lib/indocker/version'
|
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |s|
|
|
4
4
|
s.name = 'indocker'
|
|
5
|
-
s.version =
|
|
6
|
-
s.summary = "
|
|
5
|
+
s.version = Indocker::VERSION
|
|
6
|
+
s.summary = "Indocker"
|
|
7
7
|
s.description = "DSL for build, run and deploy docker containers"
|
|
8
8
|
s.authors = ["Droid Labs"]
|
|
9
9
|
s.email = 'hello@droidlabs.pro'
|
|
@@ -13,6 +13,11 @@ Gem::Specification.new do |s|
|
|
|
13
13
|
s.test_files = s.files.grep(%r{^(spec)/})
|
|
14
14
|
|
|
15
15
|
s.add_development_dependency "byebug"
|
|
16
|
+
|
|
17
|
+
s.add_dependency "smart_ioc"
|
|
18
|
+
s.add_dependency "docker-api"
|
|
19
|
+
s.add_dependency "thor"
|
|
20
|
+
s.add_dependency "colorize"
|
|
16
21
|
|
|
17
22
|
s.homepage = 'https://github.com/droidlabs/indocker'
|
|
18
23
|
s.license = 'MIT'
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
class Indocker::ApplicationInitializer
|
|
2
|
+
include SmartIoC::Iocify
|
|
3
|
+
|
|
4
|
+
bean :application_initializer
|
|
5
|
+
|
|
6
|
+
inject :config_locator
|
|
7
|
+
inject :docker_api
|
|
8
|
+
inject :registry_authenticator
|
|
9
|
+
inject :envs_manager
|
|
10
|
+
inject :config
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def init_app(current_path, env: :development)
|
|
14
|
+
docker_api.check_docker_installed!
|
|
15
|
+
|
|
16
|
+
config.root(
|
|
17
|
+
Pathname.new(
|
|
18
|
+
File.expand_path(
|
|
19
|
+
File.join(config_locator.locate(current_path), '../..')
|
|
20
|
+
)
|
|
21
|
+
)
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
require(config_locator.locate(current_path))
|
|
25
|
+
|
|
26
|
+
registry_authenticator.authenticate!
|
|
27
|
+
|
|
28
|
+
envs_manager.load_init_application_env_variables
|
|
29
|
+
end
|
|
30
|
+
end
|
data/lib/indocker/cli.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'thor'
|
|
2
|
+
|
|
3
|
+
module Indocker
|
|
4
|
+
module CLI
|
|
5
|
+
class Application < Thor
|
|
6
|
+
desc "container:run CONTAINER_NAME", "runs specified container"
|
|
7
|
+
option :env
|
|
8
|
+
define_method('container:run') do |name, env = :development|
|
|
9
|
+
ioc.run_container_handler.perform(
|
|
10
|
+
name: name,
|
|
11
|
+
current_path: Dir.pwd,
|
|
12
|
+
env: env
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Indocker::Configs
|
|
2
|
+
class Config
|
|
3
|
+
def scope
|
|
4
|
+
@scope ||= Hash.new({})
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def set(&block)
|
|
8
|
+
instance_exec(&block)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def option(name, group: :default, type: :string)
|
|
12
|
+
define_singleton_method(name) do |value = nil, &block|
|
|
13
|
+
write_value = block || value
|
|
14
|
+
|
|
15
|
+
if write_value
|
|
16
|
+
validate!(name, write_value, type)
|
|
17
|
+
|
|
18
|
+
write_setting(name, write_value, group)
|
|
19
|
+
else
|
|
20
|
+
read_setting(name)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def config(name, group: :default, &block)
|
|
26
|
+
subconfiguration = Indocker::Configs::Config.new
|
|
27
|
+
subconfiguration.instance_exec(&block)
|
|
28
|
+
|
|
29
|
+
option(name, group: group, type: :config)
|
|
30
|
+
send(name, subconfiguration)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def read_setting(key)
|
|
34
|
+
read_value = scope[key.to_s][:value]
|
|
35
|
+
|
|
36
|
+
read_value.is_a?(Proc) ? read_value.call : read_value
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def write_setting(key, value, group)
|
|
40
|
+
scope[key.to_s] = {
|
|
41
|
+
value: value,
|
|
42
|
+
group: group
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def validate!(name, value, type)
|
|
47
|
+
value_type = cast_class_to_type(value)
|
|
48
|
+
|
|
49
|
+
if type != value_type
|
|
50
|
+
raise Indocker::Errors::ConfigOptionTypeMismatch,
|
|
51
|
+
"Expected option #{name.inspect} => #{value.inspect} to be a #{type.inspect}, not a #{value_type.inspect}"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def cast_class_to_type(value)
|
|
58
|
+
case value
|
|
59
|
+
when Proc
|
|
60
|
+
cast_class_to_type(value.call)
|
|
61
|
+
when TrueClass
|
|
62
|
+
:boolean
|
|
63
|
+
when FalseClass
|
|
64
|
+
:boolean
|
|
65
|
+
when Indocker::Configs::Config
|
|
66
|
+
:config
|
|
67
|
+
else
|
|
68
|
+
Indocker::StringUtils.underscore(value.class.name).to_sym
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def method_missing(method, *args, &block)
|
|
73
|
+
raise "Undefined keyword #{method.inspect} for Indocker configuration file"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
class Indocker::Configs::ConfigFactory
|
|
2
|
+
include SmartIoC::Iocify
|
|
3
|
+
|
|
4
|
+
bean :config, factory_method: :build
|
|
5
|
+
|
|
6
|
+
CONFIG_STRUCTURE = Proc.new do
|
|
7
|
+
option :namespace, group: :common
|
|
8
|
+
option :root, group: :common, type: :pathname
|
|
9
|
+
|
|
10
|
+
option :load_env_file, group: :load, type: :array
|
|
11
|
+
option :load_docker_items, group: :load, type: :array
|
|
12
|
+
|
|
13
|
+
config :git, group: :git do
|
|
14
|
+
option :repository
|
|
15
|
+
option :tag
|
|
16
|
+
option :branch
|
|
17
|
+
option :workdir
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
config :docker, group: :docker do
|
|
21
|
+
option :registry
|
|
22
|
+
option :email
|
|
23
|
+
option :password
|
|
24
|
+
option :username
|
|
25
|
+
option :skip_push, type: :boolean
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def build(&block)
|
|
30
|
+
return @configuration if @configuration
|
|
31
|
+
|
|
32
|
+
@configuration = Indocker::Configs::Config.new
|
|
33
|
+
@configuration.instance_exec(&CONFIG_STRUCTURE)
|
|
34
|
+
@configuration
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class Indocker::Configs::Locator
|
|
2
|
+
include SmartIoC::Iocify
|
|
3
|
+
|
|
4
|
+
bean :config_locator
|
|
5
|
+
|
|
6
|
+
ROOT = '/'
|
|
7
|
+
|
|
8
|
+
def locate(path)
|
|
9
|
+
expand_path = potential_config_file File.expand_path(path)
|
|
10
|
+
|
|
11
|
+
return expand_path if File.exists?(expand_path)
|
|
12
|
+
|
|
13
|
+
raise Indocker::Errors::ConfigFilesDoesNotFound if path == ROOT
|
|
14
|
+
|
|
15
|
+
locate(File.dirname(path))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def potential_config_file(path)
|
|
21
|
+
File.join(path, '.indocker', 'config.rb')
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
class Indocker::ContainerDSL
|
|
2
|
+
attr_reader :directives
|
|
3
|
+
|
|
4
|
+
def initialize(context)
|
|
5
|
+
@context = context
|
|
6
|
+
@directives = []
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def method_missing(method, *args)
|
|
10
|
+
@context.send(method)
|
|
11
|
+
rescue
|
|
12
|
+
super
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def use(item)
|
|
18
|
+
case item
|
|
19
|
+
when Indocker::ImageMetadata
|
|
20
|
+
from_directive = @directives.detect {|d| d.instance_of?(Indocker::ContainerDirectives::From)}
|
|
21
|
+
raise Indocker::Errors::ContainerImageAlreadyDefined, from_directive.image if from_directive
|
|
22
|
+
|
|
23
|
+
@directives << Indocker::ContainerDirectives::From.new(item.repo, tag: item.tag)
|
|
24
|
+
when Indocker::Networks::NetworkMetadata
|
|
25
|
+
@directives << Indocker::ContainerDirectives::Network.new(
|
|
26
|
+
container_name: @context.container_name,
|
|
27
|
+
network_name: item.name
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def env_file(path)
|
|
33
|
+
@directives << Indocker::ContainerDirectives::EnvFile.new(path)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def expose(port)
|
|
37
|
+
@directives << Indocker::ContainerDirectives::Expose.new(path)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def ports(ports)
|
|
41
|
+
docker_port, host_port = ports.split(':').map(&:strip)
|
|
42
|
+
|
|
43
|
+
@directives << Indocker::ContainerDirectives::Ports.new(
|
|
44
|
+
docker_port: docker_port,
|
|
45
|
+
host_port: host_port
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def depends_on(container_metadata)
|
|
50
|
+
@directives << Indocker::ContainerDirectives::DependsOn.new(container_metadata.name)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def ready(sleep:, timeout:, &ready_block)
|
|
54
|
+
@directives << Indocker::ContainerDirectives::Ready.new(
|
|
55
|
+
sleep: sleep,
|
|
56
|
+
timeout: timeout,
|
|
57
|
+
ready_block: ready_block
|
|
58
|
+
)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class Indocker::ContainerEvaluator
|
|
2
|
+
include SmartIoC::Iocify
|
|
3
|
+
|
|
4
|
+
bean :container_evaluator
|
|
5
|
+
|
|
6
|
+
def evaluate(context, &block)
|
|
7
|
+
container_dsl = Indocker::ContainerDSL.new(context)
|
|
8
|
+
|
|
9
|
+
container_dsl.instance_exec(&block)
|
|
10
|
+
|
|
11
|
+
container_dsl.directives
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
class Indocker::ContainerManager
|
|
2
|
+
KEEP_CONTAINER_RUNNING_COMMAND = %w(tail -F -n0 /etc/hosts)
|
|
3
|
+
|
|
4
|
+
include SmartIoC::Iocify
|
|
5
|
+
|
|
6
|
+
bean :container_manager
|
|
7
|
+
|
|
8
|
+
inject :container_metadata_repository
|
|
9
|
+
inject :image_metadata_repository
|
|
10
|
+
inject :container_directives_runner
|
|
11
|
+
inject :docker_api
|
|
12
|
+
inject :logger
|
|
13
|
+
inject :tar_helper
|
|
14
|
+
inject :config
|
|
15
|
+
inject :envs_loader
|
|
16
|
+
|
|
17
|
+
def create(name)
|
|
18
|
+
container_metadata = container_metadata_repository.get_by_name(name)
|
|
19
|
+
|
|
20
|
+
env_metadata = container_metadata.env_files
|
|
21
|
+
.map {|path| envs_loader.parse(config.root.join(path))}
|
|
22
|
+
.inject(Indocker::Envs::EnvMetadata.new) {|sum, env| sum += env}
|
|
23
|
+
|
|
24
|
+
container_id = docker_api.create_container(
|
|
25
|
+
name: name,
|
|
26
|
+
repo: container_metadata.repo,
|
|
27
|
+
tag: container_metadata.tag,
|
|
28
|
+
exposed_ports: container_metadata.exposed_ports,
|
|
29
|
+
port_bindings: container_metadata.port_bindings,
|
|
30
|
+
env: env_metadata.to_array
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
logger.info "Successfully created container :#{name}"
|
|
34
|
+
|
|
35
|
+
container_id
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def start(name)
|
|
39
|
+
container_metadata = container_metadata_repository.get_by_name(name)
|
|
40
|
+
|
|
41
|
+
container_directives_runner.run_all(
|
|
42
|
+
container_metadata.before_start_directives
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
container_metadata.container_dependencies.each do |dependency|
|
|
46
|
+
create(dependency) unless docker_api.container_exists?(dependency)
|
|
47
|
+
|
|
48
|
+
unless docker_api.get_container_state(dependency) == Indocker::ContainerMetadata::States::RUNNING
|
|
49
|
+
start(dependency)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
container_id = docker_api.start_container(name)
|
|
54
|
+
|
|
55
|
+
logger.info "Successfully started container :#{name}"
|
|
56
|
+
|
|
57
|
+
container_directives_runner.run_all(
|
|
58
|
+
container_metadata.after_start_directives
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
container_id
|
|
62
|
+
rescue Docker::Error::ClientError => e
|
|
63
|
+
logger.error "The following error occured when starting :#{name} container"
|
|
64
|
+
logger.error e.message
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def stop(name)
|
|
68
|
+
container_id = docker_api.stop_container(name)
|
|
69
|
+
|
|
70
|
+
logger.info "Successfully stopped container :#{name}"
|
|
71
|
+
|
|
72
|
+
container_id
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def delete(name)
|
|
76
|
+
container_id = docker_api.delete_container(name)
|
|
77
|
+
|
|
78
|
+
logger.info "Successfully deleted container :#{name}"
|
|
79
|
+
|
|
80
|
+
container_id
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def copy(name:, copy_from:, copy_to:)
|
|
84
|
+
container_metadata = container_metadata_repository.get_by_name(name)
|
|
85
|
+
|
|
86
|
+
container_id = docker_api.create_container(
|
|
87
|
+
repo: container_metadata.repo,
|
|
88
|
+
tag: container_metadata.tag,
|
|
89
|
+
command: KEEP_CONTAINER_RUNNING_COMMAND
|
|
90
|
+
) if !docker_api.container_exists?(name)
|
|
91
|
+
|
|
92
|
+
tar_snapshot = File.join(config.root, 'tmp', "#{name.to_s}.tar")
|
|
93
|
+
|
|
94
|
+
docker_api.copy_from_container(name: container_id, path: copy_from) do |tar_archive|
|
|
95
|
+
File.open(tar_snapshot, 'w') {|f| f.write(tar_archive)}
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
files_list = tar_helper.untar(
|
|
99
|
+
io: File.open(tar_snapshot, 'r'),
|
|
100
|
+
destination: copy_to,
|
|
101
|
+
ignore_wrap_directory: File.basename(copy_from) == '.'
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
FileUtils.rm_rf(tar_snapshot)
|
|
105
|
+
|
|
106
|
+
docker_api.stop_container(container_id)
|
|
107
|
+
docker_api.delete_container(container_id)
|
|
108
|
+
|
|
109
|
+
files_list
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
class Indocker::ContainerMetadata
|
|
2
|
+
attr_reader :name
|
|
3
|
+
|
|
4
|
+
HOSTPORT = 'HostPort'
|
|
5
|
+
|
|
6
|
+
module States
|
|
7
|
+
CREATED = 'created'
|
|
8
|
+
RESTARTING = 'restarting'
|
|
9
|
+
RUNNING = 'running'
|
|
10
|
+
PAUSED = 'paused'
|
|
11
|
+
EXITED = 'exited'
|
|
12
|
+
DEAD = 'dead'
|
|
13
|
+
|
|
14
|
+
ALL = [CREATED, RESTARTING, RUNNING, PAUSED, EXITED, DEAD]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def initialize(name:, directives:)
|
|
18
|
+
@name = name
|
|
19
|
+
@directives = directives
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def repo
|
|
23
|
+
from_directive.repo
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def tag
|
|
27
|
+
from_directive.tag
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def image
|
|
31
|
+
from_directive.image
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def networks
|
|
35
|
+
network_directives.map(&:name)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def env_files
|
|
39
|
+
env_directives.map(&:path)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def exposed_ports
|
|
43
|
+
return nil if ports_directives.empty? && expose_directives.empty?
|
|
44
|
+
|
|
45
|
+
result = Hash.new
|
|
46
|
+
|
|
47
|
+
expose_directives.each do |d|
|
|
48
|
+
result[d.port.to_s] = {}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
ports_directives.each do |d|
|
|
52
|
+
result[d.docker_port] = {}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
result
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def port_bindings
|
|
59
|
+
return nil if ports_directives.empty?
|
|
60
|
+
|
|
61
|
+
result = Hash.new
|
|
62
|
+
|
|
63
|
+
ports_directives.each do |d|
|
|
64
|
+
result[d.docker_port] = [{ HOSTPORT => d.host_port }]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
result
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def container_dependencies
|
|
71
|
+
depends_on_directives.map(&:container_name)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def before_start_directives
|
|
75
|
+
@directives.select(&:before_start?)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def after_start_directives
|
|
79
|
+
@directives.select(&:after_start?)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
|
|
84
|
+
def from_directive
|
|
85
|
+
@directives.detect {|c| c.instance_of?(Indocker::ContainerDirectives::From)}
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def network_directives
|
|
89
|
+
@directives.select {|d| d.instance_of?(Indocker::ContainerDirectives::Network)}
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def env_directives
|
|
93
|
+
@directives.select {|d| d.instance_of?(Indocker::ContainerDirectives::EnvFile)}
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def expose_directives
|
|
97
|
+
@directives.select {|d| d.instance_of?(Indocker::ContainerDirectives::Expose)}
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def ports_directives
|
|
101
|
+
@directives.select {|d| d.instance_of?(Indocker::ContainerDirectives::Ports)}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def depends_on_directives
|
|
105
|
+
@directives.select {|d| d.instance_of?(Indocker::ContainerDirectives::DependsOn)}
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
class Indocker::ContainerMetadataFactory
|
|
2
|
+
include SmartIoC::Iocify
|
|
3
|
+
|
|
4
|
+
bean :container_metadata_factory
|
|
5
|
+
|
|
6
|
+
inject :docker_api
|
|
7
|
+
inject :container_evaluator
|
|
8
|
+
inject :image_metadata_repository
|
|
9
|
+
inject :network_metadata_repository
|
|
10
|
+
inject :container_metadata_repository
|
|
11
|
+
|
|
12
|
+
def create(name, &definition)
|
|
13
|
+
context = Indocker::DSLContext.new(
|
|
14
|
+
images: image_metadata_repository,
|
|
15
|
+
networks: network_metadata_repository,
|
|
16
|
+
containers: container_metadata_repository,
|
|
17
|
+
container_name: name
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
directives = container_evaluator.evaluate(context, &definition)
|
|
21
|
+
|
|
22
|
+
Indocker::ContainerMetadata.new(
|
|
23
|
+
name: name.to_s,
|
|
24
|
+
directives: directives
|
|
25
|
+
)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
class Indocker::ContainerMetadataRepository
|
|
2
|
+
include SmartIoC::Iocify
|
|
3
|
+
|
|
4
|
+
bean :container_metadata_repository
|
|
5
|
+
|
|
6
|
+
def put(metadata)
|
|
7
|
+
if get_by_name(metadata.name)
|
|
8
|
+
raise Indocker::Errors::InvalidParams, "Container name '#{metadata.name}' already in use"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
all.push(metadata)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def get_by_name(container_name)
|
|
15
|
+
container = all.detect {|container| container.name == container_name.to_s}
|
|
16
|
+
|
|
17
|
+
container
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def clear
|
|
21
|
+
@all = []
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def all
|
|
25
|
+
@all ||= []
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Indocker
|
|
2
|
+
module Directives
|
|
3
|
+
class Base
|
|
4
|
+
def partial?
|
|
5
|
+
self.is_a?(Indocker::Directives::Partial)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def prepare_directive?
|
|
9
|
+
self.is_a?(Indocker::PrepareDirectives::Base)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def build_directive?
|
|
13
|
+
self.is_a?(Indocker::DockerDirectives::Base)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def container_directive?
|
|
17
|
+
self.is_a?(Indocker::ContainerDirectives::Base)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|