dc 0.0.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 (4) hide show
  1. checksums.yaml +7 -0
  2. data/bin/dc +4 -0
  3. data/lib/dc.rb +200 -0
  4. metadata +59 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a1778827651668547f6a5ea1e41c8c29ad99f9675e8ecb0982f16e7fe41838e3
4
+ data.tar.gz: aaca72cc50e107ebfd0f6ba6517c1562d8b492217dfef2812048aef658e1c12b
5
+ SHA512:
6
+ metadata.gz: b540e943a2b221b098565ab653a9dc98ad240cc31b9076bb4736c4273ecd271dc301c47eb41d315f81a7caa3cacc05fdee5f97220c736b3e0ecc673b83202c0c
7
+ data.tar.gz: fc98f1883b3a9daae99d646f75fd593124d547ad024590e1979078b5f0aef241cecac9198855e072239fb6adef2096406a51208b0cffce5ca407368c3da2d377
data/bin/dc ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'dc'
4
+ DC::CLI.run
@@ -0,0 +1,200 @@
1
+ module DC
2
+ require 'forwardable'
3
+ require 'yaml'
4
+ require 'docker'
5
+
6
+ class Container
7
+ def initialize name, ports: []
8
+ @name = name
9
+ @container = if ports.empty?
10
+ Docker::Container.create name: name, Image: name
11
+ else
12
+ port_maps = ports.map do |port|
13
+ if port.is_a? PortMap
14
+ port
15
+ else
16
+ to, from = port.split ':'
17
+ PortMap.new from: from, to: to
18
+ end
19
+ end
20
+
21
+ Docker::Container.create(
22
+ name: name, Image: name,
23
+ ExposedPorts: port_maps.map do |map|
24
+ ["#{map.internal_port}/tcp", {}]
25
+ end.to_h,
26
+ HostConfig: {
27
+ PortBindings: port_maps.map do |map|
28
+ array = [{ HostPort: map.external_port, HostIp: map.external_ip }]
29
+ ["#{map.internal_port}/tcp", array]
30
+ end.to_h
31
+ }
32
+ )
33
+ end
34
+ end
35
+
36
+ attr_reader :name
37
+
38
+ def internal_container
39
+ @container
40
+ end
41
+
42
+ extend Forwardable
43
+ delegate [:id, :start, :kill!, :remove] => :internal_container
44
+
45
+ def destroy
46
+ kill!.remove
47
+ end
48
+
49
+ class PortMap
50
+ def initialize from:, to:, external_ip: '0.0.0.0'
51
+ @internal_port = from.to_s
52
+ @external_port = to.to_s
53
+ @external_ip = external_ip
54
+ end
55
+
56
+ attr_reader :internal_port, :external_port, :external_ip
57
+ end
58
+ end
59
+
60
+ class Image
61
+ class << self
62
+ def all
63
+ @all ||= {}
64
+ end
65
+
66
+ def [] name
67
+ all[name]
68
+ end
69
+
70
+ def []= name, image
71
+ all[name] = image
72
+ end
73
+ end
74
+
75
+ def initialize name, directory: name
76
+ @name = name
77
+ @directory = directory
78
+ self.class[name] = self
79
+ end
80
+
81
+ attr_reader :name
82
+
83
+ def exist?
84
+ Docker::Image.exist? @name
85
+ end
86
+
87
+ def build
88
+ build_parent_image_if_available
89
+ image = Docker::Image.build_from_dir @directory do |json|
90
+ puts JSON.parse json
91
+ end
92
+ image.tag repo: @name
93
+ image
94
+ end
95
+
96
+ private
97
+ def build_parent_image_if_available
98
+ dockerfile = IO.read "#{@directory}/Dockerfile"
99
+ from, image_name = dockerfile.each_line.first.split ' '
100
+ fail from unless from == 'FROM'
101
+
102
+ if image = self.class[image_name]
103
+ unless image.exist?
104
+ puts "Building parent image #{image.name}."
105
+ image.build
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+ class Network
112
+ def initialize name = 'common'
113
+ @network = prepare_network_with_name name
114
+ end
115
+
116
+ def internal_network
117
+ @network
118
+ end
119
+
120
+ extend Forwardable
121
+ delegate [:id, :connect] => :internal_network
122
+
123
+ def name
124
+ @network.info['Name']
125
+ end
126
+
127
+ private
128
+ def prepare_network_with_name name
129
+ Docker::Network.get name
130
+ rescue Docker::Error::NotFoundError
131
+ Docker::Network.create name
132
+ end
133
+ end
134
+
135
+ class Project
136
+ def initialize directory: '.', docker_socket: 'tcp://127.0.0.1:2375'
137
+ check_if_docker_is_available_at docker_socket
138
+
139
+ @directory = File.expand_path directory
140
+ @images_directory = "#{@directory}/.docker/images"
141
+ @services_file = "#{@directory}/.docker/services.yml"
142
+ end
143
+
144
+ attr_reader :containers
145
+
146
+ def run
147
+ prepare_images
148
+ prepare_services
149
+ end
150
+
151
+ private
152
+ def check_if_docker_is_available_at docker_socket
153
+ Docker.url = docker_socket
154
+ Docker.version
155
+ #rescue Excon::Error::Socket
156
+ end
157
+
158
+ def prepare_images
159
+ if Dir.exist? @images_directory
160
+ images = (Dir.entries(@images_directory) - ['.', '..']).map do |name|
161
+ Image.new name, directory: "#{@images_directory}/#{name}"
162
+ end
163
+
164
+ images.each do |image|
165
+ image.build unless image.exist?
166
+ end
167
+ end
168
+ end
169
+
170
+ def prepare_services
171
+ if File.exist? @services_file
172
+ hash = YAML.load_file @services_file
173
+
174
+ images = hash.keys.map do |name|
175
+ Image.new name, directory: "#{@directory}/#{name}"
176
+ end
177
+
178
+ images.each do |image|
179
+ image.build unless image.exist?
180
+ end
181
+
182
+ @containers = hash.map do |name, value|
183
+ ports = if value.is_a?(Hash) && value['ports'].is_a?(Array)
184
+ value['ports']
185
+ else
186
+ []
187
+ end
188
+
189
+ Container.new name, ports: ports
190
+ end
191
+
192
+ network = Network.new
193
+ @containers.each { |container| network.connect container.id }
194
+
195
+ @containers.each &:start
196
+ at_exit { @containers.each &:destroy }
197
+ end
198
+ end
199
+ end
200
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Anatoly Chernow
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-03-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: docker-api
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description:
28
+ email:
29
+ executables:
30
+ - dc
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - bin/dc
35
+ - lib/dc.rb
36
+ homepage:
37
+ licenses: []
38
+ metadata: {}
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubyforge_project:
55
+ rubygems_version: 2.7.6
56
+ signing_key:
57
+ specification_version: 4
58
+ summary: Manage projects with Docker conveniently.
59
+ test_files: []