Merge pull request 'lib/jsonschema: make attrs required' (#3335) from fricklerhandwerk/clan-core:required-attrs into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3335
This commit is contained in:
@@ -123,7 +123,7 @@ rec {
|
|||||||
# parse options to jsonschema properties
|
# parse options to jsonschema properties
|
||||||
properties = lib.mapAttrs (_name: option: (parseOption' (path ++ [ _name ]) option)) options';
|
properties = lib.mapAttrs (_name: option: (parseOption' (path ++ [ _name ]) option)) options';
|
||||||
# TODO: figure out how to handle if prop.anyOf is used
|
# TODO: figure out how to handle if prop.anyOf is used
|
||||||
isRequired = prop: !(prop ? default || prop.type or null == "object");
|
isRequired = prop: !(prop ? default || prop."$exportedModuleInfo".required or false);
|
||||||
requiredProps = lib.filterAttrs (_: prop: isRequired prop) properties;
|
requiredProps = lib.filterAttrs (_: prop: isRequired prop) properties;
|
||||||
required = lib.optionalAttrs (requiredProps != { }) { required = lib.attrNames requiredProps; };
|
required = lib.optionalAttrs (requiredProps != { }) { required = lib.attrNames requiredProps; };
|
||||||
header' = if addHeader then header else { };
|
header' = if addHeader then header else { };
|
||||||
@@ -150,9 +150,9 @@ rec {
|
|||||||
{ };
|
{ };
|
||||||
|
|
||||||
# Metadata about the module that is made available to the schema via '$propagatedModuleInfo'
|
# Metadata about the module that is made available to the schema via '$propagatedModuleInfo'
|
||||||
exportedModuleInfo = lib.optionalAttrs true (makeModuleInfo {
|
exportedModuleInfo = makeModuleInfo {
|
||||||
inherit path;
|
inherit path;
|
||||||
});
|
};
|
||||||
in
|
in
|
||||||
# return jsonschema
|
# return jsonschema
|
||||||
header'
|
header'
|
||||||
@@ -377,7 +377,13 @@ rec {
|
|||||||
# return jsonschema property definition for attrs
|
# return jsonschema property definition for attrs
|
||||||
then
|
then
|
||||||
default
|
default
|
||||||
// exposedModuleInfo
|
// (lib.recursiveUpdate exposedModuleInfo (
|
||||||
|
lib.optionalAttrs (!default ? default) {
|
||||||
|
"$exportedModuleInfo" = {
|
||||||
|
required = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
))
|
||||||
// example
|
// example
|
||||||
// description
|
// description
|
||||||
// {
|
// {
|
||||||
@@ -419,7 +425,19 @@ rec {
|
|||||||
# return jsonschema property definition for submodule
|
# return jsonschema property definition for submodule
|
||||||
# then (lib.attrNames (option.type.getSubOptions option.loc).opt)
|
# then (lib.attrNames (option.type.getSubOptions option.loc).opt)
|
||||||
then
|
then
|
||||||
exposedModuleInfo // example // description // parseSubOptions { inherit option; }
|
(lib.recursiveUpdate exposedModuleInfo (
|
||||||
|
if (default ? default) then
|
||||||
|
default
|
||||||
|
else
|
||||||
|
{
|
||||||
|
"$exportedModuleInfo" = {
|
||||||
|
required = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
))
|
||||||
|
// example
|
||||||
|
// description
|
||||||
|
// parseSubOptions { inherit option; }
|
||||||
# throw error if option type is not supported
|
# throw error if option type is not supported
|
||||||
else
|
else
|
||||||
notSupported option;
|
notSupported option;
|
||||||
|
|||||||
@@ -16,5 +16,10 @@
|
|||||||
"name": "John Doe",
|
"name": "John Doe",
|
||||||
"repo": "test-backup"
|
"repo": "test-backup"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"userModules": {
|
||||||
|
"some-user": {
|
||||||
|
"foo": {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
default = false;
|
default = false;
|
||||||
description = "Is the user an admin?";
|
description = "Is the user an admin?";
|
||||||
};
|
};
|
||||||
# a submodule option
|
# a submodule option without default
|
||||||
services = lib.mkOption {
|
services = lib.mkOption {
|
||||||
type = lib.types.submodule {
|
type = lib.types.submodule {
|
||||||
options.opt = lib.mkOption {
|
options.opt = lib.mkOption {
|
||||||
@@ -30,6 +30,17 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
# a submodule option with default
|
||||||
|
programs = lib.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options.opt = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "bar";
|
||||||
|
description = "Another submodule option";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
# attrs of int
|
# attrs of int
|
||||||
userIds = lib.mkOption {
|
userIds = lib.mkOption {
|
||||||
type = lib.types.attrsOf lib.types.int;
|
type = lib.types.attrsOf lib.types.int;
|
||||||
@@ -40,6 +51,14 @@
|
|||||||
albrecht = 3;
|
albrecht = 3;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
# attrs of submodule
|
||||||
|
userModules = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (
|
||||||
|
lib.types.submodule {
|
||||||
|
options.foo = lib.mkOption { };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
# list of str
|
# list of str
|
||||||
kernelModules = lib.mkOption {
|
kernelModules = lib.mkOption {
|
||||||
type = lib.types.listOf lib.types.str;
|
type = lib.types.listOf lib.types.str;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"$exportedModuleInfo": { "path": [] },
|
"$exportedModuleInfo": { "path": [] },
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
"required": ["services", "userModules"],
|
||||||
"properties": {
|
"properties": {
|
||||||
"name": {
|
"name": {
|
||||||
"$exportedModuleInfo": { "path": ["name"] },
|
"$exportedModuleInfo": { "path": ["name"] },
|
||||||
@@ -46,6 +47,32 @@
|
|||||||
},
|
},
|
||||||
"description": "Some attributes"
|
"description": "Some attributes"
|
||||||
},
|
},
|
||||||
|
"userModules": {
|
||||||
|
"$exportedModuleInfo": { "path": ["userModules"] },
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"$exportedModuleInfo": { "path": ["userModules", "<name>"] },
|
||||||
|
"additionalProperties": false,
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"foo": {
|
||||||
|
"$exportedModuleInfo": {
|
||||||
|
"path": ["userModules", "<name>", "foo"]
|
||||||
|
},
|
||||||
|
"type": [
|
||||||
|
"boolean",
|
||||||
|
"integer",
|
||||||
|
"number",
|
||||||
|
"string",
|
||||||
|
"array",
|
||||||
|
"object",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["foo"]
|
||||||
|
}
|
||||||
|
},
|
||||||
"colour": {
|
"colour": {
|
||||||
"$exportedModuleInfo": { "path": ["colour"] },
|
"$exportedModuleInfo": { "path": ["colour"] },
|
||||||
"default": "red",
|
"default": "red",
|
||||||
@@ -65,6 +92,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"programs": {
|
||||||
|
"$exportedModuleInfo": { "path": ["programs"] },
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"opt": {
|
||||||
|
"$exportedModuleInfo": { "path": ["programs", "opt"] },
|
||||||
|
"type": "string",
|
||||||
|
"default": "bar",
|
||||||
|
"description": "Another submodule option"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": {}
|
||||||
|
},
|
||||||
"destinations": {
|
"destinations": {
|
||||||
"$exportedModuleInfo": { "path": ["destinations"] },
|
"$exportedModuleInfo": { "path": ["destinations"] },
|
||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
|
|||||||
@@ -324,6 +324,7 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
default = { };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -354,6 +355,7 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
default = { };
|
||||||
required = [ "opt" ];
|
required = [ "opt" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,17 @@
|
|||||||
testParseNestedOptions =
|
testParseNestedOptions =
|
||||||
let
|
let
|
||||||
evaled = lib.evalModules {
|
evaled = lib.evalModules {
|
||||||
modules = [ { options.foo.bar = lib.mkOption { type = lib.types.bool; }; } ];
|
modules = [
|
||||||
|
{
|
||||||
|
options.foo.bar = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
};
|
||||||
|
options.foo.baz = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@@ -40,12 +50,23 @@
|
|||||||
};
|
};
|
||||||
type = "boolean";
|
type = "boolean";
|
||||||
};
|
};
|
||||||
|
baz = {
|
||||||
|
"$exportedModuleInfo" = {
|
||||||
|
path = [
|
||||||
|
"foo"
|
||||||
|
"baz"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
type = "boolean";
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
required = [ "bar" ];
|
required = [ "bar" ];
|
||||||
type = "object";
|
type = "object";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
type = "object";
|
type = "object";
|
||||||
|
required = [ "foo" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user