Skip to content

Commit

Permalink
Merge branch 'development' into development_2.6
Browse files Browse the repository at this point in the history
AhmedHanafy725 committed Jul 2, 2024
2 parents 363d0a9 + 11fa297 commit f32a697
Showing 31 changed files with 318 additions and 75 deletions.
8 changes: 2 additions & 6 deletions .github/workflows/grid_client_nightly.yml
Original file line number Diff line number Diff line change
@@ -131,15 +131,11 @@ jobs:
steps.kubernetesqsfs.outcome != 'success' ||
steps.kvstore.outcome != 'success' ||
steps.zdb.outcome != 'success' ||
steps.deleteall.outcome != 'success'
steps.deleteall.outcome != 'success'
run: exit 1

- name: Get the day of the week
id: dayofweek
run: echo "DAY_OF_WEEK=$(date +%u)" >> $GITHUB_ENV

- name: Create GitHub Issue on Failure
if: needs.teststatus.result == 'failure' && env.DAY_OF_WEEK != '5' && env.DAY_OF_WEEK != '6'
if: failure() && '$(date +%u)' != '5' && '$(date +%u)' != '6'
uses: dacbd/create-issue-action@main
with:
token: ${{ github.token }}
4 changes: 2 additions & 2 deletions docs/release.md
Original file line number Diff line number Diff line change
@@ -18,10 +18,10 @@ appVersion: "x.x.x"
- This can be done by running this command:
```bash
lerna version --force-publish
lerna version --force-publish --exact
```

This command will Update the versions of all packages and also it will update the package version if it's used as a dependency in the other packages in the monorepo.
This command will Update the versions of all packages and also it will update the package version if it's used as a dependency in the other packages in the monorepo. Make sure to add `exact` flag; this will specify updated dependencies in updated packages exactly (with no punctuation).

## Create a new release

2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
"version": "2.5.0-rc3",
"version": "2.5.0",
"npmClient": "yarn"
}
2 changes: 1 addition & 1 deletion packages/UI/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@threefold/ui",
"version": "2.5.0-rc3",
"version": "2.5.0",
"private": false,
"main": "dist/threefold-ui.umd.js",
"publishConfig": {
4 changes: 2 additions & 2 deletions packages/graphql_client/package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "@threefold/graphql_client",
"version": "2.5.0-rc3",
"version": "2.5.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"license": "MIT",
"scripts": {
"build": "tsc"
},
"dependencies": {
"@threefold/types": "^2.5.0-rc3",
"@threefold/types": "2.5.0",
"ts-mixer": "^6.0.2"
},
"devDependencies": {
9 changes: 5 additions & 4 deletions packages/grid_client/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@threefold/grid_client",
"author": "Ahmed Hanafy",
"version": "2.5.0-rc3",
"version": "2.5.0",
"license": "ISC",
"homepage": "https://github.com/threefoldtech/tfgrid-sdk-ts/tree/development/packages/grid_client/README.md",
"repository": {
@@ -14,9 +14,10 @@
"dependencies": {
"@jimber/pkid": "1.0.4",
"@noble/secp256k1": "^1.7.1",
"@threefold/rmb_direct_client": "^2.5.0-rc3",
"@threefold/tfchain_client": "^2.5.0-rc3",
"@threefold/types": "^2.5.0-rc3",
"@threefold/gridproxy_client": "2.5.0",
"@threefold/rmb_direct_client": "2.5.0",
"@threefold/tfchain_client": "2.5.0",
"@threefold/types": "2.5.0",
"algosdk": "^1.19.0",
"appdata-path": "^1.0.0",
"await-lock": "^2.2.2",
4 changes: 2 additions & 2 deletions packages/grid_http_server/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@threefold/grid_http_server",
"author": "Ahmed Hanafy",
"version": "2.5.0-rc3",
"version": "2.5.0",
"license": "ISC",
"homepage": "https://github.com/threefoldtech/tfgrid-sdk-ts/blob/development/packages/grid_http_server/README.md",
"repository": {
@@ -12,7 +12,7 @@
"access": "public"
},
"dependencies": {
"@threefold/grid_client": "^2.5.0-rc3",
"@threefold/grid_client": "2.5.0",
"express": "^4.18.1",
"http-server": "^14.1.1",
"typescript": "^4.7.4"
8 changes: 4 additions & 4 deletions packages/grid_rmb_server/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@threefold/grid_rmb_server",
"author": "Ahmed Hanafy",
"version": "2.5.0-rc3",
"version": "2.5.0",
"license": "ISC",
"homepage": "https://github.com/threefoldtech/tfgrid-sdk-ts/blob/development/packages/grid_rmb_server/README.md",
"repository": {
@@ -12,12 +12,12 @@
"access": "public"
},
"dependencies": {
"@threefold/grid_client": "^2.5.0-rc3",
"@threefold/rmb_peer_server": "^2.5.0-rc3",
"@threefold/grid_client": "2.5.0",
"@threefold/rmb_peer_server": "2.5.0",
"typescript": "^4.7.4"
},
"devDependencies": {
"@threefold/rmb_peer_client": "^2.5.0-rc3",
"@threefold/rmb_peer_client": "2.5.0",
"ts-node": "^10.9.1"
},
"main": "./dist/index.js",
2 changes: 1 addition & 1 deletion packages/gridproxy_client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@threefold/gridproxy_client",
"version": "2.5.0-rc3",
"version": "2.5.0",
"description": "gridproxy_client help to interact with gridproxy based on network",
"main": "dist/public_api.js",
"types": "dist/public_api.d.ts",
8 changes: 4 additions & 4 deletions packages/monitoring/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@threefold/monitoring",
"version": "2.5.0-rc3",
"version": "2.5.0",
"description": "Threefold monitoring package",
"license": "Apache-2.0",
"main": "dist/index.js",
@@ -16,9 +16,9 @@
"access": "public"
},
"dependencies": {
"@threefold/rmb_direct_client": "^2.5.0-rc3",
"@threefold/tfchain_client": "^2.5.0-rc3",
"@threefold/types": "^2.5.0-rc3",
"@threefold/rmb_direct_client": "2.5.0",
"@threefold/tfchain_client": "2.5.0",
"@threefold/types": "2.5.0",
"axios": "^0.27.2",
"chalk": "4.1.2",
"ts-node": "^10.9.1",
10 changes: 5 additions & 5 deletions packages/playground/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@threefold/playground",
"version": "2.5.0-rc3",
"version": "2.5.0",
"private": true,
"scripts": {
"dev": "vite",
@@ -12,10 +12,10 @@
},
"dependencies": {
"@mdi/font": "^7.2.96",
"@threefold/graphql_client": "^2.5.0-rc3",
"@threefold/grid_client": "^2.5.0-rc3",
"@threefold/gridproxy_client": "^2.5.0-rc3",
"@threefold/types": "^2.5.0-rc3",
"@threefold/graphql_client": "2.5.0",
"@threefold/grid_client": "2.5.0",
"@threefold/gridproxy_client": "2.5.0",
"@threefold/types": "2.5.0",
"@types/ip": "^1.1.3",
"@types/md5": "^2.3.5",
"await-lock": "^2.2.2",
2 changes: 1 addition & 1 deletion packages/playground/playground-charts/Chart.yaml
Original file line number Diff line number Diff line change
@@ -21,4 +21,4 @@ version: 0.1.0
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "v2.5.0-rc3"
appVersion: "v2.5.0"
2 changes: 1 addition & 1 deletion packages/playground/playground-charts/values.yaml
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ image:
repository: ghcr.io/threefoldtech/playground
pullPolicy: Always
# Overrides the image tag whose default is the chart appVersion.
tag: "2.5.0-rc3"
tag: "2.5.0"

env:
- name: "MODE"
41 changes: 39 additions & 2 deletions packages/playground/src/components/caprover_worker.vue
Original file line number Diff line number Diff line change
@@ -32,6 +32,8 @@
</input-tooltip>

<TfSelectionDetails
:selected-machines="selectedMachines"
:nodes-lock="nodesLock"
:filters="{
ipv4: true,
ipv6: $props.modelValue.ipv6,
@@ -49,8 +51,10 @@

<script lang="ts">
import { calculateRootFileSystem } from "@threefold/grid_client";
import type AwaitLock from "await-lock";
import { computed, type PropType } from "vue";
import type { SelectedMachine } from "@/types/nodeSelector";
import { manual } from "@/utils/manual";
import Networks from "../components/networks.vue";
@@ -62,10 +66,33 @@ export function createWorker(name: string = generateName({ prefix: "wr" })): Cap
return { name, mycelium: true, ipv6: false };
}
function toMachine(rootFilesystemSize: number, worker?: CaproverWorker): SelectedMachine | undefined {
if (!worker || !worker.selectionDetails || !worker.selectionDetails.node) {
return undefined;
}
return {
nodeId: worker.selectionDetails.node.nodeId,
cpu: worker.solution?.cpu ?? 0,
memory: worker.solution?.memory ?? 0,
disk: (worker.solution?.disk ?? 0) + (rootFilesystemSize ?? 0),
};
}
export default {
name: "CaproverWorker",
components: { SelectSolutionFlavor, Networks },
props: { modelValue: { type: Object as PropType<CaproverWorker>, required: true } },
props: {
modelValue: {
type: Object as PropType<CaproverWorker>,
required: true,
},
otherWorkers: {
type: Array as PropType<CaproverWorker[]>,
default: () => [],
},
nodesLock: Object as PropType<AwaitLock>,
},
setup(props) {
const rootFilesystemSize = computed(() => {
const { cpu = 0, memory = 0 } = props.modelValue.solution || {};
@@ -75,7 +102,17 @@ export default {
});
});
return { rootFilesystemSize, manual };
const selectedMachines = computed(() => {
return props.otherWorkers.reduce((res, worker) => {
const machine = toMachine(rootFilesystemSize.value, worker);
if (machine) {
res.push(machine);
}
return res;
}, [] as SelectedMachine[]);
});
return { rootFilesystemSize, manual, selectedMachines };
},
};
</script>
38 changes: 35 additions & 3 deletions packages/playground/src/components/k8s_worker.vue
Original file line number Diff line number Diff line change
@@ -84,6 +84,8 @@
</input-tooltip>

<TfSelectionDetails
:selected-machines="selectedMachines"
:nodes-lock="nodesLock"
:filters-validators="{
memory: { min: 1024 },
rootFilesystemSize: {
@@ -109,8 +111,10 @@

<script lang="ts">
import { calculateRootFileSystem } from "@threefold/grid_client";
import type { PropType } from "vue";
import type AwaitLock from "await-lock";
import { computed, type PropType } from "vue";
import type { SelectedMachine } from "@/types/nodeSelector";
import { manual } from "@/utils/manual";
import Networks from "../components/networks.vue";
@@ -135,6 +139,19 @@ export function createWorker(name: string = generateName({ prefix: "wr" })): K8S
};
}
function toMachine(worker?: K8SWorker): SelectedMachine | undefined {
if (!worker || !worker.selectionDetails || !worker.selectionDetails.node) {
return undefined;
}
return {
nodeId: worker.selectionDetails.node.nodeId,
cpu: worker.cpu,
memory: worker.memory,
disk: (worker.diskSize ?? 0) + (worker.rootFsSize ?? 0),
};
}
export default {
name: "K8SWorker",
components: { RootFsSize, Networks },
@@ -143,9 +160,24 @@ export default {
type: Object as PropType<K8SWorker>,
required: true,
},
otherWorkers: {
type: Array as PropType<K8SWorker[]>,
default: () => [],
},
nodesLock: Object as PropType<AwaitLock>,
},
setup() {
return { calculateRootFileSystem, manual };
setup(props) {
const selectedMachines = computed(() => {
return props.otherWorkers.reduce((res, worker) => {
const machine = toMachine(worker);
if (machine) {
res.push(machine);
}
return res;
}, [] as SelectedMachine[]);
});
return { calculateRootFileSystem, manual, selectedMachines };
},
};
</script>
Original file line number Diff line number Diff line change
@@ -144,22 +144,25 @@
<script lang="ts">
import type { FarmInfo, FilterOptions, NodeInfo } from "@threefold/grid_client";
import { RequestError } from "@threefold/types";
import type AwaitLock from "await-lock";
import equals from "lodash/fp/equals.js";
import sample from "lodash/fp/sample.js";
import { computed, nextTick, onMounted, onUnmounted, type PropType, ref } from "vue";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import type { VCard } from "vuetify/components/VCard";
import { useAsync, usePagination, useWatchDeep } from "../../hooks";
import { ValidatorStatus } from "../../hooks/form_validator";
import { useGrid } from "../../stores";
import type { SelectedLocation, SelectionDetailsFilters } from "../../types/nodeSelector";
import type { SelectedLocation, SelectedMachine, SelectionDetailsFilters } from "../../types/nodeSelector";
import {
checkNodeCapacityPool,
getNodePageCount,
isNodeValid,
loadValidNodes,
normalizeNodeFilters,
normalizeNodeOptions,
release,
selectValidNode,
validateRentContract,
} from "../../utils/nodeSelector";
import TfNodeDetailsCard from "./TfNodeDetailsCard.vue";
@@ -177,39 +180,57 @@ export default {
location: Object as PropType<SelectedLocation>,
farm: Object as PropType<FarmInfo>,
status: String as PropType<ValidatorStatus>,
selectedMachines: {
type: Array as PropType<SelectedMachine[]>,
required: true,
},
nodesLock: Object as PropType<AwaitLock>,
},
emits: {
"update:model-value": (node?: NodeInfo) => true || node,
"update:status": (status: ValidatorStatus) => true || status,
},
setup(props, ctx) {
const gridStore = useGrid();
const loadedNodes = ref<NodeInfo[]>([]);
const _loadedNodes = ref<NodeInfo[]>([]);
const loadedNodes = computed(() => {
return _loadedNodes.value.filter(
node => node.nodeId === props.modelValue?.nodeId || isNodeValid(node, props.selectedMachines, filters.value),
);
});
const nodesTask = useAsync(loadValidNodes, {
shouldRun: () => props.validFilters,
onBeforeTask() {
const oldNode = props.modelValue;
bindModelValue();
return oldNode?.nodeId;
},
onAfterTask({ data }, oldNodeId: number) {
loadedNodes.value = loadedNodes.value.concat(data as NodeInfo[]);
async onAfterTask({ data }, oldNodeId: number) {
_loadedNodes.value = _loadedNodes.value.concat(data as NodeInfo[]);
const node = loadedNodes.value.find(n => n.nodeId === oldNodeId) || sample(loadedNodes.value);
node && bindModelValue(node);
node && nodeInputValidateTask.value.run(node);
await _setValidNode(oldNodeId);
pagination.value.next();
},
default: [],
});
async function _setValidNode(oldNodeId?: number) {
const node = await selectValidNode(_loadedNodes.value, props.selectedMachines, filters.value, oldNodeId);
if (node) {
bindModelValue(node);
nodeInputValidateTask.value.run(node);
} else {
release(props.nodesLock);
}
}
const pageCountTask = useAsync(getNodePageCount, { default: 1, shouldRun: () => props.validFilters });
const pagination = usePagination();
const options = computed(() => normalizeNodeOptions(gridStore, props.location, pagination, props.farm));
const filters = computed(() => normalizeNodeFilters(props.filters, options.value));
const reloadNodes = () => nodesTask.value.run(gridStore, props.filters, filters.value, pagination);
const reloadNodes = () => nodesTask.value.run(gridStore, props.filters, filters.value, pagination, props.nodesLock);
const loadingError = computed(() => {
if (!nodesTask.value.error) return "";
if (nodesTask.value.error instanceof RequestError) return "Failed to fetch nodes due to a network error";
@@ -259,7 +280,7 @@ export default {
await pageCountTask.value.run(gridStore, filters.value);
pagination.value.reset(pageCountTask.value.data as number);
await nextTick();
loadedNodes.value = [];
_loadedNodes.value = [];
return reloadNodes();
}
@@ -274,6 +295,7 @@ export default {
shouldRun: () => props.validFilters,
onBeforeTask: () => bindStatus(ValidatorStatus.Pending),
onAfterTask({ data }) {
release(props.nodesLock);
bindStatus(data ? ValidatorStatus.Valid : ValidatorStatus.Invalid);
const container = nodesContainer.value as HTMLDivElement;
if (container) {
@@ -314,6 +336,18 @@ export default {
const nodesContainer = ref<HTMLDivElement>();
useWatchDeep(
() => props.selectedMachines.map(m => m.nodeId),
() => {
if (props.modelValue || nodesTask.value.loading) {
return;
}
_setValidNode();
},
{ debounce: 1000 },
);
return {
pageCountTask,
nodesTask,
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<template>
<div>
<TfNodeDetailsCard
:selected-machines="selectedMachines.filter(m => m.nodeId === nodeId)"
v-show="modelValue || placeholderNode"
:key="modelValue?.rentedByTwinId"
flat
@@ -52,16 +53,17 @@

<script lang="ts">
import type { NodeInfo } from "@threefold/grid_client";
import type AwaitLock from "await-lock";
import isInt from "validator/lib/isInt";
import { onUnmounted, type PropType, ref, watch } from "vue";
import { gridProxyClient } from "../../clients";
import { useAsync, useWatchDeep } from "../../hooks";
import { ValidatorStatus } from "../../hooks/form_validator";
import { useGrid } from "../../stores";
import type { SelectionDetailsFilters } from "../../types/nodeSelector";
import type { SelectedMachine, SelectionDetailsFilters } from "../../types/nodeSelector";
import { normalizeError } from "../../utils/helpers";
import { checkNodeCapacityPool, resolveAsync, validateRentContract } from "../../utils/nodeSelector";
import { checkNodeCapacityPool, release, resolveAsync, validateRentContract } from "../../utils/nodeSelector";
import TfNodeDetailsCard from "./TfNodeDetailsCard.vue";
const _defaultError =
@@ -78,6 +80,11 @@ export default {
required: true,
},
status: String as PropType<ValidatorStatus>,
selectedMachines: {
type: Array as PropType<SelectedMachine[]>,
required: true,
},
nodesLock: Object as PropType<AwaitLock>,
},
emits: {
"update:model-value": (node?: NodeInfo) => true || node,
@@ -159,7 +166,14 @@ export default {
}
const { cru, mru, sru } = resources;
const { cpu = 0, memory = 0, ssdDisks = [], solutionDisk = 0, rootFilesystemSize = 0 } = props.filters;
const { ssdDisks = [], rootFilesystemSize = 0 } = props.filters;
const machinesWithSameNode = props.selectedMachines.filter(machine => machine.nodeId === nodeId);
let { cpu = 0, memory = 0, solutionDisk = 0 } = props.filters;
cpu += machinesWithSameNode.reduce((res, machine) => res + machine.cpu, 0);
memory += machinesWithSameNode.reduce((res, machine) => res + machine.memory, 0);
solutionDisk += machinesWithSameNode.reduce((res, machine) => res + machine.disk, 0);
const memorySize = memory / 1024;
const requiredMru = Math.ceil(Math.round(memorySize) * 1024 ** 3);
@@ -190,16 +204,25 @@ export default {
tries: 1,
onReset: bindStatus,
shouldRun: () => props.validFilters,
onBeforeTask: () => bindStatus(ValidatorStatus.Pending),
async onBeforeTask() {
await props.nodesLock?.acquireAsync();
bindStatus(ValidatorStatus.Pending);
},
onAfterTask: ({ data }) => {
bindStatus(data ? ValidatorStatus.Valid : ValidatorStatus.Invalid);
release(props.nodesLock);
},
},
);
// reset validation to prevent form from being valid
useWatchDeep(() => props.filters, validationTask.value.reset);
useWatchDeep(nodeId, validationTask.value.reset);
useWatchDeep(
() => props.selectedMachines.map(m => m.nodeId),
() => nodeId.value && validationTask.value.run(nodeId.value),
{ debounce: 1000 },
);
// revalidate if filters updated
useWatchDeep(
Original file line number Diff line number Diff line change
@@ -157,7 +157,7 @@
<VCol class="tf-node-resource">
<ResourceDetails
name="CPU"
:used="node?.used_resources.cru ?? 0"
:used="(node?.used_resources.cru ?? 0) + selectedMachines.reduce((r, m) => r + m.cpu, 0)"
:total="node?.total_resources.cru ?? 0"
:text="cruText"
:cpuType="dmi?.processor[0]?.version"
@@ -166,7 +166,7 @@
<VCol class="tf-node-resource">
<ResourceDetails
name="Memory"
:used="node?.used_resources.mru ?? 0"
:used="(node?.used_resources.mru ?? 0) + selectedMachines.reduce((r, m) => r + (m.memory / 1024) * 1e9, 0)"
:total="node?.total_resources.mru ?? 0"
:text="mruText"
:memoryType="dmi?.memory[0]?.type"
@@ -178,7 +178,7 @@
<VCol class="tf-node-resource">
<ResourceDetails
name="SSD Disks"
:used="node?.used_resources.sru ?? 0"
:used="(node?.used_resources.sru ?? 0) + selectedMachines.reduce((r, m) => r + m.disk * 1e9, 0)"
:total="node?.total_resources.sru ?? 0"
:text="sruText"
/>
@@ -238,10 +238,11 @@
import type { GridClient, NodeInfo, NodeResources } from "@threefold/grid_client";
import { CertificationType, type GridNode } from "@threefold/gridproxy_client";
import { computed, onMounted, ref, watch } from "vue";
import { capitalize } from "vue";
import { capitalize, type PropType } from "vue";
import { gridProxyClient } from "@/clients";
import ReserveBtn from "@/dashboard/components/reserve_action_btn.vue";
import type { SelectedMachine } from "@/types/nodeSelector";
import toHumanDate from "@/utils/date";
import { getCountryCode } from "@/utils/get_nodes";
import { manual } from "@/utils/manual";
@@ -260,6 +261,7 @@ export default {
status: String as () => "Init" | "Pending" | "Invalid" | "Valid",
selectable: Boolean,
flat: Boolean,
selectedMachines: { type: Array as PropType<SelectedMachine[]>, default: () => [] },
},
emits: {
"node:select": (node: NodeInfo) => true || node,
@@ -378,7 +380,16 @@ export default {
return "";
}
const used = formatResourceSize(props.node.used_resources[name]);
let additionalUsed = 0;
if (name === "mru") {
additionalUsed = props.selectedMachines.reduce((r, m) => r + (m.memory / 1024) * 1e9, 0);
}
if (name === "sru") {
additionalUsed = props.selectedMachines.reduce((r, m) => r + m.disk * 1e9, 0);
}
const used = formatResourceSize(props.node.used_resources[name] + additionalUsed);
const total = formatResourceSize(props.node.total_resources[name]);
if (total === "0") return "";
Original file line number Diff line number Diff line change
@@ -21,6 +21,8 @@
<TfSelectLocation v-model="location" title="Choose a Location" :status="NodeStatus.Up" />
<TfSelectFarm :valid-filters="validFilters" :filters="filters" :location="location" v-model="farm" />
<TfAutoNodeSelector
:selected-machines="selectedMachines"
:nodes-lock="nodesLock"
:valid-filters="validFilters"
:filters="filters"
:location="location"
@@ -31,6 +33,8 @@
</template>

<TfManualNodeSelector
:selected-machines="selectedMachines"
:nodes-lock="nodesLock"
:valid-filters="validFilters"
:filters="filters"
v-model="node"
@@ -67,6 +71,7 @@
<script lang="ts">
import type { FarmInfo, GPUCardInfo, NodeInfo } from "@threefold/grid_client";
import { NodeStatus } from "@threefold/gridproxy_client";
import type AwaitLock from "await-lock";
import noop from "lodash/fp/noop.js";
import type { DeepPartial } from "utility-types";
import { computed, getCurrentInstance, onMounted, onUnmounted, type PropType, ref, watch } from "vue";
@@ -77,6 +82,7 @@ import type { InputValidatorService } from "../../hooks/input_validator";
import type {
DomainInfo,
SelectedLocation,
SelectedMachine,
SelectionDetails,
SelectionDetailsFilters,
SelectionDetailsFiltersValidators,
@@ -106,6 +112,11 @@ export default {
disableNodeSelection: { type: Boolean, default: () => false },
status: String as PropType<ValidatorStatus>,
useFqdn: Boolean,
selectedMachines: {
type: Array as PropType<SelectedMachine[]>,
default: () => [],
},
nodesLock: Object as PropType<AwaitLock>,
},
emits: {
"update:model-value": (value: SelectionDetails) => true || value,
7 changes: 7 additions & 0 deletions packages/playground/src/types/nodeSelector.ts
Original file line number Diff line number Diff line change
@@ -73,3 +73,10 @@ export interface SelectionDetails {
gpuCards: GPUCardInfo[];
domain?: DomainInfo;
}

export interface SelectedMachine {
nodeId: number;
cpu: number;
memory: number;
disk: number;
}
78 changes: 78 additions & 0 deletions packages/playground/src/utils/nodeSelector.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { FarmFilterOptions, FarmInfo, FilterOptions, NodeInfo } from "@threefold/grid_client";
import type { NodeStatus } from "@threefold/gridproxy_client";
import { GridClientErrors } from "@threefold/types";
import type AwaitLock from "await-lock";
import shuffle from "lodash/fp/shuffle.js";
import type { DeepPartial } from "utility-types";
import { z } from "zod";

@@ -13,6 +15,7 @@ import type {
NormalizeNodeFiltersOptions,
NumericValidator,
SelectedLocation,
SelectedMachine,
SelectionDetailsFilters,
SelectionDetailsFiltersValidators,
} from "../types/nodeSelector";
@@ -242,11 +245,33 @@ export async function validateRentContract(
throw err;
}
}

export function release(lock?: AwaitLock) {
if (lock?.acquired) {
lock.release();
return true;
}
return false;
}

export async function loadValidNodes(
gridStore: ReturnType<typeof useGrid>,
selectionFitlers: SelectionDetailsFilters,
filters: FilterOptions,
pagination: ReturnType<typeof usePagination>,
nodesLock?: AwaitLock,
): Promise<NodeInfo[]> {
if (nodesLock) {
await nodesLock.acquireAsync();
}
return _loadValidNodes(gridStore, selectionFitlers, filters, pagination);
}

async function _loadValidNodes(
gridStore: ReturnType<typeof useGrid>,
selectionFitlers: SelectionDetailsFilters,
filters: FilterOptions,
pagination: ReturnType<typeof usePagination>,
): Promise<NodeInfo[]> {
let page = pagination.value.page;

@@ -265,6 +290,59 @@ export async function loadValidNodes(
return [];
}

export function isNodeValid(node: NodeInfo, machines: SelectedMachine[], filters: FilterOptions): boolean {
const machinesWithSameNode = machines.filter(m => m.nodeId === node.nodeId);
const requiredMru = (filters.mru ?? 0) * 1e9;
const requiredSru = (filters.sru ?? 0) * 1e9;

let mru = node.total_resources.mru - node.used_resources.mru;
let sru = node.total_resources.sru - node.used_resources.sru;
for (const machine of machinesWithSameNode) {
mru -= machine.memory * 1e9;
sru -= machine.disk * 1e9;
}

return mru >= requiredMru && sru >= requiredSru;
}

export async function selectValidNode(
nodes: NodeInfo[],
selectedMachines: SelectedMachine[],
filters: FilterOptions,
oldSelectedNodeId?: number,
nodesLock?: AwaitLock,
): Promise<NodeInfo | void> {
let locked = true;
if (nodesLock && !nodesLock.acquired) {
locked = false;
await nodesLock.acquireAsync();
}

if (oldSelectedNodeId) {
const node = nodes.find(n => n.nodeId === oldSelectedNodeId);

if (node && isNodeValid(node, selectedMachines, filters)) {
if (nodesLock && !locked) {
release(nodesLock);
}
return node;
}
}

for (const node of shuffle(nodes)) {
if (isNodeValid(node, selectedMachines, filters)) {
if (nodesLock && !locked) {
release(nodesLock);
}
return node;
}
}

if (nodesLock && !locked) {
release(nodesLock);
}
}

export async function getNodePageCount(gridStore: ReturnType<typeof useGrid>, filters: FarmFilterOptions) {
const count = await gridStore.client.capacity.getNodesCount(filters);
return Math.ceil(count / window.env.PAGE_SIZE);
11 changes: 9 additions & 2 deletions packages/playground/src/weblets/tf_caprover.vue
Original file line number Diff line number Diff line change
@@ -86,12 +86,16 @@
</template>

<template #leader>
<CaproverWorker v-model="leader" />
<CaproverWorker v-model="leader" :other-workers="workers" :nodes-lock="nodesLock" />
</template>

<template #workers>
<ExpandableLayout v-model="workers" @add="addWorker" #="{ index }">
<CaproverWorker v-model="workers[index]" />
<CaproverWorker
v-model="workers[index]"
:other-workers="[workers, leader].flat(1).filter((_, i) => i !== index)"
:nodes-lock="nodesLock"
/>
</ExpandableLayout>
</template>
</d-tabs>
@@ -116,6 +120,7 @@ import { generateName, generatePassword } from "../utils/strings";
const layout = useLayout();
const tabs = ref();
const nodesLock = markRaw(new AwaitLock());
const profileManager = useProfileManager();
const domain = ref("");
const password = ref(generatePassword(10));
@@ -206,6 +211,8 @@ function updateSSHkeyEnv(selectedKeys: string) {

<script lang="ts">
import { calculateRootFileSystem, type GridClient } from "@threefold/grid_client";
import AwaitLock from "await-lock";
import { markRaw } from "vue";
import { createNetwork } from "@/utils/deploy_helpers";
12 changes: 9 additions & 3 deletions packages/playground/src/weblets/tf_kubernetes.vue
Original file line number Diff line number Diff line change
@@ -65,12 +65,16 @@
</template>

<template #master>
<K8SWorker v-model="master" />
<K8SWorker v-model="master" :other-workers="workers" :nodes-lock="nodesLock" />
</template>

<template #workers>
<ExpandableLayout v-model="workers" @add="addWorker" #="{ index }">
<K8SWorker v-model="workers[index]" />
<K8SWorker
v-model="workers[index]"
:other-workers="[workers, master].flat(1).filter((_, i) => i !== index)"
:nodes-lock="nodesLock"
/>
</ExpandableLayout>
</template>
</d-tabs>
@@ -82,7 +86,7 @@
</template>

<script lang="ts" setup>
import { ref } from "vue";
import { markRaw, ref } from "vue";
import { createWorker } from "../components/k8s_worker.vue";
import { useLayout } from "../components/weblet_layout.vue";
@@ -94,6 +98,7 @@ import { generateName, generatePassword } from "../utils/strings";
const layout = useLayout();
const tabs = ref();
const nodesLock = markRaw(new AwaitLock());
const name = ref(generateName({ prefix: "k8s" }));
const clusterToken = ref(generatePassword(10));
const master = ref(createWorker(generateName({ prefix: "mr" })));
@@ -138,6 +143,7 @@ function updateSSHkeyEnv(selectedKeys: string) {

<script lang="ts">
import type { GridClient } from "@threefold/grid_client";
import AwaitLock from "await-lock";
import ExpandableLayout from "../components/expandable_layout.vue";
import K8SWorker from "../components/k8s_worker.vue";
6 changes: 3 additions & 3 deletions packages/rmb_direct_client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@threefold/rmb_direct_client",
"version": "2.5.0-rc3",
"version": "2.5.0",
"repository": {
"type": "git",
"url": "https://github.com/threefoldtech/tfgrid-sdk-ts.git"
@@ -23,8 +23,8 @@
"dependencies": {
"@noble/secp256k1": "^1.7.1",
"@polkadot/api": "^8.9.1",
"@threefold/tfchain_client": "^2.5.0-rc3",
"@threefold/types": "^2.5.0-rc3",
"@threefold/tfchain_client": "2.5.0",
"@threefold/types": "2.5.0",
"base64url": "^3.0.1",
"bip39": "^3.1.0",
"buffer": "^6.0.3",
2 changes: 1 addition & 1 deletion packages/rmb_peer_client/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@threefold/rmb_peer_client",
"author": "Ahmed Hanafy",
"version": "2.5.0-rc3",
"version": "2.5.0",
"license": "ISC",
"homepage": "https://github.com/threefoldtech/tfgrid-sdk-ts/blob/development/packages/rmb_peer_client/README.md",
"repository": {
2 changes: 1 addition & 1 deletion packages/rmb_peer_server/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@threefold/rmb_peer_server",
"author": "Ahmed Hanafy",
"version": "2.5.0-rc3",
"version": "2.5.0",
"license": "ISC",
"homepage": "https://github.com/threefoldtech/tfgrid-sdk-ts/blob/development/packages/rmb_peer_server/README.md",
"repository": {
2 changes: 1 addition & 1 deletion packages/stats/chart/Chart.yaml
Original file line number Diff line number Diff line change
@@ -21,4 +21,4 @@ version: 1.0.0
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "v2.5.0-rc3"
appVersion: "v2.5.0"
2 changes: 1 addition & 1 deletion packages/stats/chart/values.yaml
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ image:
repository: ghcr.io/threefoldtech/stats
pullPolicy: Always
# Overrides the image tag whose default is the chart appVersion.
tag: "2.5.0-rc3"
tag: "2.5.0"

imagePullSecrets: []
nameOverride: ""
4 changes: 2 additions & 2 deletions packages/stats/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@threefold/stats",
"version": "2.5.0-rc3",
"version": "2.5.0",
"private": true,
"scripts": {
"dev": "vite",
@@ -11,7 +11,7 @@
"type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false"
},
"dependencies": {
"@threefold/gridproxy_client": "^2.5.0-rc3",
"@threefold/gridproxy_client": "2.5.0",
"vue": "^3.3.4",
"vuetify": "^3.3.21"
},
4 changes: 2 additions & 2 deletions packages/tfchain_client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@threefold/tfchain_client",
"version": "2.5.0-rc3",
"version": "2.5.0",
"description": "A client for TF chain",
"private": false,
"publishConfig": {
@@ -46,7 +46,7 @@
},
"dependencies": {
"@polkadot/api": "^8.9.1",
"@threefold/types": "^2.5.0-rc3",
"@threefold/types": "2.5.0",
"await-lock": "^2.2.2",
"bip39": "^3.1.0",
"moment": "^2.30.1"
2 changes: 1 addition & 1 deletion packages/types/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@threefold/types",
"version": "2.5.0-rc3",
"version": "2.5.0",
"main": "dist/node/index.js",
"types": "dist/es6/index.d.ts",
"scripts": {

0 comments on commit f32a697

Please sign in to comment.