Class: Dockistrano::Service

Inherits:
Object
  • Object
show all
Defined in:
lib/dockistrano/service.rb

Defined Under Namespace

Classes: ConfigurationFileMissing, EnvironmentNotFoundInConfiguration, EnvironmentVariablesMissing, NoTagFoundForImage

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config, environment = "default") ⇒ Service

Returns a new instance of Service.



32
33
34
35
# File 'lib/dockistrano/service.rb', line 32

def initialize(config, environment="default")
  @full_config = config
  self.environment = environment
end

Instance Attribute Details

#additional_commandsObject (readonly)

Returns the value of attribute additional_commands.



8
9
10
# File 'lib/dockistrano/service.rb', line 8

def additional_commands
  @additional_commands
end

#backing_service_envObject (readonly)

Returns the value of attribute backing_service_env.



8
9
10
# File 'lib/dockistrano/service.rb', line 8

def backing_service_env
  @backing_service_env
end

#configObject

Returns the value of attribute config.



8
9
10
# File 'lib/dockistrano/service.rb', line 8

def config
  @config
end

#data_directoriesObject (readonly)

Returns the value of attribute data_directories.



8
9
10
# File 'lib/dockistrano/service.rb', line 8

def data_directories
  @data_directories
end

#dependenciesObject (readonly)

Returns the value of attribute dependencies.



8
9
10
# File 'lib/dockistrano/service.rb', line 8

def dependencies
  @dependencies
end

#environmentObject

Returns the value of attribute environment.



8
9
10
# File 'lib/dockistrano/service.rb', line 8

def environment
  @environment
end

#hostObject (readonly)

Returns the value of attribute host.



8
9
10
# File 'lib/dockistrano/service.rb', line 8

def host
  @host
end

#image_nameObject (readonly)

Returns the value of attribute image_name.



8
9
10
# File 'lib/dockistrano/service.rb', line 8

def image_name
  @image_name
end

#mount_srcObject (readonly)

Returns the value of attribute mount_src.



8
9
10
# File 'lib/dockistrano/service.rb', line 8

def mount_src
  @mount_src
end

#provides_envObject (readonly)

Returns the value of attribute provides_env.



8
9
10
# File 'lib/dockistrano/service.rb', line 8

def provides_env
  @provides_env
end

#registryObject (readonly)

Returns the value of attribute registry.



8
9
10
# File 'lib/dockistrano/service.rb', line 8

def registry
  @registry
end

#tagObject

Returns the value of attribute tag.



8
9
10
# File 'lib/dockistrano/service.rb', line 8

def tag
  @tag
end

#test_commandObject (readonly)

Returns the value of attribute test_command.



8
9
10
# File 'lib/dockistrano/service.rb', line 8

def test_command
  @test_command
end

Class Method Details

.factory(path, environment = "default") ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/dockistrano/service.rb', line 18

def self.factory(path, environment="default")
  config = if File.exists?(File.join(path, "config", "dockistrano.yml"))
    YAML.load_file(File.join(path, "config", "dockistrano.yml"))
  elsif File.exists?(File.join(path, "dockistrano.yml"))
    YAML.load_file(File.join(path, "dockistrano.yml"))
  else
    raise ConfigurationFileMissing
  end

  environment ||= "default"

  Service.new(config, environment)
end

Instance Method Details

#attach(name = nil) ⇒ Object



302
303
304
305
306
307
308
# File 'lib/dockistrano/service.rb', line 302

def attach(name=nil)
  if name
    Docker.attach("#{image_name}_#{name}")
  else
    Docker.attach(image_name)
  end
end

#available_tags_in_registryObject

Returns a list of available tags in the registry for the image



263
264
265
266
267
268
269
# File 'lib/dockistrano/service.rb', line 263

def available_tags_in_registry
  @available_tags ||= begin
    registry_instance.tags_for_image(image_name)
  rescue Dockistrano::Registry::RepositoryNotFoundInRegistry
    []
  end
end

#available_tags_localObject



271
272
273
# File 'lib/dockistrano/service.rb', line 271

def available_tags_local
  @available_tags_local ||= Docker.tags_for_image("#{registry}/#{image_name}")
end

#backing_services(options = {}) ⇒ Object

Lists all backing services for this service



196
197
198
199
200
201
202
203
204
# File 'lib/dockistrano/service.rb', line 196

def backing_services(options={})
  initialize = options.delete(:initialize)
  initialize = true if initialize.nil?
  @backing_services ||= {}.tap do |hash|
    dependencies.collect do |name, config|
      hash[name] = ServiceDependency.factory(self, name, config, initialize)
    end
  end
end

#buildObject

Builds a new image for this service



85
86
87
88
89
90
91
92
93
94
# File 'lib/dockistrano/service.rb', line 85

def build
  previous_image_id = image_id
  Docker.build(full_image_name)
  if previous_image_id == image_id
    # If the image id hasn't changed the build was not successfull
    false
  else
    true
  end
end

#console(command, options = {}) ⇒ Object

Starts a console in the docker container



190
191
192
193
# File 'lib/dockistrano/service.rb', line 190

def console(command, options={})
  create_data_directories
  Docker.console(full_image_name_with_fallback, link: link_backing_services, command: command, e: environment_variables, v: volumes)
end

#create_data_directoriesObject



318
319
320
321
322
323
324
325
326
327
328
# File 'lib/dockistrano/service.rb', line 318

def create_data_directories
  if data_directories.any?
    image_config = Docker.inspect_image(full_image_name_with_fallback)
    image_user = image_config["container_config"]["User"]

    command = "mkdir -p #{data_directories.collect { |dir| "/dockistrano/data/#{dir}"}.join(" ") }; "
    command += "chown #{image_user}:#{image_user} #{data_directories.collect { |dir| "/dockistrano/data/#{dir}"}.join(" ") }"
    bash_command = "/bin/bash -c '#{command}'"
    Docker.run(full_image_name_with_fallback, command: bash_command, v: volumes, e: environment_variables, u: "root", rm: true)
  end
end

#directories_required_on_hostObject



258
259
260
# File 'lib/dockistrano/service.rb', line 258

def directories_required_on_host
  (volumes.collect { |v| v.split(":").first } + backing_services.values.map(&:directories_required_on_host)).flatten
end

#ensure_backing_servicesObject

Ensures that the right backing services are running to execute this services When a backing services is not running it is started



110
111
112
113
114
# File 'lib/dockistrano/service.rb', line 110

def ensure_backing_services
  backing_services.each do |name, service|
    service.start unless service.running?
  end
end

#environment_variablesObject

Returns an array of environment variables



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/dockistrano/service.rb', line 214

def environment_variables
  vars = {}

  config["environment"].each do |name, value|
    vars[name.upcase] = value
  end

  backing_services.each do |name, backing_service|
    backing_service.backing_service_env.each do |k,v|
      vars["#{name.upcase}_#{k.upcase}"] = v
    end

    vars.merge!(backing_service.provided_environment_variables)
  end

  vars.each do |key, value|
    vars.each do |replacement_key, replacement_value|
      vars[key] = if vars[key].nil? or replacement_value.nil? or replacement_value.empty?
        vars[key].gsub('$'+replacement_key, '$'+replacement_key)
      else
        vars[key].gsub('$'+replacement_key, replacement_value)
      end
    end
  end

  vars
end

#exec(command, options = {}) ⇒ Object

Executes a command in this container



184
185
186
187
# File 'lib/dockistrano/service.rb', line 184

def exec(command, options={})
  create_data_directories
  Docker.exec(full_image_name_with_fallback, link: link_backing_services, command: command, e: environment_variables, v: volumes)
end

#full_image_nameObject



76
77
78
# File 'lib/dockistrano/service.rb', line 76

def full_image_name
  "#{registry}/#{image_name}:#{tag}"
end

#full_image_name_with_fallbackObject



80
81
82
# File 'lib/dockistrano/service.rb', line 80

def full_image_name_with_fallback
  "#{registry}/#{image_name}:#{tag_with_fallback}"
end

#image_idObject



70
71
72
73
74
# File 'lib/dockistrano/service.rb', line 70

def image_id
  Docker.image_id(full_image_name)
rescue Dockistrano::Docker::ImageNotFound
  nil
end

#ip_addressObject



294
295
296
# File 'lib/dockistrano/service.rb', line 294

def ip_address
  container_settings["NetworkSettings"]["IPAddress"] if running?
end

Returns an array of backing services to link



207
208
209
210
211
# File 'lib/dockistrano/service.rb', line 207

def link_backing_services
  backing_services.collect { |name, service|
    "#{service.image_name}:#{service.image_name}"
  }
end

#logs(name = nil) ⇒ Object



310
311
312
313
314
315
316
# File 'lib/dockistrano/service.rb', line 310

def logs(name=nil)
  if name
    Docker.logs("#{image_name}_#{name}")
  else
    Docker.logs(image_name)
  end
end

#newer_version_available?Boolean

Returns:

  • (Boolean)


330
331
332
333
# File 'lib/dockistrano/service.rb', line 330

def newer_version_available?
  registry_image_id = registry_instance.latest_id_for_image(image_name, tag_with_fallback)
  registry_image_id and image_id != registry_image_id
end

#portsObject



298
299
300
# File 'lib/dockistrano/service.rb', line 298

def ports
  (config["ports"] || [])
end

#provided_environment_variablesObject



242
243
244
# File 'lib/dockistrano/service.rb', line 242

def provided_environment_variables
  provides_env
end

#pullObject

Pulls the service’s container



140
141
142
# File 'lib/dockistrano/service.rb', line 140

def pull
  Dockistrano::Docker.pull("#{registry}/#{image_name}", tag_with_fallback)
end

#pull_backing_servicesObject

Pulls backing services for this service



133
134
135
136
137
# File 'lib/dockistrano/service.rb', line 133

def pull_backing_services
  backing_services.each do |name, service|
    service.pull
  end
end

#pushObject

Pushes the local image for this service to the registry



145
146
147
# File 'lib/dockistrano/service.rb', line 145

def push
  Dockistrano::Docker.push("#{registry}/#{image_name}", tag)
end

#registry_instanceObject



66
67
68
# File 'lib/dockistrano/service.rb', line 66

def registry_instance
  @registry_instance ||= Registry.new(registry)
end

#run(command, options = {}) ⇒ Object

Runs a command in this container



179
180
181
# File 'lib/dockistrano/service.rb', line 179

def run(command, options={})
  Docker.run(full_image_name_with_fallback, link: link_backing_services, command: command, e: environment_variables, v: volumes)
end

#running?Boolean

Returns if this service is running

Returns:

  • (Boolean)


128
129
130
# File 'lib/dockistrano/service.rb', line 128

def running?
  Docker.running_container_id(full_image_name)
end

#start(options = {}) ⇒ Object

Starts this service



163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/dockistrano/service.rb', line 163

def start(options={})
  ensure_backing_services
  create_data_directories
  environment = checked_environment_variables

  if additional_commands.any?
    additional_commands.each do |name, command|
      Docker.run(full_image_name, name: "#{image_name}_#{name}", link: link_backing_services, e: environment, v: volumes, d: true, command: command)
    end
  end

  Docker.run(full_image_name, name: image_name, link: link_backing_services, e: environment, v: volumes, p: ports, d: true)
  update_hipache(true)
end

#stopObject

Stops the container of the current service



117
118
119
120
121
122
123
124
125
# File 'lib/dockistrano/service.rb', line 117

def stop
  update_hipache(false)
  Docker.stop(image_name)
  Docker.remove_container(image_name)
  additional_commands.each do |name, _|
    Docker.stop("#{image_name}_#{name}")
    Docker.remove_container("#{image_name}_#{name}")
  end
end

#tag_with_fallbackObject

Returns the tag that is available with fallback.



279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/dockistrano/service.rb', line 279

def tag_with_fallback
  fallback_tags = [tag, "develop", "master", "latest"]

  begin
    tag_suggestion = fallback_tags.shift
    final_tag = tag_suggestion if available_tags_local.include?(tag_suggestion)
  end while !final_tag and fallback_tags.any?

  if final_tag
    final_tag
  else
    raise NoTagFoundForImage.new("No tag found for image #{image_name}, wanted tag #{tag}, available tags: #{available_tags_local}")
  end
end

#testObject

Tests the image of this services by running a test command



97
98
99
100
101
102
103
104
105
106
# File 'lib/dockistrano/service.rb', line 97

def test
  environment = "test"
  unless test_command.nil? or test_command.empty?
    ensure_backing_services
    create_data_directories
    Docker.exec(full_image_name, command: test_command, e: checked_environment_variables, v: volumes)
  else
    true
  end
end

#update_hipache(server_up = true) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/dockistrano/service.rb', line 149

def update_hipache(server_up=true)
  if !host.nil? and (redis_url = backing_services["hipache"].ip_address)
    hipache = Hipache.new("redis://#{redis_url}:6379")
    host.each do |hostname, port|
      if server_up
        hipache.register(image_name, hostname, ip_address, port)
      else
        hipache.unregister(image_name, hostname, ip_address, port)
      end
    end
  end
end

#volumesObject

Returns the mounted volumes for this service



247
248
249
250
251
252
253
254
255
256
# File 'lib/dockistrano/service.rb', line 247

def volumes
  [].tap do |volumes|
    volumes << "/dockistrano/#{image_name.gsub("-", "_")}/data:/dockistrano/data"
    if mount_src and !mount_src.empty?
      mount_src.each do |host_src, container_src|
        volumes << "#{host_src}:#{container_src}"
      end
    end
  end
end