feat(nix): Return structured errors if packages are not found
Changes the return format of Nixery's build procedure to return a JSON structure that can indicate which errors have occured. The server can use this information to send appropriate status codes back to clients.
This commit is contained in:
parent
ec8e9eed5d
commit
3070d88051
1 changed files with 37 additions and 10 deletions
|
@ -99,6 +99,7 @@ in
|
||||||
# Since this is essentially a re-wrapping of some of the functionality that is
|
# Since this is essentially a re-wrapping of some of the functionality that is
|
||||||
# implemented in the dockerTools, we need all of its components in our top-level
|
# implemented in the dockerTools, we need all of its components in our top-level
|
||||||
# namespace.
|
# namespace.
|
||||||
|
with builtins;
|
||||||
with pkgs;
|
with pkgs;
|
||||||
with dockerTools;
|
with dockerTools;
|
||||||
|
|
||||||
|
@ -115,16 +116,29 @@ let
|
||||||
# For example, `deepFetch pkgs "xorg.xev"` retrieves `pkgs.xorg.xev`.
|
# For example, `deepFetch pkgs "xorg.xev"` retrieves `pkgs.xorg.xev`.
|
||||||
deepFetch = s: n:
|
deepFetch = s: n:
|
||||||
let path = lib.strings.splitString "." n;
|
let path = lib.strings.splitString "." n;
|
||||||
err = builtins.throw "Could not find '${n}' in package set";
|
err = { error = "not_found"; pkg = n; };
|
||||||
in lib.attrsets.attrByPath path err s;
|
in lib.attrsets.attrByPath path err s;
|
||||||
|
|
||||||
# allContents is the combination of all derivations and store paths passed in
|
# allContents is the combination of all derivations and store paths passed in
|
||||||
# directly, as well as packages referred to by name.
|
# directly, as well as packages referred to by name.
|
||||||
allContents = contents ++ (map (deepFetch pkgs) (builtins.fromJSON packages));
|
#
|
||||||
|
# It accumulates potential errors about packages that could not be found to
|
||||||
|
# return this information back to the server.
|
||||||
|
allContents =
|
||||||
|
# Folds over the results of 'deepFetch' on all requested packages to
|
||||||
|
# separate them into errors and content. This allows the program to
|
||||||
|
# terminate early and return only the errors if any are encountered.
|
||||||
|
let splitter = attrs: res:
|
||||||
|
if hasAttr "error" res
|
||||||
|
then attrs // { errors = attrs.errors ++ [ res ]; }
|
||||||
|
else attrs // { contents = attrs.contents ++ [ res ]; };
|
||||||
|
init = { inherit contents; errors = []; };
|
||||||
|
fetched = (map (deepFetch pkgs) (fromJSON packages));
|
||||||
|
in foldl' splitter init fetched;
|
||||||
|
|
||||||
contentsEnv = symlinkJoin {
|
contentsEnv = symlinkJoin {
|
||||||
name = "bulk-layers";
|
name = "bulk-layers";
|
||||||
paths = allContents;
|
paths = allContents.contents;
|
||||||
};
|
};
|
||||||
|
|
||||||
# The image build infrastructure expects to be outputting a slightly different
|
# The image build infrastructure expects to be outputting a slightly different
|
||||||
|
@ -176,7 +190,7 @@ let
|
||||||
|
|
||||||
cat fs-layers | jq -s -c '.' > $out
|
cat fs-layers | jq -s -c '.' > $out
|
||||||
'';
|
'';
|
||||||
allLayers = builtins.fromJSON (builtins.readFile allLayersJson);
|
allLayers = fromJSON (readFile allLayersJson);
|
||||||
|
|
||||||
# Image configuration corresponding to the OCI specification for the file type
|
# Image configuration corresponding to the OCI specification for the file type
|
||||||
# 'application/vnd.oci.image.config.v1+json'
|
# 'application/vnd.oci.image.config.v1+json'
|
||||||
|
@ -188,8 +202,8 @@ let
|
||||||
# Required to let Kubernetes import Nixery images
|
# Required to let Kubernetes import Nixery images
|
||||||
config = {};
|
config = {};
|
||||||
};
|
};
|
||||||
configJson = writeText "${baseName}-config.json" (builtins.toJSON config);
|
configJson = writeText "${baseName}-config.json" (toJSON config);
|
||||||
configMetadata = with builtins; fromJSON (readFile (runCommand "config-meta" {
|
configMetadata = fromJSON (readFile (runCommand "config-meta" {
|
||||||
buildInputs = [ jq openssl ];
|
buildInputs = [ jq openssl ];
|
||||||
} ''
|
} ''
|
||||||
size=$(wc -c ${configJson} | cut -d ' ' -f1)
|
size=$(wc -c ${configJson} | cut -d ' ' -f1)
|
||||||
|
@ -228,7 +242,7 @@ let
|
||||||
path = configJson;
|
path = configJson;
|
||||||
md5 = configMetadata.md5;
|
md5 = configMetadata.md5;
|
||||||
};
|
};
|
||||||
} // (builtins.listToAttrs (map (layer: {
|
} // (listToAttrs (map (layer: {
|
||||||
name = "${layer.sha256}";
|
name = "${layer.sha256}";
|
||||||
value = {
|
value = {
|
||||||
path = layer.path;
|
path = layer.path;
|
||||||
|
@ -236,6 +250,19 @@ let
|
||||||
};
|
};
|
||||||
}) allLayers));
|
}) allLayers));
|
||||||
|
|
||||||
in writeText "manifest-output.json" (builtins.toJSON {
|
# Final output structure returned to the controller in the case of a
|
||||||
inherit manifest layerLocations;
|
# successful build.
|
||||||
})
|
manifestOutput = {
|
||||||
|
inherit manifest layerLocations;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Output structure returned if errors occured during the build. Currently the
|
||||||
|
# only error type that is returned in a structured way is 'not_found'.
|
||||||
|
errorOutput = {
|
||||||
|
error = "not_found";
|
||||||
|
pkgs = map (err: err.pkg) allContents.errors;
|
||||||
|
};
|
||||||
|
in writeText "manifest-output.json" (if (length allContents.errors) == 0
|
||||||
|
then toJSON (trace manifestOutput manifestOutput)
|
||||||
|
else toJSON (trace errorOutput errorOutput)
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in a new issue