algo 0.1.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bb278f86fccf497cb5ece005a59c45ac56929fef
4
- data.tar.gz: 8cf7c48ff992326edf08c6500cb48de73e8be902
3
+ metadata.gz: 86e649323aa163f71b928277a792a0feb51a10d1
4
+ data.tar.gz: 80a24c0659991faf6098bd2b4044535e5fcf636f
5
5
  SHA512:
6
- metadata.gz: 4b3a4d6561a8adda98ad72b85e5b6e22896e5b8fad5f719adc81b9702b5b7bbcd416b50d9c04e02516cc1bb5aad81b4493d0533d82927875a9babb2f797c646c
7
- data.tar.gz: d54c9d0a2d304a8fbf8fa635f988241ba2f4b925b0c787034d93cbbc2413368287470041a2b6fcaf4a44aecd78b8006fe12aa3f1610947599860a166abbd379e
6
+ metadata.gz: 191b611c8254f37d1883e14053babe39251ed473165adc5b1c77ddb344a71a397b97fcd9def50110de6accf2d67974745fe3330e2f211929ad93850296d49d3c
7
+ data.tar.gz: f78566709a4b7e3fb9cf1fd4ebc81e51efd2f9ed35c6ead54108c4ec7171618174497a900f43407ca0a82ad755471c36d45b06775f623a712d4a31f57aae41a2
@@ -10,7 +10,13 @@ cluster 'awesomecluster' do
10
10
  label 'com.example.sample', 'clusterwidelabel'
11
11
 
12
12
  # Define network
13
- network 'net1'
13
+ network 'net1' do
14
+ ipam do
15
+ subnet '172.20.0.0/16'
16
+ ip_range '172.20.10.0/24'
17
+ gateway '172.20.10.11'
18
+ end
19
+ end
14
20
 
15
21
  # Define service
16
22
  service 'name' do
@@ -23,6 +29,21 @@ cluster 'awesomecluster' do
23
29
 
24
30
  env 'APP_DOMAIN', 'example.com'
25
31
 
32
+ # Mount host's directory/file
33
+ volume do
34
+ type 'bind'
35
+ source '/tmp/mount'
36
+ target '/mnt/sample'
37
+ end
38
+
39
+ # Mount host docker volume
40
+ volume do
41
+ type 'volume'
42
+ source 'volume-name'
43
+ target '/mnt/volume-sample'
44
+ end
45
+
46
+ # join network
26
47
  network 'net1'
27
48
  end
28
49
 
@@ -5,9 +5,12 @@ require 'active_support'
5
5
  require 'active_support/core_ext'
6
6
 
7
7
  module Algo
8
+ require 'algo/error'
8
9
  require "algo/version"
9
10
  require "algo/docker"
10
11
  require "algo/dsl"
12
+ require "algo/runner"
11
13
  require "algo/cli"
12
14
  # Your code goes here...
15
+
13
16
  end
@@ -1,70 +1,5 @@
1
1
  module Algo
2
2
  class Cli < Thor
3
- class ValidationError < StandardError; end
4
-
5
- class ServiceValidator
6
- def initialize srv_spec
7
- @srv_spec = srv_spec
8
- end
9
-
10
- def validate
11
- begin
12
- @srv = Algo::Docker::Service.find(@srv_spec['Name'])
13
- rescue Algo::Docker::Error::NotFoundError
14
- @srv = nil
15
- end
16
- check_networks
17
- end
18
-
19
- def self.validate srv_spec
20
- new(srv_spec).validate
21
- end
22
-
23
- private
24
-
25
- def check_networks
26
- return true if @srv.blank? or @srv.spec.networks.blank?
27
- srv_networks = @srv.spec.networks.map { |n| { 'Target' => n.info['Name'] } }
28
- unless srv_networks != @srv_spec['Networks']
29
- @srv_spec['Networks'] = @srv.spec.networks.map { |n| { 'Target' => n.info['Id'] } }
30
- return true
31
- end
32
- raise ValidationError, 'changing network in service is not supported'
33
- end
34
- end
35
-
36
- class ServiceUpdator
37
-
38
- def initialize srv_spec, options
39
- @srv_spec = srv_spec
40
- @options = options
41
- end
42
-
43
- def update
44
- begin
45
- srv = Algo::Docker::Service.find(@srv_spec['Name'])
46
- if srv.raw_spec == @srv_spec
47
- puts "service: #{@srv_spec['Name']}, status: ok"
48
- return
49
- end
50
- srv.update @srv_spec unless dryrun?
51
- puts "service: #{@srv_spec['Name']}, status: changed"
52
- rescue Algo::Docker::Error::NotFoundError
53
- Algo::Docker::Service.create(@srv_spec) unless dryrun?
54
- puts "service: #{@srv_spec['Name']}, status: created"
55
- end
56
- end
57
-
58
- def self.update srv_spec, dryrun=false
59
- new(srv_spec, {dryrun: dryrun}).update
60
- end
61
-
62
- private
63
-
64
- def dryrun?
65
- @options[:dryrun]
66
- end
67
- end
68
3
 
69
4
  desc 'apply [INVENTRY_FILE]', 'Apply configuration to clusters'
70
5
  option :'dry-run', type: :boolean, default: false
@@ -76,73 +11,22 @@ module Algo
76
11
  def apply inventry
77
12
  Algo::Docker.url = options[:host] if options[:host]
78
13
  Algo::Docker.options = docker_opts if docker_opts.present?
79
- puts 'Running with dry-run mode...' if options[:'dry-run']
80
14
  configuration = Algo::Dsl.load({}, inventry)
81
- configuration.each do |cluster|
82
- puts "Applying to cluster #{cluster['name']}..."
83
-
84
- cluster['networks'].each do |net_spec|
85
- begin
86
- net = Algo::Docker::Network.find net_spec['Name']
87
- puts "network: #{net_spec['Name']}, status: ok"
88
- rescue Algo::Docker::Error::NotFoundError
89
- Algo::Docker::Network.create net_spec unless options[:'dry-run']
90
- puts "network: #{net_spec['Name']}, status: created"
91
- end
92
- end
93
-
94
- cluster['services'].each do |srv_spec|
95
- ServiceValidator.validate srv_spec
96
- end
97
- cluster['services'].each do |srv_spec|
98
- ServiceUpdator.update srv_spec, options[:'dry-run']
99
- end
100
- Algo::Docker::Service.all
101
- .select { |srv| srv.spec.name.start_with?("#{cluster['prefix']}-") }
102
- .select { |srv| ! srv.spec.name.in? cluster['services'].map { |spec| spec['Name'] } }
103
- .map { |srv|
104
- srv_name = srv.spec.name
105
- srv.remove unless options[:'dry-run']
106
- puts "service: #{srv_name}, status: removed"
107
- }
108
- Algo::Docker::Network.all(skip_default=true)
109
- .select { |net| net.info['Name'].start_with?("#{cluster['prefix']}-") }
110
- .select { |net| ! net.info['Name'].in? cluster['networks'].map { |net_spec| net_spec['Name'] } }
111
- .map { |net|
112
- net_name = net.info['Name']
113
- net.remove unless options[:'dry-run']
114
- puts "network: #{net_name}, status: removed"
115
- }
116
- puts "Complete applying for cluster #{cluster['name']}!"
117
- end
118
- rescue ValidationError => e
119
- puts 'configuration validation failed because ' + e.message
15
+ Algo::Runner::Apply.call configuration, options
120
16
  end
121
17
 
122
18
  desc 'rm [INVENTRY_FILE]', 'Terminate clusters'
123
19
  option :'dry-run', type: :boolean, default: false
20
+ option :'url', type: :string, desc: 'docker swarm url like tcp://localhost:2375'
21
+ option :'client_key', type: :string, desc: 'docker swarm client key path'
22
+ option :'client_sert', type: :string, desc: 'docker swarm client sert path'
23
+ option :'ssl_ca_file', type: :string, desc: 'docker swarm ssl ca file path'
24
+ option :'scheme', type: :string, desc: 'docker swarm connection scheme'
124
25
  def rm inventry
125
- puts 'Running with dry-run mode...' if options[:'dry-run']
26
+ Algo::Docker.url = options[:host] if options[:host]
27
+ Algo::Docker.options = docker_opts if docker_opts.present?
126
28
  configuration = Algo::Dsl.load({}, inventry)
127
- configuration.each do |cluster|
128
- puts "Terminating cluster #{cluster['name']}..."
129
- Algo::Docker::Service.all
130
- .select { |srv| srv.spec.name.start_with?("#{cluster['prefix']}-") }
131
- .map { |srv|
132
- srv_name = srv.spec.name
133
- srv.remove unless options[:'dry-run']
134
- puts "service: #{srv_name}, status: removed"
135
- }
136
- Algo::Docker::Network.all(skip_default=true)
137
- .select { |net| net.info['Name'].start_with?("#{cluster['prefix']}-") }
138
- .select { |net| ! net.info['Name'].in? cluster['networks'].map { |net_spec| "#{cluster['prefix']}-#{net_spec['Name']}" } }
139
- .map { |net|
140
- net_name = net.info['Name']
141
- net.remove unless options[:'dry-run']
142
- puts "network: #{net_name}, status: removed"
143
- }
144
- puts "Complete Termination for cluster #{cluster['name']}..."
145
- end
29
+ Algo::Runner::Rm.call configuration, options
146
30
  end
147
31
 
148
32
  private
@@ -3,6 +3,10 @@ module Algo
3
3
  class Network < Base
4
4
  DEFAULT_NETWORKS = %w(ingress none host bridge docker_gwbridge)
5
5
 
6
+ def name
7
+ info['Name']
8
+ end
9
+
6
10
  def inspect
7
11
  "<Algo::Docker::Network name=#{info['Name']} scope=#{info['Scope']}>"
8
12
  end
@@ -14,6 +14,10 @@ module Algo
14
14
  @spec = nil
15
15
  end
16
16
 
17
+ def name
18
+ info["Spec"]["Name"]
19
+ end
20
+
17
21
  def info
18
22
  @info = Docker::Service.find(@info["Id"]).info if @info["Spec"].blank?
19
23
  @info
@@ -21,6 +21,13 @@ module Algo
21
21
  dsl.result
22
22
  end
23
23
 
24
+ def self.load_text(options, text)
25
+ dsl = new(options).tap do |dsl|
26
+ dsl.instance_eval(text)
27
+ end
28
+ dsl.result
29
+ end
30
+
24
31
  def initialize(options)
25
32
  @options = CLUSTER_DEFAULT.dup
26
33
  @options.merge!(options)
@@ -2,6 +2,26 @@ module Algo
2
2
  class Dsl
3
3
  module Network
4
4
 
5
+ class IPAMContext
6
+ attr_reader :context
7
+
8
+ def initialize
9
+ @context = {}
10
+ end
11
+
12
+ def subnet item
13
+ @context['Subnet'] = item
14
+ end
15
+
16
+ def ip_range item
17
+ @context['IPRange'] = item
18
+ end
19
+
20
+ def gateway item
21
+ @context['Gateway'] = item
22
+ end
23
+ end
24
+
5
25
  class Context
6
26
 
7
27
  attr_reader :context
@@ -36,6 +56,13 @@ module Algo
36
56
  @context['EnableIPv6'] = true
37
57
  end
38
58
 
59
+ def ipam &block
60
+ ctx = Network::IPAMContext.new.tap do |ctx|
61
+ ctx.instance_eval(&block) if block_given?
62
+ end
63
+ @context['IPAM']['Config'] << ctx.context
64
+ end
65
+
39
66
  private
40
67
 
41
68
  def cluster_prefix
@@ -2,6 +2,58 @@ module Algo
2
2
  class Dsl
3
3
  module Service
4
4
 
5
+ class VolumeContext
6
+ attr_reader :context
7
+
8
+ def initialize clstr_context, srv_context
9
+ @clstr_context = clstr_context
10
+ @srv_context = srv_context
11
+ @context = {}
12
+ end
13
+
14
+ def readonly
15
+ @context['ReadOnly'] = true
16
+ end
17
+
18
+ # @param [String] item volume name or host file/directory path
19
+ def source item
20
+ raise 'Need to call type at first' unless @context['Type']
21
+ if @context['Type'] == 'volume'
22
+ @context['Source'] = "#{cluster_prefix}#{item}"
23
+ else
24
+ @context['Source'] = item
25
+ end
26
+ end
27
+
28
+ # @param [String] item container mount path
29
+ def target item
30
+ @context['Target'] = item
31
+ end
32
+
33
+ # @param [String] volume type ex) bind,volume
34
+ def type item
35
+ @context['Type'] = item
36
+ end
37
+
38
+ def label key, val
39
+ @context['VolumeOptions'] ||= {}
40
+ @context['VolumeOptions']['Labels'] ||= {}
41
+ @context['VolumeOptions']['Labels'][key] = val
42
+ end
43
+
44
+ # @param [String] volume driver type ex) local
45
+ def driver item
46
+ @context['VolumeOptions'] ||= {}
47
+ @context['VolumeOptions'] = { 'DriverConfig' => { 'Name' => item } }
48
+ end
49
+
50
+ private
51
+
52
+ def cluster_prefix
53
+ "#{@clstr_context['prefix']}-" if @clstr_context['prefix']
54
+ end
55
+ end
56
+
5
57
  class Context
6
58
  attr_reader :context
7
59
 
@@ -43,20 +95,89 @@ module Algo
43
95
  @context['TaskTemplate']['ContainerSpec']['Env'] << "#{key}=#{val}"
44
96
  end
45
97
 
98
+ def workdir name
99
+ @context['TaskTemplate']['ContainerSpec']['Dir'] = name
100
+ end
101
+
102
+ def user name
103
+ @context['TaskTemplate']['ContainerSpec']['User'] = name
104
+ end
105
+
46
106
  # @param [String] period period string like 30s, 1m, 4h
47
107
  def stop_grace_period period
48
- if period.end_with?('s')
49
- period = period.chomp('s').to_i
50
- elsif period.end_with?('m')
51
- period = period.chomp('m').to_i * 60
52
- elsif period.end_with?('h')
53
- period = period.chomp('m').to_i * 60 * 60
54
- else
55
- raise
108
+ @context['TaskTemplate']['ContainerSpec']['StopGracePeriod'] = second_from_string(period) * 1e9
109
+ end
110
+
111
+ def volume &block
112
+ raise 'should be called in cluster' unless @context
113
+ ctx = Service::VolumeContext.new(@cluster, @context).tap do |ctx|
114
+ ctx.instance_eval(&block)
56
115
  end
57
- @context['TaskTemplate']['ContainerSpec']['StopGracePeriod'] = period * 1000000000
116
+ @context['TaskTemplate']['ContainerSpec']['Mounts'] ||= []
117
+ @context['TaskTemplate']['ContainerSpec']['Mounts'] << ctx.context
58
118
  end
59
119
 
120
+ # Resources
121
+
122
+ def limit_cpu decimal
123
+ @context['TaskTemplate']['Resources'] ||= {}
124
+ @context['TaskTemplate']['Resources']['Limits'] ||= {}
125
+ @context['TaskTemplate']['Resources']['Limits']['NanoCPUs'] = decimal * 1e9
126
+ end
127
+
128
+ # @param [String] memory num with unit like 1B 20KB 30MB 1GB
129
+ def limit_memory memory
130
+ @context['TaskTemplate']['Resources'] ||= {}
131
+ @context['TaskTemplate']['Resources']['Limits'] ||= {}
132
+ @context['TaskTemplate']['Resources']['Limits']['MemoryBytes'] = memory_from_string memory
133
+ end
134
+
135
+ def reserve_cpu decimal
136
+ @context['TaskTemplate']['Resources'] ||= {}
137
+ @context['TaskTemplate']['Resources']['Reservation'] ||= {}
138
+ @context['TaskTemplate']['Resources']['Reservation']['NanoCPUs'] = decimal * 1e9
139
+ end
140
+
141
+ # @param [String] memory num with unit like 1B 20KB 30MB 1GB
142
+ def reserve_memory memory
143
+ @context['TaskTemplate']['Resources'] ||= {}
144
+ @context['TaskTemplate']['Resources']['Reservation'] ||= {}
145
+ @context['TaskTemplate']['Resources']['Reservation']['MemoryBytes'] = memory_from_string memory
146
+ end
147
+
148
+ # RestartPolicy
149
+
150
+ # @param [String] name none, on-failure or any
151
+ def restart_condition name
152
+ @context['TaskTemplate']['RestartPolicy'] ||= {}
153
+ @context['TaskTemplate']['RestartPolicy']['Condition'] = name
154
+ end
155
+
156
+ def restart_delay period
157
+ @context['TaskTemplate']['RestartPolicy'] ||= {}
158
+ @context['TaskTemplate']['RestartPolicy']['Delay'] = second_from_string(period) * 10e9
159
+ end
160
+
161
+ # @param [Integer] value
162
+ def restart_max_attempts value
163
+ @context['TaskTemplate']['RestartPolicy'] ||= {}
164
+ @context['TaskTemplate']['RestartPolicy']['Attempts'] = value
165
+ end
166
+
167
+ def restart_window value
168
+ @context['TaskTemplate']['RestartPolicy'] ||= {}
169
+ @context['TaskTemplate']['RestartPolicy']['Window'] = second_from_string(period) * 10e9
170
+ end
171
+
172
+ # Placement
173
+
174
+ def constraint condition
175
+ @context['TaskTemplate']['Placement'] ||= {}
176
+ @context['TaskTemplate']['Placement']['Constraints'] ||= []
177
+ @context['TaskTemplate']['Placement']['Constraints'] << condition
178
+ end
179
+
180
+
60
181
  # Label
61
182
 
62
183
  def label key, val
@@ -67,7 +188,31 @@ module Algo
67
188
  # Mode
68
189
 
69
190
  def replicas replica_size
70
- @context['Mode']['Replicated']['Replicas']= replica_size
191
+ @context['Mode'] = { 'Replicated' => { 'Replicas' => replica_size } }
192
+ end
193
+
194
+ def global
195
+ @context['Mode'] = { 'Global' => {} }
196
+ end
197
+
198
+ # EndpointSpec
199
+
200
+ # @param [String] mode vip or dnsrr
201
+ def endpoint_mode mode
202
+ @context['EndpointSpec'] = { 'Mode' => mode }
203
+ end
204
+
205
+ # @param [String] port like 80 or 80:80 or 80/udp
206
+ def publish port
207
+ port, protocol = *port.split('/') if '/'.in? port
208
+ target, publish = *port.split(':') if ':'.in? port
209
+ @context['EndpointSpec'] ||= {}
210
+ @context['EndpointSpec']['Ports'] ||= []
211
+ @context['EndpointSpec']['Ports'] << {
212
+ 'Protocol' => protocol,
213
+ 'TargetPort' => target,
214
+ 'PublishedPort' => publish
215
+ }.compact
71
216
  end
72
217
 
73
218
  # UpdateConfig
@@ -87,7 +232,7 @@ module Algo
87
232
  def network name
88
233
  @context['Networks'] ||= []
89
234
  @context['Networks'] << { 'Target' => "#{cluster_prefix}#{name}" }
90
- end
235
+ end
91
236
 
92
237
  private
93
238
 
@@ -95,6 +240,34 @@ module Algo
95
240
  "#{@cluster['prefix']}-" if @cluster['prefix']
96
241
  end
97
242
 
243
+ def second_from_string(period)
244
+ if period.end_with?('s')
245
+ period.chomp('s').to_i
246
+ elsif period.end_with?('m')
247
+ period.chomp('m').to_i * 60
248
+ elsif period.end_with?('h')
249
+ period.chomp('m').to_i * 60 * 60
250
+ else
251
+ raise
252
+ end
253
+ end
254
+
255
+ def memory_from_string(memory)
256
+ if memory.end_with?('B')
257
+ memory.chomp('B').to_i
258
+ elsif memory.end_with?('KB')
259
+ memory.chomp('KB').to_i * 1e3
260
+ elsif memory.end_with?('MB')
261
+ memory.chomp('MB').to_i * 1e6
262
+ elsif memory.end_with?('GB')
263
+ memory.chomp('GB').to_i * 1e9
264
+ elsif memory.end_with?('TB')
265
+ memory.chomp('TB').to_i * 1e12
266
+ else
267
+ raise
268
+ end
269
+ end
270
+
98
271
  end
99
272
 
100
273
  def service name, &block
@@ -0,0 +1,9 @@
1
+ module Algo
2
+
3
+ module Error
4
+ class ValidationError < StandardError; end
5
+ end
6
+
7
+ include Error
8
+
9
+ end
@@ -0,0 +1,6 @@
1
+ module Algo
2
+ module Runner
3
+ require 'algo/runner/apply'
4
+ require 'algo/runner/rm'
5
+ end
6
+ end
@@ -0,0 +1,130 @@
1
+ module Algo
2
+ module Runner
3
+ class Apply
4
+
5
+ class ServiceValidator
6
+ def initialize srv_spec
7
+ @srv_spec = srv_spec
8
+ end
9
+
10
+ def validate
11
+ begin
12
+ @srv = Algo::Docker::Service.find(@srv_spec['Name'])
13
+ rescue Algo::Docker::Error::NotFoundError
14
+ @srv = nil
15
+ end
16
+ check_networks
17
+ end
18
+
19
+ def self.validate srv_spec
20
+ new(srv_spec).validate
21
+ end
22
+
23
+ private
24
+
25
+ def check_networks
26
+ return true if @srv.blank? or @srv.spec.networks.blank?
27
+ srv_networks = @srv.spec.networks.map { |n| { 'Target' => n.name } }
28
+ unless srv_networks != @srv_spec['Networks']
29
+ @srv_spec['Networks'] = @srv.spec.networks.map { |n| { 'Target' => n.id } }
30
+ return true
31
+ end
32
+ raise ValidationError, 'changing network in service is not supported'
33
+ end
34
+ end
35
+
36
+ class ServiceUpdator
37
+
38
+ def initialize srv_spec, options
39
+ @srv_spec = srv_spec
40
+ @options = options
41
+ end
42
+
43
+ def update
44
+ begin
45
+ srv = Algo::Docker::Service.find(@srv_spec['Name'])
46
+ if srv.raw_spec == @srv_spec
47
+ puts "service: #{@srv_spec['Name']}, status: ok"
48
+ return
49
+ end
50
+ srv.update @srv_spec unless dryrun?
51
+ puts "service: #{@srv_spec['Name']}, status: changed"
52
+ rescue Algo::Docker::Error::NotFoundError
53
+ Algo::Docker::Service.create(@srv_spec) unless dryrun?
54
+ puts "service: #{@srv_spec['Name']}, status: created"
55
+ end
56
+ end
57
+
58
+ def self.update srv_spec, dryrun=false
59
+ new(srv_spec, {dryrun: dryrun}).update
60
+ end
61
+
62
+ private
63
+
64
+ def dryrun?
65
+ @options[:dryrun]
66
+ end
67
+ end
68
+
69
+ attr_reader :configuration, :options
70
+
71
+ def initialize configuration, options
72
+ @configuration = configuration
73
+ @options = options
74
+ end
75
+
76
+ def call
77
+ puts 'Running with dry-run mode...' if dryrun?
78
+ configuration.each do |cluster|
79
+ puts "Applying to cluster #{cluster['name']}..."
80
+
81
+ cluster['networks'].each do |net_spec|
82
+ begin
83
+ net = Algo::Docker::Network.find net_spec['Name']
84
+ puts "network: #{net_spec['Name']}, status: ok"
85
+ rescue Algo::Docker::Error::NotFoundError
86
+ Algo::Docker::Network.create net_spec unless dryrun?
87
+ puts "network: #{net_spec['Name']}, status: created"
88
+ end
89
+ end
90
+ cluster['services'].each do |srv_spec|
91
+ ServiceValidator.validate srv_spec
92
+ end
93
+ cluster['services'].each do |srv_spec|
94
+ ServiceUpdator.update srv_spec, dryrun?
95
+ end
96
+ Algo::Docker::Service.all
97
+ .select { |srv| srv.spec.name.start_with?("#{cluster['prefix']}-") }
98
+ .select { |srv| ! srv.spec.name.in? cluster['services'].map { |spec| spec['Name'] } }
99
+ .map { |srv|
100
+ srv_name = srv.spec.name
101
+ srv.remove unless dryrun?
102
+ puts "service: #{srv_name}, status: removed"
103
+ }
104
+ Algo::Docker::Network.all(skip_default=true)
105
+ .select { |net| net.name.start_with?("#{cluster['prefix']}-") }
106
+ .select { |net| ! net.name.in? cluster['networks'].map { |net_spec| net_spec['Name'] } }
107
+ .map { |net|
108
+ net_name = net.name
109
+ net.remove unless dryrun?
110
+ puts "network: #{net_name}, status: removed"
111
+ }
112
+ puts "Complete applying for cluster #{cluster['name']}!"
113
+ end
114
+ rescue Algo::ValidationError => e
115
+ puts 'configuration validation failed because ' + e.message
116
+ end
117
+
118
+ def self.call configuration, options
119
+ new(configuration, options).call
120
+ end
121
+
122
+ private
123
+
124
+ def dryrun?
125
+ options[:'dry-run']
126
+ end
127
+
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,46 @@
1
+ module Algo
2
+ module Runner
3
+ class Rm
4
+ attr_reader :configuration, :options
5
+
6
+ def initialize configuration, options
7
+ @configuration = configuration
8
+ @options = options
9
+ end
10
+
11
+ def call
12
+ puts 'Running with dry-run mode...' if dryrun?
13
+ configuration.each do |cluster|
14
+ puts "Terminating cluster #{cluster['name']}..."
15
+ Algo::Docker::Service.all
16
+ .select { |srv| srv.spec.name.start_with?("#{cluster['prefix']}-") }
17
+ .map { |srv|
18
+ srv_name = srv.spec.name
19
+ srv.remove unless dryrun?
20
+ puts "service: #{srv_name}, status: removed"
21
+ }
22
+ Algo::Docker::Network.all(skip_default=true)
23
+ .select { |net| net.info['Name'].start_with?("#{cluster['prefix']}-") }
24
+ .select { |net| ! net.info['Name'].in? cluster['networks'].map { |net_spec| "#{cluster['prefix']}-#{net_spec['Name']}" } }
25
+ .map { |net|
26
+ net_name = net.info['Name']
27
+ net.remove unless dryrun?
28
+ puts "network: #{net_name}, status: removed"
29
+ }
30
+ puts "Complete Termination for cluster #{cluster['name']}..."
31
+ end
32
+ end
33
+
34
+ def self.call configuration, options
35
+ new(configuration, options).call
36
+ end
37
+
38
+ private
39
+
40
+ def dryrun?
41
+ options[:'dry-run']
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -1,3 +1,3 @@
1
1
  module Algo
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: algo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - yoshiso
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-07-25 00:00:00.000000000 Z
11
+ date: 2016-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -140,6 +140,10 @@ files:
140
140
  - lib/algo/dsl/cluster.rb
141
141
  - lib/algo/dsl/network.rb
142
142
  - lib/algo/dsl/service.rb
143
+ - lib/algo/error.rb
144
+ - lib/algo/runner.rb
145
+ - lib/algo/runner/apply.rb
146
+ - lib/algo/runner/rm.rb
143
147
  - lib/algo/version.rb
144
148
  homepage: https://github.com/yoshiso/algo
145
149
  licenses: