kubepile 0.0.4 → 0.0.6
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 +54 -20
- package/dist/package.json +1 -1
- package/dist/src/cli.js +14 -3
- package/dist/src/shell.d.ts +4 -0
- package/dist/src/shell.js +37 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,6 +13,31 @@ Kubepile lets you maintain individual, per-provider kubeconfigs in a
|
|
|
13
13
|
`~/.config/kubepile` directory, and compile them into a single, merged
|
|
14
14
|
kubeconfig.
|
|
15
15
|
|
|
16
|
+
Kubepile exposes a tiny set of commands to manage your configs:
|
|
17
|
+
|
|
18
|
+
* [`compile`](#compile): compile your Kubepile configs into a merged kubeconfig
|
|
19
|
+
* [`source`](#source): set a specific context as your default for the current
|
|
20
|
+
shell
|
|
21
|
+
* [`split`](#split): decompile an existing, messy kubeconfig into nice, clean
|
|
22
|
+
Kubepile configs
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
npm install -g kubepile
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Kubepile also includes a small shell helper that you need to install once:
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
kubepile install
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Once you've installed the shell helper, either start a new shell or re-source
|
|
37
|
+
your `.zshrc`/`.bashrc`/`.profile`/etc. Kubepile supports Zsh, Bash, and Fish.
|
|
38
|
+
|
|
39
|
+
## Kubepile configs
|
|
40
|
+
|
|
16
41
|
Each `*.yaml` file is a normal kubeconfig. You can paste in kubeconfigs from
|
|
17
42
|
providers without converting them to a kubepile-specific schema. During
|
|
18
43
|
`compile`, kubepile reads every file and merges its `clusters`, `users`, and
|
|
@@ -28,13 +53,9 @@ intentionally fail compilation with a helpful message explaining which file
|
|
|
28
53
|
broke the kubepile rules.
|
|
29
54
|
|
|
30
55
|
Kubepile will never set a `current-context`, out of the design belief that
|
|
31
|
-
`current-context` is a dangerous footgun
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
```sh
|
|
36
|
-
npm install -g kubepile
|
|
37
|
-
```
|
|
56
|
+
setting a global, cross-shell-session `current-context` is a dangerous footgun
|
|
57
|
+
in multi-cluster setups. Instead, use `kubepile source <context>` to
|
|
58
|
+
temporarily set a default context for your current shell session.
|
|
38
59
|
|
|
39
60
|
## Compile
|
|
40
61
|
|
|
@@ -65,28 +86,41 @@ Running `kubepile` with no command prints help.
|
|
|
65
86
|
|
|
66
87
|
## Source
|
|
67
88
|
|
|
68
|
-
`kubepile source <context>` switches your current shell to
|
|
69
|
-
creating a temporary kubeconfig
|
|
70
|
-
`KUBECONFIG` to point at it.
|
|
71
|
-
name.
|
|
89
|
+
`kubepile source <context>` switches your current shell to use a specific
|
|
90
|
+
Kubernetes context by default by creating a temporary kubeconfig with that
|
|
91
|
+
context set as the current-context, and exporting `KUBECONFIG` to point at it.
|
|
92
|
+
It also prefixes your shell prompt with the context name.
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
kubepile source prod
|
|
96
|
+
# Your shell prompt is now:
|
|
97
|
+
# (prod) WHATEVER_YOUR_OLD_PROMPT_WAS
|
|
98
|
+
# All kubectl commands will use the prod context
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
To list available contexts:
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
kubepile source --list
|
|
105
|
+
```
|
|
72
106
|
|
|
73
|
-
|
|
74
|
-
|
|
107
|
+
To switch to a different context, just run the `source` command with a new
|
|
108
|
+
context:
|
|
75
109
|
|
|
76
110
|
```sh
|
|
77
|
-
kubepile
|
|
111
|
+
kubepile source dev
|
|
78
112
|
```
|
|
79
113
|
|
|
80
|
-
|
|
114
|
+
Note that this requires installing the shell helpers listed in the
|
|
115
|
+
installation instructions. If you haven't installed them yet, install them
|
|
116
|
+
with:
|
|
81
117
|
|
|
82
118
|
```sh
|
|
83
|
-
kubepile
|
|
119
|
+
kubepile install
|
|
84
120
|
```
|
|
85
121
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
`kubepile` binary with `command kubepile`, so it follows whatever `kubepile` is
|
|
89
|
-
currently on your `PATH` after tools like `nvm` update it.
|
|
122
|
+
And re-source your main shell config (such as e.g. a `.zshrc`) or start a new
|
|
123
|
+
shell.
|
|
90
124
|
|
|
91
125
|
## Split
|
|
92
126
|
|
package/dist/package.json
CHANGED
package/dist/src/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createInterface } from "node:readline/promises";
|
|
|
4
4
|
import { Command } from "@commander-js/extra-typings";
|
|
5
5
|
import packageJson from "../package.json" with { type: "json" };
|
|
6
6
|
import { compileToKubeConfig, defaultKubeConfigPath, defaultKubepileDir, splitKubeConfigFile, } from "./kubepile.js";
|
|
7
|
-
import { generateShellCommand, installShellIntegration, } from "./shell.js";
|
|
7
|
+
import { generateShellCommand, installShellIntegration, listSourceContextNames, } from "./shell.js";
|
|
8
8
|
const program = createProgram();
|
|
9
9
|
if (process.argv.slice(2).length === 0) {
|
|
10
10
|
program.outputHelp();
|
|
@@ -100,8 +100,19 @@ Defaults:
|
|
|
100
100
|
program
|
|
101
101
|
.command("source")
|
|
102
102
|
.description("Switch to one kube context in the current shell.")
|
|
103
|
-
.argument("
|
|
104
|
-
.
|
|
103
|
+
.argument("[context]", "context name to source")
|
|
104
|
+
.option("--list", "list available contexts")
|
|
105
|
+
.action(async (context, options) => {
|
|
106
|
+
if (options.list) {
|
|
107
|
+
const contextNames = await listSourceContextNames();
|
|
108
|
+
if (contextNames.length > 0) {
|
|
109
|
+
process.stdout.write(`${contextNames.join("\n")}\n`);
|
|
110
|
+
}
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (!context) {
|
|
114
|
+
throw new Error("kubepile source requires a context name or --list.");
|
|
115
|
+
}
|
|
105
116
|
throw new Error("kubepile source requires shell integration. Run `kubepile install`, start a new shell, then run `kubepile source <context>`.");
|
|
106
117
|
});
|
|
107
118
|
return program;
|
package/dist/src/shell.d.ts
CHANGED
|
@@ -9,6 +9,9 @@ export interface GenerateShellCommandResult {
|
|
|
9
9
|
kubeConfigPath: string;
|
|
10
10
|
shellCommand: string;
|
|
11
11
|
}
|
|
12
|
+
export interface ListSourceContextNamesOptions {
|
|
13
|
+
sourcePath?: string;
|
|
14
|
+
}
|
|
12
15
|
export interface InstallShellIntegrationOptions {
|
|
13
16
|
shell?: ShellKind;
|
|
14
17
|
rcFile?: string;
|
|
@@ -20,6 +23,7 @@ export interface InstallShellIntegrationResult {
|
|
|
20
23
|
updated: boolean;
|
|
21
24
|
}
|
|
22
25
|
export declare function generateShellCommand(contextName: string, options?: GenerateShellCommandOptions): Promise<GenerateShellCommandResult>;
|
|
26
|
+
export declare function listSourceContextNames(options?: ListSourceContextNamesOptions): Promise<string[]>;
|
|
23
27
|
export declare function installShellIntegration(options?: InstallShellIntegrationOptions): Promise<InstallShellIntegrationResult>;
|
|
24
28
|
export declare function detectCurrentShell(shellPath?: string | undefined): ShellKind;
|
|
25
29
|
export declare function shellRcFile(shell: ShellKind, homeDir?: string): Promise<string>;
|
package/dist/src/shell.js
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import { mkdir, mkdtemp, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { defaultKubeConfigPath,
|
|
4
|
+
import { defaultKubeConfigPath, readKubeConfigFile, serializeKubeConfig, } from "./kubepile.js";
|
|
5
5
|
const SHELL_BLOCK_START = "# >>> kubepile shell integration >>>";
|
|
6
6
|
const SHELL_BLOCK_END = "# <<< kubepile shell integration <<<";
|
|
7
7
|
export async function generateShellCommand(contextName, options = {}) {
|
|
8
8
|
const sourcePath = options.sourcePath ?? defaultKubeConfigPath();
|
|
9
9
|
const shell = options.shell ?? "posix";
|
|
10
10
|
const sourceConfig = await readKubeConfigFile(sourcePath);
|
|
11
|
-
const contextConfig =
|
|
11
|
+
const contextConfig = {
|
|
12
|
+
...sourceConfig,
|
|
13
|
+
"current-context": contextName,
|
|
14
|
+
};
|
|
12
15
|
const tempRoot = await mkdtemp(path.join(options.tempDir ?? os.tmpdir(), "kubepile-source-"));
|
|
13
16
|
const kubeConfigPath = path.join(tempRoot, "config");
|
|
17
|
+
if (!contextNamesFromConfig(sourceConfig, sourcePath).includes(contextName)) {
|
|
18
|
+
throw new Error(`${sourcePath} does not contain context "${contextName}"`);
|
|
19
|
+
}
|
|
14
20
|
await writeFile(kubeConfigPath, serializeKubeConfig(contextConfig), {
|
|
15
21
|
encoding: "utf8",
|
|
16
22
|
mode: 0o600,
|
|
@@ -22,6 +28,10 @@ export async function generateShellCommand(contextName, options = {}) {
|
|
|
22
28
|
: posixSourceCommand(contextName, kubeConfigPath),
|
|
23
29
|
};
|
|
24
30
|
}
|
|
31
|
+
export async function listSourceContextNames(options = {}) {
|
|
32
|
+
const sourcePath = options.sourcePath ?? defaultKubeConfigPath();
|
|
33
|
+
return contextNamesFromConfig(await readKubeConfigFile(sourcePath), sourcePath);
|
|
34
|
+
}
|
|
25
35
|
export async function installShellIntegration(options = {}) {
|
|
26
36
|
const shell = options.shell ?? detectCurrentShell();
|
|
27
37
|
const rcFile = options.rcFile ?? await shellRcFile(shell, options.homeDir ?? os.homedir());
|
|
@@ -79,6 +89,12 @@ function posixIntegrationFunction(shell) {
|
|
|
79
89
|
return `kubepile() {
|
|
80
90
|
if [ "$1" = "source" ]; then
|
|
81
91
|
shift
|
|
92
|
+
for arg in "$@"; do
|
|
93
|
+
if [ "$arg" = "--list" ]; then
|
|
94
|
+
command \\kubepile source "$@"
|
|
95
|
+
return
|
|
96
|
+
fi
|
|
97
|
+
done
|
|
82
98
|
eval "$(command \\kubepile generate-shell-command --shell ${shell} "$@")"
|
|
83
99
|
else
|
|
84
100
|
command \\kubepile "$@"
|
|
@@ -89,7 +105,11 @@ function fishIntegrationFunction() {
|
|
|
89
105
|
return `function kubepile
|
|
90
106
|
if test (count $argv) -gt 0; and test "$argv[1]" = "source"
|
|
91
107
|
set -e argv[1]
|
|
92
|
-
|
|
108
|
+
if contains -- --list $argv
|
|
109
|
+
command kubepile source $argv
|
|
110
|
+
else
|
|
111
|
+
command kubepile generate-shell-command --shell fish $argv | source
|
|
112
|
+
end
|
|
93
113
|
else
|
|
94
114
|
command kubepile $argv
|
|
95
115
|
end
|
|
@@ -150,6 +170,20 @@ async function firstExistingPath(filePaths) {
|
|
|
150
170
|
}
|
|
151
171
|
return undefined;
|
|
152
172
|
}
|
|
173
|
+
function contextNamesFromConfig(config, sourcePath) {
|
|
174
|
+
if (config.contexts === undefined) {
|
|
175
|
+
return [];
|
|
176
|
+
}
|
|
177
|
+
if (!Array.isArray(config.contexts)) {
|
|
178
|
+
throw new Error(`${sourcePath} contexts must be an array`);
|
|
179
|
+
}
|
|
180
|
+
return config.contexts.map((context) => {
|
|
181
|
+
if (typeof context.name !== "string" || context.name.length === 0) {
|
|
182
|
+
throw new Error(`${sourcePath} context name must be a non-empty string`);
|
|
183
|
+
}
|
|
184
|
+
return context.name;
|
|
185
|
+
});
|
|
186
|
+
}
|
|
153
187
|
function escapeRegExp(value) {
|
|
154
188
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
155
189
|
}
|