containerd-config-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # containerd-config-cli
2
+
3
+ Generate containerd runtime configurations from the command line
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g containerd-config-cli
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Initialize configuration
14
+
15
+ ```bash
16
+ containerd-config init
17
+ containerd-config init --template advanced
18
+ containerd-config init --output custom-config.json
19
+ ```
20
+
21
+ ### Validate configuration
22
+
23
+ ```bash
24
+ containerd-config validate
25
+ containerd-config validate path/to/config.json
26
+ ```
27
+
28
+ ### View configuration
29
+
30
+ ```bash
31
+ containerd-config show
32
+ containerd-config show --env production
33
+ containerd-config show --json
34
+ ```
35
+
36
+ ### Modify configuration
37
+
38
+ ```bash
39
+ containerd-config set settings.debug true
40
+ containerd-config set settings.logLevel \"warn\"
41
+ ```
42
+
43
+ ### Compare configurations
44
+
45
+ ```bash
46
+ containerd-config diff config-dev.json config-prod.json
47
+ ```
48
+
49
+ ### List templates
50
+
51
+ ```bash
52
+ containerd-config templates
53
+ ```
54
+
55
+ ## Templates
56
+
57
+ | Template | Description |
58
+ |----------|-------------|
59
+ | `minimal` | Bare minimum configuration |
60
+ | `standard` | Recommended defaults for most projects |
61
+ | `advanced` | Full-featured with security, caching, and multi-environment support |
62
+
63
+ ## Why containerd-config-cli?
64
+
65
+ - **Zero dependencies at runtime** — just `commander` and `chalk`
66
+ - **Template-based** — start with minimal, standard, or advanced presets
67
+ - **Validation built-in** — catch config errors before deployment
68
+ - **Environment-aware** — manage dev/staging/production configs in one file
69
+ - **Diff support** — compare configs across environments
70
+
71
+ ## License
72
+
73
+ MIT
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,358 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+
26
+ // src/index.ts
27
+ var import_commander = require("commander");
28
+ var import_chalk = __toESM(require("chalk"));
29
+ var program = new import_commander.Command();
30
+ function printSection(title, content) {
31
+ console.log(import_chalk.default.bold.cyan(`
32
+ # ${title}`));
33
+ console.log(import_chalk.default.white(content));
34
+ }
35
+ function success(msg) {
36
+ console.log(import_chalk.default.green("\u2714 ") + msg);
37
+ }
38
+ function info(msg) {
39
+ console.log(import_chalk.default.blue("\u2139 ") + msg);
40
+ }
41
+ function baseConfigToml() {
42
+ return `version = 2
43
+
44
+ [debug]
45
+ address = ""
46
+ level = "info"
47
+
48
+ [metrics]
49
+ address = ""
50
+ grpc_histogram = false
51
+
52
+ [plugins]
53
+ [plugins."io.containerd.grpc.v1.cri"]
54
+ sandbox_image = "registry.k8s.io/pause:3.9"
55
+ max_container_log_line_size = 16384
56
+
57
+ [plugins."io.containerd.grpc.v1.cri".containerd]
58
+ snapshotter = "overlayfs"
59
+ default_runtime_name = "runc"
60
+ no_pivot = false
61
+ disable_snapshot_annotations = true
62
+ discard_unpacked_layers = false
63
+
64
+ [plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
65
+ [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
66
+ runtime_type = "io.containerd.runc.v2"
67
+ [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
68
+ SystemdCgroup = true
69
+
70
+ [plugins."io.containerd.grpc.v1.cri".cni]
71
+ bin_dir = "/opt/cni/bin"
72
+ conf_dir = "/etc/cni/net.d"
73
+ max_conf_num = 1
74
+
75
+ [plugins."io.containerd.grpc.v1.cri".registry]
76
+ config_path = "/etc/containerd/certs.d"
77
+
78
+ [plugins."io.containerd.snapshotter.v1.overlayfs"]
79
+ root_path = ""
80
+ upperdir_label = false
81
+ `;
82
+ }
83
+ function runtimeConfig(name) {
84
+ const runtimes = {
85
+ runc: `[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
86
+ runtime_type = "io.containerd.runc.v2"
87
+ [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
88
+ SystemdCgroup = true
89
+ BinaryName = ""
90
+ Root = ""
91
+ ShimCgroup = ""`,
92
+ kata: `[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata]
93
+ runtime_type = "io.containerd.kata.v2"
94
+ privileged_without_host_devices = true
95
+ pod_annotations = ["io.katacontainers.*"]
96
+ container_annotations = ["io.katacontainers.*"]
97
+ [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata.options]
98
+ ConfigPath = "/etc/kata-containers/configuration.toml"`,
99
+ gvisor: `[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc]
100
+ runtime_type = "io.containerd.runsc.v1"
101
+ pod_annotations = ["dev.gvisor.*"]
102
+ container_annotations = ["dev.gvisor.*"]
103
+ [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc.options]
104
+ TypeUrl = "io.containerd.runsc.v1.options"
105
+ ConfigPath = "/etc/gvisor/config.toml"`,
106
+ crun: `[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.crun]
107
+ runtime_type = "io.containerd.runc.v2"
108
+ [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.crun.options]
109
+ BinaryName = "/usr/bin/crun"
110
+ SystemdCgroup = true`,
111
+ youki: `[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.youki]
112
+ runtime_type = "io.containerd.runc.v2"
113
+ [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.youki.options]
114
+ BinaryName = "/usr/local/bin/youki"
115
+ SystemdCgroup = true`
116
+ };
117
+ return runtimes[name] ?? `# Runtime "${name}" is not a built-in preset.
118
+ # Define custom runtime_type manually.`;
119
+ }
120
+ function registryConfig(url) {
121
+ const host = (() => {
122
+ try {
123
+ return new URL(url.startsWith("http") ? url : `https://${url}`).host;
124
+ } catch {
125
+ return url;
126
+ }
127
+ })();
128
+ return `# Place this file at: /etc/containerd/certs.d/${host}/hosts.toml
129
+
130
+ server = "https://${host}"
131
+
132
+ [host."https://${host}"]
133
+ capabilities = ["pull", "resolve", "push"]
134
+ # skip_verify = false
135
+ # ca = ["/etc/containerd/certs.d/${host}/ca.crt"]
136
+
137
+ # --- Mirror example ---
138
+ # [host."https://mirror.example.com"]
139
+ # capabilities = ["pull", "resolve"]
140
+
141
+ # --- Auth (via credsStore or static) ---
142
+ # Configure credentials via:
143
+ # /etc/containerd/config.toml \u2192 [plugins."io.containerd.grpc.v1.cri".registry.configs."${host}".auth]
144
+ # username = "user"
145
+ # password = "pass"
146
+ # # or
147
+ # auth = "<base64(user:pass)>"
148
+ `;
149
+ }
150
+ function snapshotterConfig(type) {
151
+ const configs = {
152
+ overlayfs: `[plugins."io.containerd.snapshotter.v1.overlayfs"]
153
+ root_path = ""
154
+ upperdir_label = false
155
+ # async_remove = false`,
156
+ zfs: `[plugins."io.containerd.snapshotter.v1.zfs"]
157
+ root_path = "/var/lib/containerd/io.containerd.snapshotter.v1.zfs"
158
+ # pool_name = "containerd"`,
159
+ btrfs: `[plugins."io.containerd.snapshotter.v1.btrfs"]
160
+ root_path = "/var/lib/containerd/io.containerd.snapshotter.v1.btrfs"`,
161
+ stargz: `[plugins."io.containerd.snapshotter.v1.stargz"]
162
+ root_path = "/var/lib/containerd/io.containerd.snapshotter.v1.stargz"
163
+ no_prometheus = false
164
+
165
+ [plugins."io.containerd.snapshotter.v1.stargz".blob]
166
+ check_always = false
167
+ fetching_timeout_sec = 30
168
+ max_retries = 5
169
+
170
+ [plugins."io.containerd.snapshotter.v1.stargz".prefetch]
171
+ timeout_sec = 120`
172
+ };
173
+ return configs[type] ?? `# Snapshotter "${type}" is not a built-in preset.
174
+ # Consult containerd docs for custom configuration.`;
175
+ }
176
+ function cniConfig(name) {
177
+ const configs = {
178
+ bridge: {
179
+ cniVersion: "1.0.0",
180
+ name: "containerd-net",
181
+ plugins: [
182
+ {
183
+ type: "bridge",
184
+ bridge: "cni0",
185
+ isGateway: true,
186
+ ipMasq: true,
187
+ promiscMode: true,
188
+ ipam: {
189
+ type: "host-local",
190
+ ranges: [[{ subnet: "10.88.0.0/16" }]],
191
+ routes: [{ dst: "0.0.0.0/0" }]
192
+ }
193
+ },
194
+ { type: "portmap", capabilities: { portMappings: true } },
195
+ { type: "firewall" },
196
+ { type: "tuning" }
197
+ ]
198
+ },
199
+ flannel: {
200
+ cniVersion: "0.3.1",
201
+ name: "flannel",
202
+ plugins: [
203
+ { type: "flannel", delegate: { hairpinMode: true, isDefaultGateway: true } },
204
+ { type: "portmap", capabilities: { portMappings: true } }
205
+ ]
206
+ },
207
+ calico: {
208
+ name: "k8s-pod-network",
209
+ cniVersion: "0.3.1",
210
+ plugins: [
211
+ {
212
+ type: "calico",
213
+ log_level: "info",
214
+ log_file_path: "/var/log/calico/cni/cni.log",
215
+ datastore_type: "kubernetes",
216
+ nodename: "__KUBERNETES_NODE_NAME__",
217
+ mtu: 0,
218
+ ipam: { type: "calico-ipam" },
219
+ policy: { type: "k8s" },
220
+ kubernetes: { kubeconfig: "__KUBECONFIG_FILEPATH__" }
221
+ },
222
+ { type: "portmap", snat: true, capabilities: { portMappings: true } },
223
+ { type: "bandwidth", capabilities: { bandwidth: true } }
224
+ ]
225
+ },
226
+ weave: {
227
+ cniVersion: "0.3.1",
228
+ name: "weave",
229
+ plugins: [
230
+ { type: "weave-net", log_level: "info" },
231
+ { type: "portmap", capabilities: { portMappings: true } }
232
+ ]
233
+ }
234
+ };
235
+ const cfg = configs[name];
236
+ if (!cfg) {
237
+ return `# CNI plugin "${name}" is not a built-in preset.
238
+ # See https://www.cni.dev/plugins/ for configuration reference.`;
239
+ }
240
+ return JSON.stringify(cfg, null, 2);
241
+ }
242
+ function criConfig() {
243
+ return `[plugins."io.containerd.grpc.v1.cri"]
244
+ # Pause container image used for Kubernetes pods
245
+ sandbox_image = "registry.k8s.io/pause:3.9"
246
+
247
+ # Max size of container log line in bytes (default 16KB)
248
+ max_container_log_line_size = 16384
249
+
250
+ # Enable selinux labeling
251
+ enable_selinux = false
252
+
253
+ # Enable apparmor
254
+ enable_apparmor = true
255
+
256
+ # Tolerate image pulls that are missing some layers (for lazy pulling)
257
+ ignore_image_defined_volumes = false
258
+
259
+ [plugins."io.containerd.grpc.v1.cri".containerd]
260
+ snapshotter = "overlayfs"
261
+ default_runtime_name = "runc"
262
+ no_pivot = false
263
+ disable_snapshot_annotations = true
264
+ discard_unpacked_layers = false
265
+
266
+ [plugins."io.containerd.grpc.v1.cri".cni]
267
+ bin_dir = "/opt/cni/bin"
268
+ conf_dir = "/etc/cni/net.d"
269
+ max_conf_num = 1
270
+ # conf_template = ""
271
+
272
+ [plugins."io.containerd.grpc.v1.cri".registry]
273
+ config_path = "/etc/containerd/certs.d"
274
+
275
+ [plugins."io.containerd.grpc.v1.cri".image_decryption]
276
+ key_model = "node"
277
+
278
+ [plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming]
279
+ tls_cert_file = ""
280
+ tls_key_file = ""
281
+ `;
282
+ }
283
+ program.name("containerd-config").description(import_chalk.default.bold("containerd-config-cli") + " \u2014 Generate containerd runtime configurations").version("1.0.0");
284
+ program.command("init").description("Generate a base config.toml with runtime, snapshotter, and plugin settings").option("--runtime <name>", "Default container runtime", "runc").option("--snapshotter <type>", "Default snapshotter", "overlayfs").option("--systemd-cgroup", "Enable systemd cgroup driver", false).action((opts) => {
285
+ info(`Generating base config.toml (runtime=${opts.runtime}, snapshotter=${opts.snapshotter})`);
286
+ let cfg = baseConfigToml();
287
+ if (opts.snapshotter !== "overlayfs") {
288
+ cfg = cfg.replace('snapshotter = "overlayfs"', `snapshotter = "${opts.snapshotter}"`);
289
+ }
290
+ if (opts.runtime !== "runc") {
291
+ cfg = cfg.replace('default_runtime_name = "runc"', `default_runtime_name = "${opts.runtime}"`);
292
+ }
293
+ printSection("config.toml", cfg);
294
+ success("Save to /etc/containerd/config.toml");
295
+ });
296
+ program.command("runtime <name>").description("Configure container runtime: runc, kata, gvisor, crun, youki").option("--set-default", "Also set as default_runtime_name in containerd config").action((name, opts) => {
297
+ const supported = ["runc", "kata", "gvisor", "crun", "youki"];
298
+ if (!supported.includes(name)) {
299
+ console.log(import_chalk.default.yellow(`\u26A0 "${name}" is not a built-in preset. Supported: ${supported.join(", ")}`));
300
+ } else {
301
+ success(`Generating runtime config for: ${import_chalk.default.bold(name)}`);
302
+ }
303
+ printSection(`Runtime: ${name}`, runtimeConfig(name));
304
+ if (opts.setDefault) {
305
+ info(`Add to containerd config: default_runtime_name = "${name === "gvisor" ? "runsc" : name}"`);
306
+ }
307
+ });
308
+ program.command("registry <url>").description("Configure registry mirror and authentication").option("--mirror <mirror>", "Mirror URL to use for pulls").option("--insecure", "Skip TLS verification", false).action((url, opts) => {
309
+ success(`Generating registry config for: ${import_chalk.default.bold(url)}`);
310
+ let cfg = registryConfig(url);
311
+ if (opts.mirror) {
312
+ cfg += `
313
+ # Mirror configured: ${opts.mirror}
314
+ `;
315
+ }
316
+ if (opts.insecure) {
317
+ cfg = cfg.replace("# skip_verify = false", "skip_verify = true");
318
+ }
319
+ printSection(`Registry: ${url}`, cfg);
320
+ });
321
+ program.command("snapshotter <type>").description("Configure snapshotter: overlayfs, zfs, btrfs, stargz").action((type) => {
322
+ const supported = ["overlayfs", "zfs", "btrfs", "stargz"];
323
+ if (!supported.includes(type)) {
324
+ console.log(import_chalk.default.yellow(`\u26A0 "${type}" is not a built-in preset. Supported: ${supported.join(", ")}`));
325
+ } else {
326
+ success(`Generating snapshotter config for: ${import_chalk.default.bold(type)}`);
327
+ }
328
+ printSection(`Snapshotter: ${type}`, snapshotterConfig(type));
329
+ });
330
+ program.command("cni <name>").description("Generate CNI network plugin configuration: bridge, flannel, calico, weave").option("--subnet <cidr>", "Override default subnet", "10.88.0.0/16").action((name, opts) => {
331
+ const supported = ["bridge", "flannel", "calico", "weave"];
332
+ if (!supported.includes(name)) {
333
+ console.log(import_chalk.default.yellow(`\u26A0 "${name}" is not a built-in preset. Supported: ${supported.join(", ")}`));
334
+ } else {
335
+ success(`Generating CNI config for: ${import_chalk.default.bold(name)}`);
336
+ }
337
+ let cfg = cniConfig(name);
338
+ if (opts.subnet !== "10.88.0.0/16") {
339
+ cfg = cfg.replace("10.88.0.0/16", opts.subnet);
340
+ }
341
+ printSection(`CNI: ${name}`, cfg);
342
+ if (supported.includes(name)) {
343
+ info("Save to /etc/cni/net.d/10-containerd-net.conflist");
344
+ }
345
+ });
346
+ program.command("cri").description("Configure CRI plugin settings for Kubernetes integration").option("--sandbox-image <image>", "Override pause container image", "registry.k8s.io/pause:3.9").option("--snapshotter <type>", "Snapshotter to use", "overlayfs").action((opts) => {
347
+ success("Generating CRI plugin configuration");
348
+ let cfg = criConfig();
349
+ if (opts.sandboxImage !== "registry.k8s.io/pause:3.9") {
350
+ cfg = cfg.replace("registry.k8s.io/pause:3.9", opts.sandboxImage);
351
+ }
352
+ if (opts.snapshotter !== "overlayfs") {
353
+ cfg = cfg.replace('snapshotter = "overlayfs"', `snapshotter = "${opts.snapshotter}"`);
354
+ }
355
+ printSection("CRI Plugin Configuration", cfg);
356
+ info("Merge into /etc/containerd/config.toml under [plugins]");
357
+ });
358
+ program.parse(process.argv);
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "containerd-config-cli",
3
+ "version": "1.0.0",
4
+ "description": "Generate containerd runtime configurations from the command line",
5
+ "bin": {
6
+ "containerd-config": "./dist/index.js"
7
+ },
8
+ "main": "./dist/index.js",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "node node_modules/tsup/dist/cli-default.js src/index.ts --format cjs --dts --clean",
14
+ "dev": "node node_modules/tsup/dist/cli-default.js src/index.ts --format cjs --watch",
15
+ "start": "node dist/index.js"
16
+ },
17
+ "keywords": [
18
+ "containerd",
19
+ "container",
20
+ "runtime",
21
+ "config",
22
+ "kubernetes",
23
+ "cri",
24
+ "cni",
25
+ "runc",
26
+ "kata",
27
+ "gvisor"
28
+ ],
29
+ "author": "okirmio-create",
30
+ "license": "MIT",
31
+ "dependencies": {
32
+ "chalk": "^5.3.0",
33
+ "commander": "^12.1.0"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^20.14.0",
37
+ "tsup": "^8.1.0",
38
+ "typescript": "^5.4.5"
39
+ },
40
+ "engines": {
41
+ "node": ">=18.0.0"
42
+ },
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "https://github.com/okirmio-create/cli-forge.git",
46
+ "directory": "containerd-config-cli"
47
+ },
48
+ "homepage": "https://github.com/okirmio-create/cli-forge/tree/main/containerd-config-cli",
49
+ "bugs": {
50
+ "url": "https://github.com/okirmio-create/cli-forge/issues"
51
+ }
52
+ }