diff --git a/cypress/integration/distroSettings/host_section.ts b/cypress/integration/distroSettings/host_section.ts
index 72cc6f2720..43536ee68c 100644
--- a/cypress/integration/distroSettings/host_section.ts
+++ b/cypress/integration/distroSettings/host_section.ts
@@ -108,16 +108,6 @@ describe("host section", () => {
cy.validateToast("success");
// Reset fields
- cy.getInputByLabel("Working Directory").clear();
- cy.getInputByLabel("Jasper Credentials Path").clear();
- cy.getInputByLabel("Client Directory").clear();
- cy.getInputByLabel("Shell Path").clear();
- cy.getInputByLabel("Home Volume Format Command").clear();
- cy.getInputByLabel("Number of Files").clear();
- cy.getInputByLabel("Number of CGroup Tasks").clear();
- cy.getInputByLabel("Number of Processes").clear();
- cy.getInputByLabel("Locked Memory (kB)").clear();
- cy.getInputByLabel("Virtual Memory (kB)").clear();
cy.dataCy("delete-item-button").first().click();
cy.dataCy("delete-item-button").first().click();
diff --git a/src/components/SpruceForm/Widgets/LeafyGreenWidgets.tsx b/src/components/SpruceForm/Widgets/LeafyGreenWidgets.tsx
index 431f1edb0a..d5218ab86d 100644
--- a/src/components/SpruceForm/Widgets/LeafyGreenWidgets.tsx
+++ b/src/components/SpruceForm/Widgets/LeafyGreenWidgets.tsx
@@ -42,13 +42,13 @@ export const LeafyGreenTextInput: React.FC<
"data-cy": dataCy,
description,
elementWrapperCSS,
- emptyValue = "",
inputType,
optional,
warnings,
} = options;
const { errors, hasError } = processErrors(rawErrors);
+ const emptyValue = "emptyValue" in options ? options.emptyValue : "";
const inputProps = {
...(!isNullish(schema.maximum) && { max: schema.maximum }),
diff --git a/src/pages/distroSettings/tabs/HostTab/getFormSchema.tsx b/src/pages/distroSettings/tabs/HostTab/getFormSchema.tsx
index d30b50f846..689569f432 100644
--- a/src/pages/distroSettings/tabs/HostTab/getFormSchema.tsx
+++ b/src/pages/distroSettings/tabs/HostTab/getFormSchema.tsx
@@ -6,6 +6,7 @@ import {
CardFieldTemplate,
FieldRow,
} from "components/SpruceForm/FieldTemplates";
+import { size } from "constants/tokens";
import { Arch, BootstrapMethod, Provider, SshKey } from "gql/generated/types";
import {
architectureToCopy,
@@ -62,6 +63,7 @@ export const getFormSchema = ({
workDir: {
type: "string" as "string",
title: "Working Directory",
+ minLength: 1,
},
setupAsSudo: {
type: "boolean" as "boolean",
@@ -73,7 +75,7 @@ export const getFormSchema = ({
},
userSpawnAllowed: {
type: "boolean" as "boolean",
- title: "Allow users to spawn these hosts for personal use",
+ title: "Spawnable",
},
},
dependencies: {
@@ -107,8 +109,7 @@ export const getFormSchema = ({
userSpawnAllowed: { enum: [true] },
isVirtualWorkStation: {
type: "boolean" as "boolean",
- title:
- "Allow spawned hosts of this distro to be used as virtual workstations",
+ title: "Virtual Workstations",
},
},
dependencies: {
@@ -196,6 +197,10 @@ export const getFormSchema = ({
margin-bottom: 0;
`,
},
+ workDir: {
+ "ui:description":
+ "Absolute path in which the agent run tasks on the host machine",
+ },
setupScript: {
"ui:elementWrapperCSS": css`
margin-top: -22px;
@@ -207,21 +212,71 @@ export const getFormSchema = ({
"ui:disabled": true,
"ui:tooltipDescription": "Static distros are not spawnable.",
}),
+ "ui:description":
+ "Allow users to spawn these hosts for personal use.",
+ "ui:bold": true,
+ },
+ isVirtualWorkStation: {
+ "ui:description":
+ "Allow spawned hosts of this distro to be used as virtual workstations.",
+ "ui:bold": true,
+ },
+ icecreamSchedulerHost: {
+ "ui:elementWrapperCSS": indentCSS,
+ },
+ icecreamConfigPath: {
+ "ui:elementWrapperCSS": indentCSS,
},
},
bootstrapSettings: {
"ui:ObjectFieldTemplate": CardFieldTemplate,
serviceUser: {
+ "ui:description": "Username for setting up Evergreen services",
// Only visible for Windows
...(!windowsArchitectures.includes(architecture) && {
"ui:widget": "hidden",
}),
},
+ jasperBinaryDir: {
+ "ui:description":
+ "Absolute native path to the directory containing the Jasper binary",
+ },
+ jasperCredentialsPath: {
+ "ui:description":
+ "Absolute native path to the directory containing the Jasper credentials",
+ },
+ clientDir: {
+ "ui:description":
+ "Absolute native path to the directory containing the evergreen binary",
+ },
+ shellPath: {
+ "ui:description":
+ "Absolute native path to the shell binary file (bash)",
+ },
resourceLimits: {
// Only visible for Linux
...(!linuxArchitectures.includes(architecture) && {
"ui:widget": "hidden",
}),
+ numFiles: {
+ "ui:description":
+ "Max number of open file handles. Set -1 for unlimited.",
+ },
+ numProcesses: {
+ "ui:description": "Max number of processes. Set -1 for unlimited.",
+ },
+ numTasks: {
+ "ui:description":
+ "Max number of cgroup tasks (threads). Set -1 for unlimited.",
+ },
+ lockedMemory: {
+ "ui:description":
+ "Max size (kB) that can be locked into memory. Set -1 for unlimited.",
+ },
+ virtualMemory: {
+ "ui:description":
+ "Max size (kB) of available virtual memory. Set -1 for unlimited.",
+ },
},
env: {
"ui:addButtonText": "Add variable",
@@ -245,7 +300,7 @@ export const getFormSchema = ({
},
script: {
"ui:description":
- "The precondition script that must run and succeed.",
+ "The precondition script that must run and succeed before Jasper can start.",
"ui:widget": "textarea",
},
},
@@ -253,6 +308,9 @@ export const getFormSchema = ({
},
sshConfig: {
"ui:ObjectFieldTemplate": CardFieldTemplate,
+ user: {
+ "ui:description": "Username with which to SSH into host machine",
+ },
sshKey: {
"ui:allowDeselect": false,
},
@@ -262,9 +320,10 @@ export const getFormSchema = ({
},
sshOptions: {
"ui:addButtonText": "Add SSH option",
- "ui:descriptionNode": (
+ "ui:description": (
<>
- Option keywords supported by ssh_config.
+ Specify option keywords supported by{" "}
+ ssh_config.
>
),
"ui:orderable": false,
@@ -297,10 +356,12 @@ export const getFormSchema = ({
},
acceptableHostIdleTime: {
"ui:data-cy": "idle-time-input",
+ "ui:description": "Set 0 to use global default.",
...(!hasEC2Provider && { "ui:widget": "hidden" }),
},
futureHostFraction: {
"ui:data-cy": "future-fraction-input",
+ "ui:description": "Set 0 to use global default.",
...(!hasEC2Provider && { "ui:widget": "hidden" }),
},
},
@@ -315,50 +376,66 @@ const bootstrapSettings = {
jasperBinaryDir: {
type: "string" as "string",
title: "Jasper Binary Directory",
+ minLength: 1,
},
jasperCredentialsPath: {
type: "string" as "string",
title: "Jasper Credentials Path",
+ minLength: 1,
},
clientDir: {
type: "string" as "string",
title: "Client Directory",
+ minLength: 1,
},
shellPath: {
type: "string" as "string",
title: "Shell Path",
- },
- serviceUser: {
- type: "string" as "string",
- title: "Service User",
+ minLength: 1,
},
homeVolumeFormatCommand: {
type: "string" as "string",
title: "Home Volume Format Command",
},
+ serviceUser: {
+ type: "string" as "string",
+ title: "Service User",
+ },
resourceLimits: {
type: "object" as "object",
title: "Resource Limits",
+ required: [
+ "numFiles",
+ "numTasks",
+ "numProcesses",
+ "lockedMemoryKb",
+ "virtualMemoryKb",
+ ],
properties: {
numFiles: {
type: "number" as "number",
title: "Number of Files",
+ minimum: -1,
},
numTasks: {
type: "number" as "number",
title: "Number of CGroup Tasks",
+ minimum: -1,
},
numProcesses: {
type: "number" as "number",
title: "Number of Processes",
+ minimum: -1,
},
lockedMemoryKb: {
type: "number" as "number",
- title: "Locked Memory (kB)",
+ title: "Locked Memory",
+ minimum: -1,
},
virtualMemoryKb: {
type: "number" as "number",
title: "Virtual Memory (kB)",
+ minimum: -1,
},
},
},
@@ -421,6 +498,7 @@ const sshConfig = (sshKeys: SshKey[]) => ({
user: {
type: "string" as "string",
title: "SSH User",
+ minLength: 1,
},
sshKey: {
type: "string" as "string",
@@ -451,6 +529,12 @@ const sshConfig = (sshKeys: SshKey[]) => ({
const allocation = {
type: "object" as "object",
title: "Host Allocation",
+ required: [
+ "minimumHosts",
+ "maximumHosts",
+ "acceptableHostIdleTime",
+ "futureHostFraction",
+ ],
properties: {
version: {
type: "string" as "string",
@@ -485,6 +569,7 @@ const allocation = {
acceptableHostIdleTime: {
type: "number" as "number",
title: "Acceptable Host Idle Time (s)",
+ minimum: 0,
},
futureHostFraction: {
type: "number" as "number",
@@ -494,3 +579,7 @@ const allocation = {
},
},
};
+
+const indentCSS = css`
+ margin-left: ${size.m};
+`;
diff --git a/src/pages/distroSettings/tabs/HostTab/transformers.ts b/src/pages/distroSettings/tabs/HostTab/transformers.ts
index 7448a413f9..e71e286896 100644
--- a/src/pages/distroSettings/tabs/HostTab/transformers.ts
+++ b/src/pages/distroSettings/tabs/HostTab/transformers.ts
@@ -90,12 +90,15 @@ export const formToGql = ((
serviceUser: bootstrapSettings.serviceUser,
shellPath: bootstrapSettings.shellPath,
},
+ homeVolumeSettings: {
+ formatCommand: bootstrapSettings.homeVolumeFormatCommand,
+ },
+ hostAllocatorSettings: allocation,
iceCreamSettings: {
configPath: setup.icecreamConfigPath,
schedulerHost: setup.icecreamSchedulerHost,
},
isVirtualWorkStation: setup.isVirtualWorkStation,
- hostAllocatorSettings: allocation,
setupAsSudo: setup.setupAsSudo,
setup: setup.setupScript,
sshKey: sshConfig.sshKey,