mirror of
https://gitlab.com/TECHNOFAB/coder-templates.git
synced 2026-02-02 03:15:07 +01:00
chore: add initial nix-kubernetes template
This commit is contained in:
parent
6bd319fbe9
commit
7cd71e7537
8 changed files with 425 additions and 2 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,3 +4,4 @@
|
||||||
*.tf*
|
*.tf*
|
||||||
result
|
result
|
||||||
.pre-commit-config.yaml
|
.pre-commit-config.yaml
|
||||||
|
.terraform*
|
||||||
|
|
|
||||||
102
flake.lock
generated
102
flake.lock
generated
|
|
@ -22,6 +22,38 @@
|
||||||
"type": "gitlab"
|
"type": "gitlab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"bats-assert": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1636059754,
|
||||||
|
"narHash": "sha256-ewME0l27ZqfmAwJO4h5biTALc9bDLv7Bl3ftBzBuZwk=",
|
||||||
|
"owner": "bats-core",
|
||||||
|
"repo": "bats-assert",
|
||||||
|
"rev": "34551b1d7f8c7b677c1a66fc0ac140d6223409e5",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "bats-core",
|
||||||
|
"repo": "bats-assert",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bats-support": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1548869839,
|
||||||
|
"narHash": "sha256-Gr4ntadr42F2Ks8Pte2D4wNDbijhujuoJi4OPZnTAZU=",
|
||||||
|
"owner": "bats-core",
|
||||||
|
"repo": "bats-support",
|
||||||
|
"rev": "d140a65044b2d6810381935ae7f0c94c7023c8c3",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "bats-core",
|
||||||
|
"repo": "bats-support",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"cachix": {
|
"cachix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"devenv": "devenv_2",
|
"devenv": "devenv_2",
|
||||||
|
|
@ -348,6 +380,21 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"flake-utils_6": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1634851050,
|
||||||
|
"narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "c91f3de5adaf1de973b797ef7485e441a65b8935",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"gitignore": {
|
"gitignore": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
|
|
@ -794,6 +841,21 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nixpkgs_7": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1636823747,
|
||||||
|
"narHash": "sha256-oWo1nElRAOZqEf90Yek2ixdHyjD+gqtS/pAgwaQ9UhQ=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "f6a2ed2082d9a51668c86ba27d0b5496f7a2ea93",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"poetry2nix": {
|
"poetry2nix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
|
|
@ -898,7 +960,8 @@
|
||||||
"nix-devtools": "nix-devtools",
|
"nix-devtools": "nix-devtools",
|
||||||
"nix-gitlab-ci": "nix-gitlab-ci",
|
"nix-gitlab-ci": "nix-gitlab-ci",
|
||||||
"nixpkgs": "nixpkgs_6",
|
"nixpkgs": "nixpkgs_6",
|
||||||
"systems": "systems_5"
|
"systems": "systems_5",
|
||||||
|
"terranix": "terranix"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems": {
|
"systems": {
|
||||||
|
|
@ -975,6 +1038,43 @@
|
||||||
"repo": "default",
|
"repo": "default",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"terranix": {
|
||||||
|
"inputs": {
|
||||||
|
"bats-assert": "bats-assert",
|
||||||
|
"bats-support": "bats-support",
|
||||||
|
"flake-utils": "flake-utils_6",
|
||||||
|
"nixpkgs": "nixpkgs_7",
|
||||||
|
"terranix-examples": "terranix-examples"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1695406838,
|
||||||
|
"narHash": "sha256-xiUfVD6rtsVWFotVtUW3Q1nQh4obKzgvpN1wqZuGXvM=",
|
||||||
|
"owner": "terranix",
|
||||||
|
"repo": "terranix",
|
||||||
|
"rev": "fc9077ca02ab5681935dbf0ecd725c4d889b9275",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "terranix",
|
||||||
|
"repo": "terranix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"terranix-examples": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1636300201,
|
||||||
|
"narHash": "sha256-0n1je1WpiR6XfCsvi8ZK7GrpEnMl+DpwhWaO1949Vbc=",
|
||||||
|
"owner": "terranix",
|
||||||
|
"repo": "terranix-examples",
|
||||||
|
"rev": "a934aa1cf88f6bd6c6ddb4c77b77ec6e1660bd5e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "terranix",
|
||||||
|
"repo": "terranix-examples",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
|
|
|
||||||
34
flake.nix
34
flake.nix
|
|
@ -45,12 +45,42 @@
|
||||||
task = {
|
task = {
|
||||||
enable = true;
|
enable = true;
|
||||||
alias = ",";
|
alias = ",";
|
||||||
tasks = {};
|
tasks = {
|
||||||
|
"build" = {
|
||||||
|
requires.vars = ["TEMPLATE"];
|
||||||
|
cmds = [
|
||||||
|
"nix build .#{{ .TEMPLATE }}"
|
||||||
|
"install result {{ .TEMPLATE }}/template.tf.json"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
"validate" = {
|
||||||
|
desc = "Validate the resulting terraform files";
|
||||||
|
deps = ["build"];
|
||||||
|
requires.vars = ["TEMPLATE"];
|
||||||
|
dir = "{{ .TEMPLATE }}";
|
||||||
|
cmds = [
|
||||||
|
"${pkgs.opentofu}/bin/tofu init"
|
||||||
|
"${pkgs.opentofu}/bin/tofu validate"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
"upload-to-coder" = {
|
||||||
|
desc = "Uploads the specified template to coder";
|
||||||
|
deps = ["build" "validate"];
|
||||||
|
requires.vars = ["TEMPLATE"];
|
||||||
|
dir = "{{ .TEMPLATE }}";
|
||||||
|
interactive = true;
|
||||||
|
cmd = ''${pkgs.coder}/bin/coder templates push "{{ .TEMPLATE }}"'';
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
packages = {
|
packages = {
|
||||||
nix-coder-image = pkgs.callPackage ./image.nix {};
|
nix-coder-image = pkgs.callPackage ./image.nix {};
|
||||||
|
nix-kubernetes = inputs.terranix.lib.terranixConfiguration {
|
||||||
|
inherit system;
|
||||||
|
modules = [./nix-kubernetes];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -73,5 +103,7 @@
|
||||||
inputs.devenv.follows = "devenv";
|
inputs.devenv.follows = "devenv";
|
||||||
inputs.systems.follows = "systems";
|
inputs.systems.follows = "systems";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
terranix.url = "github:terranix/terranix";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
42
nix-kubernetes/coder.nix
Normal file
42
nix-kubernetes/coder.nix
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
{...}: {
|
||||||
|
locals."git_repo_folder" = let
|
||||||
|
split_repo = ''split("/", data.coder_parameter.git_repo.value)'';
|
||||||
|
in ''try(element(${split_repo}, length(${split_repo}) - 1), "")'';
|
||||||
|
|
||||||
|
data = {
|
||||||
|
coder_external_auth."gitlab" = {
|
||||||
|
id = "gitlab";
|
||||||
|
optional = false;
|
||||||
|
};
|
||||||
|
coder_workspace."me" = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
resource = {
|
||||||
|
coder_agent."coder" = {
|
||||||
|
arch = "\${var.arch}";
|
||||||
|
os = "linux";
|
||||||
|
};
|
||||||
|
coder_script."git_clone" = {
|
||||||
|
agent_id = "\${coder_agent.coder.id}";
|
||||||
|
display_name = "Git Clone";
|
||||||
|
icon = "/icon/git.svg";
|
||||||
|
script = let
|
||||||
|
repo = ''''${data.coder_parameter.git_repo.value}'';
|
||||||
|
repo_folder = ''''${local.git_repo_folder}'';
|
||||||
|
in ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
echo "Cloning repo \"${repo}\" if it does not exist"
|
||||||
|
mkdir -p ~/repos
|
||||||
|
pushd ~/repos
|
||||||
|
if [[ ! -z "${repo}" && ! -d "${repo_folder}" ]] then
|
||||||
|
git clone ${repo} ${repo_folder}
|
||||||
|
fi
|
||||||
|
popd
|
||||||
|
'';
|
||||||
|
run_on_start = true;
|
||||||
|
start_blocks_login = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
24
nix-kubernetes/default.nix
Normal file
24
nix-kubernetes/default.nix
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
{...}: {
|
||||||
|
imports = [
|
||||||
|
./parameters.nix
|
||||||
|
./variables.nix
|
||||||
|
./coder.nix
|
||||||
|
./kubernetes.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
terraform.required_providers = {
|
||||||
|
coder = {
|
||||||
|
source = "coder/coder";
|
||||||
|
version = "0.21.0";
|
||||||
|
};
|
||||||
|
kubernetes = {
|
||||||
|
source = "hashicorp/kubernetes";
|
||||||
|
version = "2.29.0";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
provider = {
|
||||||
|
coder = {};
|
||||||
|
kubernetes = {};
|
||||||
|
};
|
||||||
|
}
|
||||||
130
nix-kubernetes/kubernetes.nix
Normal file
130
nix-kubernetes/kubernetes.nix
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
{...}: {
|
||||||
|
resource = {
|
||||||
|
kubernetes_pod."workspace" = {
|
||||||
|
count = "\${data.coder_workspace.me.start_count}";
|
||||||
|
metadata = {
|
||||||
|
name = "coder-\${lower(data.coder_workspace.me.owner)}-\${lower(data.coder_workspace.me.name)}";
|
||||||
|
namespace = "\${var.namespace}";
|
||||||
|
annotations."com.coder.user.email" = "\${data.coder_workspace.me.owner_email}";
|
||||||
|
labels = {
|
||||||
|
"app.kubernetes.io/instance" = "coder-workspace-\${lower(data.coder_workspace.me.owner)}-\${lower(data.coder_workspace.me.name)}";
|
||||||
|
"app.kubernetes.io/name" = "coder-workspace";
|
||||||
|
"app.kubernetes.io/part-of" = "coder";
|
||||||
|
"com.coder.resource" = "true";
|
||||||
|
"com.coder.user.id" = "\${data.coder_workspace.me.owner_id}";
|
||||||
|
"com.coder.user.name" = "\${data.coder_workspace.me.owner}";
|
||||||
|
"com.coder.workspace.id" = "\${data.coder_workspace.me.id}";
|
||||||
|
"com.coder.workspace.name" = "\${data.coder_workspace.me.name}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
spec = {
|
||||||
|
affinity.pod_anti_affinity.preferred_during_scheduling_ignored_during_execution = {
|
||||||
|
weight = 1;
|
||||||
|
pod_affinity_term = {
|
||||||
|
topology_key = "kubernetes.io/hostname";
|
||||||
|
label_selector.match_expressions = {
|
||||||
|
key = "app.kubernetes.io/name";
|
||||||
|
operator = "In";
|
||||||
|
values = ["coder-workspace"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
container = [
|
||||||
|
{
|
||||||
|
name = "workspace";
|
||||||
|
image = "registry.gitlab.com/technofab/coder-templates/coder-workspace:\${data.coder_parameter.image_tag.value}";
|
||||||
|
command = ["/bin/sh" "-c" "\${resource.coder_agent.coder.init_script}"];
|
||||||
|
env = [
|
||||||
|
{
|
||||||
|
name = "CODER_AGENT_TOKEN";
|
||||||
|
value = "\${resource.coder_agent.coder.token}";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
resources = {
|
||||||
|
requests = {
|
||||||
|
# TODO: allow configuring this via variables (template wide)
|
||||||
|
cpu = "250m";
|
||||||
|
memory = "512Mi";
|
||||||
|
};
|
||||||
|
limits = {
|
||||||
|
cpu = "\${data.coder_parameter.cpu.value}";
|
||||||
|
memory = "\${data.coder_parameter.memory.value}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
security_context.run_as_user = "1000";
|
||||||
|
volume_mount = [
|
||||||
|
{
|
||||||
|
mount_path = "/home";
|
||||||
|
name = "home";
|
||||||
|
read_only = false;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
mount_path = "/nix";
|
||||||
|
name = "nix-store";
|
||||||
|
read_only = false;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
security_context = {
|
||||||
|
fs_group = "1000";
|
||||||
|
run_as_user = "1000";
|
||||||
|
};
|
||||||
|
volume = [
|
||||||
|
{
|
||||||
|
name = "home";
|
||||||
|
persistent_volume_claim.claim_name = "\${resource.kubernetes_persistent_volume_claim.home.metadata.0.name}";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "nix-store";
|
||||||
|
persistent_volume_claim.claim_name = "\${resource.kubernetes_persistent_volume_claim.nix-store.metadata.0.name}";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
kubernetes_persistent_volume_claim."home" = {
|
||||||
|
metadata = {
|
||||||
|
name = "coder-home-\${lower(data.coder_workspace.me.owner)}-\${lower(data.coder_workspace.me.name)}";
|
||||||
|
namespace = "\${var.namespace}";
|
||||||
|
annotations."com.coder.user.email" = "\${data.coder_workspace.me.owner_email}";
|
||||||
|
labels = {
|
||||||
|
"app.kubernetes.io/instance" = "coder-pvc-home-\${lower(data.coder_workspace.me.owner)}-\${lower(data.coder_workspace.me.name)}";
|
||||||
|
"app.kubernetes.io/name" = "coder-pvc";
|
||||||
|
"app.kubernetes.io/part-of" = "coder";
|
||||||
|
"com.coder.resource" = "true";
|
||||||
|
"com.coder.user.id" = "\${data.coder_workspace.me.owner_id}";
|
||||||
|
"com.coder.user.name" = "\${data.coder_workspace.me.owner}";
|
||||||
|
"com.coder.workspace.id" = "\${data.coder_workspace.me.id}";
|
||||||
|
"com.coder.workspace.name" = "\${data.coder_workspace.me.name}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
spec = {
|
||||||
|
access_modes = ["ReadWriteOnce"];
|
||||||
|
resources.requests.storage = "\${data.coder_parameter.home_disk_size.value}Gi";
|
||||||
|
};
|
||||||
|
wait_until_bound = false;
|
||||||
|
};
|
||||||
|
kubernetes_persistent_volume_claim."nix-store" = {
|
||||||
|
metadata = {
|
||||||
|
name = "coder-nix-store-\${lower(data.coder_workspace.me.owner)}-\${lower(data.coder_workspace.me.name)}";
|
||||||
|
namespace = "\${var.namespace}";
|
||||||
|
annotations."com.coder.user.email" = "\${data.coder_workspace.me.owner_email}";
|
||||||
|
labels = {
|
||||||
|
"app.kubernetes.io/instance" = "coder-pvc-nix-store-\${lower(data.coder_workspace.me.owner)}-\${lower(data.coder_workspace.me.name)}";
|
||||||
|
"app.kubernetes.io/name" = "coder-pvc";
|
||||||
|
"app.kubernetes.io/part-of" = "coder";
|
||||||
|
"com.coder.resource" = "true";
|
||||||
|
"com.coder.user.id" = "\${data.coder_workspace.me.owner_id}";
|
||||||
|
"com.coder.user.name" = "\${data.coder_workspace.me.owner}";
|
||||||
|
"com.coder.workspace.id" = "\${data.coder_workspace.me.id}";
|
||||||
|
"com.coder.workspace.name" = "\${data.coder_workspace.me.name}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
spec = {
|
||||||
|
access_modes = ["ReadWriteOnce"];
|
||||||
|
resources.requests.storage = "\${data.coder_parameter.nix_store_disk_size.value}Gi";
|
||||||
|
};
|
||||||
|
wait_until_bound = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
78
nix-kubernetes/parameters.nix
Normal file
78
nix-kubernetes/parameters.nix
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
{...}: {
|
||||||
|
data.coder_parameter = {
|
||||||
|
git_repo = {
|
||||||
|
name = "Git Repository";
|
||||||
|
description = ''
|
||||||
|
URI for a git repository which should automatically be cloned to ~/repos/<name>
|
||||||
|
'';
|
||||||
|
default = "";
|
||||||
|
order = 1;
|
||||||
|
type = "string";
|
||||||
|
mutable = true;
|
||||||
|
};
|
||||||
|
image_tag = {
|
||||||
|
name = "Image Tag";
|
||||||
|
description = ''
|
||||||
|
Which container image tag should be used.
|
||||||
|
'';
|
||||||
|
default = "latest";
|
||||||
|
order = 2;
|
||||||
|
type = "string";
|
||||||
|
mutable = true;
|
||||||
|
};
|
||||||
|
cpu = {
|
||||||
|
name = "CPU";
|
||||||
|
description = ''
|
||||||
|
CPU Limit for Kubernetes Pod. Kubernetes Notation (eg. 500m)
|
||||||
|
'';
|
||||||
|
default = "500m";
|
||||||
|
order = 3;
|
||||||
|
type = "string";
|
||||||
|
mutable = true;
|
||||||
|
};
|
||||||
|
memory = {
|
||||||
|
name = "Memory";
|
||||||
|
description = ''
|
||||||
|
Memory Limit for Kubernetes Pod. Kubernetes Notation (eg. 1Gi)
|
||||||
|
'';
|
||||||
|
default = "1Gi";
|
||||||
|
order = 4;
|
||||||
|
type = "string";
|
||||||
|
mutable = true;
|
||||||
|
};
|
||||||
|
home_disk_size = {
|
||||||
|
name = "Home Disk Size";
|
||||||
|
description = ''
|
||||||
|
Size for the /home PV in GB
|
||||||
|
'';
|
||||||
|
default = 5;
|
||||||
|
order = 5;
|
||||||
|
type = "number";
|
||||||
|
mutable = true;
|
||||||
|
validation = [
|
||||||
|
{
|
||||||
|
min = 1;
|
||||||
|
max = 100;
|
||||||
|
monotonic = "increasing";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
nix_store_disk_size = {
|
||||||
|
name = "Nix Store Disk Size";
|
||||||
|
description = ''
|
||||||
|
Size for the /nix PV in GB. This might grow pretty big.
|
||||||
|
'';
|
||||||
|
default = 5;
|
||||||
|
order = 6;
|
||||||
|
type = "number";
|
||||||
|
mutable = true;
|
||||||
|
validation = [
|
||||||
|
{
|
||||||
|
min = 1;
|
||||||
|
max = 100;
|
||||||
|
monotonic = "increasing";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
16
nix-kubernetes/variables.nix
Normal file
16
nix-kubernetes/variables.nix
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
{...}: {
|
||||||
|
variable = {
|
||||||
|
namespace = {
|
||||||
|
type = "string";
|
||||||
|
description = "Kubernetes namespace (must exist prior to creating workspaces)";
|
||||||
|
};
|
||||||
|
arch = {
|
||||||
|
type = "string";
|
||||||
|
description = "Architecture of the host";
|
||||||
|
validation = {
|
||||||
|
condition = ''''${contains(["amd64", "arm64"], var.arch)}'';
|
||||||
|
error_message = "Invalid architecture selected";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue