~angdraug/packer-provisioner-apt

b21e28f8cb9ea9c7c5c4c83165837b83acd81c38 — Dmitry Borodaenko 3 years ago 9d8427a
Update APT cache with archives from target

You no longer have to pre-populate the APT cache to reuse downloaded
packages between repeated builds of the same image. After running
`apt-get install`, the plugin will copy new package archives from target
back into `cache_dir`.
3 files changed, 29 insertions(+), 5 deletions(-)

M .gitignore
M README.md
M provisioner/provisioner.go
M .gitignore => .gitignore +1 -1
@@ 1,2 1,2 @@
packer-builder-nspawn-debootstrap
packer-builder-nspawn
packer-provisioner-apt

M README.md => README.md +5 -4
@@ 20,7 20,7 @@ Prerequisites:
- `packer` (use `--no-install-recommends` to prevent the Debian package of
  Packer from also installing Docker when you don't need it)
- (optional)
  [packer-builder-nspawn-debootstrap](https://git.sr.ht/~angdraug/packer-builder-nspawn-debootstrap/)
  [packer-builder-nspawn](https://git.sr.ht/~angdraug/packer-builder-nspawn)
  to build Debian container images with systemd-nspawn

For compatibility with the Debian package of Packer that is built with a newer


@@ 45,9 45,10 @@ built from unpatched upstream source, comment out that replace line.
  [apt-secure(8)](https://manpages.debian.org/unstable/apt/apt-secure.8.en.html).

- `cache_dir` - local APT cache directory. The default is
  `/var/cache/apt/archives`. The contents will be copied into the image under
  `/var/cache/apt/archives` before running `apt-get install`, and will be
  purged from the image with `apt-get clean` afterwards.
  `/var/cache/apt/archives`. The directory will be copied into the target under
  `/var/cache/apt/archives` before running `apt-get install`. After
  provisioning, the directory will be updated with packages from the target
  cache, and the target cache will be purged with `apt-get clean`.

When building multiple images with the same or overlapping set of packages, you
can pre-populate APT cache before running packer:

M provisioner/provisioner.go => provisioner/provisioner.go +23 -0
@@ 3,7 3,9 @@ package provisioner
import (
	"context"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"



@@ 75,6 77,8 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C
		return err
	}

	p.updateCache(ui, comm)

	cmd = &packer.RemoteCmd{Command: "/usr/bin/apt-get clean"}
	if err := cmd.RunWithUi(ctx, comm, ui); err != nil {
		ui.Error("apt-get clean failed, ignoring")


@@ 82,3 86,22 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C

	return nil
}

func (p *Provisioner) updateCache(ui packer.Ui, comm packer.Communicator) {
	dir, err := ioutil.TempDir(os.TempDir(), "archives-")
	if err != nil {
		ui.Error("APT cache update: failed to create tempdir")
		return
	}
	defer os.RemoveAll(dir)

	if err := comm.DownloadDir("/var/cache/apt/archives", dir, []string{}); err != nil {
		ui.Error(fmt.Sprintf("APT cache update: failed to download archives to %s", dir))
		return
	}

	cmd := exec.Command("/bin/sh", "-c", fmt.Sprintf("mv -n %s/*.deb %s", dir, p.config.CacheDir))
	if err := cmd.Run(); err != nil {
		ui.Error(fmt.Sprintf("APT cache update: mv: %v", err))
	}
}