Skip to content
This repository has been archived by the owner on Jul 2, 2024. It is now read-only.

EVG-19946: Support Docker on provider settings page #2017

Merged
merged 12 commits into from
Sep 18, 2023
4 changes: 2 additions & 2 deletions cypress/integration/distroSettings/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ describe("using the distro dropdown", () => {

describe("modifying the distro provider", () => {
beforeEach(() => {
cy.visit("/distro/localhost/settings/provider");
cy.visit("/distro/ubuntu1604-container-test/settings/provider");
});

it("warns when navigating to another distro settings tab after the provider has changed and allows save", () => {
cy.selectLGOption("Provider", "Docker");
cy.selectLGOption("Provider", "Static");
cy.dataCy("save-settings-button").should(
"not.have.attr",
"aria-disabled",
Expand Down
98 changes: 73 additions & 25 deletions cypress/integration/distroSettings/provider_section.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,86 @@
import { save } from "./utils";

describe("provider section", () => {
beforeEach(() => {
cy.visit("/distro/localhost/settings/provider");
});
describe("static", () => {
beforeEach(() => {
cy.visit("/distro/localhost/settings/provider");
});

it("successfully updates static provider fields", () => {
cy.dataCy("provider-select").contains("Static IP/VM");
it("successfully updates static provider fields", () => {
cy.dataCy("provider-select").contains("Static IP/VM");

// Correct fields are displayed
cy.dataCy("provider-settings").within(() => {
cy.get("button").should("have.length", 1);
cy.get("textarea").should("have.length", 1);
cy.get("input[type=checkbox]").should("have.length", 1);
cy.get("input[type=text]").should("have.length", 0);
});
// Correct section is displayed.
cy.dataCy("static-provider-settings").should("exist");

cy.getInputByLabel("User Data").type("my user data");
cy.getInputByLabel("Merge with existing user data").check({
force: true,
// Change field values.
cy.getInputByLabel("User Data").type("my user data");
cy.getInputByLabel("Merge with existing user data").check({
force: true,
});
cy.contains("button", "Add security group").click();
cy.getInputByLabel("Security Group ID").type("group-1234");
save();
cy.validateToast("success");

// Revert fields to original values.
cy.getInputByLabel("User Data").clear();
cy.getInputByLabel("Merge with existing user data").uncheck({
force: true,
});
cy.dataCy("delete-item-button").click();
save();
cy.validateToast("success");
});
cy.contains("button", "Add security group").click();
cy.getInputByLabel("Security Group ID").type("group-1234");
});

save();
cy.validateToast("success");
describe("docker", () => {
beforeEach(() => {
cy.visit("/distro/ubuntu1604-container-test/settings/provider");
});

cy.getInputByLabel("User Data").clear();
cy.getInputByLabel("Merge with existing user data").uncheck({
force: true,
it("shows pool mapping information based on container pool id", () => {
cy.getInputByLabel("Container Pool ID").should(
"contain.text",
"test-pool-1"
);
cy.getInputByLabel("Pool Mapping Information")
.should("have.attr", "placeholder")
.and("match", /test-pool-1/);
cy.selectLGOption("Container Pool ID", "test-pool-2");
cy.getInputByLabel("Pool Mapping Information")
.should("have.attr", "placeholder")
.and("match", /test-pool-2/);
});
cy.dataCy("delete-item-button").click();

save();
cy.validateToast("success");
it("successfully updates docker provider fields", () => {
cy.dataCy("provider-select").contains("Docker");

// Correct section is displayed.
cy.dataCy("docker-provider-settings").should("exist");

// Change field values.
cy.selectLGOption("Image Build Method", "Pull");
cy.selectLGOption("Container Pool ID", "test-pool-2");
cy.getInputByLabel("Username for Registries").type("username");
cy.getInputByLabel("Password for Registries").type("password");
cy.getInputByLabel("User Data").type("my user data");
cy.getInputByLabel("Merge with existing user data").check({
force: true,
});
save();
cy.validateToast("success");

// Revert fields to original values.
cy.selectLGOption("Image Build Method", "Import");
cy.selectLGOption("Container Pool ID", "test-pool-1");
cy.getInputByLabel("Username for Registries").clear();
cy.getInputByLabel("Password for Registries").clear();
cy.getInputByLabel("User Data").clear();
cy.getInputByLabel("Merge with existing user data").uncheck({
force: true,
});
save();
cy.validateToast("success");
});
});
});
4 changes: 2 additions & 2 deletions src/components/Header/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { getCommitsRoute, getUserPatchesRoute, routes } from "constants/routes";
import { size } from "constants/tokens";
import { useAuthStateContext } from "context/auth";
import { UserQuery, SpruceConfigQuery } from "gql/generated/types";
import { GET_USER, GET_SPRUCE_CONFIG } from "gql/queries";
import { GET_USER, SPRUCE_CONFIG } from "gql/queries";
import { useLegacyUIURL } from "hooks";
import { AuxiliaryDropdown } from "./AuxiliaryDropdown";
import { UserDropdown } from "./UserDropdown";
Expand Down Expand Up @@ -43,7 +43,7 @@ export const Navbar: React.FC = () => {

const currProject = projectFromUrl ?? Cookies.get(CURRENT_PROJECT);

const { data: configData } = useQuery<SpruceConfigQuery>(GET_SPRUCE_CONFIG, {
const { data: configData } = useQuery<SpruceConfigQuery>(SPRUCE_CONFIG, {
skip: currProject !== undefined,
});

Expand Down
2 changes: 2 additions & 0 deletions src/components/SpruceForm/Widgets/LeafyGreenWidgets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ export const LeafyGreenTextArea: React.FC<SpruceWidgetProps> = ({
label,
onChange,
options,
placeholder,
rawErrors,
readonly,
value,
Expand Down Expand Up @@ -362,6 +363,7 @@ export const LeafyGreenTextArea: React.FC<SpruceWidgetProps> = ({
<ElementWrapper css={elementWrapperCSS}>
<TextArea
ref={el}
placeholder={placeholder || undefined}
data-cy={dataCy}
label={label}
disabled={disabled || readonly}
Expand Down
7 changes: 0 additions & 7 deletions src/constants/fieldMaps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,6 @@ export const timeZones = [
},
];

export const awsRegions = [
{
str: "US-East-1",
value: "us-east-1",
},
];

const listOfDateFormatStrings = [
"MM-dd-yyyy",
"dd-MM-yyyy",
Expand Down
82 changes: 46 additions & 36 deletions src/gql/generated/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7815,42 +7815,6 @@ export type RepoSettingsQuery = {
};
};

export type SpruceConfigQueryVariables = Exact<{ [key: string]: never }>;

export type SpruceConfigQuery = {
__typename?: "Query";
spruceConfig?: {
__typename?: "SpruceConfig";
banner?: string | null;
bannerTheme?: string | null;
jira?: { __typename?: "JiraConfig"; host?: string | null } | null;
keys: Array<{ __typename?: "SSHKey"; location: string; name: string }>;
providers?: {
__typename?: "CloudProviderConfig";
aws?: {
__typename?: "AWSConfig";
maxVolumeSizePerUser?: number | null;
pod?: {
__typename?: "AWSPodConfig";
ecs?: {
__typename?: "ECSConfig";
maxCPU: number;
maxMemoryMb: number;
} | null;
} | null;
} | null;
} | null;
slack?: { __typename?: "SlackConfig"; name?: string | null } | null;
spawnHost: {
__typename?: "SpawnHostConfig";
spawnHostsPerUser: number;
unexpirableHostsPerUser: number;
unexpirableVolumesPerUser: number;
};
ui?: { __typename?: "UIConfig"; defaultProject: string } | null;
} | null;
};

export type SystemLogsQueryVariables = Exact<{
id: Scalars["String"]["input"];
execution?: InputMaybe<Scalars["Int"]["input"]>;
Expand Down Expand Up @@ -8678,6 +8642,52 @@ export type SpawnTaskQuery = {
} | null;
};

export type SpruceConfigQueryVariables = Exact<{ [key: string]: never }>;

export type SpruceConfigQuery = {
__typename?: "Query";
spruceConfig?: {
__typename?: "SpruceConfig";
banner?: string | null;
bannerTheme?: string | null;
containerPools?: {
__typename?: "ContainerPoolsConfig";
pools: Array<{
__typename?: "ContainerPool";
distro: string;
id: string;
maxContainers: number;
port: number;
}>;
} | null;
jira?: { __typename?: "JiraConfig"; host?: string | null } | null;
keys: Array<{ __typename?: "SSHKey"; location: string; name: string }>;
providers?: {
__typename?: "CloudProviderConfig";
aws?: {
__typename?: "AWSConfig";
maxVolumeSizePerUser?: number | null;
pod?: {
__typename?: "AWSPodConfig";
ecs?: {
__typename?: "ECSConfig";
maxCPU: number;
maxMemoryMb: number;
} | null;
} | null;
} | null;
} | null;
slack?: { __typename?: "SlackConfig"; name?: string | null } | null;
spawnHost: {
__typename?: "SpawnHostConfig";
spawnHostsPerUser: number;
unexpirableHostsPerUser: number;
unexpirableVolumesPerUser: number;
};
ui?: { __typename?: "UIConfig"; defaultProject: string } | null;
} | null;
};

export type SubnetAvailabilityZonesQueryVariables = Exact<{
[key: string]: never;
}>;
Expand Down
4 changes: 2 additions & 2 deletions src/gql/mocks/getSpruceConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import {
SpruceConfigQuery,
SpruceConfigQueryVariables,
} from "gql/generated/types";
import { GET_SPRUCE_CONFIG } from "gql/queries";
import { SPRUCE_CONFIG } from "gql/queries";
import { ApolloMock } from "types/gql";

export const getSpruceConfigMock: ApolloMock<
SpruceConfigQuery,
SpruceConfigQueryVariables
> = {
request: {
query: GET_SPRUCE_CONFIG,
query: SPRUCE_CONFIG,
variables: {},
},
result: {
Expand Down
4 changes: 2 additions & 2 deletions src/gql/queries/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ import GET_PROJECTS from "./get-projects.graphql";
import GET_MY_PUBLIC_KEYS from "./get-public-keys.graphql";
import GET_REPO_EVENT_LOGS from "./get-repo-event-logs.graphql";
import GET_REPO_SETTINGS from "./get-repo-settings.graphql";
import GET_SPRUCE_CONFIG from "./get-spruce-config.graphql";
import GET_SYSTEM_LOGS from "./get-system-logs.graphql";
import GET_TASK_ALL_EXECUTIONS from "./get-task-all-executions.graphql";
import GET_TASK_EVENT_LOGS from "./get-task-event-logs.graphql";
Expand All @@ -71,6 +70,7 @@ import PROJECT_HEALTH_VIEW from "./project-health-view.graphql";
import GET_PROJECT_PATCHES from "./project-patches.graphql";
import GET_SPAWN_EXPIRATION_INFO from "./spawn-expiration.graphql";
import GET_SPAWN_TASK from "./spawn-task.graphql";
import SPRUCE_CONFIG from "./spruce-config.graphql";
import GET_SUBNET_AVAILABILITY_ZONES from "./subnet-availability-zones.graphql";
import TASK_QUEUE_DISTROS from "./task-queue-distros.graphql";
import USER_DISTRO_SETTINGS_PERMISSIONS from "./user-distro-settings-permissions.graphql";
Expand Down Expand Up @@ -131,7 +131,7 @@ export {
GET_REPO_SETTINGS,
GET_SPAWN_EXPIRATION_INFO,
GET_SPAWN_TASK,
GET_SPRUCE_CONFIG,
SPRUCE_CONFIG,
GET_SUBNET_AVAILABILITY_ZONES,
GET_SYSTEM_LOGS,
GET_TASK_ALL_EXECUTIONS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ query SpruceConfig {
spruceConfig {
banner
bannerTheme
containerPools {
pools {
distro
id
maxContainers
port
}
}
jira {
host
}
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/useSpruceConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import {
SpruceConfigQuery,
SpruceConfigQueryVariables,
} from "gql/generated/types";
import { GET_SPRUCE_CONFIG } from "gql/queries";
import { SPRUCE_CONFIG } from "gql/queries";

export const useSpruceConfig = () => {
const { data } = useQuery<SpruceConfigQuery, SpruceConfigQueryVariables>(
GET_SPRUCE_CONFIG
SPRUCE_CONFIG
);

const { spruceConfig } = data || {};
Expand Down
4 changes: 2 additions & 2 deletions src/pages/commits/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
MainlineCommitsQueryVariables,
ProjectHealthView,
} from "gql/generated/types";
import { GET_MAINLINE_COMMITS, GET_SPRUCE_CONFIG } from "gql/queries";
import { GET_MAINLINE_COMMITS, SPRUCE_CONFIG } from "gql/queries";
import {
usePageTitle,
usePolling,
Expand Down Expand Up @@ -77,7 +77,7 @@ const Commits = () => {
const { data: spruceData } = useQuery<
SpruceConfigQuery,
SpruceConfigQueryVariables
>(GET_SPRUCE_CONFIG, {
>(SPRUCE_CONFIG, {
skip: !!projectIdentifier || !!recentlySelectedProject,
});

Expand Down
20 changes: 17 additions & 3 deletions src/pages/distroSettings/tabs/ProviderTab/ProviderTab.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useMemo } from "react";
import { useDistroSettingsContext } from "../../Context";
import { useSpruceConfig } from "hooks";
import { useDistroSettingsContext } from "pages/distroSettings/Context";
import { omitTypename } from "utils/string";
import { BaseTab } from "../BaseTab";
import {
FormToGqlFunction,
Expand All @@ -11,8 +13,6 @@ import { ProviderFormState, TabProps } from "./types";
import { UnsavedModal } from "./UnsavedModal";

export const ProviderTab: React.FC<TabProps> = ({ distro, distroData }) => {
const formSchema = useMemo(() => getFormSchema(), []);

const { getTab } = useDistroSettingsContext();

// @ts-expect-error - see TabState for details.
Expand All @@ -24,6 +24,20 @@ export const ProviderTab: React.FC<TabProps> = ({ distro, distroData }) => {
initialData: ReturnType<FormToGqlFunction<WritableDistroSettingsType>>;
} = getTab(WritableDistroSettingsTabs.Provider);

const { containerPools } = useSpruceConfig();
const { pools } = containerPools || {};

const selectedPoolId = formData?.dockerProviderSettings?.containerPoolId;
const selectedPool = pools?.find((p) => p.id === selectedPoolId) ?? null;
const poolMappingInfo = selectedPool
? JSON.stringify(omitTypename(selectedPool), null, 4)
: "";

const formSchema = useMemo(
() => getFormSchema({ pools: pools || [], poolMappingInfo }),
[pools, poolMappingInfo]
);

return (
<>
{/* Use conditional rendering instead of the shouldBlock prop so that modifying fields other than the provider triggers the standard navigation warning modal */}
Expand Down
Loading