kubepile 0.0.5 → 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 +33 -15
- 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 +30 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,22 +13,13 @@ 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
|
-
|
|
17
|
-
providers without converting them to a kubepile-specific schema. During
|
|
18
|
-
`compile`, kubepile reads every file and merges its `clusters`, `users`, and
|
|
19
|
-
`contexts` directly into the generated kubeconfig.
|
|
20
|
-
|
|
21
|
-
Kubepile automatically ensures the following:
|
|
22
|
-
|
|
23
|
-
- No kubepile files set a `current-context`.
|
|
24
|
-
- No cluster, user, or context names clash.
|
|
16
|
+
Kubepile exposes a tiny set of commands to manage your configs:
|
|
25
17
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
Kubepile
|
|
31
|
-
`current-context` is a dangerous footgun in multi-cluster setups.
|
|
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
|
|
32
23
|
|
|
33
24
|
## Install
|
|
34
25
|
|
|
@@ -45,6 +36,27 @@ kubepile install
|
|
|
45
36
|
Once you've installed the shell helper, either start a new shell or re-source
|
|
46
37
|
your `.zshrc`/`.bashrc`/`.profile`/etc. Kubepile supports Zsh, Bash, and Fish.
|
|
47
38
|
|
|
39
|
+
## Kubepile configs
|
|
40
|
+
|
|
41
|
+
Each `*.yaml` file is a normal kubeconfig. You can paste in kubeconfigs from
|
|
42
|
+
providers without converting them to a kubepile-specific schema. During
|
|
43
|
+
`compile`, kubepile reads every file and merges its `clusters`, `users`, and
|
|
44
|
+
`contexts` directly into the generated kubeconfig.
|
|
45
|
+
|
|
46
|
+
Kubepile automatically ensures the following:
|
|
47
|
+
|
|
48
|
+
- No kubepile files set a `current-context`.
|
|
49
|
+
- No cluster, user, or context names clash.
|
|
50
|
+
|
|
51
|
+
If a new file is added that clashes or sets a `current-context`, kubepile will
|
|
52
|
+
intentionally fail compilation with a helpful message explaining which file
|
|
53
|
+
broke the kubepile rules.
|
|
54
|
+
|
|
55
|
+
Kubepile will never set a `current-context`, out of the design belief that
|
|
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.
|
|
59
|
+
|
|
48
60
|
## Compile
|
|
49
61
|
|
|
50
62
|
```sh
|
|
@@ -86,6 +98,12 @@ kubepile source prod
|
|
|
86
98
|
# All kubectl commands will use the prod context
|
|
87
99
|
```
|
|
88
100
|
|
|
101
|
+
To list available contexts:
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
kubepile source --list
|
|
105
|
+
```
|
|
106
|
+
|
|
89
107
|
To switch to a different context, just run the `source` command with a new
|
|
90
108
|
context:
|
|
91
109
|
|
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
|
@@ -14,7 +14,7 @@ export async function generateShellCommand(contextName, options = {}) {
|
|
|
14
14
|
};
|
|
15
15
|
const tempRoot = await mkdtemp(path.join(options.tempDir ?? os.tmpdir(), "kubepile-source-"));
|
|
16
16
|
const kubeConfigPath = path.join(tempRoot, "config");
|
|
17
|
-
if (!sourceConfig.
|
|
17
|
+
if (!contextNamesFromConfig(sourceConfig, sourcePath).includes(contextName)) {
|
|
18
18
|
throw new Error(`${sourcePath} does not contain context "${contextName}"`);
|
|
19
19
|
}
|
|
20
20
|
await writeFile(kubeConfigPath, serializeKubeConfig(contextConfig), {
|
|
@@ -28,6 +28,10 @@ export async function generateShellCommand(contextName, options = {}) {
|
|
|
28
28
|
: posixSourceCommand(contextName, kubeConfigPath),
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
|
+
export async function listSourceContextNames(options = {}) {
|
|
32
|
+
const sourcePath = options.sourcePath ?? defaultKubeConfigPath();
|
|
33
|
+
return contextNamesFromConfig(await readKubeConfigFile(sourcePath), sourcePath);
|
|
34
|
+
}
|
|
31
35
|
export async function installShellIntegration(options = {}) {
|
|
32
36
|
const shell = options.shell ?? detectCurrentShell();
|
|
33
37
|
const rcFile = options.rcFile ?? await shellRcFile(shell, options.homeDir ?? os.homedir());
|
|
@@ -85,6 +89,12 @@ function posixIntegrationFunction(shell) {
|
|
|
85
89
|
return `kubepile() {
|
|
86
90
|
if [ "$1" = "source" ]; then
|
|
87
91
|
shift
|
|
92
|
+
for arg in "$@"; do
|
|
93
|
+
if [ "$arg" = "--list" ]; then
|
|
94
|
+
command \\kubepile source "$@"
|
|
95
|
+
return
|
|
96
|
+
fi
|
|
97
|
+
done
|
|
88
98
|
eval "$(command \\kubepile generate-shell-command --shell ${shell} "$@")"
|
|
89
99
|
else
|
|
90
100
|
command \\kubepile "$@"
|
|
@@ -95,7 +105,11 @@ function fishIntegrationFunction() {
|
|
|
95
105
|
return `function kubepile
|
|
96
106
|
if test (count $argv) -gt 0; and test "$argv[1]" = "source"
|
|
97
107
|
set -e argv[1]
|
|
98
|
-
|
|
108
|
+
if contains -- --list $argv
|
|
109
|
+
command kubepile source $argv
|
|
110
|
+
else
|
|
111
|
+
command kubepile generate-shell-command --shell fish $argv | source
|
|
112
|
+
end
|
|
99
113
|
else
|
|
100
114
|
command kubepile $argv
|
|
101
115
|
end
|
|
@@ -156,6 +170,20 @@ async function firstExistingPath(filePaths) {
|
|
|
156
170
|
}
|
|
157
171
|
return undefined;
|
|
158
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
|
+
}
|
|
159
187
|
function escapeRegExp(value) {
|
|
160
188
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
161
189
|
}
|