mirror of
https://github.com/TECHNOFAB11/kubenix.git
synced 2025-12-12 16:10:05 +01:00
first commit
This commit is contained in:
commit
cbf84e25a5
22 changed files with 131008 additions and 0 deletions
11
.editorconfig
Normal file
11
.editorconfig
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
* text=auto
|
||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
result
|
||||
6
.travis.yml
Normal file
6
.travis.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- v5
|
||||
- v4
|
||||
- '0.12'
|
||||
- '0.10'
|
||||
20
README.md
Normal file
20
README.md
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# KubeNix
|
||||
|
||||
> Kubernetes resource builder written in nix
|
||||
|
||||
## About
|
||||
|
||||
KubeNix is a kubernetes resource builder, that uses nix module system for
|
||||
definition of kubernetes resources and nix build system for building complex
|
||||
kubernetes resources very easyly.
|
||||
|
||||
### Features
|
||||
|
||||
- Loading and override of kubernetes json and yaml files
|
||||
- Support for complex merging of kubernetes resource definitions
|
||||
- No more helm stupid yaml templating, nix is a way better templating language
|
||||
- Support for all kubernetes versions
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Jaka Hudoklin](https://x-truder.net)
|
||||
89
default.nix
Normal file
89
default.nix
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
{
|
||||
pkgs ? import <nixpkgs> {}
|
||||
}:
|
||||
|
||||
with pkgs.lib;
|
||||
with import ./lib.nix { inherit pkgs; inherit (pkgs) lib; };
|
||||
|
||||
let
|
||||
evalKubernetesModules = configuration: evalModules {
|
||||
modules = [./kubernetes.nix ./modules.nix configuration];
|
||||
args = {
|
||||
inherit pkgs;
|
||||
name = "default";
|
||||
k8s = { inherit loadJSON loadYAML toBase64; };
|
||||
};
|
||||
};
|
||||
|
||||
flattenResources = resources: flatten (
|
||||
mapAttrsToList (name: resourceGroup:
|
||||
mapAttrsToList (name: resource: resource) resourceGroup
|
||||
) resources
|
||||
);
|
||||
|
||||
filterResources = resourceFilter: resources:
|
||||
mapAttrs (groupName: resources:
|
||||
(filterAttrs (name: resource:
|
||||
resourceFilter groupName name resource
|
||||
) resources)
|
||||
) resources;
|
||||
|
||||
toKubernetesList = resources: {
|
||||
kind = "List";
|
||||
apiVersion = "v1";
|
||||
items = resources;
|
||||
};
|
||||
|
||||
removeNixOptions = resources:
|
||||
map (filterAttrs (name: attr: name != "nix")) resources;
|
||||
|
||||
buildResources = {
|
||||
configuration ? {},
|
||||
resourceFilter ? groupName: name: resource: true,
|
||||
withDependencies ? true
|
||||
}: let
|
||||
evaldConfiguration = evalKubernetesModules configuration;
|
||||
|
||||
allResources = moduleToAttrs (
|
||||
evaldConfiguration.config.kubernetes.resources //
|
||||
evaldConfiguration.config.kubernetes.customResources
|
||||
);
|
||||
|
||||
filteredResources = filterResources resourceFilter allResources;
|
||||
|
||||
allDependencies = flatten (
|
||||
mapAttrsToList (groupName: resources:
|
||||
mapAttrsToList (name: resource: resource.nix.dependencies) resources
|
||||
) filteredResources
|
||||
);
|
||||
|
||||
resourceDependencies =
|
||||
filterResources (groupName: name: resource:
|
||||
elem "${groupName}/${name}" allDependencies
|
||||
) allResources;
|
||||
|
||||
finalResources =
|
||||
if withDependencies
|
||||
then recursiveUpdate resourceDependencies filteredResources
|
||||
else filteredResources;
|
||||
|
||||
resources = removeNixOptions (
|
||||
# custom resource definitions have to be allways created first
|
||||
(flattenResources (filterResources (groupName: name: resource:
|
||||
groupName == "customResourceDefinitions"
|
||||
) finalResources)) ++
|
||||
|
||||
# everything but custom resource definitions
|
||||
(flattenResources (filterResources (groupName: name: resource:
|
||||
groupName != "customResourceDefinitions"
|
||||
) finalResources))
|
||||
);
|
||||
|
||||
kubernetesList = toKubernetesList resources;
|
||||
in pkgs.writeText "resources.json" (builtins.toJSON kubernetesList);
|
||||
|
||||
in {
|
||||
inherit buildResources;
|
||||
|
||||
test = buildResources { configuration = ./test/default.nix; };
|
||||
}
|
||||
23
examples/simple/configuration.nix
Normal file
23
examples/simple/configuration.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
kubernetes.resources.deployments.nginx = {
|
||||
metadata.labels.app = "nginx";
|
||||
spec = {
|
||||
replicas = 3;
|
||||
selector.matchLabels.app = "nginx";
|
||||
template = {
|
||||
metadata.labels.app = "nginx";
|
||||
spec.containers.nginx = {
|
||||
name = "nginx";
|
||||
image = "nginx:1.7.9";
|
||||
ports."80" = {};
|
||||
resources.requests.cpu = "100m";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
kubernetes.resources.services.nginx = {
|
||||
spec.selector.app = "nginx";
|
||||
spec.ports."80".targetPort = 80;
|
||||
};
|
||||
}
|
||||
333
kubernetes.nix
Normal file
333
kubernetes.nix
Normal file
|
|
@ -0,0 +1,333 @@
|
|||
{ config, lib, k8s, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
with import ./lib.nix { inherit pkgs; inherit (pkgs) lib; };
|
||||
|
||||
let
|
||||
fixJSON = content: replaceStrings ["\\u"] ["u"] content;
|
||||
|
||||
fetchSpecs = path: builtins.fromJSON (fixJSON (builtins.readFile path));
|
||||
|
||||
hasTypeMapping = def:
|
||||
hasAttr "type" def &&
|
||||
elem def.type ["string" "integer" "boolean" "object"];
|
||||
|
||||
mapType = def:
|
||||
if def.type == "string" then
|
||||
if hasAttr "format" def && def.format == "int-or-string"
|
||||
then types.either types.int types.str
|
||||
else types.str
|
||||
else if def.type == "integer" then types.int
|
||||
else if def.type == "boolean" then types.bool
|
||||
else if def.type == "object" then types.attrs
|
||||
else throw "type ${def.type} not supported";
|
||||
|
||||
# Either value of type `finalType` or `coercedType`, the latter is
|
||||
# converted to `finalType` using `coerceFunc`.
|
||||
coercedTo = coercedType: coerceFunc: finalType:
|
||||
mkOptionType rec {
|
||||
name = "coercedTo";
|
||||
description = "${finalType.description} or ${coercedType.description}";
|
||||
check = x: finalType.check x || coercedType.check x;
|
||||
merge = loc: defs:
|
||||
let
|
||||
coerceVal = val:
|
||||
if finalType.check val then val
|
||||
else let
|
||||
coerced = coerceFunc val;
|
||||
in assert finalType.check coerced; coerced;
|
||||
|
||||
in finalType.merge loc (map (def: def // { value = coerceVal def.value; }) defs);
|
||||
getSubOptions = finalType.getSubOptions;
|
||||
getSubModules = finalType.getSubModules;
|
||||
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
|
||||
typeMerge = t1: t2: null;
|
||||
functor = (defaultFunctor name) // { wrapped = finalType; };
|
||||
};
|
||||
|
||||
submoduleOf = definition: types.submodule ({name, ...}: {
|
||||
options = definition.options;
|
||||
config = definition.config;
|
||||
});
|
||||
|
||||
refType = attr: head (tail (tail (splitString "/" attr."$ref")));
|
||||
|
||||
extraOptions = {
|
||||
nix.dependencies = mkOption {
|
||||
description = "List of resources that resource depends on";
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
};
|
||||
};
|
||||
|
||||
definitionsForKubernetesSpecs = path:
|
||||
let
|
||||
swagger = fetchSpecs path;
|
||||
swaggerDefinitions = swagger.definitions;
|
||||
|
||||
definitions = mapAttrs (name: definition:
|
||||
# if $ref is in definition it means it's an alias of other definition
|
||||
if hasAttr "$ref" definition
|
||||
then definitions."${refType definition}"
|
||||
|
||||
else if !(hasAttr "properties" definition)
|
||||
then {}
|
||||
|
||||
# in other case it's an actual definition
|
||||
else {
|
||||
options = mapAttrs (propName: property:
|
||||
let
|
||||
isRequired = elem propName (definition.required or []);
|
||||
requiredOrNot = type: if isRequired then type else types.nullOr type;
|
||||
optionProperties =
|
||||
# if $ref is in property it references other definition,
|
||||
# but if other definition does not have properties, then just take it's type
|
||||
if hasAttr "$ref" property then
|
||||
if hasTypeMapping swaggerDefinitions.${refType property} then {
|
||||
type = requiredOrNot (mapType swaggerDefinitions.${refType property});
|
||||
}
|
||||
else {
|
||||
type = requiredOrNot (submoduleOf definitions.${refType property});
|
||||
}
|
||||
|
||||
# if property has an array type
|
||||
else if property.type == "array" then
|
||||
|
||||
# if reference is in items it can reference other type of another
|
||||
# definition
|
||||
if hasAttr "$ref" property.items then
|
||||
|
||||
# if it is a reference to simple type
|
||||
if hasTypeMapping swaggerDefinitions.${refType property.items}
|
||||
then {
|
||||
type = requiredOrNot (types.listOf (mapType swaggerDefinitions.${refType property.items}.type));
|
||||
}
|
||||
|
||||
# if a reference is to complex type
|
||||
else
|
||||
# if x-kubernetes-patch-merge-key is set then make it an
|
||||
# attribute set of submodules
|
||||
if hasAttr "x-kubernetes-patch-merge-key" property
|
||||
then let
|
||||
mergeKey = property."x-kubernetes-patch-merge-key";
|
||||
convertName = name:
|
||||
if definitions.${refType property.items}.options.${mergeKey}.type == types.int
|
||||
then toInt name
|
||||
else name;
|
||||
in {
|
||||
type = requiredOrNot (coercedTo
|
||||
(types.listOf (submoduleOf definitions.${refType property.items}))
|
||||
(values:
|
||||
listToAttrs (map
|
||||
(value: nameValuePair (
|
||||
if isAttrs value.${mergeKey}
|
||||
then toString value.${mergeKey}.content
|
||||
else (toString value.${mergeKey})
|
||||
) value)
|
||||
values)
|
||||
)
|
||||
(types.attrsOf (types.submodule (
|
||||
{name, ...}: {
|
||||
options = definitions.${refType property.items}.options;
|
||||
config = definitions.${refType property.items}.config // {
|
||||
${mergeKey} = mkOverride 1002 (convertName name);
|
||||
};
|
||||
}
|
||||
))
|
||||
));
|
||||
apply = values: if values != null then mapAttrsToList (n: v: v) values else values;
|
||||
}
|
||||
|
||||
# in other case it's a simple list
|
||||
else {
|
||||
type = requiredOrNot (types.listOf (submoduleOf definitions.${refType property.items}));
|
||||
}
|
||||
|
||||
# in other case it only references a simple type
|
||||
else {
|
||||
type = requiredOrNot (types.listOf (mapType property.items));
|
||||
}
|
||||
|
||||
else if property.type == "object" && hasAttr "additionalProperties" property
|
||||
then
|
||||
# if it is a reference to simple type
|
||||
if (
|
||||
hasAttr "$ref" property.additionalProperties &&
|
||||
hasTypeMapping swaggerDefinitions.${refType property.additionalProperties}
|
||||
) then {
|
||||
type = requiredOrNot (types.attrsOf (mapType swaggerDefinitions.${refType property.additionalProperties}));
|
||||
}
|
||||
|
||||
# if is an array
|
||||
else if property.additionalProperties.type == "array"
|
||||
then {
|
||||
type = requiredOrNot (types.loaOf (mapType property.additionalProperties.items));
|
||||
}
|
||||
|
||||
else {
|
||||
type = requiredOrNot (types.attrsOf (mapType property.additionalProperties));
|
||||
}
|
||||
|
||||
# just a simple property
|
||||
else {
|
||||
type = requiredOrNot (mapType property);
|
||||
};
|
||||
in
|
||||
mkOption {
|
||||
inherit (definition) description;
|
||||
} // optionProperties // (optionalAttrs (!isRequired) {
|
||||
})
|
||||
) definition.properties;
|
||||
config =
|
||||
let
|
||||
optionalProps = filterAttrs (propName: property:
|
||||
!(elem propName (definition.required or []))
|
||||
) definition.properties;
|
||||
in mapAttrs (name: property: mkOverride 1002 null) optionalProps;
|
||||
}
|
||||
) swaggerDefinitions;
|
||||
|
||||
exportedDefinitions =
|
||||
zipAttrs (
|
||||
mapAttrsToList (name: path: let
|
||||
kind = path.post."x-kubernetes-group-version-kind".kind;
|
||||
|
||||
lastChar = substring ((stringLength kind)-1) (stringLength kind) kind;
|
||||
|
||||
suffix =
|
||||
if lastChar == "y" then "ies"
|
||||
else if hasSuffix "ss" kind then "ses"
|
||||
else if lastChar == "s" then "s"
|
||||
else "${lastChar}s";
|
||||
|
||||
optionName = "${toLower (substring 0 1 kind)}${substring 1 ((stringLength kind)-2) kind}${suffix}";
|
||||
in {
|
||||
${optionName} = refType (head path.post.parameters).schema;
|
||||
})
|
||||
(filterAttrs (name: path:
|
||||
hasAttr "post" path &&
|
||||
path.post."x-kubernetes-action" == "post"
|
||||
) swagger.paths)
|
||||
);
|
||||
|
||||
kubernetesResourceOptions = mapAttrs (groupName: value:
|
||||
let
|
||||
values = if isList value then reverseList value else [value];
|
||||
definitionName = tail values;
|
||||
|
||||
submoduleWithDefaultsOf = definition: swaggerDefinition: let
|
||||
kind = (head swaggerDefinition."x-kubernetes-group-version-kind").kind;
|
||||
group = (head swaggerDefinition."x-kubernetes-group-version-kind").group;
|
||||
version = (head swaggerDefinition."x-kubernetes-group-version-kind").version;
|
||||
groupVersion = if group != "" then "${group}/${version}" else version;
|
||||
in types.submodule ({name, ...}: {
|
||||
options = definition.options // extraOptions;
|
||||
config = mkMerge [
|
||||
definition.config
|
||||
{
|
||||
kind = mkOptionDefault kind;
|
||||
apiVersion = mkOptionDefault groupVersion;
|
||||
|
||||
# metdata.name cannot use option default, due deep config
|
||||
metadata.name = mkOptionDefault name;
|
||||
}
|
||||
(mkAllDefault config.kubernetes.defaults.${groupName} 1001)
|
||||
];
|
||||
});
|
||||
|
||||
type =
|
||||
if (length values) > 1
|
||||
then fold (name: other:
|
||||
types.either (submoduleWithDefaultsOf definitions.${name} swaggerDefinitions.${name}) other
|
||||
) (submoduleWithDefaultsOf definitions.${head values} swaggerDefinitions.${head values}) (drop 1 values)
|
||||
else submoduleWithDefaultsOf definitions.${head values} swaggerDefinitions.${head values};
|
||||
in mkOption {
|
||||
description = swaggerDefinitions.${definitionName}.description;
|
||||
type = types.attrsOf type;
|
||||
default = {};
|
||||
}) exportedDefinitions;
|
||||
|
||||
customResourceOptions = mapAttrs (name: crd:
|
||||
mkOption {
|
||||
type = types.attrsOf (types.submodule ({name, config, ...}: {
|
||||
options = {
|
||||
apiVersion = mkOption {
|
||||
description = "API version of custom resource";
|
||||
type = types.str;
|
||||
default = "${crd.spec.group}/${crd.spec.version}";
|
||||
};
|
||||
|
||||
kind = mkOption {
|
||||
description = "Custom resource kind";
|
||||
type = types.str;
|
||||
default = crd.spec.names.kind;
|
||||
};
|
||||
|
||||
metadata = mkOption {
|
||||
description = "Metadata";
|
||||
type = submoduleOf definitions."io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta";
|
||||
default = {};
|
||||
};
|
||||
|
||||
spec = mkOption {
|
||||
description = "Custom resource specification";
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
};
|
||||
} // extraOptions;
|
||||
}));
|
||||
}
|
||||
) config.kubernetes.resources.customResourceDefinitions;
|
||||
in {
|
||||
inherit swaggerDefinitions definitions exportedDefinitions kubernetesResourceOptions customResourceOptions;
|
||||
};
|
||||
|
||||
versionDefinitions = {
|
||||
"1.7" = definitionsForKubernetesSpecs ./specs/1.7/swagger.json;
|
||||
"1.8" = definitionsForKubernetesSpecs ./specs/1.8/swagger.json;
|
||||
};
|
||||
|
||||
versionOptions = {
|
||||
"1.7" = (versionDefinitions."1.7").kubernetesResourceOptions // {
|
||||
# kubernetes 1.7 supports crd, but does not have swagger definitions for some reason
|
||||
customResourceDefinitions =
|
||||
versionDefinitions."1.8".kubernetesResourceOptions.customResourceDefinitions;
|
||||
};
|
||||
"1.8" = (versionDefinitions."1.8").kubernetesResourceOptions;
|
||||
};
|
||||
|
||||
defaultOptions = mapAttrs (name: value: mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
}) versionOptions.${config.kubernetes.version};
|
||||
in {
|
||||
options.kubernetes.version = mkOption {
|
||||
description = "Kubernetes version to deploy to";
|
||||
type = types.enum (attrNames versionDefinitions);
|
||||
default = "1.7";
|
||||
};
|
||||
|
||||
options.kubernetes.resources = mkOption {
|
||||
type = types.submodule {
|
||||
options = versionOptions.${config.kubernetes.version};
|
||||
};
|
||||
description = "Attribute set of kubernetes resources";
|
||||
default = {};
|
||||
};
|
||||
|
||||
options.kubernetes.defaults = mkOption {
|
||||
type = types.submodule {
|
||||
options = defaultOptions;
|
||||
};
|
||||
description = "";
|
||||
default = {};
|
||||
};
|
||||
|
||||
options.kubernetes.customResources = mkOption {
|
||||
type = types.submodule {
|
||||
options = versionDefinitions.${config.kubernetes.version}.customResourceOptions;
|
||||
};
|
||||
description = "Attribute set of custom kubernetes resources";
|
||||
default = {};
|
||||
};
|
||||
}
|
||||
32
lib.nix
Normal file
32
lib.nix
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
{lib, pkgs}:
|
||||
|
||||
with lib;
|
||||
|
||||
rec {
|
||||
mkAllDefault = value: priority:
|
||||
if isAttrs value
|
||||
then mapAttrs (n: v: mkAllDefault v priority) value
|
||||
|
||||
else if isList value
|
||||
then map (v: mkAllDefault v priority) value
|
||||
|
||||
else mkOverride priority value;
|
||||
|
||||
moduleToAttrs = value:
|
||||
if isAttrs value
|
||||
then mapAttrs (n: v: moduleToAttrs v) (filterAttrs (n: v: !(hasPrefix "_" n) && v != null) value)
|
||||
|
||||
else if isList value
|
||||
then map (v: moduleToAttrs v) value
|
||||
|
||||
else value;
|
||||
|
||||
loadJSON = path: mkAllDefault (builtins.fromJSON (builtins.readFile path)) 1000;
|
||||
|
||||
loadYAML = path: loadJSON (pkgs.runCommand "yaml-to-json" {
|
||||
} "${pkgs.remarshal}/bin/remarshal -i ${path} -if yaml -of json > $out");
|
||||
|
||||
toBase64 = value:
|
||||
builtins.readFile
|
||||
(pkgs.runCommand "value-to-b64" {} "echo '${value}' | ${pkgs.coreutils}/bin/base64 -w0 > $out");
|
||||
}
|
||||
95
modules.nix
Normal file
95
modules.nix
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
{ config, lib, pkgs, k8s, ... }:
|
||||
|
||||
with lib;
|
||||
with import ./lib.nix { inherit pkgs lib; };
|
||||
|
||||
let
|
||||
globalConfig = config;
|
||||
|
||||
evalK8SModule = {module, name, configuration}: evalModules {
|
||||
modules = [
|
||||
./kubernetes.nix ./modules.nix module configuration
|
||||
] ++ config.kubernetes.defaultModuleConfiguration;
|
||||
args = {
|
||||
inherit pkgs k8s name;
|
||||
};
|
||||
};
|
||||
|
||||
prefixResources = resources: serviceName:
|
||||
mapAttrs (groupName: resources:
|
||||
mapAttrs' (name: resource: nameValuePair "${serviceName}-${name}" resource) resources
|
||||
) resources;
|
||||
in {
|
||||
options.kubernetes.defaultModuleConfiguration = mkOption {
|
||||
description = "Default configuration for kubernetes modules";
|
||||
type = types.listOf types.attrs;
|
||||
default = {};
|
||||
};
|
||||
|
||||
options.kubernetes.moduleDefinitions = mkOption {
|
||||
description = "Attribute set of module definitions";
|
||||
default = {};
|
||||
type = types.attrsOf (types.submodule ({name, ...}: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
description = "Module definition name";
|
||||
type = types.str;
|
||||
default = name;
|
||||
};
|
||||
|
||||
module = mkOption {
|
||||
description = "Module definition";
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
|
||||
options.kubernetes.modules = mkOption {
|
||||
description = "Attribute set of module definitions";
|
||||
default = {};
|
||||
type = types.attrsOf (types.submodule ({config, name, ...}: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
description = "Module name";
|
||||
type = types.str;
|
||||
default = name;
|
||||
};
|
||||
|
||||
configuration = mkOption {
|
||||
description = "Module configuration";
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
};
|
||||
|
||||
module = mkOption {
|
||||
description = "Name of the module to use";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
evaledModule = mkOption {
|
||||
description = "Evaluated config";
|
||||
internal = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
evaledModule = (evalK8SModule {
|
||||
module = globalConfig.kubernetes.moduleDefinitions.${config.module}.module;
|
||||
inherit (config) name configuration;
|
||||
});
|
||||
};
|
||||
}));
|
||||
};
|
||||
|
||||
config = {
|
||||
kubernetes.resources = mkMerge (
|
||||
mapAttrsToList (name: module:
|
||||
prefixResources (moduleToAttrs module.evaledModule.config.kubernetes.resources) module.name
|
||||
) config.kubernetes.modules
|
||||
);
|
||||
|
||||
kubernetes.defaultModuleConfiguration = [{
|
||||
config.kubernetes.version = mkDefault config.kubernetes.version;
|
||||
}];
|
||||
};
|
||||
}
|
||||
56391
specs/1.7/swagger.json
Normal file
56391
specs/1.7/swagger.json
Normal file
File diff suppressed because it is too large
Load diff
73741
specs/1.8/swagger.json
Normal file
73741
specs/1.8/swagger.json
Normal file
File diff suppressed because it is too large
Load diff
8
test/configMap.json
Normal file
8
test/configMap.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"apiVersion": "v1",
|
||||
"data": {
|
||||
"game.properties": "enemies=aliens\nlives=3\nenemies.cheat=true\nenemies.cheat.level=noGoodRotten\nsecret.code.passphrase=UUDDLRLRBABAS\nsecret.code.allowed=true\nsecret.code.lives=30\n",
|
||||
"ui.properties": "color.good=purple\ncolor.bad=yellow\nallow.textmode=true\nhow.nice.to.look=fairlyNice\n"
|
||||
},
|
||||
"kind": "ConfigMap"
|
||||
}
|
||||
11
test/cr.json
Normal file
11
test/cr.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"apiVersion": "stable.example.com/v1",
|
||||
"kind": "CronTab",
|
||||
"metadata": {
|
||||
"name": "my-new-cron-object"
|
||||
},
|
||||
"spec": {
|
||||
"cronSpec": "* * * * */5",
|
||||
"image": "my-awesome-cron-image"
|
||||
}
|
||||
}
|
||||
20
test/crd.json
Normal file
20
test/crd.json
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"apiVersion": "apiextensions.k8s.io/v1beta1",
|
||||
"kind": "CustomResourceDefinition",
|
||||
"metadata": {
|
||||
"name": "crontabs.stable.example.com"
|
||||
},
|
||||
"spec": {
|
||||
"group": "stable.example.com",
|
||||
"version": "v1",
|
||||
"scope": "Namespaced",
|
||||
"names": {
|
||||
"plural": "crontabs",
|
||||
"singular": "crontab",
|
||||
"kind": "CronTab",
|
||||
"shortNames": [
|
||||
"ct"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
67
test/daemonset.json
Normal file
67
test/daemonset.json
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
"kind": "DaemonSet",
|
||||
"metadata": {
|
||||
"labels": {
|
||||
"k8s-app": "fluentd-logging"
|
||||
},
|
||||
"name": "fluentd-elasticsearch",
|
||||
"namespace": "kube-system"
|
||||
},
|
||||
"spec": {
|
||||
"selector": {
|
||||
"matchLabels": {
|
||||
"name": "fluentd-elasticsearch"
|
||||
}
|
||||
},
|
||||
"template": {
|
||||
"metadata": {
|
||||
"labels": {
|
||||
"name": "fluentd-elasticsearch"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"image": "gcr.io/google-containers/fluentd-elasticsearch:1.20",
|
||||
"name": "fluentd-elasticsearch",
|
||||
"resources": {
|
||||
"limits": {
|
||||
"memory": "200Mi"
|
||||
},
|
||||
"requests": {
|
||||
"cpu": "100m",
|
||||
"memory": "200Mi"
|
||||
}
|
||||
},
|
||||
"volumeMounts": [
|
||||
{
|
||||
"mountPath": "/var/log",
|
||||
"name": "varlog"
|
||||
},
|
||||
{
|
||||
"mountPath": "/var/lib/docker/containers",
|
||||
"name": "varlibdockercontainers",
|
||||
"readOnly": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"terminationGracePeriodSeconds": 30,
|
||||
"volumes": [
|
||||
{
|
||||
"hostPath": {
|
||||
"path": "/var/log"
|
||||
},
|
||||
"name": "varlog"
|
||||
},
|
||||
{
|
||||
"hostPath": {
|
||||
"path": "/var/lib/docker/containers"
|
||||
},
|
||||
"name": "varlibdockercontainers"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
test/default.nix
Normal file
7
test/default.nix
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{ config, ... }:
|
||||
|
||||
{
|
||||
kubernetes.version = "1.7";
|
||||
|
||||
require = [./modules.nix ./deployment.nix];
|
||||
}
|
||||
38
test/deployment.json
Normal file
38
test/deployment.json
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"metadata": {
|
||||
"name": "nginx-deployment",
|
||||
"labels": {
|
||||
"app": "nginx"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"selector": {
|
||||
"matchLabels": {
|
||||
"app": "nginx"
|
||||
}
|
||||
},
|
||||
"template": {
|
||||
"metadata": {
|
||||
"labels": {
|
||||
"app": "nginx"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"containers": {
|
||||
"nginx": {
|
||||
"name": "nginx",
|
||||
"image": "nginx:1.7.9",
|
||||
"ports": {
|
||||
"80": {}
|
||||
},
|
||||
"resources": {
|
||||
"requests": {
|
||||
"cpu": "100m"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
24
test/deployment.nix
Normal file
24
test/deployment.nix
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{lib, k8s, ...}:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
config = {
|
||||
kubernetes.resources = {
|
||||
deployments.deployment = mkMerge [
|
||||
(k8s.loadJSON ./deployment.json)
|
||||
{
|
||||
metadata.name = "abcd";
|
||||
nix.dependencies = ["configMaps/configmap"];
|
||||
}
|
||||
];
|
||||
configMaps.configmap = k8s.loadJSON ./configMap.json;
|
||||
namespaces.namespace = k8s.loadJSON ./namespace.json;
|
||||
daemonSets.daemonset = k8s.loadJSON ./daemonset.json;
|
||||
services.service = k8s.loadJSON ./service.json;
|
||||
customResourceDefinitions.cron = k8s.loadJSON ./crd.json;
|
||||
};
|
||||
|
||||
kubernetes.customResources.cron.my-awesome-cron-object = k8s.loadJSON ./cr.json;
|
||||
};
|
||||
}
|
||||
54
test/modules.nix
Normal file
54
test/modules.nix
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
{lib, k8s, ...}:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
config = {
|
||||
kubernetes.moduleDefinitions.nginx.module = {name, config, ...}: {
|
||||
options = {
|
||||
port = mkOption {
|
||||
description = "Port for nginx to listen on";
|
||||
type = types.int;
|
||||
default = 80;
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
kubernetes.resources.deployments.nginx = mkMerge [
|
||||
(k8s.loadJSON ./deployment.json)
|
||||
{
|
||||
metadata.name = "${name}-nginx";
|
||||
|
||||
spec.template.spec.containers.nginx.ports."80" = {
|
||||
containerPort = config.port;
|
||||
};
|
||||
|
||||
spec.template.spec.containers.nginx.env.name.valueFrom.secretKeyRef = {
|
||||
name = config.kubernetes.resources.configMaps.nginx.metadata.name;
|
||||
key = "somekey";
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
kubernetes.resources.configMaps.nginx = mkMerge [
|
||||
(k8s.loadJSON ./configMap.json)
|
||||
{
|
||||
metadata.name = mkForce "${name}-nginx";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
kubernetes.modules.app-v1.module = "nginx";
|
||||
kubernetes.modules.app-v2 = {
|
||||
module = "nginx";
|
||||
configuration.port = 8080;
|
||||
};
|
||||
|
||||
kubernetes.resources.services.nginx = k8s.loadJSON ./service.json;
|
||||
|
||||
kubernetes.defaultModuleConfiguration = [{
|
||||
kubernetes.defaults.deployments.spec.replicas = 3;
|
||||
}];
|
||||
};
|
||||
}
|
||||
10
test/namespace.json
Normal file
10
test/namespace.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"kind": "Namespace",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "openshift-origin",
|
||||
"labels": {
|
||||
"name": "openshift-origin"
|
||||
}
|
||||
}
|
||||
}
|
||||
26
test/service.json
Normal file
26
test/service.json
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"kind": "Service",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "nginx"
|
||||
},
|
||||
"spec": {
|
||||
"selector": {
|
||||
"app": "nginx"
|
||||
},
|
||||
"ports": [
|
||||
{
|
||||
"name": "http",
|
||||
"protocol": "TCP",
|
||||
"port": 80,
|
||||
"targetPort": 80
|
||||
},
|
||||
{
|
||||
"name": "https",
|
||||
"protocol": "TCP",
|
||||
"port": 443,
|
||||
"targetPort": 443
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue