func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, error) { ppName, ok := builtins[artifact.BuilderId()] if !ok { return nil, fmt.Errorf("Unknown artifact type, can't build box: %s", artifact.BuilderId()) } // Use the premade PostProcessor if we have one. Otherwise, we // create it and configure it here. pp, ok := p.premade[ppName] if !ok { log.Printf("Premade post-processor for '%s' not found. Creating.", ppName) pp = keyToPostProcessor(ppName) if pp == nil { return nil, fmt.Errorf("Vagrant box post-processor not found: %s", ppName) } config := map[string]string{"output": p.config.OutputPath} if err := pp.Configure(config); err != nil { return nil, err } } ui.Say(fmt.Sprintf("Creating Vagrant box for '%s' provider", ppName)) return pp.PostProcess(ui, artifact) }
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) { if artifact.BuilderId() != dockerimport.BuilderId { err := fmt.Errorf( "Unknown artifact type: %s\nCan only tag from Docker builder artifacts.", artifact.BuilderId()) return nil, false, err } dockerfile, template_err := p.render_template(trim_artifact_id(artifact.Id())) if template_err != nil { // could not render template return nil, false, template_err } log.Printf("[DEBUG] Dockerfile: %s\n", dockerfile.String()) if image_id, err := p.docker_build_fn(dockerfile); err != nil { // docker build command failed ui.Error("docker build command failed: " + err.Error()) return nil, false, err } else { ui.Message("Built image: " + image_id) new_artifact := &docker.ImportArtifact{ BuilderIdValue: dockerimport.BuilderId, Driver: &docker.DockerDriver{Ui: ui, Tpl: nil}, IdValue: image_id, } log.Printf("[DEBUG] artifact: %#v\n", new_artifact) return new_artifact, true, nil } }
// Prepares the signal handlers so that we handle interrupts properly. // The signal handler exists in a goroutine. func setupSignalHandlers(ui packer.Ui) { ch := make(chan os.Signal, 1) signal.Notify(ch, os.Interrupt) signal.Notify(ch, syscall.SIGTERM) go func() { // First interrupt. We mostly ignore this because it allows the // plugins time to cleanup. <-ch log.Println("First interrupt. Ignoring to allow plugins to clean up.") ui.Error("Interrupt signal received. Cleaning up...") // Second interrupt. Go down hard. <-ch log.Println("Second interrupt. Exiting now.") ui.Error("Interrupt signal received twice. Forcefully exiting now.") // Force kill all the plugins, but mark that we're killing them // first so that we don't get panics everywhere. plugin.CleanupClients() os.Exit(1) }() }
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) { ppName, ok := builtins[artifact.BuilderId()] if !ok { return nil, false, fmt.Errorf("Unknown artifact type, can't build box: %s", artifact.BuilderId()) } // Use the premade PostProcessor if we have one. Otherwise, we // create it and configure it here. pp, ok := p.premade[ppName] if !ok { log.Printf("Premade post-processor for '%s' not found. Creating.", ppName) var err error pp, err = p.subPostProcessor(ppName, nil, p.extraConfig) if err != nil { return nil, false, err } if pp == nil { return nil, false, fmt.Errorf("Vagrant box post-processor not found: %s", ppName) } } ui.Say(fmt.Sprintf("Creating Vagrant box for '%s' provider", ppName)) return pp.PostProcess(ui, artifact) }
func RunLocalCommands(commands []string, wrappedCommand CommandWrapper, ctx interpolate.Context, ui packer.Ui) error { for _, rawCmd := range commands { intCmd, err := interpolate.Render(rawCmd, &ctx) if err != nil { return fmt.Errorf("Error interpolating: %s", err) } command, err := wrappedCommand(intCmd) if err != nil { return fmt.Errorf("Error wrapping command: %s", err) } ui.Say(fmt.Sprintf("Executing command: %s", command)) comm := &shell_local.Communicator{} cmd := &packer.RemoteCmd{Command: command} if err := cmd.StartWithUi(comm, ui); err != nil { return fmt.Errorf("Error executing command: %s", err) } if cmd.ExitStatus != 0 { return fmt.Errorf( "Received non-zero exit code %d from command: %s", cmd.ExitStatus, command) } } return nil }
func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, localCookbooks []string) (string, error) { ui.Message("Creating configuration file 'solo.rb'") cookbook_paths := make([]string, len(p.config.RemoteCookbookPaths)+len(localCookbooks)) for i, path := range p.config.RemoteCookbookPaths { cookbook_paths[i] = fmt.Sprintf(`"%s"`, path) } for i, path := range localCookbooks { i = len(p.config.RemoteCookbookPaths) + i cookbook_paths[i] = fmt.Sprintf(`"%s"`, path) } configString, err := p.config.tpl.Process(DefaultConfigTemplate, &ConfigTemplate{ CookbookPaths: strings.Join(cookbook_paths, ","), }) if err != nil { return "", err } remotePath := filepath.Join(p.config.StagingDir, "solo.rb") if err := comm.Upload(remotePath, bytes.NewReader([]byte(configString))); err != nil { return "", err } return remotePath, nil }
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) { if artifact.BuilderId() != dockerimport.BuilderId { err := fmt.Errorf( "Unknown artifact type: %s\nCan only tag from Docker builder artifacts.", artifact.BuilderId()) return nil, false, err } driver := p.Driver if driver == nil { // If no driver is set, then we use the real driver driver = &docker.DockerDriver{Ctx: &p.config.ctx, Ui: ui} } importRepo := p.config.Repository if p.config.Tag != "" { importRepo += ":" + p.config.Tag } ui.Message("Tagging image: " + artifact.Id()) ui.Message("Repository: " + importRepo) err := driver.TagImage(artifact.Id(), importRepo, p.config.Force) if err != nil { return nil, false, err } // Build the artifact artifact = &docker.ImportArtifact{ BuilderIdValue: BuilderId, Driver: driver, IdValue: importRepo, } return artifact, true, nil }
func (p *Provisioner) createDir(ui packer.Ui, comm packer.Communicator, dir string) error { ui.Message(fmt.Sprintf("Creating directory: %s", dir)) mkdirCmd := fmt.Sprintf("mkdir -p '%s'", dir) if !p.config.PreventSudo { mkdirCmd = "sudo " + mkdirCmd } cmd := &packer.RemoteCmd{Command: mkdirCmd} if err := cmd.StartWithUi(comm, ui); err != nil { return err } if cmd.ExitStatus != 0 { return fmt.Errorf("Non-zero exit status. See output above for more info.") } // Chmod the directory to 0777 just so that we can access it as our user mkdirCmd = fmt.Sprintf("chmod 0777 '%s'", dir) if !p.config.PreventSudo { mkdirCmd = "sudo " + mkdirCmd } cmd = &packer.RemoteCmd{Command: mkdirCmd} if err := cmd.StartWithUi(comm, ui); err != nil { return err } if cmd.ExitStatus != 0 { return fmt.Errorf("Non-zero exit status. See output above for more info.") } return nil }
func (p *Provisioner) ProvisionDownload(ui packer.Ui, comm packer.Communicator) error { for _, src := range p.config.Sources { ui.Say(fmt.Sprintf("Downloading %s => %s", src, p.config.Destination)) // ensure destination dir exists. p.config.Destination may either be a file or a dir. dir := p.config.Destination // if it doesn't end with a /, set dir as the parent dir if !strings.HasSuffix(p.config.Destination, "/") { dir = filepath.Dir(dir) } if dir != "" { err := os.MkdirAll(dir, os.FileMode(0755)) if err != nil { return err } } // if the config.Destination was a dir, download the dir if strings.HasSuffix(p.config.Destination, "/") { return comm.DownloadDir(src, p.config.Destination, nil) } f, err := os.OpenFile(p.config.Destination, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) if err != nil { return err } defer f.Close() err = comm.Download(src, f) if err != nil { ui.Error(fmt.Sprintf("Download failed: %s", err)) return err } } return nil }
func (p *Provisioner) installChef(ui packer.Ui, comm packer.Communicator) error { ui.Message("Installing Chef...") p.config.ctx.Data = &InstallChefTemplate{ Sudo: !p.config.PreventSudo, } command, err := interpolate.Render(p.config.InstallCommand, &p.config.ctx) if err != nil { return err } ui.Message(command) cmd := &packer.RemoteCmd{Command: command} if err := cmd.StartWithUi(comm, ui); err != nil { return err } if cmd.ExitStatus != 0 { return fmt.Errorf( "Install script exited with non-zero exit status %d", cmd.ExitStatus) } return nil }
func (p *Provisioner) uploadManifests(ui packer.Ui, comm packer.Communicator) (string, error) { // Create the remote manifests directory... ui.Message("Uploading manifests...") remoteManifestsPath := fmt.Sprintf("%s/manifests", p.config.StagingDir) if err := p.createDir(ui, comm, remoteManifestsPath); err != nil { return "", fmt.Errorf("Error creating manifests directory: %s", err) } // Upload the main manifest f, err := os.Open(p.config.ManifestFile) if err != nil { return "", err } defer f.Close() manifestFilename := p.config.ManifestFile if fi, err := os.Stat(p.config.ManifestFile); err != nil { return "", fmt.Errorf("Error inspecting manifest file: %s", err) } else if !fi.IsDir() { manifestFilename = filepath.Base(manifestFilename) } else { ui.Say("WARNING: manifest_file should be a file. Use manifest_dir for directories") } remoteManifestFile := fmt.Sprintf("%s/%s", remoteManifestsPath, manifestFilename) if err := comm.Upload(remoteManifestFile, f, nil); err != nil { return "", err } return remoteManifestFile, nil }
func (p *Provisioner) createKnifeConfig(ui packer.Ui, comm packer.Communicator, nodeName string, serverUrl string, clientKey string, sslVerifyMode string) (string, error) { ui.Message("Creating configuration file 'knife.rb'") // Read the template tpl := DefaultKnifeTemplate ctx := p.config.ctx ctx.Data = &ConfigTemplate{ NodeName: nodeName, ServerUrl: serverUrl, ClientKey: clientKey, SslVerifyMode: sslVerifyMode, } configString, err := interpolate.Render(tpl, &ctx) if err != nil { return "", err } remotePath := filepath.ToSlash(filepath.Join(p.config.StagingDir, "knife.rb")) if err := comm.Upload(remotePath, bytes.NewReader([]byte(configString)), nil); err != nil { return "", err } return remotePath, nil }
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) { if artifact.BuilderId() != dockerimport.BuilderId { err := fmt.Errorf( "Unknown artifact type: %s\nCan only import from docker-import artifacts.", artifact.BuilderId()) return nil, false, err } driver := p.Driver if driver == nil { // If no driver is set, then we use the real driver driver = &docker.DockerDriver{Tpl: p.config.tpl, Ui: ui} } // Get the name. We strip off any tags from the name because the // push doesn't use those. name := artifact.Id() if i := strings.Index(name, "/"); i >= 0 { // This should always be true because the / is required. But we have // to get the index to this so we don't accidentally strip off the port if j := strings.Index(name[i:], ":"); j >= 0 { name = name[:i+j] } } ui.Message("Pushing: " + name) if err := driver.Push(name); err != nil { return nil, false, err } return nil, false, nil }
func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { p.cancelLock.Lock() p.cancel = make(chan struct{}) p.cancelLock.Unlock() ui.Say("Restarting Machine") p.comm = comm p.ui = ui var cmd *packer.RemoteCmd command := p.config.RestartCommand err := p.retryable(func() error { cmd = &packer.RemoteCmd{Command: command} return cmd.StartWithUi(comm, ui) }) if err != nil { return err } if cmd.ExitStatus != 0 { return fmt.Errorf("Restart script exited with non-zero exit status: %d", cmd.ExitStatus) } return waitForRestart(p, comm) }
func (p *Provisioner) ProvisionUpload(ui packer.Ui, comm packer.Communicator) error { ui.Say(fmt.Sprintf("Uploading %s => %s", p.config.Source, p.config.Destination)) info, err := os.Stat(p.config.Source) if err != nil { return err } // If we're uploading a directory, short circuit and do that if info.IsDir() { return comm.UploadDir(p.config.Destination, p.config.Source, nil) } // We're uploading a file... f, err := os.Open(p.config.Source) if err != nil { return err } defer f.Close() fi, err := f.Stat() if err != nil { return err } err = comm.Upload(p.config.Destination, f, &fi) if err != nil { ui.Error(fmt.Sprintf("Upload failed: %s", err)) } return err }
func (p *Provisioner) executeAnsible(ui packer.Ui, comm packer.Communicator) error { playbook := filepath.ToSlash(filepath.Join(p.config.StagingDir, filepath.Base(p.config.PlaybookFile))) inventory := filepath.ToSlash(filepath.Join(p.config.StagingDir, filepath.Base(p.config.InventoryFile))) extraArgs := "" if len(p.config.ExtraArguments) > 0 { extraArgs = " " + strings.Join(p.config.ExtraArguments, " ") } command := fmt.Sprintf("cd %s && %s %s%s -c local -i %s", p.config.StagingDir, p.config.Command, playbook, extraArgs, inventory) ui.Message(fmt.Sprintf("Executing Ansible: %s", command)) cmd := &packer.RemoteCmd{ Command: command, } if err := cmd.StartWithUi(comm, ui); err != nil { return err } if cmd.ExitStatus != 0 { if cmd.ExitStatus == 127 { return fmt.Errorf("%s could not be found. Verify that it is available on the\n"+ "PATH after connecting to the machine.", p.config.Command) } return fmt.Errorf("Non-zero exit status: %d", cmd.ExitStatus) } return nil }
func addVNIC(ui packer.Ui, f *find.Finder, ctx context.Context, c *govmomi.Client, vm *object.VirtualMachine, network string, nwType string) error { ui.Say("Adding NIC") nets, err := f.NetworkList(ctx, network) if err != nil { return err } // TODO expose param for DVS net := nets[1] backing, err := net.EthernetCardBackingInfo(ctx) if err != nil { return err } device, err := object.EthernetCardTypes().CreateEthernetCard(nwType, backing) if err != nil { return err } err = vm.AddDevice(ctx, device) if err != nil { return err } ui.Say("Adding NIC Success") return nil } //
func (p *Provisioner) createJson(ui packer.Ui, comm packer.Communicator) (string, error) { ui.Message("Creating JSON attribute file") jsonData := make(map[string]interface{}) // Copy the configured JSON for k, v := range p.config.Json { jsonData[k] = v } // Set the run list if it was specified if len(p.config.RunList) > 0 { jsonData["run_list"] = p.config.RunList } jsonBytes, err := json.MarshalIndent(jsonData, "", " ") if err != nil { return "", err } // Upload the bytes remotePath := filepath.ToSlash(filepath.Join(p.config.StagingDir, "node.json")) if err := comm.Upload(remotePath, bytes.NewReader(jsonBytes), nil); err != nil { return "", err } return remotePath, nil }
func (p *Provisioner) uploadDeploymentManifest(ui packer.Ui, comm packer.Communicator) error { ui.Say(fmt.Sprintf("Uploading manifest: %s", p.config.Manifest)) err := runCmd("mkdir ~/deployments", ui, comm) if err != nil { return err } f, err := os.Open(p.config.Manifest) if err != nil { return err } defer f.Close() fi, err := f.Stat() if err != nil { return err } err = comm.Upload(fmt.Sprintf("~/deployments/%s", p.config.Manifest), f, &fi) if err != nil { return err } cmd := fmt.Sprintf("sed -i \"s/director_uuid: .*/director_uuid: $(bosh status --uuid)/\" ~/deployments/%s", p.config.Manifest) return runCmd(cmd, ui, comm) }
func (p *Provisioner) executeAnsible(ui packer.Ui, comm packer.Communicator) error { playbook := filepath.Join(p.config.StagingDir, filepath.Base(p.config.PlaybookFile)) // The inventory must be set to "127.0.0.1,". The comma is important // as its the only way to override the ansible inventory when dealing // with a single host. extraArgs := "" if len(p.config.ExtraArguments) > 0 { extraArgs = " " + strings.Join(p.config.ExtraArguments, " ") } command := fmt.Sprintf("%s %s%s -c local -i \"127.0.0.1,\"", p.config.Command, playbook, extraArgs) ui.Message(fmt.Sprintf("Executing Ansible: %s", command)) cmd := &packer.RemoteCmd{ Command: command, } if err := cmd.StartWithUi(comm, ui); err != nil { return err } if cmd.ExitStatus != 0 { if cmd.ExitStatus == 127 { return fmt.Errorf("%s could not be found. Verify that it is available on the\n"+ "PATH after connecting to the machine.", p.config.Command) } return fmt.Errorf("Non-zero exit status: %d", cmd.ExitStatus) } return nil }
func (p *Provisioner) Provision(ui packer.Ui, _ packer.Communicator) error { // Make another communicator for local comm := &Communicator{ Ctx: p.config.ctx, ExecuteCommand: p.config.ExecuteCommand, } // Build the remote command cmd := &packer.RemoteCmd{Command: p.config.Command} ui.Say(fmt.Sprintf( "Executing local command: %s", p.config.Command)) if err := cmd.StartWithUi(comm, ui); err != nil { return fmt.Errorf( "Error executing command: %s\n\n"+ "Please see output above for more information.", p.config.Command) } if cmd.ExitStatus != 0 { return fmt.Errorf( "Erroneous exit code %d while executing command: %s\n\n"+ "Please see output above for more information.", cmd.ExitStatus, p.config.Command) } return nil }
func (p *Provisioner) executeChef(ui packer.Ui, comm packer.Communicator, config string, json string) error { p.config.ctx.Data = &ExecuteTemplate{ ConfigPath: config, JsonPath: json, Sudo: !p.config.PreventSudo, } command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx) if err != nil { return err } ui.Message(fmt.Sprintf("Executing Chef: %s", command)) cmd := &packer.RemoteCmd{ Command: command, } if err := cmd.StartWithUi(comm, ui); err != nil { return err } if cmd.ExitStatus != 0 { return fmt.Errorf("Non-zero exit status: %d", cmd.ExitStatus) } return nil }
func (p *Provisioner) ProvisionDownload(ui packer.Ui, comm packer.Communicator) error { for _, src := range p.config.Sources { ui.Say(fmt.Sprintf("Downloading %s => %s", src, p.config.Destination)) if strings.HasSuffix(p.config.Destination, "/") { err := os.MkdirAll(p.config.Destination, os.FileMode(0755)) if err != nil { return err } return comm.DownloadDir(src, p.config.Destination, nil) } f, err := os.OpenFile(p.config.Destination, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) if err != nil { return err } defer f.Close() err = comm.Download(src, f) if err != nil { ui.Error(fmt.Sprintf("Download failed: %s", err)) return err } } return nil }
func (p *OVFPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) { if artifact.BuilderId() != "mitchellh.vmware" { return nil, false, fmt.Errorf("ovftool post-processor can only be used on VMware boxes: %s", artifact.BuilderId()) } vmx := "" for _, path := range artifact.Files() { if strings.HasSuffix(path, ".vmx") { vmx = path } } if vmx == "" { return nil, false, fmt.Errorf("VMX file could not be located.") } // Strip DVD and floppy drives from the VMX if err := p.stripDrives(vmx); err != nil { return nil, false, fmt.Errorf("Couldn't strip floppy/DVD drives from VMX") } p.cfg.ctx.Data = &OutputPathTemplate{ ArtifactId: artifact.Id(), BuildName: p.cfg.BuildName, Provider: "vmware", } targetPath, err := interpolate.Render(p.cfg.TargetPath, &p.cfg.ctx) if err != nil { return nil, false, err } // build the arguments args := []string{ "--targetType=" + p.cfg.TargetType, "--acceptAllEulas", } // append --compression, if it is set if p.cfg.Compression > 0 { args = append(args, fmt.Sprintf("--compress=%d", p.cfg.Compression)) } // add the source/target args = append(args, vmx, targetPath) ui.Message(fmt.Sprintf("Executing ovftool with arguments: %+v", args)) cmd := exec.Command(executable, args...) var buffer bytes.Buffer cmd.Stdout = &buffer cmd.Stderr = &buffer err = cmd.Run() if err != nil { return nil, false, fmt.Errorf("Unable to execute ovftool: %s", buffer.String()) } ui.Message(fmt.Sprintf("%s", buffer.String())) return artifact, false, nil }
func (p *Provisioner) cleanClient(ui packer.Ui, comm packer.Communicator, node string, knifeConfigPath string) error { ui.Say("Cleaning up chef client...") args := []string{"client", "delete", node} if err := p.knifeExec(ui, comm, node, knifeConfigPath, args); err != nil { return fmt.Errorf("Failed to cleanup client: %s", err) } return nil }
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) { if artifact.BuilderId() != dockerimport.BuilderId && artifact.BuilderId() != dockertag.BuilderId { err := fmt.Errorf( "Unknown artifact type: %s\nCan only import from docker-import and docker-tag artifacts.", artifact.BuilderId()) return nil, false, err } driver := p.Driver if driver == nil { // If no driver is set, then we use the real driver driver = &docker.DockerDriver{Ctx: &p.config.ctx, Ui: ui} } if p.config.EcrLogin { ui.Message("Fetching ECR credentials...") username, password, err := p.config.EcrGetLogin(p.config.LoginServer) if err != nil { return nil, false, err } p.config.LoginUsername = username p.config.LoginPassword = password } if p.config.Login || p.config.EcrLogin { ui.Message("Logging in...") err := driver.Login( p.config.LoginServer, p.config.LoginEmail, p.config.LoginUsername, p.config.LoginPassword) if err != nil { return nil, false, fmt.Errorf( "Error logging in to Docker: %s", err) } defer func() { ui.Message("Logging out...") if err := driver.Logout(p.config.LoginServer); err != nil { ui.Error(fmt.Sprintf("Error logging out: %s", err)) } }() } // Get the name. name := artifact.Id() ui.Message("Pushing: " + name) if err := driver.Push(name); err != nil { return nil, false, err } return nil, false, nil }
func (p *Provisioner) cleanNode(ui packer.Ui, comm packer.Communicator, node string) error { ui.Say("Cleaning up chef node...") args := []string{"node", "delete", node} if err := p.knifeExec(ui, comm, node, args); err != nil { return fmt.Errorf("Failed to cleanup node: %s", err) } return nil }
func NewStepSetCertificate(config *Config, ui packer.Ui) *StepSetCertificate { var step = &StepSetCertificate{ config: config, say: func(message string) { ui.Say(message) }, error: func(e error) { ui.Error(e.Error()) }, } return step }
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) { if artifact.BuilderId() != "mitchellh.post-processor.vagrant" { return nil, false, fmt.Errorf( "Unknown artifact type, requires box from vagrant post-processor: %s", artifact.BuilderId()) } box := artifact.Files()[0] if !strings.HasSuffix(box, ".box") { return nil, false, fmt.Errorf( "Unknown files in artifact from vagrant post-processor: %s", artifact.Files()) } provider := providerFromBuilderName(artifact.Id()) file, err := os.Open(box) if err != nil { return nil, false, err } defer file.Close() info, err := file.Stat() if err != nil { return nil, false, err } size := info.Size() ui.Message(fmt.Sprintf("Box size: %s (%d bytes)", box, size)) metadata, err := p.getMetadata() if err != nil { return nil, false, err } ui.Message("Generating checksum") checksum, err := sum256(file) if err != nil { return nil, false, err } ui.Message(fmt.Sprintf("Checksum is %s", checksum)) ui.Message(fmt.Sprintf("Adding %s %s box to metadata", provider, p.config.Version)) if err := metadata.Add(p.config.Version, &Provider{ Name: provider, Url: fmt.Sprintf("%s/%s/%s", p.config.UrlPrefix, p.config.BoxDir, path.Base(box)), ChecksumType: "sha256", Checksum: checksum, }); err != nil { return nil, false, err } ui.Message(fmt.Sprintf("Saving the metadata: %s", p.config.MetadataPath)) if err := p.putMetadata(metadata); err != nil { return nil, false, err } return &Artifact{fmt.Sprintf("%s/%s", p.config.UrlPrefix, p.config.MetadataPath)}, true, nil }
func (self *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) { ui.Say(fmt.Sprintf("Creating archive for '%s'", artifact.BuilderId())) // Create the compressed archive file at the appropriate OutputPath. fw, err := os.Create(self.config.OutputPath) if err != nil { return nil, false, fmt.Errorf( "Failed creating file for compressed archive: %s", self.config.OutputPath) } defer fw.Close() gw := gzip.NewWriter(fw) defer gw.Close() // Iterate through all of the artifact's files and put them into the // compressed archive using the tar/gzip writers. for _, path := range artifact.Files() { fi, err := os.Stat(path) if err != nil { return nil, false, fmt.Errorf( "Failed stating file: %s", path) } target, _ := os.Readlink(path) header, err := tar.FileInfoHeader(fi, target) if err != nil { return nil, false, fmt.Errorf( "Failed creating archive header: %s", path) } tw := tar.NewWriter(gw) defer tw.Close() // Write the header first to the archive. This takes partial data // from the FileInfo that is grabbed by running the stat command. if err := tw.WriteHeader(header); err != nil { return nil, false, fmt.Errorf( "Failed writing archive header: %s", path) } // Open the target file for archiving and compressing. fr, err := os.Open(path) if err != nil { return nil, false, fmt.Errorf( "Failed opening file '%s' to write compressed archive.", path) } defer fr.Close() if _, err = io.Copy(tw, fr); err != nil { return nil, false, fmt.Errorf( "Failed copying file to archive: %s", path) } } return NewArtifact(artifact.BuilderId(), self.config.OutputPath), false, nil }