Class: Vagrant::Action::General::Package
- Inherits:
-
Object
- Object
- Vagrant::Action::General::Package
- Includes:
- Util
- Defined in:
- lib/vagrant/action/general/package.rb
Overview
A general packaging (tar) middleware. Given the following options, it will do the right thing:
- package.output - The filename of the outputted package.
- package.include - An array of files to include in the package.
- package.directory - The directory which contains the contents to compress into the package.
This middleware always produces the final file in the current working directory (FileUtils.pwd)
Instance Attribute Summary collapse
-
#fullpath ⇒ String
readonly
The path to the final output file.
Class Method Summary collapse
-
.fullpath(output) ⇒ Object
Calculate the full path of the given path, relative to the current working directory (where the command was run).
-
.validate!(output, directory) ⇒ Object
Perform sanity validations that the provided output filepath is sane.
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#compress ⇒ Object
Compress the exported file into a package.
-
#copy_include_files ⇒ Object
This method copies the include files (passed in via command line) to the temporary directory so they are included in a sub-folder within the actual box.
- #create_box_folder(folder_path) ⇒ Object
-
#initialize(app, env) ⇒ Package
constructor
A new instance of Package.
- #package_with_folder_path ⇒ Object
- #recover(env) ⇒ Object
-
#setup_private_key ⇒ Object
This will copy the generated private key into the box and use it for SSH by default.
-
#write_metadata_json ⇒ Object
Write the metadata file into the box so that the provider can be automatically detected when adding the box.
Constructor Details
#initialize(app, env) ⇒ Package
Returns a new instance of Package.
62 63 64 65 66 67 68 69 |
# File 'lib/vagrant/action/general/package.rb', line 62 def initialize(app, env) @app = app env["package.files"] ||= {} env["package.output"] ||= "package.box" @fullpath = self.class.fullpath(env["package.output"]) end |
Instance Attribute Details
#fullpath ⇒ String (readonly)
The path to the final output file.
60 61 62 |
# File 'lib/vagrant/action/general/package.rb', line 60 def fullpath @fullpath end |
Class Method Details
.fullpath(output) ⇒ Object
Calculate the full path of the given path, relative to the current working directory (where the command was run).
54 55 56 |
# File 'lib/vagrant/action/general/package.rb', line 54 def self.fullpath(output) File.(output, Dir.pwd) end |
.validate!(output, directory) ⇒ Object
Perform sanity validations that the provided output filepath is sane. In particular, this function validates:
- The output path is a regular file (not a directory or symlink)
- No file currently exists at the given path
- A directory of package files was actually provided (internal)
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/vagrant/action/general/package.rb', line 33 def self.validate!(output, directory) filename = File.basename(output.to_s) output = fullpath(output) if File.directory?(output) raise Vagrant::Errors::PackageOutputDirectory end if File.exist?(output) raise Vagrant::Errors::PackageOutputExists, filename: filename end if !Vagrant::Util::Presence.present?(directory) || !File.directory?(directory) raise Vagrant::Errors::PackageRequiresDirectory end end |
Instance Method Details
#call(env) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/vagrant/action/general/package.rb', line 71 def call(env) @env = env self.class.validate!(env["package.output"], env["package.directory"]) package_with_folder_path if env["package.output"].include?(File::SEPARATOR) raise Errors::PackageOutputDirectory if File.directory?(fullpath) @app.call(env) @env[:ui].info I18n.t("vagrant.actions.general.package.compressing", fullpath: fullpath) copy_include_files setup_private_key compress end |
#compress ⇒ Object
Compress the exported file into a package
141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/vagrant/action/general/package.rb', line 141 def compress # Get the output path. We have to do this up here so that the # pwd returns the proper thing. output_path = fullpath.to_s # Switch into that directory and package everything up Util::SafeChdir.safe_chdir(@env["package.directory"]) do # Find all the files in our current directory and tar it up! files = Dir.glob(File.join(".", "*")) # Package! Util::Subprocess.execute("bsdtar", "-czf", output_path, *files) end end |
#copy_include_files ⇒ Object
This method copies the include files (passed in via command line) to the temporary directory so they are included in a sub-folder within the actual box
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/vagrant/action/general/package.rb', line 116 def copy_include_files include_directory = Pathname.new(@env["package.directory"]).join("include") @env["package.files"].each do |from, dest| # We place the file in the include directory to = include_directory.join(dest) @env[:ui].info I18n.t("vagrant.actions.general.package.packaging", file: from) FileUtils.mkdir_p(to.parent) # Copy directory contents recursively. if File.directory?(from) FileUtils.cp_r(Dir.glob(from), to.parent, preserve: true) else FileUtils.cp(from, to, preserve: true) end end rescue Errno::EEXIST => e raise if !e.to_s.include?("symlink") # The directory contains symlinks. Show a nicer error. raise Errors::PackageIncludeSymlink end |
#create_box_folder(folder_path) ⇒ Object
95 96 97 98 |
# File 'lib/vagrant/action/general/package.rb', line 95 def create_box_folder(folder_path) @env[:ui].info(I18n.t("vagrant.actions.general.package.box_folder", folder_path: folder_path)) FileUtils.mkdir_p(folder_path) end |
#package_with_folder_path ⇒ Object
90 91 92 93 |
# File 'lib/vagrant/action/general/package.rb', line 90 def package_with_folder_path folder_path = File.("..", @fullpath) create_box_folder(folder_path) unless File.directory?(folder_path) end |
#recover(env) ⇒ Object
100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/vagrant/action/general/package.rb', line 100 def recover(env) @env = env # There are certain exceptions that we don't delete the file for. ignore_exc = [Errors::PackageOutputDirectory, Errors::PackageOutputExists] ignore_exc.each do |exc| return if env["vagrant.error"].is_a?(exc) end # Cleanup any packaged files if the packaging failed at some point. File.delete(fullpath) if File.exist?(fullpath) end |
#setup_private_key ⇒ Object
This will copy the generated private key into the box and use it for SSH by default. We have to do this because we now generate random keypairs on boot, so packaged boxes would stop working without this.
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/vagrant/action/general/package.rb', line 176 def setup_private_key # If we don't have machine, we do nothing (weird) return if !@env[:machine] # If we don't have a data dir, we also do nothing (base package) return if !@env[:machine].data_dir # If we don't have a generated private key, we do nothing path = @env[:machine].data_dir.join("private_key") if !path.file? # If we have a private key that was copied into this box, # then we copy that. This is a bit of a heuristic and can be a # security risk if the key is named the correct thing, but # we'll take that risk for dev environments. (@env[:machine].config.ssh.private_key_path || []).each do |p| # If we have the correctly named key, copy it if File.basename(p) == "vagrant_private_key" path = Pathname.new(p) break end end end # If we still have no matching key, do nothing return if !path.file? # Copy it into our box directory dir = Pathname.new(@env["package.directory"]) new_path = dir.join("vagrant_private_key") FileUtils.cp(path, new_path) # Append it to the Vagrantfile (or create a Vagrantfile) vf_path = dir.join("Vagrantfile") mode = "w+" mode = "a" if vf_path.file? vf_path.open(mode) do |f| f.binmode f.puts f.puts %Q[Vagrant.configure("2") do |config|] f.puts %Q[ config.ssh.private_key_path = File.expand_path("../vagrant_private_key", __FILE__)] f.puts %Q[end] end end |
#write_metadata_json ⇒ Object
Write the metadata file into the box so that the provider can be automatically detected when adding the box
158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/vagrant/action/general/package.rb', line 158 def = File.join(@env["package.directory"], "metadata.json") return if File.exist?() if @env[:machine] && @env[:machine].provider_name provider_name = @env[:machine].provider_name elsif @env[:env] && @env[:env].default_provider provider_name = @env[:env].default_provider else return end File.write(, {provider: provider_name}.to_json) end |