Class: RubyYacht::Runner::BuildImages

Inherits:
Command
  • Object
show all
Defined in:
lib/ruby_yacht/runner/build_images.rb

Overview

This command builds the images for the system.

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Command

#backtick, #default_project, #docker, #docker_machine, #get_machine_info, #log, #option_parser, #parse_positional_arguments, #project_named, #projects, short_script_name, #system

Class Method Details

.commandObject

The identifier for the command.



7
# File 'lib/ruby_yacht/runner/build_images.rb', line 7

def self.command; 'build_images'; end

.descriptionObject

The description for the command.



10
11
12
# File 'lib/ruby_yacht/runner/build_images.rb', line 10

def self.description
  "Build images for your environment"
end

Instance Method Details

#build_image(folder_name, image_name = nil) ⇒ Object

This method builds an image.

This will copy a Dockerfile template from a folder underneath the images folder, as well as any other files in that folder, into the tmp folder. It will then evaluate the Dockerfile.erb file, using the binding from the current context, and write it to the Dockerfile in the tmp folder. It will then build the image, and clear out the tmp folder.

Depending on the image type, it may also copy and interpret other template files. For instance, for app containers we also have erb files for the startup.bash and before_startup.bash scripts.

Parameters

  • folder_name: String The name of the folder containing the Dockerfile and related files.
  • image_name: String The name for the new image. If this is not provided, the image name will be the current project's prefix, followed by a dash, followed by the folder name.


87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/ruby_yacht/runner/build_images.rb', line 87

def build_image(folder_name, image_name = nil)
  Dir[File.join(File.dirname(File.dirname(__FILE__)), 'images', folder_name, '*')].each do |path|
    FileUtils.cp(path, File.join('tmp', File.basename(path)))
  end

  set_image_settings(folder_name)

  fetch_behaviors(@hook_servers, @hook_events).each do |behavior|
    next unless behavior.is_a?(RubyYacht::Hook::CopyFileBehavior)
    FileUtils.cp behavior.file_path, "tmp"
  end

  @templates.each do |template_name|
    File.open(File.join('tmp', template_name), 'w') do |file|
      template_contents = File.read(File.join('tmp', template_name + '.erb'))
      file_contents = ERB.new(template_contents, nil, '<>').result(binding)
      file_contents.gsub!(/\n\n\n+/, "\n\n")
      file_contents.gsub!(/\n*\Z/, "")
      file.write(file_contents)
    end
  end
  
  image_name ||= "#{@project.system_prefix}-#{folder_name}"

  docker "build -t #{image_name} tmp"
  
  FileUtils.rm(Dir[File.join("tmp", "*")])
end

#build_images(project) ⇒ Object

This method builds the images for a project.

Parameters

  • project: Project The project we are building.


39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/ruby_yacht/runner/build_images.rb', line 39

def build_images(project)
  @project = project
  project.apps.map(&:server_type).uniq.each do |type_name|
    @server_type = RubyYacht.configuration.find_server_type(type_name)
    build_image 'app-dependencies', "#{@project.system_prefix}-#{@server_type.name}-app-dependencies"
  end
  
  @app_server_type = RubyYacht.configuration.find_server_type(project.apps.first.server_type)
  project.databases.select(&:local?).each do |database|
    @database = database
    @server_type = RubyYacht.configuration.find_server_type(@database.server_type)
    build_image 'database', @database.container_name
  end
  @database = nil
  
  @project.apps.each do |app|
    @app = app
    @server_type = RubyYacht.configuration.find_server_type(@app.server_type)
    build_image 'app', @app.container_name
  end
  @app = nil

  project.web_servers.each do |server|
    @server = server
    build_image 'web', @server.container_name
  end
end

#copy_hooks(servers, event_types) ⇒ Object

This method includes commands for copying script files for the hooks for the current app type.

Parameters

  • servers: Database/App/Array: The server or servers whose hooks we are running.
  • event_types: [Symbol] The events whose hooks we should include.

Returns

A String with the contents of the Dockerfile for copying the script.



217
218
219
220
221
222
223
224
225
# File 'lib/ruby_yacht/runner/build_images.rb', line 217

def copy_hooks(servers, event_types)
  result = ""
  
  fetch_behaviors(servers, event_types).each do |behavior|
    next unless behavior.is_a?(RubyYacht::Hook::CopyFileBehavior)
    result += behavior.dockerfile_command + "\n"
  end
  result
end

#include_event(servers, event_type, times = [:before, :during, :after], options = {}) ⇒ Object

This method includes the hooks for an event in a Dockerfile.

It will run the commands for the before hooks, then the during hooks, then the after hooks.

Parameters

  • servers: Database/App/Array: The server or servers whose hooks we are running.
  • event_type: Symbol The event whose hooks we are running.
  • times: [Symbol] The event times whose hooks we want to include. You can also pass a symbol to this method, which will cause it to include only that event time.
  • options: [Hash] Additional flags for customizing the output. At this time, the only option is in_bash, which indicates whether the commands are running in bash rather than a Dockerfile.
  • block This also takes a block, which should yield fixed contents for the "during" section of the event.

Returns

A String with the contents of the Dockerfile for running the hooks.



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/ruby_yacht/runner/build_images.rb', line 179

def include_event(servers, event_type, times = [:before, :during, :after], options = {})
  result = ""
  if times.is_a?(Symbol)
    times = [times]
  end
  times.each do |time|
    if time == :during && block_given?
      result += yield
      result += "\n"
      next
    end
    
    fetch_behaviors(servers, [event_type], time).each do |behavior|
      behavior.context = self
      if options[:in_bash]
        result += "#{behavior.shell_command}\n"
      else
        result += "#{behavior.dockerfile_command}\n"
      end
    end
  end
  
  result
end

#runObject

This method runs the logic for the command.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/ruby_yacht/runner/build_images.rb', line 15

def run
  FileUtils.mkdir_p 'tmp'
  
  default_system_prefix = projects.first.system_prefix
  docker "network create #{default_system_prefix} 2> /dev/null"
  
  projects.each do |project|
    log "Building images for #{project.name}"
    
    id_path = File.join(ENV['HOME'], '.ssh', 'id_rsa')
    tmp_id_path = File.join('tmp', 'id_rsa')
    FileUtils.cp(id_path, tmp_id_path) if File.exist?(id_path)

    build_images(project)
  end
  
  true
end

#set_image_settings(folder_name) ⇒ Object

This method establishes settings for building an image.

This will set the @templates, @hook_events, and @hook_servers instance variables.

Parameters

  • folder_name: String The name of the folder containing the image files.


125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/ruby_yacht/runner/build_images.rb', line 125

def set_image_settings(folder_name)
  @templates = 
    case folder_name
    when 'app' then ['Dockerfile', 'before_startup.bash', 'startup.bash']
    when 'database' then ['Dockerfile', 'startup.bash']
    when 'web' then ['Dockerfile']
    else ['Dockerfile']
    end

  @hook_events =
    case folder_name
    when 'app' then [:startup, :build_checkout, :build_new_app]
    when 'app-dependencies' then [:initialize_app_environment, :install_libraries]
    when 'database' then [:create_databases, :install_libraries, :load_database_seeds]
    when 'web' then [:install_libraries, :add_project_landing, :add_app_config]
    else []
    end
    
  @hook_servers =
    case folder_name
    when 'database' then [@database]
    when 'app' then [@app]
    when 'app-dependencies' then @project.apps
    when 'web' then [@server]
    else []
    end
end