Skip to content

Commit

Permalink
feat: added support for editing custom kubernetes resources
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeroen Nijhuis committed Jan 23, 2024
1 parent 367dc88 commit 98047a4
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 33 deletions.
3 changes: 2 additions & 1 deletion src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"allowlist": {
"all": true,
"fs": {
"scope": ["$APPCONFIG/", "$APPCONFIG/*"]
"all": true,
"scope": ["$APPCONFIG/", "$APPCONFIG/*", "$TEMP/", "$TEMP/*", "$TEMP/*/**", "$TEMP/**"]
},
"shell": {
"scope": [
Expand Down
2 changes: 1 addition & 1 deletion src/components/NavigationGroup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ watch(
<ArrowDownIcon class="w-5" />
</div>
</div>
<div v-if="!collapsed" class="mb-5 space-y-1">
<div v-show="!collapsed" class="mb-5 space-y-1">
<slot />
</div>
</div>
Expand Down
28 changes: 18 additions & 10 deletions src/components/NavigationItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
import NavigationItemIcon from "@/components/NavigationItemIcon.vue";
import { RouteLocationRaw, useRouter } from "vue-router";
import { injectStrict } from "@/lib/utils";
import { RegisterCommandStateKey } from "@/providers/CommandPaletteProvider";
import {
RegisterCommandStateKey,
UnregisterCommandStateKey,
} from "@/providers/CommandPaletteProvider";
const router = useRouter();
Expand All @@ -13,15 +16,20 @@ const props = defineProps<{
}>();
const registerCommand = injectStrict(RegisterCommandStateKey);
onMounted(() => {
registerCommand({
id: crypto.randomUUID(),
name: props.title,
description: "Navigate to " + props.title,
execute: () => {
router.push(props.to);
},
});
const unregisterCommand = injectStrict(UnregisterCommandStateKey);
const commandId = crypto.randomUUID();
registerCommand({
id: commandId,
name: props.title,
description: "Navigate to " + props.title,
execute: () => {
router.push(props.to);
},
});
onUnmounted(() => {
unregisterCommand(commandId);
});
</script>
<template>
Expand Down
4 changes: 3 additions & 1 deletion src/components/tables/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export type RowAction<T> = WithOptions<T> | WithHandler<T>;

export function getDefaultActions<T extends KubernetesObject | VirtualService>(
addTab: any,
context: string
context: string,
isGenericResource: boolean = false
): RowAction<T>[] {
return [
{
Expand All @@ -34,6 +35,7 @@ export function getDefaultActions<T extends KubernetesObject | VirtualService>(
namespace: row.metadata?.namespace,
type: row.kind,
name: row.metadata?.name,
useKubeCtl: isGenericResource,
},
"edit"
);
Expand Down
17 changes: 17 additions & 0 deletions src/providers/CommandPaletteProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { provide, reactive, InjectionKey, toRefs, ToRefs } from "vue";

export const RegisterCommandStateKey: InjectionKey<(command: Command) => void> =
Symbol("RegisterComand");
export const UnregisterCommandStateKey: InjectionKey<(id: string) => void> =
Symbol("UnregisterCommand");
export const CommandPaletteStateKey: InjectionKey<ToRefs<CommandPaletteState>> =
Symbol("CommandPaletteState");
export const OpenCommandPaletteKey: InjectionKey<() => void> =
Expand Down Expand Up @@ -91,6 +93,20 @@ export default {
state.commands.push(command);
};

const unregisterCommand = (commandId: string) => {
const command = state.commands.find(
(command) => command.id === commandId
);

if (!command) {
return;
}

state.commands = state.commands.filter(
(command) => command.id !== commandId
);
};

const executeCommand = (command: Command) => {
if (command.commands) {
state.loading = true;
Expand Down Expand Up @@ -132,6 +148,7 @@ export default {
provide(ClearCommandCallStackKey, clearStack);
provide(ShowSingleCommandKey, showSingleCommand);
provide(RegisterCommandStateKey, registerCommand);
provide(UnregisterCommandStateKey, unregisterCommand);
},
render(): any {
return this.$slots.default();
Expand Down
5 changes: 3 additions & 2 deletions src/services/Kubernetes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
KubernetesObject,
V1APIGroup,
V1APIResource,
V1ConfigMap,
Expand Down Expand Up @@ -95,13 +96,13 @@ export class Kubernetes {
type: string,
name: string,
object: unknown
): Promise<V1Pod> {
): Promise<KubernetesObject> {
return invoke(`replace_${type.toLowerCase()}`, {
context: context,
namespace: namespace,
name: name,
object,
});
}) as Promise<KubernetesObject>;
}

static async deletePod(
Expand Down
2 changes: 1 addition & 1 deletion src/views/GenericResource.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { TabProviderAddTabKey } from "@/providers/TabProvider";
const addTab = injectStrict(TabProviderAddTabKey);
const rowActions: RowAction<any>[] = [
...getDefaultActions<any>(addTab, context.value),
...getDefaultActions<any>(addTab, context.value, true),
];
onBeforeRouteUpdate((to, from, next) => {
Expand Down
73 changes: 56 additions & 17 deletions src/views/ObjectEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import { getCurrentInstance } from "vue";
import Loading from "@/components/Loading.vue";
import { Command } from "@tauri-apps/api/shell";
import { writeFile, removeFile, BaseDirectory } from "@tauri-apps/api/fs";
import { tempdir } from "@tauri-apps/api/os";
import loader from "@monaco-editor/loader";
import Theme from "@/components/monaco/themes/BrillianceBlack";
import { Button } from "@/components/ui/button";
Expand All @@ -24,6 +26,7 @@ const props = defineProps<{
namespace: string;
type: string;
name: string;
useKubeCtl: boolean;
}>();
const editorElement = ref<HTMLElement | null>(null);
Expand Down Expand Up @@ -99,24 +102,60 @@ const onClose = () => {
};
const onSave = () => {
Kubernetes.replaceObject(
props.context,
props.namespace,
props.type,
props.name,
yaml.load(editContents.value)
)
.then((result) => {
onClose();
})
.catch((error) => {
console.log(error);
toast({
title: "An error occured",
description: error.message,
variant: "destructive",
if (!props.useKubeCtl) {
Kubernetes.replaceObject(
props.context,
props.namespace,
props.type,
props.name,
yaml.load(editContents.value)
)
.then((result) => {
onClose();
})
.catch((error) => {
console.log(error);
toast({
title: "An error occured",
description: error.message,
variant: "destructive",
});
});
});
} else {
const filename = `${props.name}-${crypto.randomUUID()}.yaml`;
writeFile(filename, editContents.value, { dir: BaseDirectory.Temp }).then(
async () => {
const tempDir = await tempdir();
const command = new Command("kubectl", [
"replace",
"--context",
props.context,
"--namespace",
props.namespace,
"-f",
`${tempDir}${filename}`,
]);
command.stdout.on("data", (data) => {
console.log(data);
});
command.stderr.on("data", (error) => {
console.log(error);
});
command.on("close", ({ code }) => {
if (code === 0) {
removeFile(filename, { dir: BaseDirectory.Temp });
onClose();
}
});
command.spawn();
}
);
}
};
onUnmounted(() => {
Expand Down

0 comments on commit 98047a4

Please sign in to comment.