Class: Dapp::Dimg::Dimg

Inherits:
Object
  • Object
show all
Includes:
GitArtifact, Path, Stages, Helper::Sha256, Helper::Trivia
Defined in:
lib/dapp/dimg/dimg.rb,
lib/dapp/dimg/dimg/path.rb,
lib/dapp/dimg/dimg/stages.rb,
lib/dapp/dimg/dimg/git_artifact.rb

Direct Known Subclasses

Artifact

Defined Under Namespace

Modules: GitArtifact, Path, Stages

Instance Attribute Summary collapse

Attributes included from Stages

#last_stage

Instance Method Summary collapse

Methods included from Helper::Trivia

#check_path?, #check_subpath?, #class_to_lowercase, class_to_lowercase, #delete_file, #ignore_path?, #ignore_path_base, #kwargs, #make_path, #path_checker, #search_file_upward

Methods included from Helper::Sha256

#hashsum, #paths_content_hashsum, #sha256

Methods included from Stages

#all_tagged_images, #signature, #stage_by_name, #stage_cache_format, #stage_dapp_label

Methods included from Path

#build_path, #container_dapp_path, #container_tmp_path, #home_path, #tmp_dir_exists?, #tmp_path

Methods included from GitArtifact

#generate_git_artifacts, #generate_git_embedded_artifacts, #git_artifacts, #local_git_artifacts, #remote_git_artifacts

Constructor Details

#initialize(config:, dapp:, should_be_built: false, ignore_git_fetch: false, ignore_signature_auto_calculation: false) ⇒ Dimg

Returns a new instance of Dimg.



17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/dapp/dimg/dimg.rb', line 17

def initialize(config:, dapp:, should_be_built: false, ignore_git_fetch: false, ignore_signature_auto_calculation: false)
  @config = config
  @dapp = dapp

  @ignore_git_fetch                  = ignore_git_fetch
  @ignore_signature_auto_calculation = ignore_signature_auto_calculation

  @dapp._terminate_dimg_on_terminate(self)

  enable_should_be_built if should_be_built
  should_be_built!
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



11
12
13
# File 'lib/dapp/dimg/dimg.rb', line 11

def config
  @config
end

#dappObject (readonly)

Returns the value of attribute dapp.



15
16
17
# File 'lib/dapp/dimg/dimg.rb', line 15

def dapp
  @dapp
end

#ignore_git_fetchObject (readonly)

Returns the value of attribute ignore_git_fetch.



12
13
14
# File 'lib/dapp/dimg/dimg.rb', line 12

def ignore_git_fetch
  @ignore_git_fetch
end

#ignore_signature_auto_calculationObject (readonly)

Returns the value of attribute ignore_signature_auto_calculation.



13
14
15
# File 'lib/dapp/dimg/dimg.rb', line 13

def ignore_signature_auto_calculation
  @ignore_signature_auto_calculation
end

#should_be_builtObject (readonly)

Returns the value of attribute should_be_built.



14
15
16
# File 'lib/dapp/dimg/dimg.rb', line 14

def should_be_built
  @should_be_built
end

Instance Method Details

#after_stages_build!Object



61
62
63
64
# File 'lib/dapp/dimg/dimg.rb', line 61

def after_stages_build!
  last_stage.save_in_cache!
  artifacts.each { |artifact| artifact.last_stage.save_in_cache! }
end

#artifact?Boolean

Returns:

  • (Boolean)


233
234
235
# File 'lib/dapp/dimg/dimg.rb', line 233

def artifact?
  false
end

#artifactsObject



229
230
231
# File 'lib/dapp/dimg/dimg.rb', line 229

def artifacts
  @artifacts ||= artifacts_stages.map { |stage| stage.artifacts.map { |artifact| artifact[:dimg] } }.flatten
end

#build!Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/dapp/dimg/dimg.rb', line 46

def build!
  with_introspection do
    dapp.lock("#{dapp.name}.images", readonly: true) do
      last_stage.build_lock! do
        begin
          builder.before_build_check
          last_stage.build!
        ensure
          after_stages_build!
        end
      end
    end
  end
end

#build_cache_versionObject



245
246
247
# File 'lib/dapp/dimg/dimg.rb', line 245

def build_cache_version
  [::Dapp::BUILD_CACHE_VERSION, dev_mode? ? 1 : 0]
end

#build_export_image!(image_name, scheme_name:) ⇒ Object



148
149
150
151
152
153
154
155
# File 'lib/dapp/dimg/dimg.rb', line 148

def build_export_image!(image_name, scheme_name:)
  Image::Dimg.image_by_name(name: image_name, from: last_stage.image, dapp: dapp).tap do |export_image|
    export_image.untag! if export_image.built?
    export_image.add_service_change_label(:'dapp-tag-scheme' => scheme_name)
    export_image.add_service_change_label(:'dapp-dimg' => true)
    export_image.build!
  end
end

#builderObject



225
226
227
# File 'lib/dapp/dimg/dimg.rb', line 225

def builder
  @builder ||= Builder.const_get(config._builder.capitalize).new(self)
end

#cleanup_tmpObject



254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/dapp/dimg/dimg.rb', line 254

def cleanup_tmp
  return unless tmp_dir_exists?

  # В tmp-директории могли остаться файлы, владельцами которых мы не являемся.
  # Такие файлы могут попасть туда при экспорте файлов артефакта.
  # Чтобы от них избавиться — запускаем docker-контейнер под root-пользователем
  # и удаляем примонтированную tmp-директорию.
  cmd = "".tap do |cmd|
    cmd << "#{dapp.host_docker} run --rm"
    cmd << " --volume #{dapp.tmp_base_dir}:#{dapp.tmp_base_dir}"
    cmd << " --label dapp=#{dapp.name}"
    cmd << " alpine:3.6"
    cmd << " rm -rf #{tmp_path}"
  end
  dapp.shellout! cmd
end

#dev_mode?Boolean

Returns:

  • (Boolean)


241
242
243
# File 'lib/dapp/dimg/dimg.rb', line 241

def dev_mode?
  dapp.dev_mode?
end

#dimg_export_base!(repo, export_format:, push: false) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/dapp/dimg/dimg.rb', line 93

def dimg_export_base!(repo, export_format:, push: false)
  dapp.lock("#{dapp.name}.images", readonly: true) do
    dapp.tags_by_scheme.each do |tag_scheme_name, tags|
      dapp.log_step_with_indent(tag_scheme_name) do
        tags.each do |tag|
          image_name = format(export_format, repo: repo, dimg_name: name, tag: tag)

          if push && tag_should_not_be_pushed?(tag.to_s)
            dapp.log_state(image_name, state: dapp.t(code: 'state.exist'))
            next
          end

          export_base!(image_name, push: push) do
            export_image = build_export_image!(image_name, scheme_name: tag_scheme_name)
            if push
              export_image.export!
            else
              export_image.tag!
            end
          end
        end
      end unless tags.empty?
    end
  end
end

#dimgstage_should_not_be_pushed?(signature) ⇒ Boolean

Returns:

  • (Boolean)


119
120
121
# File 'lib/dapp/dimg/dimg.rb', line 119

def dimgstage_should_not_be_pushed?(signature)
  registry_dimgstages_tags.include?(signature)
end

#enable_should_be_builtObject



30
31
32
# File 'lib/dapp/dimg/dimg.rb', line 30

def enable_should_be_built
  @should_be_built = true
end

#export!(repo, format:) ⇒ Object



70
71
72
# File 'lib/dapp/dimg/dimg.rb', line 70

def export!(repo, format:)
  dimg_export_base!(repo, export_format: format, push: true)
end

#export_base!(image_name, push: true) ⇒ Object



157
158
159
160
161
162
163
164
165
166
# File 'lib/dapp/dimg/dimg.rb', line 157

def export_base!(image_name, push: true)
  if dapp.dry_run?
    dapp.log_state(image_name, state: dapp.t(code: push ? 'state.push' : 'state.export'), styles: { status: :success })
  else
    dapp.lock("image.#{hashsum image_name}") do
      ::Dapp::Dimg::Image::Docker.reset_image_inspect(image_name)
      dapp.log_process(image_name, process: dapp.t(code: push ? 'status.process.pushing' : 'status.process.exporting')) { yield }
    end
  end
end

#export_stages!(repo, format:) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/dapp/dimg/dimg.rb', line 74

def export_stages!(repo, format:)
  dapp.lock("#{dapp.name}.images", readonly: true) do
    export_images.each do |stage_image|
      signature = stage_image.name.split(':').last
      image_name = format(format, repo: repo, signature: signature)

      if dimgstage_should_not_be_pushed?(format(dapp.dimgstage_push_tag_format, signature: signature))
        dapp.log_state(image_name, state: dapp.t(code: 'state.exist'))
        next
      end

      export_base!(image_name, push: true) do
        stage_image.export!(image_name)
      end
    end
    artifacts.each { |artifact| artifact.export_stages!(repo, format: format) }
  end
end

#import_base!(image, image_name) ⇒ Object



191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/dapp/dimg/dimg.rb', line 191

def import_base!(image, image_name)
  if dapp.dry_run?
    dapp.log_state(image_name, state: dapp.t(code: 'state.pull'), styles: { status: :success })
  else
    dapp.lock("image.#{hashsum image_name}") do
      dapp.log_process(image_name,
                       process: dapp.t(code: 'status.process.pulling'),
                       status: { failed: dapp.t(code: 'status.failed.not_pulled') },
                       style: { failed: :secondary }) do
        image.import!(image_name)
      end
    end
  end
end

#import_stages!(repo, format:) ⇒ Object



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/dapp/dimg/dimg.rb', line 168

def import_stages!(repo, format:)
  dapp.lock("#{dapp.name}.images", readonly: true) do
    import_images.each do |image|
      signature = image.name.split(':').last
      image_name = format(format, repo: repo, signature:signature )

      unless dimgstage_should_not_be_pushed?(format(dapp.dimgstage_push_tag_format, signature: signature))
        dapp.log_state(image_name, state: dapp.t(code: 'state.not_exist'))
        next
      end

      begin
        import_base!(image, image_name)
      rescue ::Dapp::Error::Shellout => e
        dapp.log_info ::Dapp::Helper::NetStatus.message(e)
        next
      end
      break unless !!dapp.options[:pull_all_stages]
    end
    artifacts.each { |artifact| artifact.import_stages!(repo, format: format) }
  end
end

#introspect_image!(image:, options:) ⇒ Object



249
250
251
252
# File 'lib/dapp/dimg/dimg.rb', line 249

def introspect_image!(image:, options:)
  cmd = "#{dapp.host_docker} run -ti --rm --entrypoint #{dapp.bash_bin} #{options} #{image}"
  system(cmd)
end

#nameObject



38
39
40
# File 'lib/dapp/dimg/dimg.rb', line 38

def name
  config._name
end

#registryObject



144
145
146
# File 'lib/dapp/dimg/dimg.rb', line 144

def registry
  @registry ||= dapp.dimg_registry
end

#registry_dimgstages_tagsObject



140
141
142
# File 'lib/dapp/dimg/dimg.rb', line 140

def registry_dimgstages_tags
  @registry_dimgstages_tags ||= registry.dimgstages_tags
end

#registry_tagsObject



130
131
132
133
134
135
136
137
138
# File 'lib/dapp/dimg/dimg.rb', line 130

def registry_tags
  @registry_tags ||= begin
    if name.nil?
      registry.nameless_dimg_tags
    else
      registry.dimg_tags(name)
    end
  end
end

#run(docker_options, command) ⇒ Object



206
207
208
# File 'lib/dapp/dimg/dimg.rb', line 206

def run(docker_options, command)
  run_stage(nil, docker_options, command)
end

#run_stage(stage_name, docker_options, command) ⇒ Object

Raises:



210
211
212
213
214
215
216
217
218
219
# File 'lib/dapp/dimg/dimg.rb', line 210

def run_stage(stage_name, docker_options, command)
  stage_image = (stage_name.nil? ? last_stage : stage_by_name(stage_name)).image
  raise Error::Dimg, code: :dimg_stage_not_built, data: { stage_name: stage_name } unless stage_image.built?
  cmd = "#{dapp.host_docker} run #{[docker_options, stage_image.built_id, command].flatten.compact.join(' ')}"
  if dapp.dry_run?
    dapp.log(cmd)
  else
    system(cmd) || raise(Error::Dimg, code: :dimg_not_run)
  end
end

#scratch?Boolean

Returns:

  • (Boolean)


237
238
239
# File 'lib/dapp/dimg/dimg.rb', line 237

def scratch?
  config._docker._from.nil? && config._from_dimg.nil? && config._from_dimg_artifact.nil?
end

#should_be_built!Object

Raises:



34
35
36
# File 'lib/dapp/dimg/dimg.rb', line 34

def should_be_built!
  raise Error::Dimg, code: :dimg_not_built if should_be_built?
end

#stage_image_name(stage_name) ⇒ Object



221
222
223
# File 'lib/dapp/dimg/dimg.rb', line 221

def stage_image_name(stage_name)
  stages.find { |stage| stage.name == stage_name }.image.name
end

#stage_should_be_introspected_after_build?(name) ⇒ Boolean

Returns:

  • (Boolean)


275
276
277
# File 'lib/dapp/dimg/dimg.rb', line 275

def stage_should_be_introspected_after_build?(name)
  dapp.options[:introspect_stage] == name
end

#stage_should_be_introspected_before_build?(name) ⇒ Boolean

Returns:

  • (Boolean)


271
272
273
# File 'lib/dapp/dimg/dimg.rb', line 271

def stage_should_be_introspected_before_build?(name)
  dapp.options[:introspect_before] == name
end

#tag!(repo, format:) ⇒ Object



66
67
68
# File 'lib/dapp/dimg/dimg.rb', line 66

def tag!(repo, format:)
  dimg_export_base!(repo, export_format: format)
end

#tag_should_not_be_pushed?(tag) ⇒ Boolean

Returns:

  • (Boolean)


123
124
125
126
127
128
# File 'lib/dapp/dimg/dimg.rb', line 123

def tag_should_not_be_pushed?(tag)
  registry_tags.include?(tag) && begin
    registry_tag_parent = registry.image_history(tag, name)['container_config']['Image']
    registry_tag_parent == last_stage.image.built_id
  end
end

#terminateObject



42
43
44
# File 'lib/dapp/dimg/dimg.rb', line 42

def terminate
  cleanup_tmp
end