switch formatting to nixpkgs-fmt

This commit is contained in:
Bryton Hall 2023-07-07 22:01:34 -04:00
parent 3598716c73
commit 2712e89716
65 changed files with 4839 additions and 5222 deletions

View file

@ -1,5 +1,6 @@
{
"recommendations": [
"jnoortheen.nix-ide",
"mkhl.direnv"
]
}

View file

@ -1,6 +1,6 @@
{
"git.detectSubmodules": false,
"nix.formatterPath": "alejandra",
"nix.enableLanguageServer": true,
"search.exclude": {
"docs/themes": true
}

View file

@ -9,6 +9,5 @@
sha256 = lock.nodes.flake-compat.locked.narHash;
}
)
{src = ./.;}
)
.defaultNix
{ src = ./.; }
).defaultNix

View file

@ -1,4 +1,4 @@
{
deployment = import ./deployment {};
testing = import ./testing {};
deployment = import ./deployment { };
testing = import ./testing { };
}

View file

@ -1,8 +1,8 @@
{kubenix ? import ../../../..}:
{ kubenix ? import ../../../.. }:
kubenix.evalModules.${builtins.currentSystem} {
module = {kubenix, ...}: {
module = { kubenix, ... }: {
# instead of defining everything inline, let's import it
imports = [./module.nix];
imports = [ ./module.nix ];
# annotate the generated resources with a project name
kubenix.project = "example";

View file

@ -1,5 +1,5 @@
{kubenix, ...}: {
imports = [kubenix.modules.k8s];
{ kubenix, ... }: {
imports = [ kubenix.modules.k8s ];
kubernetes.resources = {
deployments.nginx.spec = {
@ -50,12 +50,10 @@
services.nginx.spec = {
selector.app = "nginx";
ports = [
{
ports = [{
name = "http";
port = 80;
}
];
}];
};
};
}

View file

@ -1,7 +1,7 @@
{kubenix ? import ../../../..}:
{ kubenix ? import ../../../.. }:
kubenix.evalModules.${builtins.currentSystem} {
module = {kubenix, ...}: {
imports = [kubenix.modules.helm];
module = { kubenix, ... }: {
imports = [ kubenix.modules.helm ];
kubernetes.helm.releases.example = {
chart = kubenix.lib.helm.fetch {
repo = "https://charts.bitnami.com/bitnami";

View file

@ -1,15 +1,10 @@
{kubenix ? import ../../../..}:
{ kubenix ? import ../../../.. }:
kubenix.evalModules.${builtins.currentSystem} {
module = {
kubenix,
config,
pkgs,
...
}: {
imports = with kubenix.modules; [k8s docker];
module = { kubenix, config, pkgs, ... }: {
imports = with kubenix.modules; [ k8s docker ];
docker = {
registry.url = "docker.somewhere.io";
images.example.image = pkgs.callPackage ./image.nix {};
images.example.image = pkgs.callPackage ./image.nix { };
};
kubernetes.resources.pods.example.spec.containers = {
custom.image = config.docker.images.example.path;

View file

@ -1,10 +1,7 @@
{
dockerTools,
nginx,
}:
{ dockerTools, nginx }:
dockerTools.buildLayeredImage {
name = "nginx";
contents = [nginx];
contents = [ nginx ];
extraCommands = ''
mkdir -p etc
chmod u+w etc
@ -12,9 +9,9 @@ dockerTools.buildLayeredImage {
echo "nginx:x:1000:nginx" > etc/group
'';
config = {
Cmd = ["nginx" "-c" "/etc/nginx/nginx.conf"];
Cmd = [ "nginx" "-c" "/etc/nginx/nginx.conf" ];
ExposedPorts = {
"80/tcp" = {};
"80/tcp" = { };
};
};
}

View file

@ -1,7 +1,7 @@
{kubenix ? import ../../../..}:
{ kubenix ? import ../../../.. }:
kubenix.evalModules.${builtins.currentSystem} {
module = {kubenix, ...}: {
imports = [./module.nix];
module = { kubenix, ... }: {
imports = [ ./module.nix ];
kubenix.project = "multi-namespace-example";
kubernetes.version = "1.24";

View file

@ -1,11 +1,5 @@
{
config,
lib,
pkgs,
kubenix,
...
}: {
imports = with kubenix.modules; [submodules k8s];
{ config, lib, pkgs, kubenix, ... }: {
imports = with kubenix.modules; [ submodules k8s ];
# Import submodule.
submodules.imports = [
@ -26,12 +20,10 @@
# Now we can set the args options defined in the submodule.
args.kubernetes.resources = {
services.nginx.spec = {
ports = [
{
ports = [{
name = "http";
port = 80;
}
];
}];
selector.app = "nginx";
};
};
@ -41,12 +33,10 @@
submodule = "namespaced";
args.kubernetes.resources = {
services.nginx.spec = {
ports = [
{
ports = [{
name = "https";
port = 443;
}
];
}];
selector.app = "nginx";
};
};

View file

@ -1,13 +1,12 @@
{
config,
kubenix,
lib,
# Name of submodule instance.
name,
# This is a shorthand for config.submodule.args and contains
{ config
, kubenix
, lib
, # Name of submodule instance.
name
, # This is a shorthand for config.submodule.args and contains
# final values of the args options.
args,
...
args
, ...
}: {
imports = with kubenix.modules; [
# This needs to be imported in order to define a submodule.
@ -25,7 +24,7 @@
# to set kubernetes options from the k8s module which are already
# precisely typed.
type = lib.types.attrs;
default = {};
default = { };
};
};
@ -54,9 +53,9 @@
kubernetes = lib.mkMerge [
# Use instance name as namespace
{namespace = name;}
{ namespace = name; }
# Create namespace object
{resources.namespaces.${name} = {};}
{ resources.namespaces.${name} = { }; }
# All resources defined here will use the above namespace
args.kubernetes
];

View file

@ -1,11 +1,11 @@
# let's creata a function whose only input is the kubenix package
{kubenix ? import ../../../..}:
{ kubenix ? import ../../../.. }:
# evalModules is our main entrypoint
kubenix.evalModules.${builtins.currentSystem} {
# to it, we pass a module that accepts a (different) kubenix object
module = {kubenix, ...}: {
module = { kubenix, ... }: {
# in order to define options, we need to import their definitions
imports = [kubenix.modules.k8s];
imports = [ kubenix.modules.k8s ];
# now we have full access to define Kubernetes resources
kubernetes.resources.pods = {
# "example" is the name of our pod

View file

@ -1,7 +1,7 @@
{kubenix ? import ../../../..}:
{ kubenix ? import ../../../.. }:
kubenix.evalModules.${builtins.currentSystem} {
module = {kubenix, ...}: {
imports = [kubenix.modules.k8s];
module = { kubenix, ... }: {
imports = [ kubenix.modules.k8s ];
kubernetes.resources.secrets.example.stringData = {
password = "ref+file:///path/to/secret";
};

View file

@ -1,17 +1,15 @@
{kubenix ? import ../../../..}:
{ kubenix ? import ../../../.. }:
kubenix.evalModules.x86_64-linux {
module = {kubenix, ...}: {
imports = [kubenix.modules.testing];
module = { kubenix, ... }: {
imports = [ kubenix.modules.testing ];
testing = {
tests = [./test.nix];
common = [
{
features = ["k8s"];
tests = [ ./test.nix ];
common = [{
features = [ "k8s" ];
options = {
kubernetes.version = "1.24";
};
}
];
}];
};
};
}

View file

@ -1,9 +1,5 @@
{
kubenix,
test,
...
}: {
imports = [kubenix.modules.test];
{ kubenix, test, ... }: {
imports = [ kubenix.modules.test ];
test = {
name = "example";

View file

@ -1,14 +1,10 @@
# adapted from: https://discourse.nixos.org/t/franken-script-to-generate-nixos-options-docs-with-custom-modules/1674/4
{
pkgs,
options,
}: let
extraSources = [];
{ pkgs, options }:
let
extraSources = [ ];
lib = pkgs.lib;
optionsListVisible =
lib.filter (opt: opt.visible && !opt.internal)
(lib.optionAttrSetToDocList options);
optionsListVisible = lib.filter (opt: opt.visible && !opt.internal) (lib.optionAttrSetToDocList options);
# Replace functions by the string <function>
substFunction = x:
@ -24,45 +20,40 @@
isPath = x: (builtins.typeOf x) == "path";
optionsListDesc = lib.flip map optionsListVisible (
opt:
opt
// {
description = let
optionsListDesc = lib.flip map optionsListVisible (opt:
opt // {
description =
let
attempt = builtins.tryEval opt.description;
in
if attempt.success
then attempt.value
else "N/A";
declarations = map stripAnyPrefixes opt.declarations;
}
// lib.optionalAttrs (opt ? example) {
} // lib.optionalAttrs (opt ? example) {
example = substFunction opt.example;
}
// lib.optionalAttrs (opt ? default) {
} // lib.optionalAttrs (opt ? default) {
default = substFunction opt.default;
}
// lib.optionalAttrs (opt ? type) {
} // lib.optionalAttrs (opt ? type) {
type = substFunction opt.type;
}
// lib.optionalAttrs
(opt ? relatedPackages && opt.relatedPackages != [])
{
} // lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != [ ]) {
relatedPackages = genRelatedPackages opt.relatedPackages;
}
);
genRelatedPackages = packages: let
genRelatedPackages = packages:
let
unpack = p:
if lib.isString p
then {name = p;}
then { name = p; }
else if lib.isList p
then {path = p;}
then { path = p; }
else p;
describe = args: let
describe = args:
let
title = args.title or null;
name = args.name or (lib.concatStringsSep "." args.path);
path = args.path or [args.name];
path = args.path or [ args.name ];
package =
args.package
or (lib.attrByPath path
@ -82,11 +73,13 @@
"\n<programlisting>${package.meta.longDescription}"
+ "</programlisting>"
+ "</listitem>";
in "<itemizedlist>${lib.concatStringsSep "\n" (map (p:
in
"<itemizedlist>${lib.concatStringsSep "\n" (map (p:
describe (unpack p))
packages)}</itemizedlist>";
optionLess = a: b: let
optionLess = a: b:
let
ise = lib.hasPrefix "enable";
isp = lib.hasPrefix "package";
cmp =
@ -95,7 +88,7 @@
in
lib.compareLists cmp a.loc b.loc < 0;
prefixesToStrip = map (p: "${toString p}/") ([../../..] ++ extraSources);
prefixesToStrip = map (p: "${toString p}/") ([ ../../.. ] ++ extraSources);
stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix) prefixesToStrip;
###############################################################################
@ -119,4 +112,4 @@
})
optionsList)));
in
pkgs.writeText "options.json" optionsJSON
pkgs.writeText "options.json" optionsJSON

View file

@ -11,57 +11,50 @@
};
};
outputs = inputs @ {self, ...}:
(inputs.flake-utils.lib.eachDefaultSystem (
system: let
outputs = inputs @ { self, ... }:
(inputs.flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import inputs.nixpkgs {
inherit system;
overlays = [self.overlays.default];
overlays = [ self.overlays.default ];
config.allowUnsupportedSystem = true;
};
inherit (pkgs) lib;
kubenix = {
lib = import ./lib {inherit lib pkgs;};
lib = import ./lib { inherit lib pkgs; };
evalModules = self.evalModules.${system};
modules = self.nixosModules.kubenix;
};
# evalModules with same interface as lib.evalModules and kubenix as
# special argument
evalModules = attrs @ {
module ? null,
modules ? [module],
...
}: let
lib' = lib.extend (lib: _self: import ./lib/upstreamables.nix {inherit lib pkgs;});
attrs' = builtins.removeAttrs attrs ["module"];
evalModules = attrs @ { module ? null, modules ? [ module ], ... }:
let
lib' = lib.extend (lib: _self: import ./lib/upstreamables.nix { inherit lib pkgs; });
attrs' = builtins.removeAttrs attrs [ "module" ];
in
lib'.evalModules (lib.recursiveUpdate
{
modules =
modules
++ [
{
modules = modules ++ [{
config._module.args = {
inherit pkgs;
name = "default";
};
}
];
}];
specialArgs = {
inherit kubenix;
inherit pkgs;
};
}
attrs');
in {
in
{
inherit evalModules pkgs;
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
# extra tools
dive
fd
k9s
@ -81,11 +74,10 @@
'';
};
formatter =
(inputs.treefmt.lib.evalModule pkgs {
formatter = (inputs.treefmt.lib.evalModule pkgs {
projectRootFile = "flake.nix";
programs = {
alejandra.enable = true;
nixpkgs-fmt.enable = true;
black.enable = true;
prettier.enable = true;
shfmt.enable = true;
@ -95,16 +87,12 @@
"docs/layouts/*"
"modules/generated/*"
];
})
.config
.build
.wrapper;
}).config.build.wrapper;
apps = {
docs = {
type = "app";
program =
(pkgs.writeShellScript "gen-docs" ''
program = (pkgs.writeShellScript "gen-docs" ''
set -eo pipefail
# generate json object of module options
@ -123,14 +111,12 @@
# build the site
cd docs && ${pkgs.hugo}/bin/hugo "$@"
'')
.outPath;
'').outPath;
};
generate = {
type = "app";
program =
(pkgs.writeShellScript "gen-modules" ''
program = (pkgs.writeShellScript "gen-modules" ''
set -eo pipefail
dir=./modules/generated
@ -140,13 +126,11 @@
cp ./result/* $dir/
rm result
'')
.outPath;
'').outPath;
};
};
packages =
{
packages = {
inherit (pkgs) kubernetes kubectl;
default = pkgs.callPackage ./pkgs/kubenix.nix {
inherit (self.packages.${system});
@ -154,29 +138,28 @@
};
docs = import ./docs {
inherit pkgs;
options =
(self.evalModules.${system} {
options = (self.evalModules.${system} {
modules = builtins.attrValues (builtins.removeAttrs
# the submodules module currently doesn't evaluate:
# error: No module found name/latest
# not sure how important that documentation is a this time
self.nixosModules.kubenix ["submodule" "submodules"]);
})
.options;
self.nixosModules.kubenix [ "submodule" "submodules" ]);
}).options;
};
}
// pkgs.lib.attrsets.mapAttrs' (name: value: pkgs.lib.attrsets.nameValuePair "generate-${name}" value)
(builtins.removeAttrs (pkgs.callPackage ./pkgs/generators {}) ["override" "overrideDerivation"]);
(builtins.removeAttrs (pkgs.callPackage ./pkgs/generators { }) [ "override" "overrideDerivation" ]);
checks = let
checks =
let
wasSuccess = suite:
if suite.success
then pkgs.runCommandNoCC "testing-suite-config-assertions-for-${suite.name}-succeeded" {} "echo success > $out"
else pkgs.runCommandNoCC "testing-suite-config-assertions-for-${suite.name}-failed" {} "exit 1";
then pkgs.runCommandNoCC "testing-suite-config-assertions-for-${suite.name}-succeeded" { } "echo success > $out"
else pkgs.runCommandNoCC "testing-suite-config-assertions-for-${suite.name}-failed" { } "exit 1";
examples = import ./docs/content/examples;
mkK8STests = attrs:
(import ./tests {inherit evalModules;})
({registry = "docker.io/gatehub";} // attrs);
(import ./tests { inherit evalModules; })
({ registry = "docker.io/gatehub"; } // attrs);
in
{
# TODO: access "success" derivation with nice testing utils for nice output
@ -185,7 +168,7 @@
// builtins.listToAttrs (builtins.map
(v: {
name = "test-k8s-${builtins.replaceStrings ["."] ["_"] v}";
value = wasSuccess (mkK8STests {k8sVersion = v;});
value = wasSuccess (mkK8STests { k8sVersion = v; });
})
(import ./versions.nix).versions);
}

View file

@ -1,8 +1,5 @@
{
lib,
pkgs,
}: {
k8s = import ./k8s {inherit lib;};
docker = import ./docker {inherit lib pkgs;};
helm = import ./helm {inherit pkgs;};
{ lib, pkgs }: {
k8s = import ./k8s { inherit lib; };
docker = import ./docker { inherit lib pkgs; };
helm = import ./helm { inherit pkgs; };
}

View file

@ -1,13 +1,6 @@
{
lib,
pkgs,
}:
{ lib, pkgs }:
with lib; {
copyDockerImages = {
images,
dest,
args ? "",
}:
copyDockerImages = { images, dest, args ? "" }:
pkgs.writeScript "copy-docker-images.sh" (concatMapStrings
(image: ''
#!${pkgs.runtimeShell}

View file

@ -1,29 +1,25 @@
{
runCommand,
lib,
kubernetes-helm,
yq,
}:
{ runCommand, lib, kubernetes-helm, yq }:
with lib;
{
{
# chart to template
chart,
chart
# release name
name,
, name
# namespace to install release into
namespace ? null,
, namespace ? null
# values to pass to chart
values ? {},
, values ? { }
# kubernetes version to template chart for
kubeVersion ? null,
, kubeVersion ? null
# whether to include CRD
includeCRDs ? false,
, includeCRDs ? false
# whether to include hooks
noHooks ? false,
}: let
, noHooks ? false
}:
let
valuesJsonFile = builtins.toFile "${name}-values.json" (builtins.toJSON values);
# The `helm template` and YAML -> JSON steps are separate `runCommand` derivations for easier debuggability
resourcesYaml = runCommand "${name}.yaml" {nativeBuildInputs = [kubernetes-helm];} ''
resourcesYaml = runCommand "${name}.yaml" { nativeBuildInputs = [ kubernetes-helm ]; } ''
helm template "${name}" \
${optionalString (kubeVersion != null) "--kube-version ${kubeVersion}"} \
${optionalString (namespace != null) "--namespace ${namespace}"} \
@ -32,8 +28,8 @@ with lib;
${optionalString noHooks "--no-hooks"} \
${chart} >$out
'';
in
runCommand "${name}.json" {} ''
in
runCommand "${name}.json" { } ''
# Remove null values
${yq}/bin/yq -Scs 'walk(
if type == "object" then
@ -43,4 +39,4 @@ with lib;
else
.
end)' ${resourcesYaml} >$out
''
''

View file

@ -1,4 +1,4 @@
{pkgs}: {
chart2json = pkgs.callPackage ./chart2json.nix {};
fetch = pkgs.callPackage ./fetchhelm.nix {};
{ pkgs }: {
chart2json = pkgs.callPackage ./chart2json.nix { };
fetch = pkgs.callPackage ./fetchhelm.nix { };
}

View file

@ -1,80 +1,48 @@
{
stdenvNoCC,
lib,
kubernetes-helm,
cacert,
}: let
cleanName = lib.replaceStrings ["/"] ["-"];
{ stdenvNoCC, lib, kubernetes-helm, cacert }:
let
cleanName = lib.replaceStrings [ "/" ] [ "-" ];
in
{
{
# name of the chart
chart,
# chart url to fetch from custom location
chartUrl ? null,
# version of the chart
version ? null,
# chart hash
sha256,
# whether to extract chart
untar ? true,
# use custom charts repo
repo ? null,
# pass --verify to helm chart
verify ? false,
# pass --devel to helm chart
devel ? false,
}:
stdenvNoCC.mkDerivation {
name = "${cleanName chart}-${
if version == null
then "dev"
else version
}";
chart
, # chart url to fetch from custom location
chartUrl ? null
, # version of the chart
version ? null
, # chart hash
sha256
, # whether to extract chart
untar ? true
, # use custom charts repo
repo ? null
, # pass --verify to helm chart
verify ? false
, # pass --devel to helm chart
devel ? false
,
}:
stdenvNoCC.mkDerivation {
name = "${cleanName chart}-${ if version == null then "dev" else version }";
buildCommand = ''
export HOME="$PWD"
echo "adding helm repo"
${
if repo == null
then ""
else "helm repo add repository ${repo}"
}
${ if repo == null then "" else "helm repo add repository ${repo}" }
echo "fetching helm chart"
helm fetch -d ./chart \
${
if untar
then "--untar"
else ""
} \
${
if version == null
then ""
else "--version ${version}"
} \
${
if devel
then "--devel"
else ""
} \
${
if verify
then "--verify"
else ""
} \
${
if chartUrl == null
then
(
${ if untar then "--untar" else ""} \
${ if version == null then "" else "--version ${version}" } \
${ if devel then "--devel" else "" } \
${ if verify then "--verify" else "" } \
${ if chartUrl == null then (
if repo == null
then chart
else "repository/${chart}"
)
else chartUrl
}
) else chartUrl}
cp -r chart/*/ $out
'';
outputHashMode = "recursive";
outputHashAlgo = "sha256";
outputHash = sha256;
nativeBuildInputs = [kubernetes-helm cacert];
}
nativeBuildInputs = [ kubernetes-helm cacert ];
}

View file

@ -1,7 +1,9 @@
{pkgs ? import <nixpkgs> {}}: let
fetchhelm = pkgs.callPackage ./fetchhelm.nix {};
chart2json = pkgs.callPackage ./chart2json.nix {};
in rec {
{ pkgs ? import <nixpkgs> { } }:
let
fetchhelm = pkgs.callPackage ./fetchhelm.nix { };
chart2json = pkgs.callPackage ./chart2json.nix { };
in
rec {
postgresql-chart = fetchhelm {
chart = "stable/postgresql";
version = "0.18.1";

View file

@ -1,15 +1,10 @@
{lib}:
{ lib }:
with lib; rec {
# TODO: refactor with mkOptionType
mkSecretOption = {
description ? "",
default ? {},
allowNull ? true,
}:
mkSecretOption = { description ? "", default ? { }, allowNull ? true }:
mkOption {
inherit description;
type =
(
type = (
if allowNull
then types.nullOr
else id
@ -19,24 +14,19 @@ with lib; rec {
description = "Name of the secret where secret is stored";
type = types.str;
default = default.name;
}
// (optionalAttrs (default ? "name") {
} // (optionalAttrs (default ? "name") {
default = default.name;
}));
key = mkOption ({
description = "Name of the key where secret is stored";
type = types.str;
}
// (optionalAttrs (default ? "key") {
} // (optionalAttrs (default ? "key") {
default = default.key;
}));
};
});
default =
if default == null
then null
else {};
default = if default == null then null else { };
};
secretToEnv = value: {
@ -46,10 +36,7 @@ with lib; rec {
};
# Creates kubernetes list from a list of kubernetes objects
mkList = {
items,
labels ? {},
}: {
mkList = { items, labels ? { } }: {
kind = "List";
apiVersion = "v1";
@ -57,14 +44,11 @@ with lib; rec {
};
# Creates hashed kubernetes list from a list of kubernetes objects
mkHashedList = {
items,
labels ? {},
}: let
mkHashedList = { items, labels ? { } }:
let
hash = builtins.hashString "sha1" (builtins.toJSON items);
labeledItems =
map
labeledItems = map
(item:
recursiveUpdate item {
metadata.labels."kubenix/hash" = hash;
@ -73,11 +57,9 @@ with lib; rec {
in
mkList {
items = labeledItems;
labels =
{
labels = {
"kubenix/hash" = hash;
}
// labels;
} // labels;
};
inherit (lib) toBase64;

View file

@ -1,21 +1,18 @@
{
lib,
pkgs,
}:
{ lib, pkgs }:
with lib; let
self = {
importYAML = path:
importJSON (pkgs.runCommand "yaml-to-json" {} ''
importJSON (pkgs.runCommand "yaml-to-json" { } ''
${pkgs.yq}/bin/yq -c . ${path} > $out
'');
toYAML = config:
builtins.readFile (pkgs.runCommand "to-yaml" {} ''
builtins.readFile (pkgs.runCommand "to-yaml" { } ''
${pkgs.yq}/bin/yq -y . ${pkgs.writeText "to-json" (builtins.toJSON config)} > $out
'');
toMultiDocumentYaml = name: documents:
pkgs.runCommand name {}
pkgs.runCommand name { }
(concatMapStringsSep "\necho --- >> $out\n"
(
d: "${pkgs.yq}/bin/yq -y . ${pkgs.writeText "to-json" (builtins.toJSON config)} >> $out"
@ -24,7 +21,7 @@ with lib; let
toBase64 = value:
builtins.readFile
(pkgs.runCommand "value-to-b64" {} "echo -n '${value}' | ${pkgs.coreutils}/bin/base64 -w0 > $out");
(pkgs.runCommand "value-to-b64" { } "echo -n '${value}' | ${pkgs.coreutils}/bin/base64 -w0 > $out");
exp = base: exp: foldr (_value: acc: acc * base) 1 (range 1 exp);
@ -38,8 +35,7 @@ with lib; let
i = 0;
value = 0;
}
(stringToCharacters value))
.value;
(stringToCharacters value)).value;
};
in
self
self

View file

@ -1,4 +1,4 @@
{lib, ...}:
{ lib, ... }:
with lib; {
options = {
kubenix.project = mkOption {
@ -10,7 +10,7 @@ with lib; {
_m.features = mkOption {
description = "List of features exposed by module";
type = types.listOf types.str;
default = [];
default = [ ];
};
_m.propagate = mkOption {
@ -20,17 +20,17 @@ with lib; {
features = mkOption {
description = "List of features that submodule has to have to propagate module";
type = types.listOf types.str;
default = [];
default = [ ];
};
module = mkOption {
description = "Module to propagate";
type = types.unspecified;
default = {};
default = { };
};
};
}));
default = [];
default = [ ];
};
};
}

View file

@ -1,14 +1,9 @@
{
config,
lib,
pkgs,
docker,
...
}:
{ config, lib, pkgs, docker, ... }:
with lib; let
cfg = config.docker;
in {
imports = [./base.nix];
in
{
imports = [ ./base.nix ];
options.docker = {
registry.url = mkOption {
@ -19,11 +14,7 @@ in {
images = mkOption {
description = "Attribute set of docker images that should be published";
type = types.attrsOf (types.submodule ({
name,
config,
...
}: {
type = types.attrsOf (types.submodule ({ name, config, ... }: {
options = {
image = mkOption {
description = "Docker image to publish";
@ -65,13 +56,13 @@ in {
};
};
}));
default = {};
default = { };
};
export = mkOption {
description = "List of images to export";
type = types.listOf types.package;
default = [];
default = [ ];
};
copyScript = mkOption {
@ -86,25 +77,22 @@ in {
config = {
# define docker feature
_m.features = ["docker"];
_m.features = [ "docker" ];
# propagate docker options if docker feature is enabled
_m.propagate = [
{
features = ["docker"];
_m.propagate = [{
features = [ "docker" ];
module = _: {
# propagate registry options
docker.registry = cfg.registry;
};
}
];
}];
# pass docker library as param
_module.args.docker = import ../lib/docker {inherit lib pkgs;};
_module.args.docker = import ../lib/docker { inherit lib pkgs; };
# list of exported docker images
docker.export =
mapAttrsToList (_: i: i.image)
docker.export = mapAttrsToList (_: i: i.image)
(filterAttrs (_: i: i.registry != null) config.docker.images);
};
}

View file

@ -1,12 +1,6 @@
# helm defines kubenix module with options for using helm charts
# with kubenix
{
config,
lib,
pkgs,
helm,
...
}:
{ config, lib, pkgs, helm, ... }:
with lib; let
cfg = config.kubernetes.helm;
@ -16,29 +10,28 @@ with lib; let
name = "recursive-attrs";
description = "recursive attribute set";
check = isAttrs;
merge = _loc: foldl' (res: def: recursiveUpdate res def.value) {};
merge = _loc: foldl' (res: def: recursiveUpdate res def.value) { };
};
parseApiVersion = apiVersion: let
parseApiVersion = apiVersion:
let
splitted = splitString "/" apiVersion;
in {
in
{
group =
if length splitted == 1
then "core"
else head splitted;
version = last splitted;
};
in {
imports = [./k8s.nix];
in
{
imports = [ ./k8s.nix ];
options.kubernetes.helm = {
releases = mkOption {
description = "Attribute set of helm releases";
type = types.attrsOf (types.submodule ({
config,
name,
...
}: {
type = types.attrsOf (types.submodule ({ config, name, ... }: {
options = {
name = mkOption {
description = "Helm release name";
@ -60,7 +53,7 @@ in {
values = mkOption {
description = "Values to pass to chart";
type = recursiveAttrs;
default = {};
default = { };
};
kubeVersion = mkOption {
@ -72,7 +65,7 @@ in {
overrides = mkOption {
description = "Overrides to apply to all chart resources";
type = types.listOf types.unspecified;
default = [];
default = [ ];
};
overrideNamespace = mkOption {
@ -109,36 +102,34 @@ in {
objects = mkOption {
description = "Generated kubernetes objects";
type = types.listOf types.attrs;
default = [];
default = [ ];
};
};
config.overrides = mkIf (config.overrideNamespace && config.namespace != null) [
{
config.overrides = mkIf (config.overrideNamespace && config.namespace != null) [{
metadata.namespace = config.namespace;
}
];
}];
config.objects = importJSON (helm.chart2json {
inherit (config) chart name namespace values kubeVersion includeCRDs noHooks;
});
}));
default = {};
default = { };
};
};
config = {
# expose helm helper methods as module argument
_module.args.helm = import ../lib/helm {inherit pkgs;};
_module.args.helm = import ../lib/helm { inherit pkgs; };
kubernetes.api.resources = mkMerge (flatten (mapAttrsToList
(
_: release:
map
(object: let
(_: release: map
(object:
let
apiVersion = parseApiVersion object.apiVersion;
inherit (object.metadata) name;
in {
in
{
"${apiVersion.group}"."${apiVersion.version}".${object.kind}."${name}" = mkMerge ([
object
]

View file

@ -1,19 +1,13 @@
{
lib,
definitions,
}:
{ lib, definitions }:
with lib; {
"istio_networking_v1alpha3_StringMatch" =
recursiveUpdate
(
recursiveUpdate
"istio_networking_v1alpha3_StringMatch" = recursiveUpdate
(recursiveUpdate
definitions."istio_networking_v1alpha3_StringMatch_Exact"
definitions."istio_networking_v1alpha3_StringMatch_Prefix"
)
definitions."istio_networking_v1alpha3_StringMatch_Regex";
"istio_networking_v1alpha3_PortSelector" =
recursiveUpdate
"istio_networking_v1alpha3_PortSelector" = recursiveUpdate
definitions."istio_networking_v1alpha3_PortSelector_Name"
definitions."istio_networking_v1alpha3_PortSelector_Number";
}

View file

@ -1,13 +1,7 @@
# This file was generated with kubenix k8s generator, do not edit
{
lib,
config,
...
}:
{ lib, config, ... }:
with lib; let
types =
lib.types
// rec {
types = lib.types // rec {
str = mkOptionType {
name = "str";
description = "string";
@ -22,28 +16,30 @@ with lib; let
name = "coercedTo";
description = "${finalType.description} or ${coercedType.description}";
check = x: finalType.check x || coercedType.check x;
merge = loc: defs: let
merge = loc: defs:
let
coerceVal = val:
if finalType.check val
then val
else let
else
let
coerced = coerceFunc val;
in
assert finalType.check coerced; coerced;
in
finalType.merge loc (map (def: def // {value = coerceVal def.value;}) defs);
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;};
functor = (defaultFunctor name) // { wrapped = finalType; };
};
};
mkOptionDefault = mkOverride 1001;
extraOptions = {
kubenix = {};
kubenix = { };
};
mergeValuesByKey = mergeKey: values:
@ -59,18 +55,20 @@ with lib; let
values);
submoduleOf = ref:
types.submodule ({name, ...}: {
types.submodule ({ name, ... }: {
options = definitions."${ref}".options;
config = definitions."${ref}".config;
});
submoduleWithMergeOf = ref: mergeKey:
types.submodule ({name, ...}: let
types.submodule ({ name, ... }:
let
convertName = name:
if definitions."${ref}".options.${mergeKey}.type == types.int
then toInt name
else name;
in {
in
{
options = definitions."${ref}".options;
config =
definitions."${ref}".config
@ -80,7 +78,7 @@ with lib; let
});
submoduleForDefinition = ref: resource: kind: group: version:
types.submodule ({name, ...}: {
types.submodule ({ name, ... }: {
options = definitions."${ref}".options // extraOptions;
config = mkMerge ([
definitions."${ref}".config
@ -92,8 +90,8 @@ with lib; let
metadata.name = mkOptionDefault name;
}
]
++ (config.defaults.${resource} or [])
++ (config.defaults.all or []));
++ (config.defaults.${resource} or [ ])
++ (config.defaults.all or [ ]));
});
coerceAttrsOfSubmodulesToListByKey = ref: mergeKey: (
@ -103,8 +101,7 @@ with lib; let
(types.attrsOf (submoduleWithMergeOf ref mergeKey))
);
definitions =
{
definitions = {
"google_rpc_Status" = {
options = {
"code" = mkOption {
@ -2859,7 +2856,7 @@ with lib; let
};
};
"istio_mixer_v1_ReportResponse" = {};
"istio_mixer_v1_ReportResponse" = { };
"istio_mixer_v1_RouteDirective" = {
options = {
@ -4710,8 +4707,9 @@ with lib; let
};
};
}
// (import ./istio-overrides.nix {inherit definitions lib;});
in {
// (import ./istio-overrides.nix { inherit definitions lib; });
in
{
kubernetes.customResources = [
{
group = "networking.istio.io";

View file

@ -1,12 +1,5 @@
# K8S module defines kubernetes definitions for kubenix
{
options,
config,
lib,
pkgs,
k8s,
...
}:
{ options, config, lib, pkgs, k8s, ... }:
with lib; let
versions = (import ../versions.nix).versions;
cfg = config.kubernetes;
@ -15,8 +8,7 @@ with lib; let
getDefaults = resource: group: version: kind:
catAttrs "default" (filter
(
default:
(default:
(resource == null || default.resource == null || default.resource == resource)
&& (default.group == null || default.group == group)
&& (default.version == null || default.version == version)
@ -31,7 +23,7 @@ with lib; let
then map moduleToAttrs value
else value;
apiOptions = {config, ...}: {
apiOptions = { config, ... }: {
options = {
definitions = mkOption {
description = "Attribute set of kubernetes definitions";
@ -74,18 +66,17 @@ with lib; let
default = mkOption {
description = "Default to apply";
type = types.unspecified;
default = {};
default = { };
};
};
}));
default = [];
default = [ ];
apply = unique;
};
types = mkOption {
description = "List of registered kubernetes types";
type =
coerceListOfSubmodulesToAttrs
type = coerceListOfSubmodulesToAttrs
{
options = {
group = mkOption {
@ -115,7 +106,7 @@ with lib; let
};
}
gvkKeyFn;
default = {};
default = { };
};
};
@ -133,7 +124,8 @@ with lib; let
else -1)
lst));
compareVersions = ver1: ver2: let
compareVersions = ver1: ver2:
let
getVersion = substring 1 10;
splittedVer1 = builtins.splitVersion (getVersion ver1);
splittedVer2 = builtins.splitVersion (getVersion ver2);
@ -155,10 +147,8 @@ with lib; let
})
cfg.customTypes);
customResourceTypesByAttrNameSortByVersion =
mapAttrs
(
_: resourceTypes:
customResourceTypesByAttrNameSortByVersion = mapAttrs
(_: resourceTypes:
reverseList (sort
(
r1: r2:
@ -168,10 +158,9 @@ with lib; let
)
customResourceTypesByAttrName;
latestCustomResourceTypes =
mapAttrsToList (_: last) customResourceTypesByAttrNameSortByVersion;
latestCustomResourceTypes = mapAttrsToList (_: last) customResourceTypesByAttrNameSortByVersion;
customResourceModuleForType = config: ct: {name, ...}: {
customResourceModuleForType = config: ct: { name, ... }: {
imports = getDefaults ct.name ct.group ct.version ct.kind;
options = {
apiVersion = mkOption {
@ -192,7 +181,7 @@ with lib; let
spec = mkOption {
description = "Module spec";
type = types.either types.attrs (types.submodule ct.module);
default = {};
default = { };
};
};
@ -203,30 +192,29 @@ with lib; let
};
};
customResourceOptions =
(mapAttrsToList
(_: ct: {config, ...}: let
customResourceOptions = (mapAttrsToList
(_: ct: { config, ... }:
let
module = customResourceModuleForType config ct;
in {
in
{
options.resources.${ct.group}.${ct.version}.${ct.kind} = mkOption {
inherit (ct) description;
type = types.attrsOf (types.submodule module);
default = {};
default = { };
};
})
cfg.customTypes)
++ (map
(ct: {
options,
config,
...
}: let
(ct: { options, config, ... }:
let
module = customResourceModuleForType config ct;
in {
in
{
options.resources.${ct.attrName} = mkOption {
inherit (ct) description;
type = types.attrsOf (types.submodule module);
default = {};
default = { };
};
config.resources.${ct.group}.${ct.version}.${ct.kind} =
@ -234,11 +222,11 @@ with lib; let
})
latestCustomResourceTypes);
coerceListOfSubmodulesToAttrs = submodule: keyFn: let
coerceListOfSubmodulesToAttrs = submodule: keyFn:
let
mergeValuesByFn = keyFn: values:
listToAttrs (map
(
value:
(value:
nameValuePair (toString (keyFn value)) value
)
values);
@ -250,26 +238,28 @@ with lib; let
name = "coercedTo";
description = "${finalType.description} or ${coercedType.description}";
check = x: finalType.check x || coercedType.check x;
merge = loc: defs: let
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);
finalType.merge loc (map (def: def // { value = coerceVal def.value; }) defs);
inherit (finalType) getSubOptions;
inherit (finalType) getSubModules;
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
typeMerge = _t1: _t2: null;
functor = (defaultFunctor name) // {wrapped = finalType;};
functor = (defaultFunctor name) // { wrapped = finalType; };
};
in
coercedTo
(types.listOf (types.submodule submodule))
(mergeValuesByFn keyFn)
(types.attrsOf (types.submodule submodule));
in {
imports = [./base.nix];
in
{
imports = [ ./base.nix ];
options.kubernetes = {
kubeconfig = mkOption {
@ -296,7 +286,7 @@ in {
customResources = mkOption {
description = "Setup custom resources";
type = types.listOf types.attrs;
default = [];
default = [ ];
};
resourceOrder = mkOption {
@ -310,25 +300,24 @@ in {
api = mkOption {
type = types.submodule {
imports =
[
imports = [
./generated/v${cfg.version}.nix
apiOptions
]
++ customResourceOptions;
};
default = {};
default = { };
};
imports = mkOption {
type = types.listOf (types.either types.package types.path);
description = "List of resources to import";
default = [];
default = [ ];
};
resources = mkOption {
description = "Alias for `config.kubernetes.api.resources` options";
default = {};
default = { };
type = types.attrsOf types.attrs;
};
@ -342,8 +331,7 @@ in {
group = "helm.cattle.io";
};
};
type =
coerceListOfSubmodulesToAttrs
type = coerceListOfSubmodulesToAttrs
{
options = {
group = mkOption {
@ -385,12 +373,12 @@ in {
module = mkOption {
description = "Custom type module";
type = types.unspecified;
default = {};
default = { };
};
};
}
gvkKeyFn;
default = {};
default = { };
};
objects = mkOption {
@ -398,8 +386,7 @@ in {
type = types.listOf types.attrs;
apply = items:
sort
(
r1: r2:
(r1: r2:
if elem r1.kind cfg.resourceOrder && elem r2.kind cfg.resourceOrder
then indexOf cfg.resourceOrder r1.kind < indexOf cfg.resourceOrder r2.kind
else if elem r1.kind cfg.resourceOrder
@ -407,7 +394,7 @@ in {
else false
)
(unique items);
default = [];
default = [ ];
};
generated = mkOption {
@ -428,12 +415,12 @@ in {
config = {
# features that module is defining
_m.features = ["k8s"];
_m.features = [ "k8s" ];
# module propagation options
_m.propagate = [
{
features = ["k8s"];
features = [ "k8s" ];
module = _: {
# propagate kubernetes version and namespace
kubernetes.version = mkDefault cfg.version;
@ -441,8 +428,8 @@ in {
};
}
{
features = ["k8s" "submodule"];
module = {config, ...}: {
features = [ "k8s" "submodule" ];
module = { config, ... }: {
# set module defaults
kubernetes.api.defaults =
(filter (default: default.propagate) cfg.api.defaults)
@ -460,24 +447,21 @@ in {
];
# expose k8s helper methods as module argument
_module.args.k8s = import ../lib/k8s {inherit lib;};
_module.args.k8s = import ../lib/k8s { inherit lib; };
kubernetes.api = mkMerge ([
{
# register custom types
types =
mapAttrsToList
types = mapAttrsToList
(_: cr: {
inherit (cr) name group version kind attrName;
})
cfg.customTypes;
defaults = [
{
defaults = [{
default = {
# set default kubernetes namespace to all resources
metadata.namespace =
mkIf (config.kubernetes.namespace != null)
metadata.namespace = mkIf (config.kubernetes.namespace != null)
(mkDefault config.kubernetes.namespace);
# set project name to all resources
@ -486,14 +470,14 @@ in {
"kubenix/k8s-version" = cfg.version;
};
};
}
];
}];
}
]
++
# import of yaml files
(map
(i: let
(i:
let
# load yaml file
object = importYAML i;
groupVersion = splitString "/" object.apiVersion;
@ -504,14 +488,14 @@ in {
then "core"
else head groupVersion;
inherit (object) kind;
in {
in
{
resources.${group}.${version}.${kind}.${name} = object;
})
cfg.imports));
kubernetes.objects = flatten (mapAttrsToList
(
_: type:
(_: type:
mapAttrsToList (_name: moduleToAttrs)
cfg.api.resources.${type.group}.${type.version}.${type.kind}
)

View file

@ -1,10 +1,6 @@
{
config,
lib,
...
}:
{ config, lib, ... }:
with lib; {
imports = [./base.nix];
imports = [ ./base.nix ];
options.submodule = {
name = mkOption {
@ -27,24 +23,24 @@ with lib; {
tags = mkOption {
description = "List of submodule tags";
type = types.listOf types.str;
default = [];
default = [ ];
};
exports = mkOption {
description = "Attribute set of functions to export";
type = types.attrs;
default = {};
default = { };
};
passthru = mkOption {
description = "Attribute set to passthru";
type = types.attrs;
default = {};
default = { };
};
args._empty = mkOption {};
args._empty = mkOption { };
};
config._module.args.args = config.submodule.args;
config._m.features = ["submodule"];
config._m.features = [ "submodule" ];
}

View file

@ -1,11 +1,4 @@
{
config,
options,
kubenix,
pkgs,
lib,
...
}:
{ config, options, kubenix, pkgs, lib, ... }:
with lib; let
cfg = config.submodules;
parentConfig = config;
@ -18,15 +11,9 @@ with lib; let
else requiredVersion == version
else true;
getDefaults = {
name,
version,
tags,
features,
}:
getDefaults = { name, version, tags, features }:
catAttrs "default" (filter
(
submoduleDefault:
(submoduleDefault:
(submoduleDefault.name == null || submoduleDefault.name == name)
&& (matchesVersion submoduleDefault.version version)
&& (
@ -40,31 +27,22 @@ with lib; let
)
config.submodules.defaults);
specialArgs =
cfg.specialArgs
// {
specialArgs = cfg.specialArgs // {
parentConfig = config;
};
findSubmodule = {
name,
version ? null,
latest ? true,
}: let
matchingSubmodules =
filter
(
el:
findSubmodule = { name, version ? null, latest ? true }:
let
matchingSubmodules = filter
(el:
el.definition.name
== name
&& (matchesVersion version el.definition.version)
)
cfg.imports;
versionSortedSubmodules =
sort
(
s1: s2:
versionSortedSubmodules = sort
(s1: s2:
if builtins.compareVersions s1.definition.version s2.definition.version > 0
then true
else false
@ -83,57 +61,52 @@ with lib; let
in
matchingModule;
passthruConfig =
mapAttrsToList
passthruConfig = mapAttrsToList
(name: _opt: {
${name} = mkMerge (mapAttrsToList
(
_: inst:
(_: inst:
if inst.passthru.enable
then inst.config.submodule.passthru.${name} or {}
else {}
then inst.config.submodule.passthru.${name} or { }
else { }
)
config.submodules.instances);
_module.args = mkMerge (mapAttrsToList
(
_: inst:
(_: inst:
if inst.passthru.enable
then inst.config.submodule.passthru._module.args or {}
else {}
then inst.config.submodule.passthru._module.args or { }
else { }
)
config.submodules.instances);
})
(removeAttrs options ["_definedNames" "_module" "_m" "submodules"]);
(removeAttrs options [ "_definedNames" "_module" "_m" "submodules" ]);
submoduleWithSpecialArgs = opts: specialArgs: let
submoduleWithSpecialArgs = opts: specialArgs:
let
opts' = toList opts;
inherit (lib.modules) evalModules;
in
mkOptionType rec {
name = "submodule";
check = x: isAttrs x || isFunction x;
merge = loc: defs: let
merge = loc: defs:
let
coerce = def:
if isFunction def
then def
else {config = def;};
modules =
opts'
++ map (def: {
else { config = def; };
modules = opts' ++ map
(def: {
_file = def.file;
imports = [(coerce def.value)];
imports = [ (coerce def.value) ];
})
defs;
in
(evalModules {
inherit modules specialArgs;
prefix = loc;
})
.config;
getSubOptions = prefix:
(evalModules
{
}).config;
getSubOptions = prefix: (evalModules {
modules = opts';
inherit prefix specialArgs;
# This is a work-around due to the fact that some sub-modules,
@ -152,27 +125,25 @@ with lib; let
# would be used, and use of `<` and `>` would break the XML document.
# It shouldn't cause an issue since this is cosmetic for the manual.
args.name = "name";
})
.options;
}).options;
getSubModules = opts';
substSubModules = m: submoduleWithSpecialArgs m specialArgs;
functor =
(defaultFunctor name)
// {
functor = (defaultFunctor name) // {
# Merging of submodules is done as part of mergeOptionDecls, as we have to annotate
# each submodule with its location.
payload = [];
binOp = _lhs: _rhs: [];
payload = [ ];
binOp = _lhs: _rhs: [ ];
};
};
in {
imports = [./base.nix];
in
{
imports = [ ./base.nix ];
options = {
submodules.specialArgs = mkOption {
description = "Special args to pass to submodules. These arguments can be used for imports";
type = types.attrs;
default = {};
default = { };
};
submodules.defaults = mkOption {
@ -197,23 +168,23 @@ in {
tags = mkOption {
description = "List of tags to apply defaults for";
type = types.listOf types.str;
default = [];
default = [ ];
};
features = mkOption {
description = "List of features that submodule has to have to apply defaults";
type = types.listOf types.str;
default = [];
default = [ ];
};
default = mkOption {
description = "Default to apply to submodule instance";
type = types.unspecified;
default = {};
default = { };
};
};
}));
default = [];
default = [ ];
};
submodules.propagate.enable = mkOption {
@ -227,30 +198,25 @@ in {
type = types.listOf (
types.coercedTo
types.path
(module: {inherit module;})
(module: { inherit module; })
(
types.submodule ({
name,
config,
...
}: let
types.submodule ({ name, config, ... }:
let
evaledSubmodule' = evalModules {
inherit specialArgs;
modules =
config.modules
++ [./base.nix]
++ [
{
modules = config.modules
++ [ ./base.nix ]
++ [{
_module.args.check = false;
}
];
}];
};
evaledSubmodule =
if (!(elem "submodule" evaledSubmodule'.config._m.features))
then throw "no submodule defined"
else evaledSubmodule';
in {
in
{
options = {
module = mkOption {
description = "Module defining submodule";
@ -260,7 +226,7 @@ in {
modules = mkOption {
description = "List of modules defining submodule";
type = types.listOf types.unspecified;
default = [config.module];
default = [ config.module ];
};
features = mkOption {
@ -290,18 +256,14 @@ in {
})
)
);
default = [];
default = [ ];
};
submodules.instances = mkOption {
description = "Attribute set of submodule instances";
default = {};
type = types.attrsOf (types.submodule ({
name,
config,
options,
...
}: let
default = { };
type = types.attrsOf (types.submodule ({ name, config, options, ... }:
let
# submodule associated with
submodule = findSubmodule {
name = config.submodule;
@ -318,7 +280,8 @@ in {
inherit (submoduleDefinition) tags;
inherit (submodule) features;
};
in {
in
{
options = {
name = mkOption {
description = "Submodule instance name";
@ -349,17 +312,16 @@ in {
config = mkOption {
description = "Submodule instance ${config.name} for ${submoduleDefinition.name}:${submoduleDefinition.version} config";
type =
submoduleWithSpecialArgs
({...}: {
imports = submodule.modules ++ defaults ++ [./base.nix];
type = submoduleWithSpecialArgs
({ ... }: {
imports = submodule.modules ++ defaults ++ [ ./base.nix ];
_module.args.pkgs = pkgs;
_module.args.name = config.name;
_module.args.submodule = config;
submodule.args = mkAliasDefinitions options.args;
})
specialArgs;
default = {};
default = { };
};
args = mkOption {
@ -368,7 +330,7 @@ in {
};
}));
};
default = {};
default = { };
};
config = mkMerge ([
@ -380,19 +342,17 @@ in {
})
(filter (submodule: submodule.exportAs != null) cfg.imports));
_m.features = ["submodules"];
_m.features = [ "submodules" ];
submodules.specialArgs.kubenix = kubenix;
# passthru kubenix.project to submodules
submodules.defaults = mkMerge [
[
{
[{
default = {
kubenix.project = parentConfig.kubenix.project;
};
}
]
}]
(map
(propagate: {
@ -405,17 +365,15 @@ in {
(mkIf cfg.propagate.enable {
# if propagate is enabled and submodule has submodules included propagage defaults and imports
submodules.defaults = [
{
features = ["submodules"];
submodules.defaults = [{
features = [ "submodules" ];
default = {
submodules = {
inherit (cfg) defaults;
inherit (cfg) imports;
};
};
}
];
}];
})
]
++ passthruConfig);

View file

@ -1,15 +1,9 @@
{
config,
pkgs,
lib,
kubenix,
...
}:
{ config, pkgs, lib, kubenix, ... }:
with lib; let
cfg = config.testing;
testModule = {
imports = [./evalTest.nix];
imports = [ ./evalTest.nix ];
# passthru testing configuration
config._module.args = {
@ -18,9 +12,9 @@ with lib; let
};
};
isTestEnabled = test:
(cfg.enabledTests == null || elem test.name cfg.enabledTests) && test.enable;
in {
isTestEnabled = test: (cfg.enabledTests == null || elem test.name cfg.enabledTests) && test.enable;
in
{
imports = [
./docker.nix
./driver/kubetest.nix
@ -48,23 +42,23 @@ in {
features = mkOption {
description = "List of features that test has to have to apply options";
type = types.listOf types.str;
default = [];
default = [ ];
};
options = mkOption {
description = "Options to apply to test";
type = types.unspecified;
default = {};
apply = default: {_file = "testing.common";} // default;
default = { };
apply = default: { _file = "testing.common"; } // default;
};
};
}));
default = [];
default = [ ];
};
tests = mkOption {
description = "List of test cases";
default = [];
default = [ ];
type = types.listOf (types.coercedTo types.path
(module: {
inherit module;
@ -88,7 +82,7 @@ in {
args = mkOption {
description = "Attribute set of extra args passed to tests";
type = types.attrs;
default = {};
default = { };
};
success = mkOption {

View file

@ -1,17 +1,13 @@
{
config,
lib,
pkgs,
...
}:
{ config, lib, pkgs, ... }:
with lib;
with import ../../lib/docker {inherit lib pkgs;}; let
with import ../../lib/docker { inherit lib pkgs; }; let
inherit (config) testing;
allImages = unique (flatten (map (t: t.evaled.config.docker.export or []) testing.tests));
allImages = unique (flatten (map (t: t.evaled.config.docker.export or [ ]) testing.tests));
cfg = config.testing.docker;
in {
in
{
options.testing.docker = {
registryUrl = mkOption {
description = "Docker registry url";
@ -38,13 +34,11 @@ in {
};
};
config.testing.common = [
{
features = ["docker"];
config.testing.common = [{
features = [ "docker" ];
options = {
_file = "testing.docker.registryUrl";
docker.registry.url = cfg.registryUrl;
};
}
];
}];
}

View file

@ -1,23 +1,15 @@
{
lib,
config,
pkgs,
...
}:
{ lib, config, pkgs, ... }:
with lib; let
inherit (config) testing;
cfg = testing.driver.kubetest;
kubetest = import ./kubetestdrv.nix {inherit pkgs;};
kubetest = import ./kubetestdrv.nix { inherit pkgs; };
pythonEnv = pkgs.python38.withPackages (ps:
with ps;
[
pythonEnv = pkgs.python38.withPackages (ps: with ps; [
pytest
kubetest
kubernetes
]
++ cfg.extraPackages);
] ++ cfg.extraPackages);
toTestScript = t:
if isString t.script
@ -28,7 +20,8 @@ with lib; let
''
else t.script;
tests = let
tests =
let
# make sure tests are prefixed so that alphanumerical
# sorting reproduces them in the same order as they
# have been declared in the list.
@ -43,9 +36,11 @@ with lib; let
);
op = i: t: {
path = toTestScript t;
name = let
name =
let
prefix = lib.fixedWidthNumber listLengthPadding i;
in "${prefix}_${t.name}_test.py";
in
"${prefix}_${t.name}_test.py";
};
in
pkgs.linkFarm "${testing.name}-tests" (
@ -56,7 +51,8 @@ with lib; let
#!/usr/bin/env bash
${pythonEnv}/bin/pytest -p no:cacheprovider ${tests} $@
'';
in {
in
{
options.testing.driver.kubetest = {
defaultHeader = mkOption {
type = types.lines;
@ -69,7 +65,7 @@ in {
extraPackages = mkOption {
type = types.listOf types.package;
description = "Extra packages to pass to tests";
default = [];
default = [ ];
};
};

View file

@ -1,14 +1,14 @@
{pkgs ? import <nixpkgs> {}}:
{ pkgs ? import <nixpkgs> { } }:
with pkgs;
with pkgs.python38Packages;
with pkgs.python38;
pkgs.python38Packages.buildPythonPackage rec {
pkgs.python38Packages.buildPythonPackage rec {
pname = "kubetest";
version = "0.9.5";
src = fetchPypi {
inherit pname version;
sha256 = "sha256-TqDHMciAEXv4vMWLJY1YdtXsP4ho+INgdFB3xQQNoZU=";
};
propagatedBuildInputs = [pytest kubernetes];
propagatedBuildInputs = [ pytest kubernetes ];
doCheck = false;
}
}

View file

@ -1,10 +1,4 @@
{
lib,
config,
testing,
kubenix,
...
}:
{ lib, config, testing, kubenix, ... }:
with lib; let
modules = [
# testing module
@ -29,13 +23,9 @@ with lib; let
# eval without checking
evaled' = kubenix.evalModules {
modules =
modules
++ [
{
modules = modules ++ [{
_module.args.check = false;
}
];
}];
};
# test configuration
@ -45,10 +35,8 @@ with lib; let
testFeatures = evaled'.config._m.features;
# common options that can be applied on this test
commonOpts =
filter
(
d:
commonOpts = filter
(d:
(intersectLists d.features testFeatures)
== d.features
|| (length d.features) == 0
@ -59,7 +47,8 @@ with lib; let
modulesWithCommonOptions = modules ++ (map (d: d.options) commonOpts);
# evaled test
evaled = let
evaled =
let
evaled' = kubenix.evalModules {
modules = modulesWithCommonOptions;
};
@ -69,7 +58,8 @@ with lib; let
else if (builtins.tryEval evaled'.config.test.assertions).success
then evaled'
else null;
in {
in
{
options = {
module = mkOption {
description = "Module defining kubenix test";
@ -112,7 +102,7 @@ in {
description = "Test result";
type = types.unspecified;
internal = true;
default = [];
default = [ ];
};
script = mkOption {

View file

@ -1,9 +1,4 @@
{
lib,
config,
pkgs,
...
}:
{ lib, config, pkgs, ... }:
with lib; let
inherit (config) testing;
@ -34,7 +29,8 @@ with lib; let
echo "--> running tests"
${testing.testScript} --kube-config=$KUBECONFIG
'';
in {
in
{
options.testing.runtime.local = {
script = mkOption {
type = types.package;

View file

@ -1,10 +1,5 @@
# nixos-k8s implements nixos kubernetes testing runtime
{
config,
pkgs,
lib,
...
}:
{ config, pkgs, lib, ... }:
with lib; let
inherit (config) testing;
# kubeconfig = "/etc/${config.services.kubernetes.pki.etcClusterAdminKubeconfig}";
@ -12,15 +7,15 @@ with lib; let
kubecerts = "/var/lib/kubernetes/secrets";
# how we differ from the standard configuration of mkKubernetesBaseTest
extraConfiguration = {config, ...}: {
extraConfiguration = { config, ... }: {
virtualisation = {
memorySize = 2048;
};
networking = {
nameservers = ["10.0.0.254"];
nameservers = [ "10.0.0.254" ];
firewall = {
trustedInterfaces = ["docker0" "cni0"];
trustedInterfaces = [ "docker0" "cni0" ];
};
};
@ -29,8 +24,7 @@ with lib; let
kubelet = {
seedDockerImages = testing.docker.images;
networkPlugin = "cni";
cni.config = [
{
cni.config = [{
name = "mynet";
type = "bridge";
bridge = "cni0";
@ -41,14 +35,11 @@ with lib; let
type = "host-local";
subnet = "10.1.0.0/16";
gateway = "10.1.0.1";
routes = [
{
routes = [{
dst = "0.0.0.0/0";
}
];
}];
};
}
];
}];
};
};
@ -58,8 +49,8 @@ with lib; let
services.copy-certs = {
description = "Share k8s certificates with host";
script = "cp -rf ${kubecerts} /tmp/xchg/; cp -f ${kubeconfig} /tmp/xchg/;";
after = ["kubernetes.target"];
wantedBy = ["multi-user.target"];
after = [ "kubernetes.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
@ -72,7 +63,8 @@ with lib; let
machine1.succeed("${testing.testScript} --kube-config=${kubeconfig}")
'';
test = with import "${pkgs.path}/nixos/tests/kubernetes/base.nix" {
test = with import "${pkgs.path}/nixos/tests/kubernetes/base.nix"
{
inherit pkgs;
inherit (pkgs) system;
};
@ -81,7 +73,8 @@ with lib; let
inherit (config.testing) name;
test = script;
};
in {
in
{
options.testing.runtime.nixos-k8s = {
driver = mkOption {
description = "Test driver";

View file

@ -1,8 +1,4 @@
{
lib,
config,
...
}:
{ lib, config, ... }:
with lib; {
options.test = {
name = mkOption {
@ -36,13 +32,11 @@ with lib; {
};
};
});
default = [];
example = [
{
default = [ ];
example = [{
assertion = false;
message = "you can't enable this for some reason";
}
];
}];
description = ''
This option allows modules to express conditions that must
hold for the evaluation of the system configuration to

View file

@ -1,7 +1,6 @@
{
stdenv,
kubernetes,
installShellFiles,
{ stdenv
, kubernetes
, installShellFiles
}:
stdenv.mkDerivation {
name = "kubectl-${kubernetes.version}";
@ -10,9 +9,9 @@ stdenv.mkDerivation {
# split out (see homepage)
dontUnpack = true;
nativeBuildInputs = [installShellFiles];
nativeBuildInputs = [ installShellFiles ];
outputs = ["out" "man"];
outputs = [ "out" "man" ];
installPhase = ''
install -D ${kubernetes}/bin/kubectl -t $out/bin

View file

@ -1,21 +1,20 @@
{
stdenv,
lib,
fetchFromGitHub,
removeReferencesTo,
which,
go,
makeWrapper,
rsync,
installShellFiles,
components ? [
{ stdenv
, lib
, fetchFromGitHub
, removeReferencesTo
, which
, go
, makeWrapper
, rsync
, installShellFiles
, components ? [
"cmd/kubelet"
"cmd/kube-apiserver"
"cmd/kube-controller-manager"
"cmd/kube-proxy"
"cmd/kube-scheduler"
"test/e2e/e2e.test"
],
]
}:
stdenv.mkDerivation rec {
pname = "kubernetes";
@ -28,11 +27,11 @@ stdenv.mkDerivation rec {
hash = "sha256-r9Clwr+87Ns4VXUW9F6cgks+LknY39ngbQgZ5UMZ0Vo=";
};
nativeBuildInputs = [removeReferencesTo makeWrapper which go rsync installShellFiles];
nativeBuildInputs = [ removeReferencesTo makeWrapper which go rsync installShellFiles ];
outputs = ["out" "man" "pause"];
outputs = [ "out" "man" "pause" ];
patches = [./fixup-addonmanager-lib-path.patch];
patches = [ ./fixup-addonmanager-lib-path.patch ];
postPatch = ''
# go env breaks the sandbox
@ -84,7 +83,7 @@ stdenv.mkDerivation rec {
description = "Production-Grade Container Scheduling and Management";
license = licenses.asl20;
homepage = "https://kubernetes.io";
maintainers = with maintainers; [johanot offline saschagrunert];
maintainers = with maintainers; [ johanot offline saschagrunert ];
platforms = platforms.unix;
};
}

View file

@ -1,37 +1,28 @@
{
pkgs,
lib,
}: let
{ pkgs, lib }:
let
generateIstio = import ./istio {
inherit
pkgs
lib
;
inherit pkgs lib;
};
generateK8S = name: spec:
import ./k8s {
inherit
name
pkgs
lib
spec
;
inherit name pkgs lib spec;
};
in {
istio = pkgs.linkFarm "istio-generated" [
{
in
{
istio = pkgs.linkFarm "istio-generated" [{
name = "latest.nix";
path = generateIstio;
}
];
}];
k8s = pkgs.linkFarm "k8s-generated" (
builtins.attrValues (
builtins.mapAttrs (
version: sha: let
builtins.mapAttrs
(version: sha:
let
short = builtins.concatStringsSep "." (lib.lists.sublist 0 2 (builtins.splitVersion version));
in {
in
{
name = "v${short}.nix";
path = generateK8S "v${short}" (builtins.fetchurl {
url = "https://github.com/kubernetes/kubernetes/raw/v${version}/api/openapi-spec/swagger.json";

View file

@ -1,7 +1,6 @@
{
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 {
@ -20,14 +19,9 @@ with lib; let
then "null"
else builtins.toString value;
removeEmptyLines = str: concatStringsSep "\n" (filter (l: builtins.match "[[:space:]]*" l != []) (splitString "\n" str));
removeEmptyLines = str: concatStringsSep "\n" (filter (l: builtins.match "[[:space:]]*" l != [ ]) (splitString "\n" str));
mkOption = {
description ? null,
type ? null,
default ? null,
apply ? null,
}:
mkOption = { description ? null, type ? null, default ? null, apply ? null }:
removeEmptyLines '' mkOption {
${optionalString (description != null) "description = ${builtins.toJSON description};"}
${optionalString (type != null) ''type = ${type};''}
@ -53,7 +47,7 @@ with lib; let
hasTypeMapping = def:
hasAttr "type" def
&& elem def.type ["string" "integer" "boolean"];
&& elem def.type [ "string" "integer" "boolean" ];
mergeValuesByKey = mergeKey: ''(mergeValuesByKey "${mergeKey}")'';
@ -84,14 +78,12 @@ with lib; let
refDefinition = attr: head (tail (tail (splitString "/" attr."$ref")));
};
fixJSON = replaceStrings ["\\u"] ["u"];
fixJSON = replaceStrings [ "\\u" ] [ "u" ];
fetchSpecs = path: builtins.fromJSON (fixJSON (builtins.readFile path));
genDefinitions = swagger:
with gen; (mapAttrs
(
_name: 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}"
@ -100,11 +92,10 @@ with lib; let
type = mapType definition;
}
else {
options =
mapAttrs
(
propName: property: let
isRequired = elem propName (definition.required or []);
options = mapAttrs
(propName: property:
let
isRequired = elem propName (definition.required or [ ]);
requiredOrNot = type:
if isRequired
then type
@ -142,9 +133,11 @@ with lib; let
# 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
then
let
mergeKey = property."x-kubernetes-patch-merge-key";
in {
in
{
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey);
apply = attrsToList;
}
@ -190,12 +183,11 @@ with lib; let
// optionProperties)
)
definition.properties;
config = let
optionalProps =
filterAttrs
(
propName: _property:
!(elem propName (definition.required or []))
config =
let
optionalProps = filterAttrs
(propName: _property:
!(elem propName (definition.required or [ ]))
)
definition.properties;
in
@ -204,8 +196,7 @@ with lib; let
)
swagger.definitions);
genResources = swagger:
(mapAttrsToList
genResources = swagger: (mapAttrsToList
(_name: property: rec {
splittedType = splitString "." (removePrefix "me.snowdrop.istio.api." property.javaType);
group = (concatStringsSep "." (take ((length splittedType) - 2) splittedType)) + ".istio.io";
@ -214,8 +205,7 @@ with lib; let
ref = removePrefix "#/definitions/" property."$ref";
})
(filterAttrs
(
_name: property:
(_name: property:
(hasPrefix "me.snowdrop.istio.api" property.javaType)
&& hasSuffix "Spec" property.javaType
)
@ -229,8 +219,7 @@ with lib; let
ref = removePrefix "#/definitions/" property."$ref";
})
(filterAttrs
(
_name: property:
(_name: property:
(hasPrefix "me.snowdrop.istio.mixer" property.javaType)
&& hasSuffix "Spec" property.javaType
)
@ -367,14 +356,14 @@ with lib; let
}
'';
in
pkgs.runCommand "istio-gen.nix"
{
buildInputs = [pkgs.nixpkgs-fmt];
} ''
pkgs.runCommand "istio-gen.nix"
{
buildInputs = [ pkgs.nixpkgs-fmt ];
} ''
cat << 'GENERATED' > ./raw
"${generated}"
GENERATED
nixpkgs-fmt ./raw
cp ./raw $out
''
''

View file

@ -1,9 +1,4 @@
{
name,
pkgs,
lib,
spec,
}:
{ name, pkgs, lib, spec }:
with lib; let
gen = rec {
mkMerge = values: ''mkMerge [${concatMapStrings
@ -21,14 +16,9 @@ with lib; let
then "null"
else builtins.toString value;
removeEmptyLines = str: concatStringsSep "\n" (filter (l: builtins.match "[[:space:]]*" l != []) (splitString "\n" str));
removeEmptyLines = str: concatStringsSep "\n" (filter (l: builtins.match "[[:space:]]*" l != [ ]) (splitString "\n" str));
mkOption = {
description ? null,
type ? null,
default ? null,
apply ? null,
}:
mkOption = { description ? null, type ? null, default ? null, apply ? null }:
removeEmptyLines '' mkOption {
${optionalString (description != null) "description = ${builtins.toJSON description};"}
${optionalString (type != null) ''type = ${type};''}
@ -52,9 +42,7 @@ with lib; let
loaOf = type: "(types.loaOf ${type})";
};
hasTypeMapping = def:
hasAttr "type" def
&& elem def.type ["string" "integer" "boolean"];
hasTypeMapping = def: hasAttr "type" def && elem def.type [ "string" "integer" "boolean" ];
mergeValuesByKey = mergeKey: ''(mergeValuesByKey "${mergeKey}")'';
@ -87,7 +75,8 @@ with lib; let
refType = attr: head (tail (tail (splitString "/" attr."$ref")));
compareVersions = ver1: ver2: let
compareVersions = ver1: ver2:
let
getVersion = substring 1 10;
splitVersion = v: builtins.splitVersion (getVersion v);
isAlpha = v: elem "alpha" (splitVersion v);
@ -103,27 +92,25 @@ with lib; let
in
builtins.compareVersions v1 v2;
fixJSON = replaceStrings ["\\u"] ["u"];
fixJSON = replaceStrings [ "\\u" ] [ "u" ];
fetchSpecs = path: builtins.fromJSON (fixJSON (builtins.readFile path));
genDefinitions = swagger:
with gen;
mapAttrs
(
_name: 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 {}
then { }
# in other case it's an actual definition
else {
options =
mapAttrs
(
propName: property: let
isRequired = elem propName (definition.required or []);
propName: property:
let
isRequired = elem propName (definition.required or [ ]);
requiredOrNot = type:
if isRequired
then type
@ -159,11 +146,13 @@ with lib; let
else
# make it an attribute set of submodules if only x-kubernetes-patch-merge-key is present, or
# x-kubernetes-patch-merge-key == x-kubernetes-list-map-keys.
if (hasAttr "x-kubernetes-patch-merge-key" property) && (!(hasAttr "x-kubernetes-list-map-keys" property) || (property."x-kubernetes-list-map-keys" == [property."x-kubernetes-patch-merge-key"]))
then let
if (hasAttr "x-kubernetes-patch-merge-key" property) && (!(hasAttr "x-kubernetes-list-map-keys" property) || (property."x-kubernetes-list-map-keys" == [ property."x-kubernetes-patch-merge-key" ]))
then
let
mergeKey = property."x-kubernetes-patch-merge-key";
in {
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey []);
in
{
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey [ ]);
apply = attrsToList;
}
# in other case it's a simple list
@ -173,13 +162,15 @@ with lib; let
if
hasAttr "properties" swagger.definitions.${refDefinition property.items}
&& hasAttr "name" swagger.definitions.${refDefinition property.items}.properties
then let
then
let
mergeKey = "name";
in {
in
{
type = requiredOrNot (coerceAttrsOfSubmodulesToListByKey (refDefinition property.items) mergeKey (
if hasAttr "x-kubernetes-list-map-keys" property
then property."x-kubernetes-list-map-keys"
else []
else [ ]
));
apply = attrsToList;
}
@ -227,12 +218,13 @@ with lib; let
// optionProperties)
)
definition.properties;
config = let
config =
let
optionalProps =
filterAttrs
(
propName: _property:
!(elem propName (definition.required or []))
!(elem propName (definition.required or [ ]))
)
definition.properties;
in
@ -241,10 +233,8 @@ with lib; let
)
swagger.definitions;
mapCharPairs = f: s1: s2:
concatStrings (imap0
(
i: c1:
mapCharPairs = f: s1: s2: concatStrings (imap0
(i: c1:
f i c1 (
if i >= stringLength s2
then ""
@ -253,10 +243,8 @@ with lib; let
)
(stringToCharacters s1));
getAttrName = resource: kind:
mapCharPairs
(
i: c1: c2:
getAttrName = resource: kind: mapCharPairs
(i: c1: c2:
if hasPrefix "API" kind && i == 0
then "A"
else if i == 0
@ -268,9 +256,9 @@ with lib; let
resource
kind;
genResourceTypes = swagger:
mapAttrs'
(name: path: let
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;
@ -309,10 +297,8 @@ with lib; let
})
resourceTypes);
resourcesTypesByKindSortByVersion =
mapAttrs
(
_kind: resourceTypes:
resourcesTypesByKindSortByVersion = mapAttrs
(_kind: resourceTypes:
reverseList (sort
(
r1: r2:
@ -322,8 +308,7 @@ with lib; let
)
resourceTypesByKind;
latestResourceTypesByKind =
mapAttrs (_kind: last) resourcesTypesByKindSortByVersion;
latestResourceTypesByKind = mapAttrs (_kind: last) resourcesTypesByKindSortByVersion;
genResourceOptions = resource:
with gen; let
@ -338,7 +323,7 @@ with lib; let
mkOption {
inherit (resource) description;
type = types.attrsOf (submoduleForDefinition' resource);
default = {};
default = { };
};
generated = ''
@ -530,14 +515,14 @@ with lib; let
}
'';
in
pkgs.runCommand "k8s-${name}-gen.nix"
{
buildInputs = [pkgs.nixpkgs-fmt];
} ''
pkgs.runCommand "k8s-${name}-gen.nix"
{
buildInputs = [ pkgs.nixpkgs-fmt ];
} ''
cat << 'GENERATED' > ./raw
${generated}
GENERATED
nixpkgs-fmt ./raw
cp ./raw $out
''
''

View file

@ -1,23 +1,19 @@
{
kubectl,
vals,
colordiff,
evalModules,
runCommand,
writeShellScript,
module ? {},
specialArgs ? {},
}: let
kubernetes =
(evalModules {
{ kubectl
, vals
, colordiff
, evalModules
, runCommand
, writeShellScript
, module ? { }
, specialArgs ? { }
}:
let
kubernetes = (evalModules {
inherit module specialArgs;
})
.config
.kubernetes
or {};
}).config.kubernetes or { };
in
runCommand "kubenix"
{
runCommand "kubenix"
{
kubeconfig = kubernetes.kubeconfig or "";
result = kubernetes.result or "";
@ -27,7 +23,7 @@ in
diff = writeShellScript "kubenix-diff" ''
${colordiff}/bin/colordiff --nobanner -N -u -I ' kubenix/hash: ' -I ' generation: ' $@
'';
} ''
} ''
set -euo pipefail
mkdir -p $out/bin
@ -96,4 +92,4 @@ in
EOF
chmod +x $out/bin/kubenix
''
''

View file

@ -1,20 +1,15 @@
{
system ? builtins.currentSystem,
evalModules ? (import ../. {}).evalModules.${system},
}: {
k8sVersion ? "1.23",
registry ? throw "Registry url not defined",
doThrowError ? true, # whether any testing error should throw an error
enabledTests ? null,
}: let
{ system ? builtins.currentSystem, evalModules ? (import ../. { }).evalModules.${system} }:
{ k8sVersion ? "1.23"
, registry ? throw "Registry url not defined"
, doThrowError ? true
# whether any testing error should throw an error
, enabledTests ? null
}:
let
inherit
((evalModules {
module = {
kubenix,
pkgs,
...
}: {
imports = [kubenix.modules.testing];
module = { kubenix, pkgs, ... }: {
imports = [ kubenix.modules.testing ];
testing = {
inherit doThrowError enabledTests;
@ -38,21 +33,19 @@
./submodules/passthru.nix
];
args = {images = pkgs.callPackage ./images.nix {};};
args = { images = pkgs.callPackage ./images.nix { }; };
docker.registryUrl = registry;
common = [
{
features = ["k8s"];
common = [{
features = [ "k8s" ];
options = {
kubernetes.version = k8sVersion;
};
}
];
}];
};
};
}))
config
;
in
config.testing // {recurseForDerivations = true;}
config.testing // { recurseForDerivations = true; }

View file

@ -1,11 +1,4 @@
{
config,
lib,
pkgs,
kubenix,
helm,
...
}:
{ config, lib, pkgs, kubenix, helm, ... }:
with lib;
with kubenix.lib;
with pkgs.dockerTools; let
@ -35,8 +28,9 @@ with pkgs.dockerTools; let
finalImageName = "docker.io/bitnami/bitnami-shell";
finalImageTag = "10";
};
in {
imports = [kubenix.modules.test kubenix.modules.helm kubenix.modules.k8s kubenix.modules.docker];
in
{
imports = [ kubenix.modules.test kubenix.modules.helm kubenix.modules.k8s kubenix.modules.docker ];
docker.images = {
postgresql.image = postgresql;

View file

@ -1,18 +1,14 @@
{
pkgs,
dockerTools,
lib,
...
}:
{ pkgs, dockerTools, lib, ... }:
with lib; {
curl = dockerTools.buildLayeredImage {
name = "curl";
tag = "latest";
config.Cmd = ["${pkgs.bash}" "-c" "sleep infinity"];
contents = [pkgs.bash pkgs.curl pkgs.cacert];
config.Cmd = [ "${pkgs.bash}" "-c" "sleep infinity" ];
contents = [ pkgs.bash pkgs.curl pkgs.cacert ];
};
nginx = let
nginx =
let
nginxPort = "80";
nginxConf = pkgs.writeText "nginx.conf" ''
user nginx nginx;
@ -38,7 +34,7 @@ with lib; {
dockerTools.buildLayeredImage {
name = "xtruder/nginx";
tag = "latest";
contents = [pkgs.nginx];
contents = [ pkgs.nginx ];
extraCommands = ''
mkdir -p etc
chmod u+w etc
@ -50,9 +46,9 @@ with lib; {
echo "nginx:x:1000:nginx" > etc/group
'';
config = {
Cmd = ["nginx" "-c" nginxConf];
Cmd = [ "nginx" "-c" nginxConf ];
ExposedPorts = {
"${nginxPort}/tcp" = {};
"${nginxPort}/tcp" = { };
};
};
};

View file

@ -1,5 +1,5 @@
{kubenix, ...}: {
imports = with kubenix.modules; [test k8s istio];
{ kubenix, ... }: {
imports = with kubenix.modules; [ test k8s istio ];
test = {
name = "istio-bookinfo";
@ -17,7 +17,7 @@
name = "http";
protocol = "HTTP";
};
hosts = ["*"];
hosts = [ "*" ];
}
];
};
@ -25,8 +25,8 @@
VirtualService.bookinfo = {
spec = {
hosts = ["*"];
gateways = ["bookinfo-gateway"];
hosts = [ "*" ];
gateways = [ "bookinfo-gateway" ];
http = [
{
match = [

View file

@ -1,24 +1,18 @@
{
config,
lib,
kubenix,
...
}:
{ config, lib, kubenix, ... }:
with lib; let
latestCrontab = config.kubernetes.api.resources.cronTabs.latest;
in {
imports = with kubenix.modules; [test k8s];
in
{
imports = with kubenix.modules; [ test k8s ];
test = {
name = "k8s-crd";
description = "Simple test tesing CRD";
enable = builtins.compareVersions config.kubernetes.version "1.8" >= 0;
assertions = [
{
assertions = [{
message = "Custom resource should have correct version set";
assertion = latestCrontab.apiVersion == "stable.example.com/v2";
}
];
}];
script = ''
@pytest.mark.applymanifest('${config.kubernetes.resultYAML}')
def test_testing_module(kube):

View file

@ -1,14 +1,10 @@
{
config,
lib,
kubenix,
...
}:
{ config, lib, kubenix, ... }:
with lib; let
inherit (config.kubernetes.api.resources.pods) pod1;
inherit (config.kubernetes.api.resources.pods) pod2;
in {
imports = with kubenix.modules; [test k8s];
in
{
imports = with kubenix.modules; [ test k8s ];
test = {
name = "k8s-defaults";
@ -29,7 +25,7 @@ in {
];
};
kubernetes.resources.pods.pod1 = {};
kubernetes.resources.pods.pod1 = { };
kubernetes.resources.pods.pod2 = {
metadata.labels.custom-label = "value";
@ -48,7 +44,7 @@ in {
}
{
resource = "pods";
default = {config, ...}: {
default = { config, ... }: {
config.metadata.annotations = mkIf (config.metadata.labels ? "custom-label") {
conditional-annotation = "value";
};

View file

@ -1,11 +1,4 @@
{
config,
lib,
kubenix,
images,
test,
...
}:
{ config, lib, kubenix, images, test, ... }:
with lib; let
cfg = config.kubernetes.api.resources.deployments.nginx;
image = images.nginx;
@ -17,17 +10,16 @@ with lib; let
inherit (config.kubernetes) namespace;
name = "curl";
};
spec.containers = [
{
spec.containers = [{
name = "curl";
image = config.docker.images.curl.path;
args = ["curl" "--retry" "20" "--retry-connrefused" "http://nginx"];
}
];
args = [ "curl" "--retry" "20" "--retry-connrefused" "http://nginx" ];
}];
spec.restartPolicy = "Never";
});
in {
imports = [kubenix.modules.test kubenix.modules.k8s kubenix.modules.docker];
in
{
imports = [ kubenix.modules.test kubenix.modules.k8s kubenix.modules.docker ];
test = {
name = "k8s-deployment";

View file

@ -1,14 +1,10 @@
{
config,
lib,
kubenix,
...
}:
{ config, lib, kubenix, ... }:
with lib; let
pod = config.kubernetes.api.resources.core.v1.Pod.test;
deployment = config.kubernetes.api.resources.apps.v1.Deployment.nginx-deployment;
in {
imports = with kubenix.modules; [test k8s];
in
{
imports = with kubenix.modules; [ test k8s ];
test = {
name = "k8s-imports";

View file

@ -1,11 +1,6 @@
{
config,
lib,
kubenix,
...
}:
{ config, lib, kubenix, ... }:
with lib; {
imports = with kubenix.modules; [test k8s];
imports = with kubenix.modules; [ test k8s ];
test = {
name = "k8s-order";
@ -39,7 +34,7 @@ with lib; {
plural = "crontabs";
singular = "crontab";
kind = "CronTab";
shortNames = ["ct"];
shortNames = [ "ct" ];
};
};
};
@ -62,7 +57,7 @@ with lib; {
}
];
kubernetes.resources.namespaces.test = {};
kubernetes.resources.namespaces.test = { };
kubernetes.resources."stable.example.com"."v1".CronTab.crontab.spec.schedule = "* * * * *";
}

View file

@ -1,11 +1,9 @@
{
config,
kubenix,
...
}: let
{ config, kubenix, ... }:
let
cfg = config.kubernetes.api.resources.pods.nginx;
in {
imports = [kubenix.modules.test kubenix.modules.k8s];
in
{
imports = [ kubenix.modules.test kubenix.modules.k8s ];
test = {
name = "k8s-simple";
@ -22,5 +20,5 @@ in {
];
};
kubernetes.resources.pods.nginx = {};
kubernetes.resources.pods.nginx = { };
}

View file

@ -1,13 +1,6 @@
{
name,
config,
lib,
kubenix,
images,
...
}:
{ name, config, lib, kubenix, images, ... }:
with lib; {
imports = with kubenix.modules; [test submodules k8s docker];
imports = with kubenix.modules; [ test submodules k8s docker ];
test = {
name = "k8s-submodule";
@ -26,14 +19,9 @@ with lib; {
kubernetes.namespace = "test-namespace";
submodules.imports = [
{
module = {
name,
config,
...
}: {
imports = with kubenix.modules; [submodule k8s docker];
submodules.imports = [{
module = { name, config, ... }: {
imports = with kubenix.modules; [ submodule k8s docker ];
config = {
submodule = {
@ -52,15 +40,12 @@ with lib; {
docker.images.nginx.image = images.nginx;
};
};
}
];
}];
kubernetes.api.defaults = [
{
kubernetes.api.defaults = [{
propagate = true;
default.metadata.labels.my-label = "my-value";
}
];
}];
submodules.instances.passthru = {
submodule = "test-submodule";

View file

@ -1,10 +1,4 @@
{
name,
config,
lib,
kubenix,
...
}:
{ name, config, lib, kubenix, ... }:
with lib; let
inherit (config.submodules.instances) instance1;
inherit (config.submodules.instances) instance2;
@ -13,8 +7,8 @@ with lib; let
inherit (config.submodules.instances) instance5;
inherit (config.submodules.instances) versioned-submodule;
submodule = {...}: {
imports = [kubenix.modules.submodule];
submodule = { ... }: {
imports = [ kubenix.modules.submodule ];
options.submodule.args = {
value = mkOption {
@ -28,8 +22,9 @@ with lib; let
};
};
};
in {
imports = with kubenix.modules; [test submodules];
in
{
imports = with kubenix.modules; [ test submodules ];
test = {
name = "submodules-defaults";
@ -80,7 +75,7 @@ in {
{
submodule = {
name = "submodule1";
tags = ["tag1"];
tags = [ "tag1" ];
};
}
];
@ -91,7 +86,7 @@ in {
{
submodule = {
name = "submodule2";
tags = ["tag2"];
tags = [ "tag2" ];
};
}
];
@ -102,7 +97,7 @@ in {
{
submodule = {
name = "submodule3";
tags = ["tag2"];
tags = [ "tag2" ];
};
}
];
@ -146,11 +141,11 @@ in {
default.submodule.args.defaultValue = mkDefault "value";
}
{
tags = ["tag1"];
tags = [ "tag1" ];
default.submodule.args.value = mkDefault "value1";
}
{
tags = ["tag2"];
tags = [ "tag2" ];
default.submodule.args.value = mkDefault "value2";
}
{
@ -158,7 +153,7 @@ in {
default.submodule.args.value = mkDefault "value4";
}
{
default = {config, ...}: {
default = { config, ... }: {
submodule.args.defaultValue = mkIf (config.submodule.args.value == "custom-value") "my-custom-value";
};
}

View file

@ -1,14 +1,7 @@
{
name,
config,
lib,
kubenix,
subm-lib,
...
}:
{ name, config, lib, kubenix, subm-lib, ... }:
with lib; let
submodule = {
imports = [kubenix.modules.submodule];
imports = [ kubenix.modules.submodule ];
config.submodule = {
name = "subm";
@ -17,8 +10,9 @@ with lib; let
};
};
};
in {
imports = with kubenix.modules; [test submodules];
in
{
imports = with kubenix.modules; [ test submodules ];
test = {
name = "submodules-exports";
@ -33,7 +27,7 @@ in {
submodules.imports = [
{
modules = [submodule];
modules = [ submodule ];
exportAs = "subm-lib";
}
];

View file

@ -1,27 +1,22 @@
{
name,
config,
lib,
kubenix,
...
}:
{ name, config, lib, kubenix, ... }:
with lib; let
submodule = {name, ...}: {
imports = [kubenix.modules.submodule];
submodule = { name, ... }: {
imports = [ kubenix.modules.submodule ];
config.submodule = {
name = "subm";
passthru.global.${name} = "true";
};
};
in {
imports = with kubenix.modules; [test submodules];
in
{
imports = with kubenix.modules; [ test submodules ];
options = {
global = mkOption {
description = "Global value";
type = types.attrs;
default = {};
default = { };
};
};
@ -45,11 +40,9 @@ in {
];
};
submodules.imports = [
{
modules = [submodule];
}
];
submodules.imports = [{
modules = [ submodule ];
}];
submodules.instances.inst1 = {
submodule = "subm";

View file

@ -1,15 +1,10 @@
{
name,
config,
lib,
kubenix,
...
}:
{ name, config, lib, kubenix, ... }:
with lib; let
cfg = config.submodules.instances.instance;
inherit (cfg.config.submodule) args;
in {
imports = with kubenix.modules; [test submodules];
in
{
imports = with kubenix.modules; [ test submodules ];
test = {
name = "submodules-simple";
@ -45,8 +40,8 @@ in {
submodules.propagate.enable = true;
submodules.imports = [
{
module = {submodule, ...}: {
imports = [kubenix.modules.submodule];
module = { submodule, ... }: {
imports = [ kubenix.modules.submodule ];
options.submodule.args = {
name = mkOption {
@ -62,7 +57,7 @@ in {
config = {
submodule.name = "submodule";
submodule.tags = ["tag"];
submodule.tags = [ "tag" ];
};
};
}

View file

@ -1,17 +1,11 @@
{
name,
config,
lib,
kubenix,
...
}:
{ name, config, lib, kubenix, ... }:
with lib; let
inst-exact = config.submodules.instances.inst-exact.config;
inst-regex = config.submodules.instances.inst-regex.config;
inst-latest = config.submodules.instances.inst-latest.config;
submodule = {
imports = [kubenix.modules.submodule];
imports = [ kubenix.modules.submodule ];
options.version = mkOption {
type = types.str;
@ -20,8 +14,9 @@ with lib; let
config.submodule.name = "subm";
};
in {
imports = with kubenix.modules; [test submodules];
in
{
imports = with kubenix.modules; [ test submodules ];
test = {
name = "submodules-versioning";

View file

@ -12,19 +12,17 @@ let
"1.26.5" = "sha256:1dyqvggyvqw3z9sml2x06v1l9kynqcs8bkfrkx8jy81gkvg7qxdi";
"1.27.2" = "sha256:1yqcds6lvpnvc5dsv9pnvp5qb3kc5y6cdgx827szljdlwf51wd15";
};
in {
in
{
inherit full;
# sorted list of major.minor version numbers
# NOTE: avoiding pulling in lib here (not for any good reason)
versions =
map (v: let
arr = builtins.splitVersion v;
in (
builtins.concatStringsSep "."
[
(builtins.elemAt arr 0)
(builtins.elemAt arr 1)
versions = with builtins; map
(v: (
concatStringsSep "." [
(elemAt (splitVersion v) 0)
(elemAt (splitVersion v) 1)
]
))
(builtins.attrNames full);
(attrNames full);
}