packer: add withPlugins
This commit is contained in:
@@ -25,6 +25,7 @@ etc-files.section.md
|
||||
nginx.section.md
|
||||
nrfutil.section.md
|
||||
opengl.section.md
|
||||
packer.section.md
|
||||
shell-helpers.section.md
|
||||
python-tree-sitter.section.md
|
||||
treefmt.section.md
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
# Packer {#sec-packer}
|
||||
|
||||
[Packer](https://www.packer.io) is a tool for creating identical machine images
|
||||
for multiple platforms from a single source configuration.
|
||||
|
||||
## Using Packer with plugins {#sec-packer-with-plugins}
|
||||
|
||||
Packer's functionality is extended through
|
||||
[plugins](https://developer.hashicorp.com/packer/docs/plugins). Rather than
|
||||
letting Packer download plugins at runtime, you can build a Packer wrapper that
|
||||
bundles the plugins you need with `packer.withPlugins`.
|
||||
|
||||
`packer.withPlugins` takes a function that receives the set of available plugins
|
||||
and returns the list of plugins to include:
|
||||
|
||||
```nix
|
||||
packer.withPlugins (ps: [ ps.docker ])
|
||||
```
|
||||
|
||||
This produces a `packer` executable wrapped with the `PACKER_PLUGIN_PATH`
|
||||
environment variable set, so the selected plugins are available without a
|
||||
separate `packer plugins install` step.
|
||||
|
||||
For example, to get a development shell with Packer and the Docker plugin:
|
||||
|
||||
```nix
|
||||
{
|
||||
pkgs ? import <nixpkgs> { },
|
||||
}:
|
||||
|
||||
pkgs.mkShell {
|
||||
packages = [
|
||||
(pkgs.packer.withPlugins (ps: [ ps.docker ]))
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
Multiple plugins can be selected at once:
|
||||
|
||||
```nix
|
||||
packer.withPlugins (ps: [
|
||||
ps.docker
|
||||
ps.qemu
|
||||
])
|
||||
```
|
||||
|
||||
## Listing available plugins {#sec-packer-list-plugins}
|
||||
|
||||
The packaged plugins are exposed as the `packer.plugins` attribute set. To list
|
||||
every plugin available in your version of Nixpkgs, query its attribute names:
|
||||
|
||||
```ShellSession
|
||||
$ nix eval nixpkgs#packer.plugins --apply builtins.attrNames
|
||||
[ "docker" "qemu" ]
|
||||
```
|
||||
|
||||
Without flakes:
|
||||
|
||||
```ShellSession
|
||||
$ nix-env -f '<nixpkgs>' -qaP -A packer.plugins
|
||||
packer.plugins.docker packer-plugin-docker-1.1.2
|
||||
packer.plugins.qemu packer-plugin-qemu-1.1.4
|
||||
```
|
||||
|
||||
The attribute name (for example `docker` or `qemu`) is what you pass to
|
||||
`packer.withPlugins`.
|
||||
|
||||
Notes:
|
||||
|
||||
- `mkPackerPlugin` currently only supports `fetchFromGitHub` as the fetcher.
|
||||
@@ -620,6 +620,15 @@
|
||||
"chap-overrides": [
|
||||
"index.html#chap-overrides"
|
||||
],
|
||||
"sec-packer": [
|
||||
"index.html#sec-packer"
|
||||
],
|
||||
"sec-packer-list-plugins": [
|
||||
"index.html#sec-packer-list-plugins"
|
||||
],
|
||||
"sec-packer-with-plugins": [
|
||||
"index.html#sec-packer-with-plugins"
|
||||
],
|
||||
"sec-pkg-override": [
|
||||
"index.html#sec-pkg-override"
|
||||
],
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
let
|
||||
platformSuffix = {
|
||||
x86_64-linux = "linux_amd64";
|
||||
x86_64-darwin = "darwin_amd64";
|
||||
aarch64-linux = "linux_arm64";
|
||||
aarch64-darwin = "darwin_arm64";
|
||||
};
|
||||
in
|
||||
|
||||
{
|
||||
stdenv,
|
||||
lib,
|
||||
buildGoModule,
|
||||
versionCheckHook,
|
||||
nix-update-script,
|
||||
}:
|
||||
|
||||
lib.extendMkDerivation {
|
||||
constructDrv = buildGoModule;
|
||||
|
||||
excludeDrvArgNames = [
|
||||
"apiVersion"
|
||||
];
|
||||
|
||||
extendDrvArgs =
|
||||
finalAttrs:
|
||||
{
|
||||
pname,
|
||||
version,
|
||||
src,
|
||||
ldflags ? [ ],
|
||||
nativeInstallCheckInputs ? [ ],
|
||||
postFixup ? "",
|
||||
subPackages ? [ "." ],
|
||||
apiVersion ? "x5.0",
|
||||
versionCheckProgramArg ? "describe",
|
||||
doInstallCheck ? true,
|
||||
...
|
||||
}@prevAttrs:
|
||||
# Packer expects plugins to be hosted on GitHub and follow a specific release structure
|
||||
# (see: https://developer.hashicorp.com/packer/docs/plugins/creation#creating-a-github-release).
|
||||
# This introduces two requirements:
|
||||
#
|
||||
# 1. Directory Structure: Packer expects the plugin binary to reside in:
|
||||
# $PACKER_PLUGIN_PATH/github.com/$OWNER/$TYPE/
|
||||
# where $TYPE is the repo name without the "packer-plugin-" prefix.
|
||||
#
|
||||
# 2. Configuration Source: When declaring the plugin in a Packer template, the `source`
|
||||
# attribute must match this GitHub address format (e.g.: "github.com/$OWNER/$TYPE")
|
||||
let
|
||||
_ = lib.assertMsg (
|
||||
src ? repo && src ? owner && src ? githubBase
|
||||
) "mk-packer-plugin: fetchFromGitHub is currently the only supported fetcher";
|
||||
suffix =
|
||||
platformSuffix."${stdenv.hostPlatform.system}"
|
||||
or (throw "Unsupported system: ${stdenv.hostPlatform.system}");
|
||||
binName = "${finalAttrs.src.repo}_v${finalAttrs.version}_${apiVersion}_${suffix}";
|
||||
in
|
||||
{
|
||||
inherit
|
||||
subPackages
|
||||
doInstallCheck
|
||||
versionCheckProgramArg
|
||||
;
|
||||
|
||||
__structuredAttrs = true;
|
||||
strictDeps = true;
|
||||
|
||||
ldflags =
|
||||
ldflags
|
||||
++ (
|
||||
let
|
||||
versionFlag = "${finalAttrs.src.githubBase}/${finalAttrs.src.owner}/${finalAttrs.src.repo}/version";
|
||||
in
|
||||
[
|
||||
"-s"
|
||||
"-w"
|
||||
"-X ${versionFlag}.Version=${finalAttrs.version}"
|
||||
"-X ${versionFlag}.VersionPrerelease="
|
||||
]
|
||||
);
|
||||
|
||||
versionCheckProgram = prevAttrs.versionCheckProgram or "${placeholder "out"}/bin/${binName}";
|
||||
|
||||
nativeInstallCheckInputs = nativeInstallCheckInputs ++ [ versionCheckHook ];
|
||||
|
||||
# Generate checksums AFTER fixup phase when binary is finalized
|
||||
postFixup = postFixup + ''
|
||||
mv "$out/bin/${finalAttrs.src.repo}" "$out/bin/${binName}"
|
||||
sha256sum "$out/bin/${binName}" | cut -d' ' -f1 > "$out/bin/${binName}_SHA256SUM"
|
||||
'';
|
||||
|
||||
meta.mainProgram = binName;
|
||||
|
||||
passthru = {
|
||||
pluginPath = "${finalAttrs.src.githubBase}/${finalAttrs.src.owner}/${lib.removePrefix "packer-plugin-" finalAttrs.src.repo}/${binName}";
|
||||
updateScript = prevAttrs.passthru.updateScript or (nix-update-script { });
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -3,16 +3,18 @@
|
||||
buildGoModule,
|
||||
fetchFromGitHub,
|
||||
installShellFiles,
|
||||
callPackage,
|
||||
runCommand,
|
||||
}:
|
||||
|
||||
buildGoModule rec {
|
||||
buildGoModule (finalAttrs: {
|
||||
pname = "packer";
|
||||
version = "1.15.4";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "hashicorp";
|
||||
repo = "packer";
|
||||
rev = "v${version}";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-mhHES+/FCvVBBQm1qDQeH6WY2c9hIV7N3iFBCqJqJLw=";
|
||||
};
|
||||
|
||||
@@ -31,6 +33,46 @@ buildGoModule rec {
|
||||
installShellCompletion --zsh contrib/zsh-completion/_packer
|
||||
'';
|
||||
|
||||
passthru =
|
||||
let
|
||||
pluginScope = callPackage ./plugins.nix { };
|
||||
in
|
||||
{
|
||||
plugins = lib.filterAttrs (_: lib.isDerivation) pluginScope;
|
||||
|
||||
withPlugins =
|
||||
f:
|
||||
(callPackage ./with-plugins.nix {
|
||||
packer = finalAttrs.finalPackage;
|
||||
packerPlugins = pluginScope;
|
||||
})
|
||||
{ selector = f; };
|
||||
|
||||
tests.withPlugins =
|
||||
let
|
||||
packer-with-docker = finalAttrs.passthru.withPlugins (ps: [ ps.docker ]);
|
||||
in
|
||||
runCommand "packer-test-with-plugins"
|
||||
{
|
||||
nativeBuildInputs = [ packer-with-docker ];
|
||||
}
|
||||
''
|
||||
packer plugins installed > output.txt
|
||||
cat output.txt
|
||||
|
||||
expected_path="${finalAttrs.passthru.plugins.docker.pluginPath}"
|
||||
if ! grep -q "$expected_path" output.txt; then
|
||||
echo "ERROR: Expected plugin path not found in 'packer plugins installed' output"
|
||||
echo "Expected: $expected_path"
|
||||
echo "Got:"
|
||||
cat output.txt
|
||||
exit 1
|
||||
fi
|
||||
|
||||
touch $out
|
||||
'';
|
||||
};
|
||||
|
||||
meta = {
|
||||
description = "Tool for creating identical machine images for multiple platforms from a single source configuration";
|
||||
homepage = "https://www.packer.io";
|
||||
@@ -40,7 +82,8 @@ buildGoModule rec {
|
||||
ma27
|
||||
techknowlogick
|
||||
qjoly
|
||||
jlesquembre
|
||||
];
|
||||
changelog = "https://github.com/hashicorp/packer/blob/v${version}/CHANGELOG.md";
|
||||
changelog = "https://github.com/hashicorp/packer/blob/v${finalAttrs.version}/CHANGELOG.md";
|
||||
};
|
||||
}
|
||||
})
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
lib,
|
||||
newScope,
|
||||
}:
|
||||
lib.makeScope newScope (
|
||||
self:
|
||||
let
|
||||
packages = lib.packagesFromDirectoryRecursive {
|
||||
inherit (self) callPackage;
|
||||
directory = ./plugins;
|
||||
};
|
||||
in
|
||||
{
|
||||
mkPackerPlugin = self.callPackage ./extra/mk-packer-plugin.nix { };
|
||||
}
|
||||
// lib.mapAttrs' (
|
||||
name: pkg: lib.nameValuePair (lib.removePrefix "packer-plugin-" name) pkg
|
||||
) packages
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
lib,
|
||||
mkPackerPlugin,
|
||||
fetchFromGitHub,
|
||||
}:
|
||||
|
||||
mkPackerPlugin (finalAttrs: {
|
||||
|
||||
pname = "packer-plugin-docker";
|
||||
version = "1.1.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "hashicorp";
|
||||
repo = "packer-plugin-docker";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-h89FGwUQjTk81CYUe1xmKxSHr1t3wyBg9lHUTqmVym8=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-mvyafYSLi/q7lWorfKc4Gc4oM7yti3v/bLcVnNkH7ZY=";
|
||||
|
||||
meta = {
|
||||
description = "Packer plugin for Docker";
|
||||
homepage = "https://github.com/hashicorp/packer-plugin-docker";
|
||||
license = lib.licenses.mpl20;
|
||||
maintainers = with lib.maintainers; [ jlesquembre ];
|
||||
};
|
||||
})
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
lib,
|
||||
mkPackerPlugin,
|
||||
fetchFromGitHub,
|
||||
}:
|
||||
|
||||
mkPackerPlugin (finalAttrs: {
|
||||
|
||||
pname = "packer-plugin-qemu";
|
||||
version = "1.1.4";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "hashicorp";
|
||||
repo = "packer-plugin-qemu";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-Ose7ueo9V2zJ5K5yvew9ErTD9lR+rkp1UB/yDi+U+fY=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-pgfI/ntG6Fesimw3jk70GP+lBUEUMfq6wbqXx8xCTf0=";
|
||||
|
||||
meta = {
|
||||
description = "Packer plugin for QEMU";
|
||||
homepage = "https://github.com/hashicorp/packer-plugin-qemu";
|
||||
license = lib.licenses.mpl20;
|
||||
maintainers = with lib.maintainers; [ jlesquembre ];
|
||||
};
|
||||
})
|
||||
@@ -0,0 +1,54 @@
|
||||
{
|
||||
lib,
|
||||
packer,
|
||||
packerPlugins,
|
||||
makeBinaryWrapper,
|
||||
linkFarm,
|
||||
stdenvNoCC,
|
||||
}:
|
||||
lib.extendMkDerivation {
|
||||
constructDrv = stdenvNoCC.mkDerivation;
|
||||
|
||||
excludeDrvArgNames = [
|
||||
"derivationArgs"
|
||||
"selector"
|
||||
];
|
||||
|
||||
extendDrvArgs =
|
||||
finalAttrs:
|
||||
{
|
||||
selector ? (_: [ ]),
|
||||
name ? "packer-with-plugins",
|
||||
nativeBuildInputs ? [ makeBinaryWrapper ],
|
||||
...
|
||||
}:
|
||||
let
|
||||
plugins = selector packerPlugins;
|
||||
pluginFarm = linkFarm "packer-plugins" (
|
||||
builtins.concatMap (p: [
|
||||
{
|
||||
name = p.pluginPath;
|
||||
path = "${p}/bin/${p.meta.mainProgram}";
|
||||
}
|
||||
{
|
||||
name = "${p.pluginPath}_SHA256SUM";
|
||||
path = "${p}/bin/${p.meta.mainProgram}_SHA256SUM";
|
||||
}
|
||||
]) plugins
|
||||
);
|
||||
in
|
||||
{
|
||||
inherit name nativeBuildInputs;
|
||||
__structuredAttrs = true;
|
||||
strictDeps = true;
|
||||
|
||||
meta.mainProgram = "packer";
|
||||
|
||||
dontUnpack = true;
|
||||
|
||||
buildCommand = ''
|
||||
makeWrapper "${packer}/bin/packer" "$out/bin/packer" \
|
||||
--set PACKER_PLUGIN_PATH "${pluginFarm}"
|
||||
'';
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user