Skip to content
This repository has been archived by the owner on Mar 7, 2023. It is now read-only.

backports: for release v0.2.1 #140

Merged
merged 11 commits into from
Apr 8, 2022
2 changes: 1 addition & 1 deletion .conform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ policies:
gitHubOrganization: siderolabs
spellcheck:
locale: US
maximumOfOneCommit: true
maximumOfOneCommit: false
header:
length: 89
imperative: true
Expand Down
25 changes: 22 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
# theila

Cluster management UI which is like many others relies on `kubeconfig` but also provides OS level hooks
when running against Talos based clusters by reading `talosconfig` and connecting to Talos gRPC API.
Cluster management UI which relies on local `~/.talos/config` and provides OS level hooks
by connecting to Talos gRPC API.
Then Kubernetes credentials are requested from the Talos API.

`TALOSCONFIG` environment variable can be used to alter the lookup path for the Talos configuration.

## Compatibility Matrix

Theila versions are compatible with the following versions of Talos:

| | v0.11 | v0.12 | v0.13 | v0.14 | v1.0 |
| ------------- | ----- | ------ | ----- | ----- | ----- |
| Theila (v0.1) | ✓ | ✓ | ✓ | ✓ | |
| Theila (v0.2) | ✓ | ✓ | ✓ | ✓ | ✓ |

CAPI compatibility matrix:

| | v1alpha3 (v0.3) | v1alpha4 (v0.4) | v1beta1 (v1.x) |
| ------------- | --------------- | --------------- | -------------- |
| Theila (v0.1) | ✓ | ✓ | |
| Theila (v0.2) | | | ✓ |

## Documentation

Expand All @@ -14,7 +33,7 @@ By default it binds `localhost:8080` address.
## Community

- Slack: Join our [slack channel](https://slack.dev.talos-systems.io)
- Support: Questions, bugs, feature requests [GitHub Discussions](https://github.com/talos-systems/talos/discussions)
- Support: Questions, bugs, feature requests [GitHub Discussions](https://github.com/siderolabs/talos/discussions)
- Forum: [community](https://groups.google.com/a/talos-systems.com/forum/#!forum/community)
- Twitter: [@SideroLabs](https://twitter.com/SideroLabs)
- Email: [info@SideroLabs.com](mailto:info@SideroLabs.com)
Expand Down
6 changes: 3 additions & 3 deletions api/rpc/resource.pb.gw.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"vue-class-component": "^8.0.0-0",
"vue-property-decorator": "^v10.0.0-rc.3",
"vue-router": "^4.0.6",
"vue-word-highlighter": "^1.0.4",
"vue3-apexcharts": "^1.4.0",
"vue3-popper": "^1.4.1"
},
Expand Down
Binary file modified frontend/public/favicon.ico
Binary file not shown.
8 changes: 6 additions & 2 deletions frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<template>
<div :class="{ dark: dark }" v-if="connected">
<t-header />
<div v-if="connected">
<t-header :key="headerComponentKey" />
<t-shell>
<template v-slot:menu>
<t-side-bar :contexts="contexts">{{
Expand Down Expand Up @@ -46,6 +46,8 @@ export default {
const router = useRouter();
const route = useRoute();

const headerComponentKey = ref(0);

const updateTheme = (mode: string) => {
dark.value = isDark(mode);
};
Expand Down Expand Up @@ -80,6 +82,7 @@ export default {
(val, old) => {
if (val.cluster != old.cluster) {
detectCapabilities(route);
headerComponentKey.value += 1;
}
}
);
Expand All @@ -105,6 +108,7 @@ export default {
};

return {
headerComponentKey,
connected,
dark,
contexts,
Expand Down
8 changes: 3 additions & 5 deletions frontend/src/api/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,13 @@ export const encodeProtobuf = (type?: string, spec?: any) => {
return res.encode(res.fromPartial(spec)).finish();
}

const capiVersion = "v1alpha4"

export const kubernetes = {
service: "services.v1",
pod: "pods.v1",
node: "nodes.v1",
cluster: `clusters.${capiVersion}.cluster.x-k8s.io`,
machine: `machines.${capiVersion}.cluster.x-k8s.io`,
sideroServers: "servers.v1alpha1.metal.sidero.dev",
cluster: `clusters`,
machine: `machines`,
sideroServers: "servers",
crd: "customresourcedefinitions.v1.apiextensions.k8s.io",
};

Expand Down
12 changes: 10 additions & 2 deletions frontend/src/components/ShellMenuItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,20 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
<template>
<div>
<div class="flex flex-col gap-2">
<component :is="link ? 'router-link' : 'a'" :to="link" :class="{'shell-menu-link': true, 'router-link-active': active, 'cursor-pointer': true}">
<component
:is="link ? 'router-link' : 'a'"
:to="link"
:class="{
'shell-menu-link': true,
'router-link-active': active,
'cursor-pointer': true,
}"
>
<div class="flex flex-row items-center gap-2">
<slot name="icon"></slot>
<span class="text-sm leading-none font-medium">{{ name }}</span>
</div>
</component>
</component>
</div>
</div>
</template>
Expand Down
115 changes: 33 additions & 82 deletions frontend/src/components/TAlert.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,77 +4,54 @@ License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<template>
<div :class="classes" v-if="!closed">
<div class="flex">
<div class="flex-shrink-0" id="icon">
<div class="alert" :class="'alert-' + type">
<div class="alert__box">
<div class="alert__icon-wrapper" id="icon">
<component :is="'icon-' + type" />
</div>
<div class="ml-3">
<div class="alert__info-wrapper">
<h3 id="title">{{ title }}</h3>
<div id="description">
<p>
<slot></slot>
</p>
</div>
</div>
<div class="pl-3 ml-auto" v-if="withDismiss">
<div class="-mx-1.5 -my-1.5">
<button
type="button"
@click="closed = true"
id="dismiss"
class="hover:bg-black dark:hover:bg-white hover:bg-opacity-10 focus:bg-black dark:focus:bg-white focus:outline-none focus:bg-opacity-10 focus:shadow-outline"
>
<span class="sr-only">Dismiss</span><x-icon class="w-5 h-5" />
</button>
</div>
</div>
</div>
</div>
</template>

<script lang="ts">
import { ref } from "vue";
import {
ExclamationIcon,
XCircleIcon,
InformationCircleIcon,
CheckCircleIcon,
} from "@heroicons/vue/solid";
import { XCircleIcon, InformationCircleIcon } from "@heroicons/vue/solid";
import { XIcon } from "@heroicons/vue/outline";

export default {
components: {
XIcon,
"icon-warning": ExclamationIcon,
"icon-error": XCircleIcon,
"icon-success": CheckCircleIcon,
"icon-info": InformationCircleIcon,
},

props: {
type: String,
title: String,
withDismiss: Boolean,
},

setup() {
const closed = ref(false);

return {
closed,
};
},

computed: {
classes() {
return `p-4 rounded-md alert-${this.type}`;
},
},
};
</script>

<style>
.alert {
@apply p-4 rounded-md;
}
.alert__box {
@apply flex;
}
.alert__icon-wrapper {
@apply flex justify-center items-center;
}
.alert__info-wrapper {
@apply ml-3;
}
#title {
@apply text-sm font-medium;
}
Expand All @@ -87,63 +64,37 @@ export default {
@apply w-5 h-5;
}

#dismiss {
@apply relative block px-1 py-1 text-sm font-semibold leading-5 transition-colors duration-200 bg-transparent rounded-md select-none;
}

.alert-error {
@apply bg-red-300 bg-opacity-10;
border: 1px solid #272932;
border-left-width: 4px;
border-left-color: #6e2f30;
}

.alert-error #title,
.alert-error #dismiss,
.alert-error #description {
.alert-error #title {
@apply text-red-400;
}
.alert-error #description {
@apply text-naturals-N9;
}

.alert-error #icon {
@apply text-red-300;
@apply text-red-400;
}

.alert-info {
@apply bg-blue-300 bg-opacity-10;
border: 1px solid #272932;
border-left-width: 4px;
border-left-color: #0c6ee7;
}

.alert-info #title,
.alert-info #dismiss,
.alert-info #description {
.alert-info #title {
@apply text-blue-400;
}

.alert-info #icon {
@apply text-blue-300;
}

.alert-success {
@apply bg-green-300 bg-opacity-10;
}

.alert-success #title,
.alert-success #dismiss,
.alert-success #description {
@apply text-green-400;
}

.alert-success #icon {
@apply text-green-300;
}

.alert-warning {
@apply bg-yellow-300 bg-opacity-10;
}

.alert-warning #title,
.alert-warning #dismiss,
.alert-warning #description {
@apply text-yellow-200;
.alert-info #description {
@apply text-naturals-N9;
}

.alert-warning #icon {
@apply text-yellow-400;
.alert-info #icon {
@apply text-blue-400;
}
</style>
1 change: 1 addition & 0 deletions frontend/src/components/THeader/THeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
:context="context"
:recordsNotificationStatus="false"
:isSpinnerActive="false"
:errorNotificationStatus="false"
>
<template #default="items">
<header class="theHeader">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
!router.currentRoute.value.query.cluster
"
:context="context"
:searchOption="searchOption"
/>
</div>
</template>
Expand Down Expand Up @@ -77,6 +78,7 @@ export default {
ctx,
router,
setInputValue,
searchOption: computed(() => inputValue.value),
kubernetes,
};
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
class="item__name"
:class="isNameChecked && 'item__name--checked'"
>
{{ name }}
<WordHighlighter
:query="searchOption"
:textToHighlight="name"
:highlightStyle="{ 'background-color': 'white' }"
/>
<t-icon
class="item__check"
icon="check"
Expand Down Expand Up @@ -53,14 +57,21 @@ import TSideBarClusterDropdownSubItem from "./TSideBarClusterDropdownSubItem.vue
import { changeContext, getContext } from "@/context";
import { useRouter } from "vue-router";
import { onMounted } from "@vue/runtime-core";
import WordHighlighter from "vue-word-highlighter";

export default {
components: { TIcon, TAnimation, TSideBarClusterDropdownSubItem },
components: {
TIcon,
TAnimation,
TSideBarClusterDropdownSubItem,
WordHighlighter,
},
props: {
name: String,
isNameChecked: Boolean,
context: Object,
clusters: Object,
searchOption: String,
},
setup(props) {
const { clusters, name } = toRefs(props);
Expand Down
Loading