Class: R10K::Forge::ModuleRelease

Inherits:
Object
  • Object
show all
Includes:
Logging, Settings::Mixin
Defined in:
lib/r10k/forge/module_release.rb

Overview

Download, unpack, and install modules from the Puppet Forge

Constant Summary

Constants included from Logging

Logging::LOG_LEVELS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Logging

debug_formatter, default_formatter, default_outputter, #logger, #logger_name, parse_level

Methods included from Settings::Mixin

included

Constructor Details

#initialize(full_name, version) ⇒ ModuleRelease

Returns a new instance of ModuleRelease.

Parameters:

  • full_name (String)

    The hyphen separated name of the module

  • version (String)

    The version of the module



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/r10k/forge/module_release.rb', line 49

def initialize(full_name, version)
  @full_name = PuppetForge::V3.normalize_name(full_name)
  @version   = version

  # Copy the PuppetForge base connection to the release class; the connection
  # objects are created in the class instances and thus are not shared with
  # subclasses.
  PuppetForge::V3::Release.conn = PuppetForge::V3::Base.conn

  @forge_release = PuppetForge::V3::Release.new({ :name => @full_name, :version => @version, :slug => "#{@full_name}-#{@version}" })

  tarball_name = @forge_release.slug + '.tar.gz'
  @download_path = Pathname.new(Dir.mktmpdir) + (tarball_name)
  @tarball_cache_root = Pathname.new(settings[:cache_root]) + (@forge_release.slug + "/tarball/")
  @tarball_cache_path = @tarball_cache_root + tarball_name

  md5_filename = @forge_release.slug + '.md5'
  @md5_file_path = @tarball_cache_root + md5_filename

  @unpack_path   = Pathname.new(Dir.mktmpdir) + @forge_release.slug
end

Instance Attribute Details

#download_pathPathname

Returns Where the module tarball will be downloaded to.

Returns:

  • (Pathname)

    Where the module tarball will be downloaded to.



29
30
31
# File 'lib/r10k/forge/module_release.rb', line 29

def download_path
  @download_path
end

#forge_releaseObject (readonly)

Returns the value of attribute forge_release.



25
26
27
# File 'lib/r10k/forge/module_release.rb', line 25

def forge_release
  @forge_release
end

#md5_file_pathPathname

Returns Where the md5 of the cached tarball is stored.

Returns:

  • (Pathname)

    Where the md5 of the cached tarball is stored.



41
42
43
# File 'lib/r10k/forge/module_release.rb', line 41

def md5_file_path
  @md5_file_path
end

#tarball_cache_pathPathname

Returns Where the module tarball will be cached to.

Returns:

  • (Pathname)

    Where the module tarball will be cached to.



33
34
35
# File 'lib/r10k/forge/module_release.rb', line 33

def tarball_cache_path
  @tarball_cache_path
end

#tarball_cache_rootPathname

Returns Directory where the module tarball will be cached to.

Returns:

  • (Pathname)

    Directory where the module tarball will be cached to.



37
38
39
# File 'lib/r10k/forge/module_release.rb', line 37

def tarball_cache_root
  @tarball_cache_root
end

#unpack_pathPathname

Returns Where the module will be unpacked to.

Returns:

  • (Pathname)

    Where the module will be unpacked to.



45
46
47
# File 'lib/r10k/forge/module_release.rb', line 45

def unpack_path
  @unpack_path
end

Instance Method Details

#cleanupObject

Remove all files created while downloading and unpacking the module.



176
177
178
179
# File 'lib/r10k/forge/module_release.rb', line 176

def cleanup
  cleanup_unpack_path
  cleanup_download_path
end

#cleanup_cached_tarball_pathObject

Remove the cached module release.



196
197
198
199
200
# File 'lib/r10k/forge/module_release.rb', line 196

def cleanup_cached_tarball_path
  if tarball_cache_path.exist?
    tarball_cache_path.delete
  end
end

#cleanup_download_pathObject

Remove the downloaded module release.



189
190
191
192
193
# File 'lib/r10k/forge/module_release.rb', line 189

def cleanup_download_path
  if download_path.exist?
    download_path.parent.rmtree
  end
end

#cleanup_md5_file_pathObject

Remove the module release md5.



203
204
205
206
207
# File 'lib/r10k/forge/module_release.rb', line 203

def cleanup_md5_file_path
  if md5_file_path.exist?
    md5_file_path.delete
  end
end

#cleanup_unpack_pathObject

Remove the temporary directory used for unpacking the module.



182
183
184
185
186
# File 'lib/r10k/forge/module_release.rb', line 182

def cleanup_unpack_path
  if unpack_path.exist?
    unpack_path.parent.rmtree
  end
end

#downloadvoid

This method returns an undefined value.

Download the module release to #download_path and cache to #tarball_cache_path



92
93
94
95
96
97
98
99
100
101
# File 'lib/r10k/forge/module_release.rb', line 92

def download
  if @tarball_cache_path.exist?
    logger.debug1 "Using cached copy of #{@forge_release.slug} tarball"
  else
    logger.debug1 "Downloading #{@forge_release.slug} from #{PuppetForge::Release.conn.url_prefix} to #{@download_path}"
    @forge_release.download(download_path)
    FileUtils::mkdir_p(@tarball_cache_root)
    FileUtils::mv(@download_path, @tarball_cache_path)
  end
end

#install(target_dir) ⇒ void

This method returns an undefined value.

Download, unpack, and install this module release to the target directory.

Examples:

environment_path = Pathname.new('/etc/puppetlabs/puppet/environments/production')
target_dir = environment_path + 'eight_hundred'
mod = R10K::Forge::ModuleRelease.new('branan-eight_hundred', '8.0.0')
mod.install(target_dir)

Parameters:

  • target_dir (Pathname)

    The full path to where the module should be installed.



81
82
83
84
85
86
87
# File 'lib/r10k/forge/module_release.rb', line 81

def install(target_dir)
  download
  verify
  unpack(target_dir)
ensure
  cleanup
end

#unpack(target_dir) ⇒ void

This method returns an undefined value.

Unpack the module release at #tarball_cache_path into the given target_dir

Parameters:

  • target_dir (Pathname)

    The final path where the module release should be unpacked/installed into.



163
164
165
166
167
168
169
170
171
172
173
# File 'lib/r10k/forge/module_release.rb', line 163

def unpack(target_dir)
  logger.debug1 _("Unpacking %{tarball_cache_path} to %{target_dir} (with tmpdir %{tmp_path})") % {tarball_cache_path: tarball_cache_path, target_dir: target_dir, tmp_path: unpack_path}
  file_lists = PuppetForge::Unpacker.unpack(tarball_cache_path.to_s, target_dir.to_s, unpack_path.to_s)
  logger.debug2 _("Valid files unpacked: %{valid_files}") % {valid_files: file_lists[:valid]}
  if !file_lists[:invalid].empty?
    logger.debug1 _("These files existed in the module's tar file, but are invalid filetypes and were not unpacked: %{invalid_files}") % {invalid_files: file_lists[:invalid]}
  end
  if !file_lists[:symlinks].empty?
    logger.warn _("Symlinks are unsupported and were not unpacked from the module tarball. %{release_slug} contained these ignored symlinks: %{symlinks}") % {release_slug: @forge_release.slug, symlinks: file_lists[:symlinks]}
  end
end

#verifyvoid

This method returns an undefined value.

Verify the module release cached in #tarball_cache_path against the module release checksum given by the Puppet Forge. On mismatch, remove the cached copy.



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/r10k/forge/module_release.rb', line 108

def verify
  logger.debug1 "Verifying that #{@tarball_cache_path} matches checksum"

  md5_of_tarball = Digest::MD5.hexdigest(File.read(@tarball_cache_path, mode: 'rb'))

  if @md5_file_path.exist?
    verify_from_md5_file(md5_of_tarball)
  else
    verify_from_forge(md5_of_tarball)
  end
end

#verify_from_forge(md5_of_tarball) ⇒ void

This method returns an undefined value.

Verify the md5 of the cached tarball against the module release checksum from the forge. On mismatch, remove the cached copy of the tarball.

Raises:

  • (PuppetForge::V3::Release::ChecksumMismatch)

    The cached module release checksum doesn’t match the forge checksum.



146
147
148
149
150
151
152
153
154
155
156
# File 'lib/r10k/forge/module_release.rb', line 146

def verify_from_forge(md5_of_tarball)
  md5_from_forge = @forge_release.file_md5
  #compare file_md5 to md5_of_tarball
  if md5_of_tarball != md5_from_forge
    logger.debug1 "MD5 of #{@tarball_cache_path} (#{md5_of_tarball}) does not match checksum #{md5_from_forge} found on the forge. Removing tarball."
    cleanup_cached_tarball_path
    raise PuppetForge::V3::Release::ChecksumMismatch.new
  else
    File.write(@md5_file_path, md5_from_forge)
  end
end

#verify_from_md5_file(md5_of_tarball) ⇒ void

This method returns an undefined value.

Verify the md5 of the cached tarball against the module release checksum stored in the cache as well. On mismatch, remove the cached copy of both files.

Raises:

  • (PuppetForge::V3::Release::ChecksumMismatch)

    The cached module release checksum doesn’t match the cached checksum.



128
129
130
131
132
133
134
135
136
# File 'lib/r10k/forge/module_release.rb', line 128

def verify_from_md5_file(md5_of_tarball)
  md5_from_file = File.read(@md5_file_path).strip
  if md5_of_tarball != md5_from_file
    logger.error "MD5 of #{@tarball_cache_path} (#{md5_of_tarball}) does not match checksum #{md5_from_file} in #{@md5_file_path}. Removing both files."
    cleanup_cached_tarball_path
    cleanup_md5_file_path
    raise PuppetForge::V3::Release::ChecksumMismatch.new
  end
end