Class: QB::Ansible::Modules::Docker::Image

Inherits:
QB::Ansible::Module show all
Defined in:
lib/qb/ansible/modules/docker/image.rb

Overview

Build a Docker image if needed. Features to deal with version-tagging.

Instance Attribute Summary collapse

Attributes inherited from QB::Ansible::Module

#args, #args_source, #response

Instance Method Summary collapse

Methods inherited from QB::Ansible::Module

WANT_JSON_mode?, arg, #changed!, #debug, #done, #exit_json, #fail, #info, #initialize, load_args, load_args_from_JSON_file, run!, #run!, run_from_JSON_args_file!, run_from_args!, setup_io!, #warn

Constructor Details

This class inherits a constructor from QB::Ansible::Module

Instance Attribute Details

#nowTime (readonly)

The time to use as now. Defaults to get the current time, but here so that it can be provided externally so if you're doing a bunch of work you can make all the timestamps sync up. Pls don't abuse.

Returns:

  • (Time)

    UTC Time to use as now.



68
69
70
# File 'lib/qb/ansible/modules/docker/image.rb', line 68

arg :now,
type: Time,
default: ->{ Time.now.utc }

Instance Method Details

#build_segments_for_from_imageObject

'openresty/openresty:1.11.2.4-xenial' => repository: 'openresty' name: 'openresty' tag: { major: 1, minor: 11, patch: 2, revision: [4], prerelease: ['xenial'], } => ['openresty--openresty', 1, 11, 2, 4, 'xenial']

which eventually becomes the Docker tag

  <semver>_openresty.openresty.1.11.2.4.xenial.<build_info?>


92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/qb/ansible/modules/docker/image.rb', line 92

def build_segments_for_from_image
  return [] unless include_from_image_build
  
  [
    [
      (from_image.repository == 'beiarea' ? nil : from_image.repository),
      from_image.name,
    ].
      compact.
      map { |name| name.gsub( '_', '-' ) }.
      join( '-' ),
    *from_image.tag.version.to_a.flatten,
  ]
end

#force?Boolean

Returns:

  • (Boolean)


209
210
211
# File 'lib/qb/ansible/modules/docker/image.rb', line 209

def force?
  source_base_version.dev? && repo_dirty?
end

#gitObject



108
109
110
111
112
# File 'lib/qb/ansible/modules/docker/image.rb', line 108

def git
  lazy_var :@git do
    QB::Repo::Git.from_path path
  end
end

#image_nameObject



186
187
188
189
190
191
192
193
194
# File 'lib/qb/ansible/modules/docker/image.rb', line 186

def image_name
  lazy_var :@image_name do
    name.merge \
      source: nil, # NEED this!
      tag: QB::Docker::Image::Tag.from_s(
        image_version.docker_tag
      )
  end
end

#image_versionObject



175
176
177
178
179
180
181
182
183
# File 'lib/qb/ansible/modules/docker/image.rb', line 175

def image_version
  lazy_var :@image_version do
    source_version.merge \
      build: [
        *build_segments_for_from_image,
        *source_version.build
      ]
  end
end

#mainnil | {Symbol => #to_json}

Entry point for the module. invoked by QB::Ansible::Module#run!.

Returns:

  • (nil | {Symbol => #to_json})

    when returning:

    • nil: module will successfully exit with no additional changes.

    • {Symbol => #to_json}: Hash will be merged over @facts that are returned by the module to be set in the Ansible runtime and the module will exit successfully.



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/qb/ansible/modules/docker/image.rb', line 228

def main
  logger.info \
    "Starting `_image`...",
    path: path,
    from_image: from_image.to_s,
    build_arg: build_arg,
    fact_name: fact_name
    
  
  QB::Docker::Image.ensure_present! \
    name: image_name,
    pull: !image_version.dev?,
    build: {
      path: path,
      build_arg: {
        from_image: from_image.string,
        image_version: image_version.semver,
        **build_arg.to_options,
      },
    },
    # Don't push dev images
    push: !image_version.dev?,
    force: force?
  
  response[:image] = {
    name: image_name,
    version: image_version,
  }
  
  if fact_name
    response.facts[fact_name] = response[:image]
  end
  
  return nil
end

#repo_clean?Boolean

Returns:

  • (Boolean)


197
198
199
200
201
# File 'lib/qb/ansible/modules/docker/image.rb', line 197

def repo_clean?
  lazy_var :@repo_clean do
    git.clean?
  end
end

#repo_dirty?Boolean

Returns:

  • (Boolean)


204
205
206
# File 'lib/qb/ansible/modules/docker/image.rb', line 204

def repo_dirty?
  !repo_clean?
end

#source_base_versionObject



115
116
117
118
119
# File 'lib/qb/ansible/modules/docker/image.rb', line 115

def source_base_version
  lazy_var :@source_base_version do
    QB::Package::Version.from_string (path.to_pn / 'VERSION').read
  end
end

#source_dev_versionObject



122
123
124
125
126
127
128
129
130
# File 'lib/qb/ansible/modules/docker/image.rb', line 122

def source_dev_version
  lazy_var :@source_dev_version do
    source_base_version.build_version \
      branch: git.branch,
      ref: git.head_short,
      dirty: !git.clean?
      # time: now
  end
end

#source_non_dev_versionObject



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/qb/ansible/modules/docker/image.rb', line 144

def source_non_dev_version
  tag = "v#{ source_base_version.semver }"
  
  # We check...
  # 
  # 1.  Repo is clean
  unless git.clean?
    raise "Can't build #{ source_base_version.level } version from " \
          "dirty repo"
  end
  
  # 2.  Tag exists
  unless git.tags.include? tag
    raise "Tag #{ tag } not found"
  end
  
  # 3.  Tag points to current commit
  tag_commit = Cmds.
    new( "git rev-list -n 1 %s", chdir: path ).
    out!( tag ).
    chomp
  
  unless tag_commit == git.head
    raise "Repo is not at tag #{ tag } commit #{ tag_commit }"
  end
  
  # Ok, we just use the version in the file!
  source_base_version
end

#source_versionObject



133
134
135
136
137
138
139
140
141
# File 'lib/qb/ansible/modules/docker/image.rb', line 133

def source_version
  lazy_var :@source_version do
    if source_base_version.dev?
      source_dev_version
    else
      source_non_dev_version
    end
  end
end