algo 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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: