feat(k8s): improvements

- format k8s generated files with nixfmt
- improve k8s module true and mount resources at `kubernetes.api.resources`
- create alias `kubernetes.resources` to `kubernetes.api.resources`
- rename from `kubernetes.api.resources` to `kubernetes.api.types`
- rename from `kubernetes.customResources` to `kubernetes.customTypes`
This commit is contained in:
Jaka Hudoklin 2019-09-25 00:58:39 +02:00
parent 42b7d5f551
commit 3d149d6101
No known key found for this signature in database
GPG key ID: D1F18234B07BD6E2
11 changed files with 116285 additions and 122144 deletions

View file

@ -1,4 +1,5 @@
{ pkgs ? import <nixpkgs> {} { name ? "k8s"
, pkgs ? import <nixpkgs> {}
, lib ? pkgs.lib , lib ? pkgs.lib
, spec ? ./specs/1.10/swagger.json , spec ? ./specs/1.10/swagger.json
, ... }: , ... }:
@ -198,18 +199,18 @@ let
} }
) swagger.definitions; ) swagger.definitions;
genResources = swagger: mapAttrs' (name: path: let genResourceTypes = swagger: mapAttrs' (name: path: let
ref = refType (head path.post.parameters).schema; ref = refType (head path.post.parameters).schema;
group' = path.post."x-kubernetes-group-version-kind".group; group' = path.post."x-kubernetes-group-version-kind".group;
version' = path.post."x-kubernetes-group-version-kind".version; version' = path.post."x-kubernetes-group-version-kind".version;
in nameValuePair ref { in nameValuePair ref {
inherit ref; inherit ref;
kind = path.post."x-kubernetes-group-version-kind".kind; name = last (splitString "/" name);
version = version';
resource = last (splitString "/" name);
description = swagger.definitions.${ref}.description;
group = if group' == "" then "core" else group'; group = if group' == "" then "core" else group';
version = version';
kind = path.post."x-kubernetes-group-version-kind".kind;
description = swagger.definitions.${ref}.description;
defintion = refDefinition (head path.post.parameters).schema; defintion = refDefinition (head path.post.parameters).schema;
}) })
(filterAttrs (name: path: (filterAttrs (name: path:
@ -219,157 +220,184 @@ let
swagger = fetchSpecs spec; swagger = fetchSpecs spec;
definitions = genDefinitions swagger; definitions = genDefinitions swagger;
resources = genResources swagger; resourceTypes = genResourceTypes swagger;
resourcesByKind = zipAttrs (mapAttrsToList (name: resource: { resourceTypesByKind = zipAttrs (mapAttrsToList (name: resourceType: {
${resource.kind} = resource; ${resourceType.kind} = resourceType;
}) resources); }) resourceTypes);
resourcesByKindOrderedByVersion = mapAttrs (kind: resources: resourcesTypesByKindSortByVersion = mapAttrs (kind: resourceTypes:
reverseList (sort (r1: r2: reverseList (sort (r1: r2:
compareVersions r1.version r2.version > 0 compareVersions r1.version r2.version > 0
) resources) ) resourceTypes)
) resourcesByKind; ) resourceTypesByKind;
latestResourcesByKind = latestResourceTypesByKind =
mapAttrs (kind: resources: last resources) resourcesByKindOrderedByVersion; mapAttrs (kind: resources: last resources) resourcesTypesByKindSortByVersion;
genResourceOptions = resource: with gen; let genResourceOptions = resource: with gen; let
submoduleForDefinition' = definition: let submoduleForDefinition' = definition: let
in submoduleForDefinition in submoduleForDefinition
definition.ref definition.resource definition.kind definition.group definition.version; definition.ref definition.name definition.kind definition.group definition.version;
in mkOption { in mkOption {
description = resource.description; description = resource.description;
type = types.attrsOf (submoduleForDefinition' resource); type = types.attrsOf (submoduleForDefinition' resource);
default = {}; default = {};
}; };
in pkgs.writeText "gen.nix"
"# This file was generated with kubenix k8s generator, do not edit
{lib, config, ... }:
with lib; generated = ''
# This file was generated with kubenix k8s generator, do not edit
{ lib, options, config, ... }:
let with lib;
getDefaults = resource: group: version: kind:
catAttrs \"default\" (filter (default:
(default.resource == null || default.resource == resource) &&
(default.group == null || default.group == group) &&
(default.version == null || default.version == version) &&
(default.kind == null || default.kind == kind)
) config.defaults);
types = lib.types // rec { let
str = mkOptionType { getDefaults = resource: group: version: kind:
name = \"str\"; catAttrs "default" (filter (default:
description = \"string\"; (default.resource == null || default.resource == resource) &&
check = isString; (default.group == null || default.group == group) &&
merge = mergeEqualOption; (default.version == null || default.version == version) &&
}; (default.kind == null || default.kind == kind)
) config.defaults);
# Either value of type `finalType` or `coercedType`, the latter is types = lib.types // rec {
# converted to `finalType` using `coerceFunc`. str = mkOptionType {
coercedTo = coercedType: coerceFunc: finalType: name = "str";
mkOptionType rec { description = "string";
name = \"coercedTo\"; check = isString;
description = \"\${finalType.description} or \${coercedType.description}\"; merge = mergeEqualOption;
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); # Either value of type `finalType` or `coercedType`, the latter is
getSubOptions = finalType.getSubOptions; # converted to `finalType` using `coerceFunc`.
getSubModules = finalType.getSubModules; coercedTo = coercedType: coerceFunc: finalType:
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m); mkOptionType rec {
typeMerge = t1: t2: null; name = "coercedTo";
functor = (defaultFunctor name) // { wrapped = finalType; }; 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;
mkOptionDefault = mkOverride 1001; 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; };
};
};
mergeValuesByKey = mergeKey: values: mkOptionDefault = mkOverride 1001;
listToAttrs (map
(value: nameValuePair (
if isAttrs value.\${mergeKey}
then toString value.\${mergeKey}.content
else (toString value.\${mergeKey})
) value)
values);
submoduleOf = ref: types.submodule ({name, ...}: { mergeValuesByKey = mergeKey: values:
options = definitions.\"\${ref}\".options or {}; listToAttrs (map
config = definitions.\"\${ref}\".config or {}; (value: nameValuePair (
}); if isAttrs value.''${mergeKey}
then toString value.''${mergeKey}.content
else (toString value.''${mergeKey})
) value)
values);
submoduleWithMergeOf = ref: mergeKey: types.submodule ({name, ...}: let submoduleOf = ref: types.submodule ({name, ...}: {
convertName = name: options = definitions."''${ref}".options or {};
if definitions.\"\${ref}\".options.\${mergeKey}.type == types.int config = definitions."''${ref}".config or {};
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: let submoduleWithMergeOf = ref: mergeKey: types.submodule ({name, ...}: let
apiVersion = if group == \"core\" then version else \"\${group}/\${version}\"; convertName = name:
in types.submodule ({name, ...}: { if definitions."''${ref}".options.''${mergeKey}.type == types.int
imports = getDefaults resource group version kind; then toInt name
options = definitions.\"\${ref}\".options; else name;
config = mkMerge [ in {
definitions.\"\${ref}\".config options = definitions."''${ref}".options;
{ config = definitions."''${ref}".config // {
kind = mkOptionDefault kind; ''${mergeKey} = mkOverride 1002 (convertName name);
apiVersion = mkOptionDefault apiVersion; };
});
# metdata.name cannot use option default, due deep config submoduleForDefinition = ref: resource: kind: group: version: let
metadata.name = mkOptionDefault name; apiVersion = if group == "core" then version else "''${group}/''${version}";
} in types.submodule ({name, ...}: {
]; imports = getDefaults resource group version kind;
}); options = definitions."''${ref}".options;
config = mkMerge [
definitions."''${ref}".config
{
kind = mkOptionDefault kind;
apiVersion = mkOptionDefault apiVersion;
coerceAttrsOfSubmodulesToListByKey = ref: mergeKey: (types.coercedTo # metdata.name cannot use option default, due deep config
(types.listOf (submoduleOf ref)) metadata.name = mkOptionDefault name;
(mergeValuesByKey mergeKey) }
(types.attrsOf (submoduleWithMergeOf ref mergeKey)) ];
); });
definitions = { coerceAttrsOfSubmodulesToListByKey = ref: mergeKey: (types.coercedTo
${concatStrings (mapAttrsToList (name: value: " (types.listOf (submoduleOf ref))
\"${name}\" = {${optionalString (hasAttr "options" value) " (mergeValuesByKey mergeKey)
options = {${concatStrings (mapAttrsToList (name: value: " (types.attrsOf (submoduleWithMergeOf ref mergeKey))
\"${name}\" = ${value}; );
") value.options)}};
"}${optionalString (hasAttr "config" value) "
config = {${concatStrings (mapAttrsToList (name: value: "
\"${name}\" = ${value};
") value.config)}};
"}};
") definitions)}
};
in {
options = {${concatStrings (mapAttrsToList (name: resource: "
\"${resource.group}\".\"${resource.version}\".\"${resource.kind}\" = ${genResourceOptions resource};
") resources)}} // {${concatStrings (mapAttrsToList (name: resource: "
\"${resource.resource}\" = ${genResourceOptions resource};
") latestResourcesByKind)}};
config = { definitions = {
inherit definitions; ${concatStrings (mapAttrsToList (name: value: ''
"${name}" = {
${optionalString (hasAttr "options" value) "
options = {${concatStrings (mapAttrsToList (name: value: ''
"${name}" = ${value};
'') value.options)}};
"}
resources = [${concatStrings (mapAttrsToList (name: resource: "{ ${optionalString (hasAttr "config" value) ''
group = \"${resource.group}\"; config = {${concatStrings (mapAttrsToList (name: value: ''
version = \"${resource.version}\"; "${name}" = ${value};
kind = \"${resource.kind}\"; '') value.config)}};
resource = \"${resource.resource}\"; ''}
}") resources)}]; };
}; '') definitions)}
} };
" in {
# all resource versions
options = {
resources = {
${concatStrings (mapAttrsToList (_: rt: ''
"${rt.group}"."${rt.version}"."${rt.kind}" = ${genResourceOptions rt};
'') resourceTypes)}
} // {
${concatStrings (mapAttrsToList (_: rt: ''
"${rt.name}" = ${genResourceOptions rt};
'') latestResourceTypesByKind)}
};
};
config = {
# expose resource definitions
inherit definitions;
# register resource types
types = [${concatStrings (mapAttrsToList (_: rt: ''{
name = "${rt.name}";
group = "${rt.group}";
version = "${rt.version}";
kind = "${rt.kind}";
}'') resourceTypes)}];
resources = {
${concatStrings (mapAttrsToList (_: rt: ''
"${rt.name}" =
mkAliasDefinitions options.resources."${rt.group}"."${rt.version}"."${rt.kind}";
'') latestResourceTypesByKind)}
};
};
}
'';
in pkgs.runCommand "k8s-${name}-gen.nix" {
buildInputs = [ pkgs.haskellPackages.nixfmt ];
} ''
cp ${builtins.toFile "k8s-${name}-gen-raw.nix" generated} $out
nixfmt -w 100 $out
''

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
# K8S module defines kubernetes definitions for kubenix # K8S module defines kubernetes definitions for kubenix
{ config, lib, pkgs, k8s, ... }: { options, config, lib, pkgs, k8s, ... }:
with lib; with lib;
@ -24,14 +24,6 @@ let
else value; else value;
flattenResources = resources: flatten (
mapAttrsToList (groupName: versions:
mapAttrsToList (versionName: kinds:
builtins.trace versionName kinds
) versions
) resources
);
apiOptions = { config, ... }: { apiOptions = { config, ... }: {
options = { options = {
definitions = mkOption { definitions = mkOption {
@ -82,91 +74,119 @@ let
default = []; default = [];
}; };
resources = mkOption { types = mkOption {
description = "List of registered kubernetes types";
type = types.listOf (types.submodule { type = types.listOf (types.submodule {
options = { options = {
name = mkOption {
description = "Resource type name";
type = types.nullOr types.str;
};
group = mkOption { group = mkOption {
description = "Resoruce group"; description = "Resource type group";
type = types.str; type = types.str;
}; };
version = mkOption { version = mkOption {
description = "Resoruce version"; description = "Resoruce type version";
type = types.str; type = types.str;
}; };
kind = mkOption { kind = mkOption {
description = "Resource kind"; description = "Resource type kind";
type = types.str; type = types.str;
}; };
resource = mkOption {
description = "Resource name";
type = types.nullOr types.str;
};
}; };
}); });
default = []; default = [];
}; };
}; };
config = {
# apply aliased option
resources = mkAliasDefinitions options.kubernetes.resources;
};
}; };
indexOf = lst: value: indexOf = lst: value:
head (filter (v: v != -1) (imap0 (i: v: if v == value then i else -1) lst)); head (filter (v: v != -1) (imap0 (i: v: if v == value then i else -1) lst));
customResourceOptions = map (cr: {config, ...}: let compareVersions = ver1: ver2: let
module = { name, ... }: { getVersion = v: substring 1 10 v;
imports = getDefaults cr.resource cr.group cr.version cr.kind; splittedVer1 = builtins.splitVersion (getVersion ver1);
options = { splittedVer2 = builtins.splitVersion (getVersion ver2);
apiVersion = mkOption {
description = "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources";
type = types.nullOr types.str;
};
kind = mkOption { v1 = if length splittedVer1 == 1 then "${getVersion ver1}prod" else getVersion ver1;
description = "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds"; v2 = if length splittedVer2 == 1 then "${getVersion ver2}prod" else getVersion ver2;
type = types.nullOr types.str; in builtins.compareVersions v1 v2;
};
metadata = mkOption { customResourceTypesByKind = zipAttrs (map (resourceType: {
description = "Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata."; ${resourceType.kind} = resourceType;
type = types.nullOr (types.submodule config.definitions."io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"); }) cfg.customTypes);
};
spec = mkOption { customResourceTypesByKindSortByVersion = mapAttrs (_: resourceTypes:
description = "Module spec"; reverseList (sort (r1: r2:
type = types.either types.attrs (types.submodule cr.module); compareVersions r1.version r2.version > 0
default = {}; ) resourceTypes)
}; ) customResourceTypesByKind;
latestCustomResourceTypes =
mapAttrsToList (_: resources: last resources) customResourceTypesByKindSortByVersion;
customResourceModuleForType = config: ct: { name, ... }: {
imports = getDefaults ct.name ct.group ct.version ct.kind;
options = {
apiVersion = mkOption {
description = "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources";
type = types.nullOr types.str;
}; };
config = { kind = mkOption {
apiVersion = mkOptionDefault "${cr.group}/${cr.version}"; description = "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds";
kind = mkOptionDefault cr.kind; type = types.nullOr types.str;
metadata.name = mkOptionDefault name; };
metadata = mkOption {
description = "Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata.";
type = types.nullOr (types.submodule config.definitions."io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta");
};
spec = mkOption {
description = "Module spec";
type = types.either types.attrs (types.submodule ct.module);
default = {};
}; };
}; };
in if cr.resource != null then {
options.${cr.group}.${cr.version}.${cr.kind} = mkOption { config = {
description = cr.description; apiVersion = mkOptionDefault "${ct.group}/${ct.version}";
kind = mkOptionDefault ct.kind;
metadata.name = mkOptionDefault name;
};
};
customResourceOptions = (map (ct: {config, ...}: let
module = customResourceModuleForType config ct;
in {
options.resources.${ct.group}.${ct.version}.${ct.kind} = mkOption {
description = ct.description;
type = types.attrsOf (types.submodule module);
default = {};
};
}) cfg.customTypes) ++ (map (ct: { options, config, ... }: let
module = customResourceModuleForType config ct;
in {
options.resources.${ct.name} = mkOption {
description = ct.description;
type = types.attrsOf (types.submodule module); type = types.attrsOf (types.submodule module);
default = {}; default = {};
}; };
options.${cr.resource} = mkOption { config.resources.${ct.group}.${ct.version}.${ct.kind} =
description = cr.description; mkAliasDefinitions options.resources.${ct.name};
type = types.attrsOf (types.submodule module); }) latestCustomResourceTypes);
default = {};
};
config.${cr.group}.${cr.version}.${cr.kind} = config.${cr.resource};
} else {
options.${cr.group}.${cr.version}.${cr.kind} = mkOption {
description = cr.description;
type = types.attrsOf (types.submodule module);
default = {};
};
}) cfg.customResources;
in { in {
imports = [ ./base.nix ./submodules.nix ]; imports = [ ./base.nix ./submodules.nix ];
@ -208,9 +228,13 @@ in {
default = []; default = [];
}; };
customResources = mkOption { resources = mkOption {
description = "Alias for `config.kubernetes.api.resources` options";
};
customTypes = mkOption {
default = []; default = [];
description = "List of custom resource definitions to make API for"; description = "List of custom resource types to make API for";
type = types.listOf (types.submodule ({config, ...}: { type = types.listOf (types.submodule ({config, ...}: {
options = { options = {
group = mkOption { group = mkOption {
@ -228,7 +252,7 @@ in {
type = types.str; type = types.str;
}; };
resource = mkOption { name = mkOption {
description = "Custom resource definition resource name"; description = "Custom resource definition resource name";
type = types.nullOr types.str; type = types.nullOr types.str;
default = null; default = null;
@ -245,12 +269,6 @@ in {
type = types.unspecified; type = types.unspecified;
default = {}; default = {};
}; };
alias = mkOption {
description = "Alias to create for API";
type = types.nullOr types.str;
default = null;
};
}; };
})); }));
}; };
@ -279,9 +297,10 @@ in {
_module.features = [ "k8s" ]; _module.features = [ "k8s" ];
kubernetes.api = mkMerge ([{ kubernetes.api = mkMerge ([{
resources = map (cr: { # register custom types
inherit (cr) group version kind resource; types = map (cr: {
}) cfg.customResources; inherit (cr) name group version kind;
}) cfg.customTypes;
defaults = [{ defaults = [{
default = { default = {
@ -316,20 +335,18 @@ in {
}) cfg.imports)); }) cfg.imports));
kubernetes.objects = mkMerge [ kubernetes.objects = mkMerge [
# gvk resources # versioned resources
(flatten (map (gvk: (flatten (map (type:
mapAttrsToList (name: resource: mapAttrsToList (name: resource: moduleToAttrs resource)
moduleToAttrs resource cfg.api.resources.${type.group}.${type.version}.${type.kind}
) cfg.api.${gvk.group}.${gvk.version}.${gvk.kind} ) cfg.api.types))
) cfg.api.resources))
# aliased gvk resources # latest resources
(flatten (map (gvk: (flatten (map (type:
if gvk.resource == null then [] if type.name == null then []
else mapAttrsToList (name: resource: else mapAttrsToList (name: resource: moduleToAttrs resource)
moduleToAttrs resource cfg.api.resources.${type.name}
) cfg.api.${gvk.resource} ) cfg.api.types))
) cfg.api.resources))
# passthru of child kubernetes objects if passthru is enabled on submodule # passthru of child kubernetes objects if passthru is enabled on submodule
# and submodule has k8s module loaded # and submodule has k8s module loaded

View file

@ -8,7 +8,8 @@ let
lib = kubenix.lib; lib = kubenix.lib;
generateK8S = spec: import ./generators/k8s { generateK8S = name: spec: import ./generators/k8s {
inherit name;
inherit pkgs; inherit pkgs;
inherit (pkgs) lib; inherit (pkgs) lib;
inherit spec; inherit spec;
@ -23,63 +24,77 @@ let
inherit pkgs lib kubenix k8sVersion e2e throwError nixosPath; inherit pkgs lib kubenix k8sVersion e2e throwError nixosPath;
}; };
in rec { in rec {
generate.k8s = pkgs.linkFarm "k8s-generated.nix" [{ generate.k8s = pkgs.linkFarm "k8s-generated.nix" [
name = "v1.7.nix"; {
path = generateK8S "${pkgs.fetchFromGitHub { name = "v1.7.nix";
owner = "kubernetes"; path = generateK8S "v1.7" "${pkgs.fetchFromGitHub {
repo = "kubernetes"; owner = "kubernetes";
rev = "v1.7.16"; repo = "kubernetes";
sha256 = "1ksalw3hzbcca89n9h3pas9nqj2n5gq3rbpdx633ycqb8g46h1iw"; rev = "v1.7.16";
}}/api/openapi-spec/swagger.json"; sha256 = "1ksalw3hzbcca89n9h3pas9nqj2n5gq3rbpdx633ycqb8g46h1iw";
} { }}/api/openapi-spec/swagger.json";
name = "v1.8.nix"; }
path = generateK8S "${pkgs.fetchFromGitHub {
owner = "kubernetes"; {
repo = "kubernetes"; name = "v1.8.nix";
rev = "v1.8.15"; path = generateK8S "v1.8" "${pkgs.fetchFromGitHub {
sha256 = "1mwaafnkimr4kwqws4qli11wbavpmf27i6pjq77sfsapw9sz54j4"; owner = "kubernetes";
}}/api/openapi-spec/swagger.json"; repo = "kubernetes";
} { rev = "v1.8.15";
name = "v1.9.nix"; sha256 = "1mwaafnkimr4kwqws4qli11wbavpmf27i6pjq77sfsapw9sz54j4";
path = generateK8S "${pkgs.fetchFromGitHub { }}/api/openapi-spec/swagger.json";
owner = "kubernetes"; }
repo = "kubernetes";
rev = "v1.9.11"; {
sha256 = "1wl944ci7k8knrkdrc328agyq4c953j9dm0sn314s42j18lfd7rv"; name = "v1.9.nix";
}}/api/openapi-spec/swagger.json"; path = generateK8S "v1.9" "${pkgs.fetchFromGitHub {
} { owner = "kubernetes";
name = "v1.10.nix"; repo = "kubernetes";
path = generateK8S "${pkgs.fetchFromGitHub { rev = "v1.9.11";
owner = "kubernetes"; sha256 = "1wl944ci7k8knrkdrc328agyq4c953j9dm0sn314s42j18lfd7rv";
repo = "kubernetes"; }}/api/openapi-spec/swagger.json";
rev = "v1.10.13"; }
sha256 = "07hwcamlc1kh5flwv4ahfkcg2lyhnbs8q2xczaws6v3sjxaycrrn";
}}/api/openapi-spec/swagger.json"; {
} { name = "v1.10.nix";
name = "v1.11.nix"; path = generateK8S "v1.10" "${pkgs.fetchFromGitHub {
path = generateK8S "${pkgs.fetchFromGitHub { owner = "kubernetes";
owner = "kubernetes"; repo = "kubernetes";
repo = "kubernetes"; rev = "v1.10.13";
rev = "v1.11.8"; sha256 = "07hwcamlc1kh5flwv4ahfkcg2lyhnbs8q2xczaws6v3sjxaycrrn";
sha256 = "1q6x38zdycd4ai31gn666hg41bs4q32dyz2d07x76hj33fkzqs1f"; }}/api/openapi-spec/swagger.json";
}}/api/openapi-spec/swagger.json"; }
} {
name = "v1.12.nix"; {
path = generateK8S "${pkgs.fetchFromGitHub { name = "v1.11.nix";
owner = "kubernetes"; path = generateK8S "v1.11" "${pkgs.fetchFromGitHub {
repo = "kubernetes"; owner = "kubernetes";
rev = "v1.12.6"; repo = "kubernetes";
sha256 = "0p9wh264xfm4c0inz99jclf603c414807vn19gfn62bfls3jcmgf"; rev = "v1.11.8";
}}/api/openapi-spec/swagger.json"; sha256 = "1q6x38zdycd4ai31gn666hg41bs4q32dyz2d07x76hj33fkzqs1f";
} { }}/api/openapi-spec/swagger.json";
name = "v1.13.nix"; }
path = generateK8S "${pkgs.fetchFromGitHub {
owner = "kubernetes"; {
repo = "kubernetes"; name = "v1.12.nix";
rev = "v1.13.4"; path = generateK8S "v1.12" "${pkgs.fetchFromGitHub {
sha256 = "1q3dc416fr9nzy64pl7rydahygnird0vpk9yflssw7v9gx84m6x9"; owner = "kubernetes";
}}/api/openapi-spec/swagger.json"; repo = "kubernetes";
}]; rev = "v1.12.6";
sha256 = "0p9wh264xfm4c0inz99jclf603c414807vn19gfn62bfls3jcmgf";
}}/api/openapi-spec/swagger.json";
}
{
name = "v1.13.nix";
path = generateK8S "v1.13" "${pkgs.fetchFromGitHub {
owner = "kubernetes";
repo = "kubernetes";
rev = "v1.13.4";
sha256 = "1q3dc416fr9nzy64pl7rydahygnird0vpk9yflssw7v9gx84m6x9";
}}/api/openapi-spec/swagger.json";
}
];
generate.istio = pkgs.linkFarm "istio-generated.nix" [{ generate.istio = pkgs.linkFarm "istio-generated.nix" [{
name = "latest.nix"; name = "latest.nix";

View file

@ -3,7 +3,8 @@
with lib; with lib;
let let
cfg = config.kubernetes.api.customresourcedefinitions.crontabs; crd = config.kubernetes.api.resources.customresourcedefinitions.crontabs;
latestCrontab = config.kubernetes.api.resources.crontabs.latest;
in { in {
imports = with kubenix.modules; [ test k8s ]; imports = with kubenix.modules; [ test k8s ];
@ -12,19 +13,25 @@ in {
description = "Simple test tesing CRD"; description = "Simple test tesing CRD";
enable = builtins.compareVersions config.kubernetes.version "1.8" >= 0; enable = builtins.compareVersions config.kubernetes.version "1.8" >= 0;
assertions = [{ assertions = [{
message = "should have group set"; message = "CRD should have group and version set";
assertion = cfg.spec.group == "stable.example.com"; assertion =
crd.spec.group == "stable.example.com" &&
crd.spec.version == "v1";
} {
message = "Custom resource should have correct version set";
assertion = latestCrontab.apiVersion == "stable.example.com/v2";
}]; }];
testScript = '' testScript = ''
$kube->waitUntilSucceeds("kubectl apply -f ${toYAML config.kubernetes.generated}"); $kube->waitUntilSucceeds("kubectl apply -f ${toYAML config.kubernetes.generated}");
$kube->succeed("kubectl get crds | grep -i crontabs"); $kube->succeed("kubectl get crds | grep -i crontabs");
$kube->succeed("kubectl get crontabs | grep -i crontab"); $kube->succeed("kubectl get crontabs | grep -i versioned");
$kube->succeed("kubectl get crontabs | grep -i latest");
''; '';
}; };
kubernetes.version = k8sVersion; kubernetes.version = k8sVersion;
kubernetes.api.customresourcedefinitions.crontabs = { kubernetes.resources.customresourcedefinitions.crontabs = {
metadata.name = "crontabs.stable.example.com"; metadata.name = "crontabs.stable.example.com";
spec = { spec = {
group = "stable.example.com"; group = "stable.example.com";
@ -39,11 +46,26 @@ in {
}; };
}; };
kubernetes.customResources = [{ kubernetes.resources.customresourcedefinitions.crontabsv2 = {
metadata.name = "crontabs.stable.example.com";
spec = {
group = "stable.example.com";
version = "v2";
scope = "Namespaced";
names = {
plural = "crontabs";
singular = "crontab";
kind = "CronTab";
shortNames = ["ct"];
};
};
};
kubernetes.customTypes = [{
name = "crontabs";
group = "stable.example.com"; group = "stable.example.com";
version = "v1"; version = "v1";
kind = "CronTab"; kind = "CronTab";
resource = "crontabs";
description = "CronTabs resources"; description = "CronTabs resources";
module = { module = {
options.schedule = mkOption { options.schedule = mkOption {
@ -51,7 +73,27 @@ in {
type = types.str; type = types.str;
}; };
}; };
} {
name = "crontabs";
group = "stable.example.com";
version = "v2";
kind = "CronTab";
description = "CronTabs resources";
module = {
options = {
schedule = mkOption {
description = "Crontab schedule script";
type = types.str;
};
command = mkOption {
description = "Command to run";
type = types.str;
};
};
};
}]; }];
kubernetes.api."stable.example.com"."v1".CronTab.crontab.spec.schedule = "* * * * *"; kubernetes.resources."stable.example.com"."v1".CronTab.versioned.spec.schedule = "* * * * *";
kubernetes.resources.crontabs.latest.spec.schedule = "* * * * *";
} }