feat: interface and lib refactoring

This commit is contained in:
Jaka Hudoklin 2019-03-07 18:02:26 +01:00
parent e260ad9bb4
commit 5d8b66f8a0
No known key found for this signature in database
GPG key ID: 6A08896BFD32BD95
10 changed files with 111 additions and 88 deletions

View file

@ -1,14 +1,21 @@
{ pkgs ? import <nixpkgs> {}, lib ? pkgs.lib }: { pkgs ? import <nixpkgs> {}, lib ? pkgs.lib }:
let with lib;
lib' = lib.extend (lib: self: import ./lib.nix { inherit lib pkgs; });
specialArgs' = { let
kubenixLib = import ./lib { inherit lib pkgs; };
lib' = lib.extend (lib: self: import ./lib/extra.nix { inherit lib pkgs; });
defaultSpecialArgs = {
inherit kubenix; inherit kubenix;
}; };
evalKubernetesModules = {module ? null, modules ? [module], specialArgs ? specialArgs', ...}@attrs: let evalModules = {
attrs' = lib.filterAttrs (n: _: n != "module") attrs; module ? null,
modules ? [module],
specialArgs ? defaultSpecialArgs, ...
}@attrs: let
attrs' = filterAttrs (n: _: n != "module") attrs;
in lib'.evalModules (attrs' // { in lib'.evalModules (attrs' // {
inherit specialArgs modules; inherit specialArgs modules;
args = { args = {
@ -17,14 +24,11 @@ let
}; };
}); });
buildResources = args:
(evalKubernetesModules args).config.kubernetes.generated;
modules = import ./modules; modules = import ./modules;
kubenix = { kubenix = {
inherit evalKubernetesModules buildResources kubenix; inherit evalModules kubenix;
lib = lib'; lib = kubenixLib;
} // modules; } // modules;
in kubenix in kubenix

6
lib/default.nix Normal file
View file

@ -0,0 +1,6 @@
{ lib, pkgs }:
(import ./extra.nix { inherit pkgs lib; }) // {
k8s = import ./k8s.nix { inherit lib; };
docker = import ./docker.nix { inherit lib pkgs; };
}

15
lib/docker.nix Normal file
View file

@ -0,0 +1,15 @@
{ lib, pkgs }:
with lib;
{
copyDockerImages = { images, dest, args ? "" }:
pkgs.writeScriptBin "copy-docker-images" (concatMapStrings (image: ''
#!${pkgs.bash}/bin/bash
set -e
echo "copying ${image.imageName}:${image.imageTag}"
${pkgs.skopeo}/bin/skopeo copy ${args} $@ docker-archive:${image} ${dest}/${image.imageName}:${image.imageTag}
'') images);
}

View file

@ -2,8 +2,7 @@
with lib; with lib;
let rec {
in rec {
moduleToAttrs = value: moduleToAttrs = value:
if isAttrs value if isAttrs value
then mapAttrs (n: v: moduleToAttrs v) (filterAttrs (n: v: !(hasPrefix "_" n) && v != null) value) then mapAttrs (n: v: moduleToAttrs v) (filterAttrs (n: v: !(hasPrefix "_" n) && v != null) value)
@ -39,8 +38,7 @@ in rec {
exp = base: exp: foldr (value: acc: acc * base) 1 (range 1 exp); exp = base: exp: foldr (value: acc: acc * base) 1 (range 1 exp);
octalToDecimal = value: octalToDecimal = value: (foldr (char: acc: {
(foldr (char: acc: {
i = acc.i + 1; i = acc.i + 1;
value = acc.value + (toInt char) * (exp 8 acc.i); value = acc.value + (toInt char) * (exp 8 acc.i);
}) {i = 0; value = 0;} (stringToCharacters value)).value; }) {i = 0; value = 0;} (stringToCharacters value)).value;

54
lib/k8s.nix Normal file
View file

@ -0,0 +1,54 @@
{ lib }:
with lib;
rec {
mkSecretOption = {description ? "", default ? null}: mkOption {
inherit description;
type = types.nullOr (types.submodule {
options = {
name = mkOption {
description = "Name of the secret where secret is stored";
type = types.str;
};
key = mkOption {
description = "Name of the key where secret is stored";
type = types.str;
};
};
config = mkDefault (if default == null then {} else default);
});
default = {};
};
secretToEnv = value: {
valueFrom.secretKeyRef = {
inherit (value) name key;
};
};
# Creates kubernetes list from a list of kubernetes objects
mkList = { items, labels ? {} }: {
kind = "List";
apiVersion = "v1";
inherit items labels;
};
# Creates hashed kubernetes list from a list of kubernetes objects
mkHashedList = { items, labels ? {} }: let
hash = builtins.hashString "sha1" (builtins.toJSON items);
labeledItems = map (item: recursiveUpdate item {
metadata.labels."kubenix/hash" = hash;
}) items;
in mkList {
items = labeledItems;
labels = {
"kubenix/hash" = hash;
} // labels;
};
}

View file

@ -1,4 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, k8s, ... }:
with lib; with lib;
@ -32,12 +32,6 @@ let
) resources ) resources
); );
toKubernetesList = resources: {
kind = "List";
apiVersion = "v1";
items = resources;
};
apiOptions = { config, ... }: { apiOptions = { config, ... }: {
options = { options = {
definitions = mkOption { definitions = mkOption {
@ -114,7 +108,8 @@ let
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));
in { in {
imports = [./lib.nix]; # expose k8s helper methods through arg in modules
config._module.args.k8s = import ../../lib/k8s.nix { inherit lib; };
options.kubernetes.version = mkOption { options.kubernetes.version = mkOption {
description = "Kubernetes version to use"; description = "Kubernetes version to use";
@ -222,7 +217,7 @@ in {
}) cfg.customResources; }) cfg.customResources;
options.kubernetes.objects = mkOption { options.kubernetes.objects = mkOption {
description = "Attribute set of kubernetes objects"; description = "List of generated kubernetes objects";
type = types.listOf types.attrs; type = types.listOf types.attrs;
apply = items: sort (r1: r2: apply = items: sort (r1: r2:
if elem r1.kind cfg.resourceOrder && elem r2.kind cfg.resourceOrder if elem r1.kind cfg.resourceOrder && elem r2.kind cfg.resourceOrder
@ -239,25 +234,11 @@ in {
) cfg.api.resources); ) cfg.api.resources);
options.kubernetes.generated = mkOption { options.kubernetes.generated = mkOption {
description = "Generated kubernetes list object";
type = types.attrs; type = types.attrs;
description = "Generated json file";
}; };
config.kubernetes.generated = let config.kubernetes.generated = k8s.mkHashedList {
kubernetesList = toKubernetesList cfg.objects; items = config.kubernetes.objects;
hashedList = kubernetesList // {
labels."kubenix/build" = cfg.hash;
items = map (resource: recursiveUpdate resource {
metadata.labels."kubenix/build" = cfg.hash;
}) kubernetesList.items;
}; };
in hashedList;
options.kubernetes.hash = mkOption {
type = types.str;
description = "Output hash";
};
config.kubernetes.hash = builtins.hashString "sha1" (builtins.toJSON cfg.objects);
} }

View file

@ -1,35 +0,0 @@
{ lib, ... }:
with lib;
let
k8s = {
mkSecretOption = {description ? "", default ? null}: mkOption {
inherit description;
type = types.nullOr (types.submodule {
options = {
name = mkOption {
description = "Name of the secret where secret is stored";
type = types.str;
};
key = mkOption {
description = "Name of the key where secret is stored";
type = types.str;
};
};
config = mkDefault (if default == null then {} else default);
});
default = {};
};
secretToEnv = value: {
valueFrom.secretKeyRef = {
inherit (value) name key;
};
};
};
in {
_module.args.k8s = k8s;
}

View file

@ -71,7 +71,7 @@ let
nixosTesting.makeTest { nixosTesting.makeTest {
inherit name; inherit name;
nodes.kube = { config, pkgs, lib, nodes, ... }: { nodes.kube = { config, pkgs, nodes, ... }: {
imports = [ kubernetesBaseConfig ]; imports = [ kubernetesBaseConfig ];
services.kubernetes = { services.kubernetes = {
roles = ["master" "node"]; roles = ["master" "node"];
@ -113,14 +113,14 @@ let
config._module.args.test = config; config._module.args.test = config;
}] ++ cfg.defaults; }] ++ cfg.defaults;
test = (kubenix.evalKubernetesModules { test = (kubenix.evalModules {
check = false; check = false;
inherit modules; inherit modules;
}).config.test; }).config.test;
evaled = evaled =
if test.enable if test.enable
then builtins.trace "testing ${test.name}" (kubenix.evalKubernetesModules { then builtins.trace "testing ${test.name}" (kubenix.evalModules {
inherit modules; inherit modules;
}) })
else {success = false;}; else {success = false;};

View file

@ -1,6 +1,6 @@
{ pkgs ? import <nixpkgs> {} { pkgs ? import <nixpkgs> {}
, kubenix ? import ../. {inherit pkgs;} , lib ? pkgs.lib
, lib ? kubenix.lib , kubenix ? import ../. { inherit pkgs lib; }
, k8sVersions ? ["1.7" "1.8" "1.9" "1.10" "1.11" "1.12" "1.13"] , k8sVersions ? ["1.7" "1.8" "1.9" "1.10" "1.11" "1.12" "1.13"]
# whether any testing error should throw an error # whether any testing error should throw an error
@ -14,7 +14,7 @@ let
tests = listToAttrs (map (version: let tests = listToAttrs (map (version: let
version' = replaceStrings ["."] ["_"] version; version' = replaceStrings ["."] ["_"] version;
in nameValuePair "v${version'}" (evalModules { in nameValuePair "v${version'}" (kubenix.evalModules {
modules = [ modules = [
kubenix.testing kubenix.testing

View file

@ -1,7 +1,7 @@
{ config, lib, test, pkgs, kubenix, k8s, helm, ... }: { config, lib, test, pkgs, kubenix, helm, ... }:
with lib; with lib;
with k8s; with kubenix.lib;
with pkgs.dockerTools; with pkgs.dockerTools;
let let
@ -56,7 +56,7 @@ in {
$kube->waitUntilSucceeds("docker load < ${postgresql}"); $kube->waitUntilSucceeds("docker load < ${postgresql}");
$kube->waitUntilSucceeds("docker load < ${postgresqlExporter}"); $kube->waitUntilSucceeds("docker load < ${postgresqlExporter}");
$kube->waitUntilSucceeds("docker load < ${minideb}"); $kube->waitUntilSucceeds("docker load < ${minideb}");
$kube->waitUntilSucceeds("kubectl apply -f ${toYAML config.kubernetes.generated}"); $kube->waitUntilSucceeds("kubectl apply -f ${toYAML config.kubernetes.objects}");
$kube->waitUntilSucceeds("PGPASSWORD=postgres ${pkgs.postgresql}/bin/psql -h app-psql-postgresql.test.svc.cluster.local -U postgres -l"); $kube->waitUntilSucceeds("PGPASSWORD=postgres ${pkgs.postgresql}/bin/psql -h app-psql-postgresql.test.svc.cluster.local -U postgres -l");
''; '';
}; };