Skip to content

Commit

Permalink
Merge pull request #3215 from threefoldtech/development_expose_applic…
Browse files Browse the repository at this point in the history
…ation

Adding expose application
  • Loading branch information
MohamedElmdary authored Aug 28, 2024
2 parents a212cef + f7a6fe6 commit 448a213
Show file tree
Hide file tree
Showing 16 changed files with 332 additions and 13 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions packages/playground/public/info/domains.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
title: Domains
---

Domains allows users to securely expose servers hosted on local machines or VMs to the public internet. Users are required to specify the machine's IP, which can be a Mycelium IP, Yggdrasil IP, or a public IP (IPv4 or IPv6). For more details, check the [Domains documentation](https://www.manual.grid.tf/documentation/dashboard/solutions/domains.html).
23 changes: 21 additions & 2 deletions packages/playground/src/components/deployment_data_dialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,20 @@
>
<v-tooltip location="bottom" :text="getTooltipText(item, index)" :disabled="!hasMaster(item)">
<template #activator="{ props }">
<span v-bind="props" class="text-lowercase">{{ item.name }}</span>
<span v-bind="props" class="text-lowercase">{{
contracts && contracts.length === 1 && "name" in contracts ? (contracts as any).name : item.name
}}</span>
</template>
</v-tooltip>
</v-tab>
</v-tabs>
</v-card-title>
<v-card-text>
<template v-if="showType === 0">
<v-form readonly v-if="contract">
<v-form
readonly
v-if="contract && !['gateway-name-proxy', 'gateway-fqdn-proxy'].includes(data?.[0]?.workloads?.[0]?.type)"
>
<v-alert class="my-4" variant="tonal" v-if="contract.customDomain" type="info">
Make sure to create an A record on your name provider with
<span class="font-weight-bold">{{ contract.customDomain }}</span>
Expand Down Expand Up @@ -102,6 +107,20 @@
<CopyReadonlyInput label="GPU Cards" :data="gpuInfo" :loading="loadingCard" v-if="showGpuCard" />
<CopyReadonlyInput label="Monitoring URL" :data="grafanaURL" :loading="isLoading" />
</v-form>
<v-form readonly v-else>
<CopyReadonlyInput label="Name" :data="data.name" />
<CopyReadonlyInput label="IP" :data="data[0].workloads[0].data.backends.join(', ')" />
<CopyReadonlyInput
label="Domain"
:data="data[0].workloads[0].result.data.fqdn || data[0].workloads[0].data.fqdn"
/>
<v-switch
inset
color="primary"
:model-value="data[0].workloads[0].data.tls_passthrough"
label="TLS Passthrough"
/>
</v-form>
</template>
<template v-else>
<HighlightDark v-if="$vuetify.theme.name === 'dark'" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<div ref="input">
<VForm v-model="domainNameValid">
<VExpandTransition>
<input-tooltip tooltip="Domain Name that will points to this instance" v-if="enableCustomDomain">
<input-tooltip tooltip="Domain Name that will point to this instance" v-if="enableCustomDomain">
<VTextField
ref="customDomainInput"
label="Custom Domain"
Expand Down
60 changes: 59 additions & 1 deletion packages/playground/src/components/vm_deployment_table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@
</template>

<script lang="ts" setup>
import { computed, onMounted, ref } from "vue";
import { capitalize, computed, onMounted, ref } from "vue";
import { getNodeHealthColor, NodeHealth } from "@/utils/get_nodes";
Expand Down Expand Up @@ -190,7 +190,28 @@ const failedDeployments = ref<
onMounted(loadDeployments);
async function loadDomains() {
try {
loading.value = true;
const grid = await getGrid(profileManager.profile!, props.projectName.toLowerCase());
const gateways = await grid!.gateway.list();
const gws = await Promise.all(gateways.map(name => grid!.gateway.get_name({ name })));
items.value = gws.map(gw => {
(gw as any).name = gw[0].workloads[0].name;
return gw;
});
} catch (e) {
errorMessage.value = `Failed to load Deployments: ${e}`;
} finally {
loading.value = false;
}
}
async function loadDeployments() {
if (props.projectName.toLowerCase() === ProjectName.Domains.toLowerCase()) {
return loadDomains();
}
const migrateGateways = props.projectName.toLowerCase() !== "fullvm" && props.projectName.toLowerCase() !== "vm";
items.value = [];
Expand Down Expand Up @@ -245,6 +266,43 @@ async function loadDeployments() {
}
const filteredHeaders = computed(() => {
if (props.projectName.toLowerCase() === ProjectName.Domains.toLowerCase()) {
return [
{
title: "Name",
key: "domain-name",
value(item: any) {
const [workload] = item[0].workloads;
return workload.data.name || workload.name;
},
},
{
title: "Backends",
key: "0.workloads.0.data.backends",
value(item: any) {
return item[0].workloads[0].data.backends.join(", ");
},
},
{
title: "Domain",
key: "fqdn",
value(item: any) {
const [workload] = item[0].workloads;
return workload.result.data.fqdn || workload.data.fqdn;
},
},
{
title: "Health",
key: "health",
value(item: any) {
return capitalize(item[0].workloads[0].result.state);
},
sortable: false,
},
{ title: "Actions", key: "actions", sortable: false },
];
}
let headers = [
{ title: "PLACEHOLDER", key: "data-table-select" },
{ title: "Name", key: "name" },
Expand Down
2 changes: 1 addition & 1 deletion packages/playground/src/components/weblet_layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ provideService({
},
});
function validateBeforeDeploy(fn: () => void, documentScrollend = true) {
function validateBeforeDeploy(fn: () => void, documentScrollend = false) {
const forms = __forms;
let errorInput: [number, any, boolean] | null = null;
Expand Down
5 changes: 5 additions & 0 deletions packages/playground/src/constants/deployment_list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ export const deploymentListEnvironments = {
CHAIN_ENDPOINT: "Chain Endpoint",
},

expose: {
SSH_KEY: _ssh,
EXPOSE_WEBSERVER_HOSTNAME: "Expose Webserver Hostname",
},

static_website: {
SSH_KEY: _ssh,
GITHUB_URL: "HTTPS URL for git repository",
Expand Down
22 changes: 22 additions & 0 deletions packages/playground/src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,28 @@ function createApplicationsRoutes(): RouteRecordRaw[] {
},
},
},
{
path: DashboardRoutes.Applications.Domains,
component: () => import("../views/domains_view.vue"),
meta: {
title: "Domains",
info: { page: "info/domains.md" },
navbarConfig: {
back: true,
path: [
{ title: "Deploy" },
{
title: "Applications",
disabled: false,
to: DashboardRoutes.Deploy.Applications,
},
{
title: "Domains",
},
],
},
},
},
// Commented for now and will be user later.
// {
// path: DashboardRoutes.Applications.Freeflow,
Expand Down
1 change: 1 addition & 0 deletions packages/playground/src/router/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ enum ApplicationRoutes {
TFRobot = "/deploy/applications/tfrobot/",
Gitea = "/deploy/applications/gitea/",
Nostr = "/deploy/applications/nostr/",
Domains = "/deploy/applications/domains/",
}

const DashboardRoutes = {
Expand Down
3 changes: 3 additions & 0 deletions packages/playground/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export enum ProjectName {
TFRobot = "TFRobot",
Gitea = "Gitea",
Nostr = "Nostr",
Domains = "Domains",
}

export enum SolutionCode {
Expand Down Expand Up @@ -155,6 +156,7 @@ export enum SolutionCode {
tfrobot = "tfr",
gitea = "gt",
nostr = "nt",
Domains = "dm",
}

export const solutionType: { [key: string]: string } = {
Expand All @@ -181,6 +183,7 @@ export const solutionType: { [key: string]: string } = {
tfrobot: "TFRobot",
Gitea: "Gitea",
nostr: "Nostr",
domains: "Domains",
};

export interface solutionFlavor {
Expand Down
3 changes: 3 additions & 0 deletions packages/playground/src/utils/delete_deployment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ export async function deleteGateway(grid: GridClient, name: string) {
const { deleted } = await grid.gateway.delete_name({ name });
return deleted.length > 0;
}
export async function deleteGatewayDeployment(grid: GridClient, name: string) {
return await grid.gateway.delete_name({ name });
}

export function solutionHasGateway(projectName: ProjectName) {
const solutions = [
Expand Down
4 changes: 4 additions & 0 deletions packages/playground/src/utils/gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ export async function rollbackDeployment(grid: GridClient, name: string) {

return result;
}
export async function rollbackGateway(grid: GridClient, name: string) {
const result = await grid.gateway.delete_name({ name });
return result;
}

export type GridGateway = Awaited<ReturnType<GridClient["gateway"]["getObj"]>>[0];
interface LoadDeploymentGatewaysOptions {
Expand Down
26 changes: 26 additions & 0 deletions packages/playground/src/views/domains_view.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<template>
<view-layout>
<TfDomains />

<template #list>
<TfDeploymentList title="Domains" :project-name="name" />
</template>
</view-layout>
</template>

<script lang="ts">
import { ProjectName } from "../types";
import TfDeploymentList from "../weblets/tf_deployment_list.vue";
import TfDomains from "../weblets/tf_domains.vue";
export default {
name: "DomainsView",
components: {
TfDomains,
TfDeploymentList,
},
setup() {
return { name: ProjectName.Domains };
},
};
</script>
7 changes: 7 additions & 0 deletions packages/playground/src/views/solutions_view.vue
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,13 @@ export default {
icon: "wordpress.png",
route: DashboardRoutes.Applications.Wordpress,
},
{
title: "Domains",
excerpt:
"Domains allow users to securely expose servers hosted on local machines or VMs to the public internet.",
icon: "domains.png",
route: DashboardRoutes.Applications.Domains,
},
];
cards = cards.sort((a, b) => a.title.localeCompare(b.title));
Expand Down
39 changes: 31 additions & 8 deletions packages/playground/src/weblets/tf_deployment_list.vue
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,21 @@
/>
</template>

<template #Domains-actions="{ item }">
<IconActionBtn
tooltip="Show Details"
icon="mdi-eye-outline"
@click="openDialog(tabs[activeTab].value, item)"
/>

<IconActionBtn
tooltip="Visit"
icon="mdi-web"
color="anchor"
:href="'https://' + (item[0].workloads[0].result.data.fqdn || item[0].workloads[0].data.fqdn)"
/>
</template>

<template #StaticWebsite-actions="{ item }">
<IconActionBtn
tooltip="Show Details"
Expand Down Expand Up @@ -396,7 +411,7 @@ import type { Tab } from "../components/dynamic_tabs.vue";
import { useLayout } from "../components/weblet_layout.vue";
import { deploymentListEnvironments } from "../constants/deployment_list";
import { useGrid } from "../stores";
import { deleteDeployment } from "../utils/delete_deployment";
import { deleteDeployment, deleteGatewayDeployment } from "../utils/delete_deployment";
import { updateGrid } from "../utils/grid";
const props = defineProps<{
Expand Down Expand Up @@ -428,6 +443,7 @@ const tabs: Tab[] = [
{ title: "TFRobot", value: "TFRobot", imgPath: "images/icons/tfrobot.png" },
{ title: "Gitea", value: "Gitea", imgPath: "images/icons/gitea.png" },
{ title: "Nostr", value: "Nostr", imgPath: "images/icons/nostr.png" },
{ title: "Domains", value: "Domains", imgPath: "images/icons/domains.png" },
];
const layout = useLayout();
Expand All @@ -449,13 +465,20 @@ async function onDelete(k8s = false) {
try {
for (const item of selectedItems.value) {
try {
await deleteDeployment(updateGrid(grid!, { projectName: item.projectName }), {
deploymentName: item.deploymentName,
name: k8s ? item.deploymentName : item.name,
projectName: item.projectName,
ip: item.interfaces?.[0]?.ip,
k8s,
});
if (props.projectName?.toLowerCase() === ProjectName.Domains.toLowerCase()) {
await deleteGatewayDeployment(
updateGrid(grid, { projectName: props.projectName.toLocaleLowerCase() }),
item[0].workloads[0].name as string,
);
} else {
await deleteDeployment(updateGrid(grid!, { projectName: item.projectName }), {
deploymentName: item.deploymentName,
name: k8s ? item.deploymentName : item.name,
projectName: item.projectName,
ip: item.interfaces?.[0]?.ip,
k8s,
});
}
} catch (e: any) {
createCustomToast(`Failed to delete deployment with name: ${item.name}`, ToastType.danger);
console.log("Error while deleting deployment", e.message);
Expand Down
Loading

0 comments on commit 448a213

Please sign in to comment.