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

#attachObject



287
288
289
# File 'lib/dockistrano/service.rb', line 287

def attach
  Docker.attach(Docker.running_container_id(full_image_name))
end

#available_tagsObject

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



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

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

#backing_servicesObject

Lists all backing services for this service



194
195
196
197
198
199
200
# File 'lib/dockistrano/service.rb', line 194

def backing_services
  @backing_services ||= {}.tap do |hash|
    dependencies.collect do |name, config|
      hash[name] = ServiceDependency.factory(self, name, config)
    end
  end
end

#buildObject

Builds a new image for this service



81
82
83
84
85
86
87
88
89
90
# File 'lib/dockistrano/service.rb', line 81

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



188
189
190
191
# File 'lib/dockistrano/service.rb', line 188

def console(command, options={})
  create_data_directories
  Docker.console(full_image_name, command: command, e: environment_variables, v: volumes, p: ports)
end

#create_data_directoriesObject



295
296
297
298
299
300
301
302
303
304
305
# File 'lib/dockistrano/service.rb', line 295

def create_data_directories
  if data_directories.any?
    image_config = Docker.inspect_image(full_image_name)
    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, command: bash_command, v: volumes, e: environment_variables, u: "root")
  end
end

#directories_required_on_hostObject



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

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



106
107
108
109
110
# File 'lib/dockistrano/service.rb', line 106

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



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/dockistrano/service.rb', line 203

def environment_variables
  vars = {}

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

  backing_services.each do |name, backing_service|
    vars["#{name.upcase}_IP"] = backing_service.ip_address
    vars["#{name.upcase}_PORT"] = backing_service.port

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

    vars.merge!(backing_service.environment_variables)
  end

  vars.merge!(provides_env)
  vars.each do |key, value|
    vars.each do |replacement_key, replacement_value|
      unless vars[key].nil? or replacement_value.nil?
        vars[key] = vars[key].gsub('$'+replacement_key, replacement_value)
      end
    end
  end

  vars
end

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

Executes a command in this container



182
183
184
185
# File 'lib/dockistrano/service.rb', line 182

def exec(command, options={})
  create_data_directories
  Docker.exec(full_image_name, command: command, e: environment_variables, v: volumes, p: ports)
end

#full_image_nameObject



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

def full_image_name
  "#{registry}/#{image_name}:#{tag}"
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



275
276
277
# File 'lib/dockistrano/service.rb', line 275

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

#logsObject



291
292
293
# File 'lib/dockistrano/service.rb', line 291

def logs
  Docker.logs(Docker.last_run_container_id(full_image_name))
end

#newer_version_available?Boolean

Returns:

  • (Boolean)


307
308
309
310
# File 'lib/dockistrano/service.rb', line 307

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

#portObject



279
280
281
# File 'lib/dockistrano/service.rb', line 279

def port
  container_settings["NetworkSettings"]["PortMapping"]["Tcp"].keys.first if running?
end

#portsObject



283
284
285
# File 'lib/dockistrano/service.rb', line 283

def ports
  (config["ports"] || {}).collect { |k,v| "#{k}:#{v}" }
end

#pullObject

Pulls the service’s container



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

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

#pull_backing_servicesObject

Pulls backing services for this service



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

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



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

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



177
178
179
# File 'lib/dockistrano/service.rb', line 177

def run(command, options={})
  Docker.run(full_image_name, command: command, e: environment_variables, v: volumes, p: ports)
end

#running?Boolean

Returns if this service is running

Returns:

  • (Boolean)


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

def running?
  Docker.running_container_id(full_image_name)
end

#start(options = {}) ⇒ Object

Starts this service



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/dockistrano/service.rb', line 151

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, e: environment, v: volumes, p: ports, d: true, command: command)
    end
  end

  Docker.run(full_image_name, e: environment, v: volumes, p: ports, d: true)

  if !host.nil?
    hipache = Hipache.new(ENV['DOCKER_HOST_IP'])
    if host.kind_of?(String)
      hipache.register(image_name, host, ip_address, port)
    else
      host.each do |hostname, port|
        hipache.register(image_name, hostname, ip_address, port)
      end
    end
  end
end

#stopObject

Stops the container of the current service



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

def stop
  if !host.nil?
    hipache = Hipache.new(ENV['DOCKER_HOST_IP'])
    if host.kind_of?(String)
      hipache.unregister(image_name, host, ip_address, port)
    else
      host.each do |hostname, port|
        hipache.unregister(image_name, hostname, ip_address, port)
      end
    end
  end

  Docker.stop_all_containers_from_image(full_image_name)
end

#tag_with_fallbackObject

Returns the tag that is available with fallback.



260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/dockistrano/service.rb', line 260

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

  begin
    tag_suggestion = fallback_tags.shift
    final_tag = tag_suggestion if available_tags.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}, available tags: #{available_tags}")
  end
end

#testObject

Tests the image of this services by running a test command



93
94
95
96
97
98
99
100
101
102
# File 'lib/dockistrano/service.rb', line 93

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

#volumesObject

Returns the mounted volumes for this service



234
235
236
237
238
239
240
241
# File 'lib/dockistrano/service.rb', line 234

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