This commit is contained in:
David Arnold 2021-05-13 17:27:08 -04:00
parent c3fa598922
commit db6d83c61e
No known key found for this signature in database
GPG key ID: 6D6A936E69C59D08
53 changed files with 1916 additions and 1599 deletions

View file

@ -1,14 +1,16 @@
{ pkgs ? import <nixpkgs> {}, lib ? pkgs.lib, spec ? ./istio-schema.json }:
{ pkgs ? import <nixpkgs> { }, lib ? pkgs.lib, spec ? ./istio-schema.json }:
with lib;
let
gen = rec {
mkMerge = values: ''mkMerge [${concatMapStrings (value: "
mkMerge = values: ''mkMerge [${concatMapStrings
(value: "
${value}
") values}]'';
")
values}]'';
toNixString = value: if isAttrs value || isList value
toNixString = value:
if isAttrs value || isList value
then builtins.toJSON value
else if isString value
then ''"${value}"''
@ -18,19 +20,19 @@ let
removeEmptyLines = str: concatStringsSep "\n" (filter (l: (builtins.match "( |)+" l) == null) (splitString "\n" str));
mkOption = {
description ? null,
type ? null,
default ? null,
apply ? null
}: removeEmptyLines ''mkOption {
mkOption =
{ description ? null
, type ? null
, default ? null
, apply ? null
}: removeEmptyLines ''mkOption {
${optionalString (description != null) "description = ${builtins.toJSON description};"}
${optionalString (type != null) ''type = ${type};''}
${optionalString (default != null) ''default = ${toNixString default};''}
${optionalString (apply != null) ''apply = ${apply};''}
}'';
mkOverride = priority: value: "mkOverride ${toString priority} ${toNixString value}";
mkOverride = priority: value: "mkOverride ${toString priority} ${toNixString value}";
types = {
unspecified = "types.unspecified";
@ -49,7 +51,7 @@ let
hasTypeMapping = def:
hasAttr "type" def &&
elem def.type ["string" "integer" "boolean"];
elem def.type [ "string" "integer" "boolean" ];
mergeValuesByKey = mergeKey: ''(mergeValuesByKey "${mergeKey}")'';
@ -77,256 +79,282 @@ let
refDefinition = attr: head (tail (tail (splitString "/" attr."$ref")));
};
fixJSON = content: replaceStrings ["\\u"] ["u"] content;
fixJSON = content: replaceStrings [ "\\u" ] [ "u" ] content;
fetchSpecs = path: builtins.fromJSON (fixJSON (builtins.readFile path));
genDefinitions = swagger: with gen; (mapAttrs (name: definition:
# if $ref is in definition it means it's an alias of other definition
if hasAttr "$ref" definition
then definitions."${refDefinition definition}"
genDefinitions = swagger: with gen; (mapAttrs
(name: definition:
# if $ref is in definition it means it's an alias of other definition
if hasAttr "$ref" definition
then definitions."${refDefinition definition}"
else if !(hasAttr "properties" definition)
then {
type = mapType definition;
}
else if !(hasAttr "properties" definition)
then {
type = mapType definition;
}
else {
options = mapAttrs (propName: property:
let
isRequired = elem propName (definition.required or []);
requiredOrNot = type: if isRequired then type else types.nullOr type;
optionProperties =
# if $ref is in property it references other definition,
# but if other definition does not have properties, then just take it's type
if hasAttr "$ref" property then
if hasTypeMapping swagger.definitions.${refDefinition property} then {
type = requiredOrNot (mapType swagger.definitions.${refDefinition property});
}
else {
type = requiredOrNot (submoduleOf definitions (refDefinition property));
}
else {
options = mapAttrs
(propName: property:
let
isRequired = elem propName (definition.required or [ ]);
requiredOrNot = type: if isRequired then type else types.nullOr type;
optionProperties =
# if $ref is in property it references other definition,
# but if other definition does not have properties, then just take it's type
if hasAttr "$ref" property then
if hasTypeMapping swagger.definitions.${refDefinition property} then {
type = requiredOrNot (mapType swagger.definitions.${refDefinition property});
}
else {
type = requiredOrNot (submoduleOf definitions (refDefinition property));
}
else if !(hasAttr "type" property) then {
type = types.unspecified;
}
# if property has an array type
else if property.type == "array" then
# if reference is in items it can reference other type of another
# definition
if hasAttr "$ref" property.items then
# if it is a reference to simple type
if hasTypeMapping swagger.definitions.${refDefinition property.items}
then {
type = requiredOrNot (types.listOf (mapType swagger.definitions.${refDefinition property.items}.type));
else if !(hasAttr "type" property) then {
type = types.unspecified;
}
# if a reference is to complex type
else
# if x-kubernetes-patch-merge-key is set then make it an
# attribute set of submodules
if hasAttr "x-kubernetes-patch-merge-key" property
then let
mergeKey = property."x-kubernetes-patch-merge-key";
in {
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey);
apply = attrsToList;
}
# if property has an array type
else if property.type == "array" then
# in other case it's a simple list
# if reference is in items it can reference other type of another
# definition
if hasAttr "$ref" property.items then
# if it is a reference to simple type
if hasTypeMapping swagger.definitions.${refDefinition property.items}
then {
type = requiredOrNot (types.listOf (mapType swagger.definitions.${refDefinition property.items}.type));
}
# if a reference is to complex type
else
# if x-kubernetes-patch-merge-key is set then make it an
# attribute set of submodules
if hasAttr "x-kubernetes-patch-merge-key" property
then
let
mergeKey = property."x-kubernetes-patch-merge-key";
in
{
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey);
apply = attrsToList;
}
# in other case it's a simple list
else {
type = requiredOrNot (types.listOf (submoduleOf definitions (refDefinition property.items)));
}
# in other case it only references a simple type
else {
type = requiredOrNot (types.listOf (submoduleOf definitions (refDefinition property.items)));
type = requiredOrNot (types.listOf (mapType property.items));
}
# in other case it only references a simple type
else {
type = requiredOrNot (types.listOf (mapType property.items));
}
else if property.type == "object" && hasAttr "additionalProperties" property
then
# if it is a reference to simple type
if (
hasAttr "$ref" property.additionalProperties &&
hasTypeMapping swagger.definitions.${refDefinition property.additionalProperties}
) then {
type = requiredOrNot (types.attrsOf (mapType swagger.definitions.${refDefinition property.additionalProperties}));
}
else if property.type == "object" && hasAttr "additionalProperties" property
then
# if it is a reference to simple type
if (
hasAttr "$ref" property.additionalProperties &&
hasTypeMapping swagger.definitions.${refDefinition property.additionalProperties}
) then {
type = requiredOrNot (types.attrsOf (mapType swagger.definitions.${refDefinition property.additionalProperties}));
}
else if hasAttr "$ref" property.additionalProperties
then {
type = requiredOrNot types.attrs;
}
else if hasAttr "$ref" property.additionalProperties
then {
type = requiredOrNot types.attrs;
}
# if is an array
else if property.additionalProperties.type == "array"
then {
type = requiredOrNot (types.loaOf (mapType property.additionalProperties.items));
}
# if is an array
else if property.additionalProperties.type == "array"
then {
type = requiredOrNot (types.loaOf (mapType property.additionalProperties.items));
}
else {
type = requiredOrNot (types.attrsOf (mapType property.additionalProperties));
}
else {
type = requiredOrNot (types.attrsOf (mapType property.additionalProperties));
}
# just a simple property
else {
type = requiredOrNot (mapType property);
};
in
mkOption ({
description = property.description or "";
} // optionProperties)
)
definition.properties;
config =
let
optionalProps = filterAttrs
(propName: property:
!(elem propName (definition.required or [ ]))
)
definition.properties;
in
mapAttrs (name: property: mkOverride 1002 null) optionalProps;
}
)
swagger.definitions);
# just a simple property
else {
type = requiredOrNot (mapType property);
};
in mkOption ({
description = property.description or "";
} // optionProperties)
) definition.properties;
config =
let
optionalProps = filterAttrs (propName: property:
!(elem propName (definition.required or []))
) definition.properties;
in mapAttrs (name: property: mkOverride 1002 null) optionalProps;
}
) swagger.definitions);
genResources = swagger: (mapAttrsToList (name: property: rec {
splittedType = splitString "." (removePrefix "me.snowdrop.istio.api." property.javaType);
group = (concatStringsSep "." (take ((length splittedType) - 2) splittedType)) + ".istio.io";
kind = removeSuffix "Spec" (last splittedType);
version = last (take ((length splittedType) - 1) splittedType);
ref = removePrefix "#/definitions/" property."$ref";
})
(filterAttrs (name: property:
(hasPrefix "me.snowdrop.istio.api" property.javaType) &&
hasSuffix "Spec" property.javaType
) swagger.properties)) ++ (mapAttrsToList (name: property: rec {
splittedType = splitString "." (removePrefix "me.snowdrop.istio.mixer." property.javaType);
group = "config.istio.io";
version = "v1alpha2";
kind = head (tail splittedType);
ref = removePrefix "#/definitions/" property."$ref";
}) (filterAttrs (name: property:
(hasPrefix "me.snowdrop.istio.mixer" property.javaType) &&
hasSuffix "Spec" property.javaType
) swagger.properties));
genResources = swagger: (mapAttrsToList
(name: property: rec {
splittedType = splitString "." (removePrefix "me.snowdrop.istio.api." property.javaType);
group = (concatStringsSep "." (take ((length splittedType) - 2) splittedType)) + ".istio.io";
kind = removeSuffix "Spec" (last splittedType);
version = last (take ((length splittedType) - 1) splittedType);
ref = removePrefix "#/definitions/" property."$ref";
})
(filterAttrs
(name: property:
(hasPrefix "me.snowdrop.istio.api" property.javaType) &&
hasSuffix "Spec" property.javaType
)
swagger.properties)) ++ (mapAttrsToList
(name: property: rec {
splittedType = splitString "." (removePrefix "me.snowdrop.istio.mixer." property.javaType);
group = "config.istio.io";
version = "v1alpha2";
kind = head (tail splittedType);
ref = removePrefix "#/definitions/" property."$ref";
})
(filterAttrs
(name: property:
(hasPrefix "me.snowdrop.istio.mixer" property.javaType) &&
hasSuffix "Spec" property.javaType
)
swagger.properties));
swagger = fetchSpecs spec;
definitions = genDefinitions swagger;
in pkgs.writeText "gen.nix"
"# This file was generated with kubenix k8s generator, do not edit
{lib, config, ... }:
with lib;
let
types = lib.types // rec {
str = mkOptionType {
name = \"str\";
description = \"string\";
check = isString;
merge = mergeEqualOption;
in
pkgs.writeText "gen.nix" ''
# This file was generated with kubenix k8s generator, do not edit
{lib, config, ... }:
with lib;
let
types = lib.types // rec {
str = mkOptionType {
name = \"str\";
description = \"string\";
check = isString;
merge = mergeEqualOption;
};
# Either value of type `finalType` or `coercedType`, the latter is
# converted to `finalType` using `coerceFunc`.
coercedTo = coercedType: coerceFunc: finalType:
mkOptionType rec {
name = \"coercedTo\";
description = \"\${finalType.description} or \${coercedType.description}\";
check = x: finalType.check x || coercedType.check x;
merge = loc: defs:
let
coerceVal = val:
if finalType.check val then val
else let
coerced = coerceFunc val;
in assert finalType.check coerced; coerced;
in finalType.merge loc (map (def: def // { value = coerceVal def.value; }) defs);
getSubOptions = finalType.getSubOptions;
getSubModules = finalType.getSubModules;
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
typeMerge = t1: t2: null;
functor = (defaultFunctor name) // { wrapped = finalType; };
};
};
# Either value of type `finalType` or `coercedType`, the latter is
# converted to `finalType` using `coerceFunc`.
coercedTo = coercedType: coerceFunc: finalType:
mkOptionType rec {
name = \"coercedTo\";
description = \"\${finalType.description} or \${coercedType.description}\";
check = x: finalType.check x || coercedType.check x;
merge = loc: defs:
let
coerceVal = val:
if finalType.check val then val
else let
coerced = coerceFunc val;
in assert finalType.check coerced; coerced;
in finalType.merge loc (map (def: def // { value = coerceVal def.value; }) defs);
getSubOptions = finalType.getSubOptions;
getSubModules = finalType.getSubModules;
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
typeMerge = t1: t2: null;
functor = (defaultFunctor name) // { wrapped = finalType; };
mkOptionDefault = mkOverride 1001;
extraOptions = {
kubenix = {};
};
};
mkOptionDefault = mkOverride 1001;
extraOptions = {
kubenix = {};
};
mergeValuesByKey = mergeKey: values:
listToAttrs (map
(value: nameValuePair (
if isAttrs value.\${mergeKey}
then toString value.\${mergeKey}.content
else (toString value.\${mergeKey})
) value)
values);
submoduleOf = ref: types.submodule ({name, ...}: {
options = definitions.\"\${ref}\".options;
config = definitions.\"\${ref}\".config;
});
submoduleWithMergeOf = ref: mergeKey: types.submodule ({name, ...}: let
convertName = name:
if definitions.\"\${ref}\".options.\${mergeKey}.type == types.int
then toInt name
else name;
in {
options = definitions.\"\${ref}\".options;
config = definitions.\"\${ref}\".config // {
\${mergeKey} = mkOverride 1002 (convertName name);
};
});
submoduleForDefinition = ref: resource: kind: group: version:
types.submodule ({name, ...}: {
options = definitions.\"\${ref}\".options // extraOptions;
config = mkMerge ([
definitions.\"\${ref}\".config
{
kind = mkOptionDefault kind;
apiVersion = mkOptionDefault version;
# metdata.name cannot use option default, due deep config
metadata.name = mkOptionDefault name;
}
] ++ (config.defaults.\${resource} or [])
++ (config.defaults.all or []));
mergeValuesByKey = mergeKey: values:
listToAttrs (map
(value: nameValuePair (
if isAttrs value.\${mergeKey}
then toString value.\${mergeKey}.content
else (toString value.\${mergeKey})
) value)
values);
submoduleOf = ref: types.submodule ({name, ...}: {
options = definitions.\"\${ref}\".options;
config = definitions.\"\${ref}\".config;
});
coerceAttrsOfSubmodulesToListByKey = ref: mergeKey: (types.coercedTo
(types.listOf (submoduleOf ref))
(mergeValuesByKey mergeKey)
(types.attrsOf (submoduleWithMergeOf ref mergeKey))
);
definitions = {
${concatStrings (mapAttrsToList (name: value: "
\"${name}\" = {${optionalString (hasAttr "options" value) "
options = {${concatStrings (mapAttrsToList (name: value: "
\"${name}\" = ${value};
") value.options)}};
"}${optionalString (hasAttr "config" value) "
config = {${concatStrings (mapAttrsToList (name: value: "
\"${name}\" = ${value};
") value.config)}};
"}};
") definitions)}
} // (import ./overrides.nix {inheirt definitions lib;}));
in {
kubernetes.customResources = [
${concatMapStrings (resource: ''{
group = "${resource.group}";
version = "${resource.version}";
kind = "${resource.kind}";
description = "";
module = definitions."${resource.ref}";
}'') (genResources swagger)}
];
}
"
submoduleWithMergeOf = ref: mergeKey: types.submodule ({name, ...}: let
convertName = name:
if definitions.\"\${ref}\".options.\${mergeKey}.type == types.int
then toInt name
else name;
in {
options = definitions.\"\${ref}\".options;
config = definitions.\"\${ref}\".config // {
\${mergeKey} = mkOverride 1002 (convertName name);
};
});
submoduleForDefinition = ref: resource: kind: group: version:
types.submodule ({name, ...}: {
options = definitions.\"\${ref}\".options // extraOptions;
config = mkMerge ([
definitions.\"\${ref}\".config
{
kind = mkOptionDefault kind;
apiVersion = mkOptionDefault version;
# metdata.name cannot use option default, due deep config
metadata.name = mkOptionDefault name;
}
] ++ (config.defaults.\${resource} or [])
++ (config.defaults.all or []));
});
coerceAttrsOfSubmodulesToListByKey = ref: mergeKey: (types.coercedTo
(types.listOf (submoduleOf ref))
(mergeValuesByKey mergeKey)
(types.attrsOf (submoduleWithMergeOf ref mergeKey))
);
definitions = {
${concatStrings (mapAttrsToList
(name: value: "
\"${name}\" = {${optionalString (hasAttr "options" value) "
options = {${concatStrings (mapAttrsToList
(name: value: "
\"${name}\" = ${value};
")
value.options)}};
"}${optionalString (hasAttr "config" value) "
config = {${concatStrings (mapAttrsToList
(name: value: "
\"${name}\" = ${value};
")
value.config)}};
"}};
")
definitions)}
} // (import ./overrides.nix {inheirt definitions lib;}));
in {
kubernetes.customResources = [
${concatMapStrings
(resource: ''{
group = "${resource.group}";
version = "${resource.version}";
kind = "${resource.kind}";
description = "";
module = definitions."${resource.ref}";
}'')
(genResources swagger)}
];
}
''

View file

@ -1,18 +1,21 @@
{ name ? "k8s"
, pkgs ? import <nixpkgs> {}
, pkgs ? import <nixpkgs> { }
, lib ? pkgs.lib
, spec ? ./specs/1.21/swagger.json
, ... }:
, ...
}:
with lib;
let
gen = rec {
mkMerge = values: ''mkMerge [${concatMapStrings (value: "
mkMerge = values: ''mkMerge [${concatMapStrings
(value: "
${value}
") values}]'';
")
values}]'';
toNixString = value: if isAttrs value || isList value
toNixString = value:
if isAttrs value || isList value
then builtins.toJSON value
else if isString value
then ''"${value}"''
@ -22,19 +25,19 @@ let
removeEmptyLines = str: concatStringsSep "\n" (filter (l: (builtins.match "( |)+" l) == null) (splitString "\n" str));
mkOption = {
description ? null,
type ? null,
default ? null,
apply ? null
}: removeEmptyLines ''mkOption {
mkOption =
{ description ? null
, type ? null
, default ? null
, apply ? null
}: removeEmptyLines ''mkOption {
${optionalString (description != null) "description = ${builtins.toJSON description};"}
${optionalString (type != null) ''type = ${type};''}
${optionalString (default != null) ''default = ${toNixString default};''}
${optionalString (apply != null) ''apply = ${apply};''}
}'';
mkOverride = priority: value: "mkOverride ${toString priority} ${toNixString value}";
mkOverride = priority: value: "mkOverride ${toString priority} ${toNixString value}";
types = {
unspecified = "types.unspecified";
@ -53,7 +56,7 @@ let
hasTypeMapping = def:
hasAttr "type" def &&
elem def.type ["string" "integer" "boolean"];
elem def.type [ "string" "integer" "boolean" ];
mergeValuesByKey = mergeKey: ''(mergeValuesByKey "${mergeKey}")'';
@ -83,185 +86,220 @@ let
refType = attr: head (tail (tail (splitString "/" attr."$ref")));
compareVersions = ver1: ver2: let
getVersion = v: substring 1 10 v;
splitVersion = v: builtins.splitVersion (getVersion v);
isAlpha = v: elem "alpha" (splitVersion v);
patchVersion = v:
if isAlpha v then ""
else if length (splitVersion v) == 1 then "${getVersion v}prod"
else getVersion v;
compareVersions = ver1: ver2:
let
getVersion = v: substring 1 10 v;
splitVersion = v: builtins.splitVersion (getVersion v);
isAlpha = v: elem "alpha" (splitVersion v);
patchVersion = v:
if isAlpha v then ""
else if length (splitVersion v) == 1 then "${getVersion v}prod"
else getVersion v;
v1 = patchVersion ver1;
v2 = patchVersion ver2;
in builtins.compareVersions v1 v2;
v1 = patchVersion ver1;
v2 = patchVersion ver2;
in
builtins.compareVersions v1 v2;
fixJSON = content: replaceStrings ["\\u"] ["u"] content;
fixJSON = content: replaceStrings [ "\\u" ] [ "u" ] content;
fetchSpecs = path: builtins.fromJSON (fixJSON (builtins.readFile path));
genDefinitions = swagger: with gen; mapAttrs (name: definition:
# if $ref is in definition it means it's an alias of other definition
if hasAttr "$ref" definition
then definitions."${refDefinition definition}"
genDefinitions = swagger: with gen; mapAttrs
(name: definition:
# if $ref is in definition it means it's an alias of other definition
if hasAttr "$ref" definition
then definitions."${refDefinition definition}"
else if !(hasAttr "properties" definition)
then {}
else if !(hasAttr "properties" definition)
then { }
# in other case it's an actual definition
else {
options = mapAttrs (propName: property:
let
isRequired = elem propName (definition.required or []);
requiredOrNot = type: if isRequired then type else types.nullOr type;
optionProperties =
# in other case it's an actual definition
else {
options = mapAttrs
(propName: property:
let
isRequired = elem propName (definition.required or [ ]);
requiredOrNot = type: if isRequired then type else types.nullOr type;
optionProperties =
# if $ref is in property it references other definition,
# but if other definition does not have properties, then just take it's type
if hasAttr "$ref" property then
if hasTypeMapping swagger.definitions.${refDefinition property} then {
type = requiredOrNot (mapType swagger.definitions.${refDefinition property});
}
else {
type = requiredOrNot (submoduleOf definitions (refDefinition property));
}
# if property has an array type
else if property.type == "array" then
# if reference is in items it can reference other type of another
# definition
if hasAttr "$ref" property.items then
# if it is a reference to simple type
if hasTypeMapping swagger.definitions.${refDefinition property.items}
then {
type = requiredOrNot (types.listOf (mapType swagger.definitions.${refDefinition property.items}.type));
}
# if a reference is to complex type
else
# if x-kubernetes-patch-merge-key is set then make it an
# attribute set of submodules
if hasAttr "x-kubernetes-patch-merge-key" property
then let
mergeKey = property."x-kubernetes-patch-merge-key";
in {
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey);
apply = attrsToList;
# if $ref is in property it references other definition,
# but if other definition does not have properties, then just take it's type
if hasAttr "$ref" property then
if hasTypeMapping swagger.definitions.${refDefinition property} then {
type = requiredOrNot (mapType swagger.definitions.${refDefinition property});
}
# in other case it's a simple list
else {
type = requiredOrNot (types.listOf (submoduleOf definitions (refDefinition property.items)));
type = requiredOrNot (submoduleOf definitions (refDefinition property));
}
# in other case it only references a simple type
else {
type = requiredOrNot (types.listOf (mapType property.items));
}
# if property has an array type
else if property.type == "array" then
else if property.type == "object" && hasAttr "additionalProperties" property
then
# if it is a reference to simple type
if (
hasAttr "$ref" property.additionalProperties &&
hasTypeMapping swagger.definitions.${refDefinition property.additionalProperties}
) then {
type = requiredOrNot (types.attrsOf (mapType swagger.definitions.${refDefinition property.additionalProperties}));
}
# if reference is in items it can reference other type of another
# definition
if hasAttr "$ref" property.items then
else if hasAttr "$ref" property.additionalProperties
then {
type = requiredOrNot types.attrs;
}
# if it is a reference to simple type
if hasTypeMapping swagger.definitions.${refDefinition property.items}
then {
type = requiredOrNot (types.listOf (mapType swagger.definitions.${refDefinition property.items}.type));
}
# if is an array
else if property.additionalProperties.type == "array"
then {
type = requiredOrNot (types.loaOf (mapType property.additionalProperties.items));
}
# if a reference is to complex type
else
# if x-kubernetes-patch-merge-key is set then make it an
# attribute set of submodules
if hasAttr "x-kubernetes-patch-merge-key" property
then
let
mergeKey = property."x-kubernetes-patch-merge-key";
in
{
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey);
apply = attrsToList;
}
else {
type = requiredOrNot (types.attrsOf (mapType property.additionalProperties));
}
# in other case it's a simple list
else {
type = requiredOrNot (types.listOf (submoduleOf definitions (refDefinition property.items)));
}
# just a simple property
else {
type = requiredOrNot (mapType property);
};
in mkOption ({
description = property.description or "";
} // optionProperties)
) definition.properties;
config =
let
optionalProps = filterAttrs (propName: property:
!(elem propName (definition.required or []))
) definition.properties;
in mapAttrs (name: property: mkOverride 1002 null) optionalProps;
}
) swagger.definitions;
# in other case it only references a simple type
else {
type = requiredOrNot (types.listOf (mapType property.items));
}
mapCharPairs = f: s1: s2: concatStrings (imap0 (i: c1:
f i c1 (if i >= stringLength s2 then "" else elemAt (stringToCharacters s2) i)
) (stringToCharacters s1));
else if property.type == "object" && hasAttr "additionalProperties" property
then
# if it is a reference to simple type
if (
hasAttr "$ref" property.additionalProperties &&
hasTypeMapping swagger.definitions.${refDefinition property.additionalProperties}
) then {
type = requiredOrNot (types.attrsOf (mapType swagger.definitions.${refDefinition property.additionalProperties}));
}
else if hasAttr "$ref" property.additionalProperties
then {
type = requiredOrNot types.attrs;
}
# if is an array
else if property.additionalProperties.type == "array"
then {
type = requiredOrNot (types.loaOf (mapType property.additionalProperties.items));
}
else {
type = requiredOrNot (types.attrsOf (mapType property.additionalProperties));
}
# just a simple property
else {
type = requiredOrNot (mapType property);
};
in
mkOption ({
description = property.description or "";
} // optionProperties)
)
definition.properties;
config =
let
optionalProps = filterAttrs
(propName: property:
!(elem propName (definition.required or [ ]))
)
definition.properties;
in
mapAttrs (name: property: mkOverride 1002 null) optionalProps;
}
)
swagger.definitions;
mapCharPairs = f: s1: s2: concatStrings (imap0
(i: c1:
f i c1 (if i >= stringLength s2 then "" else elemAt (stringToCharacters s2) i)
)
(stringToCharacters s1));
getAttrName = resource: kind:
mapCharPairs (i: c1: c2:
if hasPrefix "API" kind && i == 0 then "A"
else if i == 0 then c1
else if c2 == "" || (toLower c2) != c1 then c1
else c2
) resource kind;
mapCharPairs
(i: c1: c2:
if hasPrefix "API" kind && i == 0 then "A"
else if i == 0 then c1
else if c2 == "" || (toLower c2) != c1 then c1
else c2
)
resource
kind;
genResourceTypes = swagger: mapAttrs' (name: path: let
ref = refType (head path.post.parameters).schema;
group' = path.post."x-kubernetes-group-version-kind".group;
version' = path.post."x-kubernetes-group-version-kind".version;
kind' = path.post."x-kubernetes-group-version-kind".kind;
name' = last (splitString "/" name);
attrName = getAttrName name' kind';
in nameValuePair ref {
inherit ref attrName;
genResourceTypes = swagger: mapAttrs'
(name: path:
let
ref = refType (head path.post.parameters).schema;
group' = path.post."x-kubernetes-group-version-kind".group;
version' = path.post."x-kubernetes-group-version-kind".version;
kind' = path.post."x-kubernetes-group-version-kind".kind;
name' = last (splitString "/" name);
attrName = getAttrName name' kind';
in
nameValuePair ref {
inherit ref attrName;
name = name';
group = if group' == "" then "core" else group';
version = version';
kind = kind';
description = swagger.definitions.${ref}.description;
defintion = refDefinition (head path.post.parameters).schema;
})
(filterAttrs (name: path:
hasAttr "post" path &&
path.post."x-kubernetes-action" == "post"
) swagger.paths);
name = name';
group = if group' == "" then "core" else group';
version = version';
kind = kind';
description = swagger.definitions.${ref}.description;
defintion = refDefinition (head path.post.parameters).schema;
})
(filterAttrs
(name: path:
hasAttr "post" path &&
path.post."x-kubernetes-action" == "post"
)
swagger.paths);
swagger = fetchSpecs spec;
definitions = genDefinitions swagger;
resourceTypes = genResourceTypes swagger;
resourceTypesByKind = zipAttrs (mapAttrsToList (name: resourceType: {
${resourceType.kind} = resourceType;
}) resourceTypes);
resourceTypesByKind = zipAttrs (mapAttrsToList
(name: resourceType: {
${resourceType.kind} = resourceType;
})
resourceTypes);
resourcesTypesByKindSortByVersion = mapAttrs (kind: resourceTypes:
reverseList (sort (r1: r2:
compareVersions r1.version r2.version > 0
) resourceTypes)
) resourceTypesByKind;
resourcesTypesByKindSortByVersion = mapAttrs
(kind: resourceTypes:
reverseList (sort
(r1: r2:
compareVersions r1.version r2.version > 0
)
resourceTypes)
)
resourceTypesByKind;
latestResourceTypesByKind =
mapAttrs (kind: resources: last resources) resourcesTypesByKindSortByVersion;
genResourceOptions = resource: with gen; let
submoduleForDefinition' = definition: let
in submoduleForDefinition
definition.ref definition.name definition.kind definition.group definition.version;
in mkOption {
submoduleForDefinition' = definition:
let
in
submoduleForDefinition
definition.ref
definition.name
definition.kind
definition.group
definition.version;
in
mkOption {
description = resource.description;
type = types.attrsOf (submoduleForDefinition' resource);
default = {};
default = { };
};
generated = ''
@ -415,7 +453,9 @@ let
};
}
'';
in pkgs.runCommand "k8s-${name}-gen.nix" {
in
pkgs.runCommand "k8s-${name}-gen.nix"
{
buildInputs = [ pkgs.haskellPackages.nixfmt ];
} ''
cp ${builtins.toFile "k8s-${name}-gen-raw.nix" generated} $out