feat!: drop support for legacy parameters (#7663)

This commit is contained in:
Marcin Tojek
2023-06-02 11:16:46 +02:00
committed by GitHub
parent 2b63492649
commit a7366a8b76
106 changed files with 1153 additions and 8553 deletions
-18
View File
@@ -239,15 +239,6 @@ export const getTemplateVersion = async (
return response.data
}
export const getTemplateVersionSchema = async (
versionId: string,
): Promise<TypesGen.ParameterSchema[]> => {
const response = await axios.get<TypesGen.ParameterSchema[]>(
`/api/v2/templateversions/${versionId}/schema`,
)
return response.data
}
export const getTemplateVersionResources = async (
versionId: string,
): Promise<TypesGen.WorkspaceResource[]> => {
@@ -335,15 +326,6 @@ export const getTemplateVersionGitAuth = async (
return response.data
}
export const getTemplateVersionParameters = async (
versionId: string,
): Promise<TypesGen.ComputedParameter[]> => {
const response = await axios.get(
`/api/v2/templateversions/${versionId}/parameters`,
)
return response.data
}
export const getTemplateVersionRichParameters = async (
versionId: string,
): Promise<TypesGen.TemplateVersionParameter[]> => {
+2 -83
View File
@@ -139,12 +139,6 @@ export interface BuildInfoResponse {
readonly workspace_proxy: boolean
}
// From codersdk/parameters.go
export interface ComputedParameter extends Parameter {
readonly schema_id: string
readonly default_source_value: boolean
}
// From codersdk/users.go
export interface CreateFirstUserRequest {
readonly email: string
@@ -171,15 +165,6 @@ export interface CreateOrganizationRequest {
readonly name: string
}
// From codersdk/parameters.go
export interface CreateParameterRequest {
readonly copy_from_parameter?: string
readonly name: string
readonly source_value: string
readonly source_scheme: ParameterSourceScheme
readonly destination_scheme: ParameterDestinationScheme
}
// From codersdk/organizations.go
export interface CreateTemplateRequest {
readonly name: string
@@ -187,7 +172,6 @@ export interface CreateTemplateRequest {
readonly description?: string
readonly icon?: string
readonly template_version_id: string
readonly parameter_values?: CreateParameterRequest[]
readonly default_ttl_ms?: number
readonly max_ttl_ms?: number
readonly allow_user_cancel_workspace_jobs?: boolean
@@ -200,7 +184,6 @@ export interface CreateTemplateRequest {
// From codersdk/templateversions.go
export interface CreateTemplateVersionDryRunRequest {
readonly workspace_name: string
readonly parameter_values: CreateParameterRequest[]
readonly rich_parameter_values: WorkspaceBuildParameter[]
readonly user_variable_values?: VariableValue[]
}
@@ -214,7 +197,6 @@ export interface CreateTemplateVersionRequest {
readonly example_id?: string
readonly provisioner: ProvisionerType
readonly tags: Record<string, string>
readonly parameter_values?: CreateParameterRequest[]
readonly user_variable_values?: VariableValue[]
}
@@ -251,7 +233,6 @@ export interface CreateWorkspaceBuildRequest {
readonly dry_run?: boolean
readonly state?: string
readonly orphan?: boolean
readonly parameter_values?: CreateParameterRequest[]
readonly rich_parameter_values?: WorkspaceBuildParameter[]
readonly log_level?: ProvisionerLogLevel
}
@@ -269,7 +250,6 @@ export interface CreateWorkspaceRequest {
readonly name: string
readonly autostart_schedule?: string
readonly ttl_ms?: number
readonly parameter_values?: CreateParameterRequest[]
readonly rich_parameter_values?: WorkspaceBuildParameter[]
}
@@ -585,40 +565,6 @@ export interface Pagination {
readonly offset?: number
}
// From codersdk/parameters.go
export interface Parameter {
readonly id: string
readonly scope: ParameterScope
readonly scope_id: string
readonly name: string
readonly source_scheme: ParameterSourceScheme
readonly destination_scheme: ParameterDestinationScheme
readonly created_at: string
readonly updated_at: string
readonly source_value: string
}
// From codersdk/parameters.go
export interface ParameterSchema {
readonly id: string
readonly created_at: string
readonly job_id: string
readonly name: string
readonly description: string
readonly default_source_scheme: ParameterSourceScheme
readonly default_source_value: string
readonly allow_override_source: boolean
readonly default_destination_scheme: ParameterDestinationScheme
readonly allow_override_destination: boolean
readonly default_refresh: string
readonly redisplay_value: boolean
readonly validation_error: string
readonly validation_condition: string
readonly validation_type_system: string
readonly validation_value_type: string
readonly validation_contains?: string[]
}
// From codersdk/groups.go
export interface PatchGroupRequest {
readonly add_users: string[]
@@ -1450,33 +1396,6 @@ export const LogSources: LogSource[] = ["provisioner", "provisioner_daemon"]
export type LoginType = "github" | "oidc" | "password" | "token"
export const LoginTypes: LoginType[] = ["github", "oidc", "password", "token"]
// From codersdk/parameters.go
export type ParameterDestinationScheme =
| "environment_variable"
| "none"
| "provisioner_variable"
export const ParameterDestinationSchemes: ParameterDestinationScheme[] = [
"environment_variable",
"none",
"provisioner_variable",
]
// From codersdk/parameters.go
export type ParameterScope = "import_job" | "template" | "workspace"
export const ParameterScopes: ParameterScope[] = [
"import_job",
"template",
"workspace",
]
// From codersdk/parameters.go
export type ParameterSourceScheme = "data" | "none"
export const ParameterSourceSchemes: ParameterSourceScheme[] = ["data", "none"]
// From codersdk/parameters.go
export type ParameterTypeSystem = "hcl" | "none"
export const ParameterTypeSystems: ParameterTypeSystem[] = ["hcl", "none"]
// From codersdk/provisionerdaemons.go
export type ProvisionerJobStatus =
| "canceled"
@@ -1604,9 +1523,9 @@ export type TemplateRole = "" | "admin" | "use"
export const TemplateRoles: TemplateRole[] = ["", "admin", "use"]
// From codersdk/templateversions.go
export type TemplateVersionWarning = "DEPRECATED_PARAMETERS"
export type TemplateVersionWarning = "UNSUPPORTED_WORKSPACES"
export const TemplateVersionWarnings: TemplateVersionWarning[] = [
"DEPRECATED_PARAMETERS",
"UNSUPPORTED_WORKSPACES",
]
// From codersdk/users.go
@@ -1,71 +0,0 @@
import { Story } from "@storybook/react"
import { ParameterSchema } from "../../api/typesGenerated"
import { ParameterInput, ParameterInputProps } from "./ParameterInput"
export default {
title: "components/ParameterInput",
component: ParameterInput,
}
const Template: Story<ParameterInputProps> = (args: ParameterInputProps) => (
<ParameterInput {...args} />
)
const createParameterSchema = (
partial: Partial<ParameterSchema>,
): ParameterSchema => {
return {
id: "000000",
job_id: "000000",
allow_override_destination: false,
allow_override_source: true,
created_at: "",
default_destination_scheme: "none",
default_refresh: "",
default_source_scheme: "data",
default_source_value: "default-value",
name: "parameter name",
description: "Some description!",
redisplay_value: false,
validation_condition: "",
validation_contains: [],
validation_error: "",
validation_type_system: "",
validation_value_type: "",
...partial,
}
}
export const Basic = Template.bind({})
Basic.args = {
schema: createParameterSchema({
name: "project_name",
description:
"Customize the name of a Google Cloud project that will be created!",
}),
}
export const Boolean = Template.bind({})
Boolean.args = {
schema: createParameterSchema({
name: "disable_docker",
description: "Disable Docker?",
validation_value_type: "bool",
default_source_value: "false",
}),
}
export const Contains = Template.bind({})
Contains.args = {
schema: createParameterSchema({
name: "region",
default_source_value: "🏈 US Central",
description: "Where would you like your workspace to live?",
validation_contains: [
"🏈 US Central",
"⚽ Brazil East",
"💶 EU West",
"🦘 Australia South",
],
}),
}
@@ -1,155 +0,0 @@
import FormControlLabel from "@mui/material/FormControlLabel"
import MenuItem from "@mui/material/MenuItem"
import Radio from "@mui/material/Radio"
import RadioGroup from "@mui/material/RadioGroup"
import { makeStyles } from "@mui/styles"
import TextField from "@mui/material/TextField"
import { Stack } from "components/Stack/Stack"
import { FC } from "react"
import { ParameterSchema } from "../../api/typesGenerated"
const isBoolean = (schema: ParameterSchema) => {
return schema.validation_value_type === "bool"
}
const ParameterLabel: React.FC<{ schema: ParameterSchema }> = ({ schema }) => {
const styles = useStyles()
if (schema.name && schema.description) {
return (
<label htmlFor={schema.name}>
<span className={styles.labelName}>var.{schema.name}</span>
<span className={styles.labelDescription}>{schema.description}</span>
</label>
)
}
return (
<label htmlFor={schema.name}>
<span className={styles.labelDescription}>var.{schema.name}</span>
</label>
)
}
export interface ParameterInputProps {
disabled?: boolean
schema: ParameterSchema
onChange: (value: string) => void
defaultValue?: string
}
export const ParameterInput: FC<ParameterInputProps> = ({
disabled,
onChange,
schema,
defaultValue,
}) => {
const styles = useStyles()
return (
<Stack direction="column" spacing={2}>
<ParameterLabel schema={schema} />
<div className={styles.input}>
<ParameterField
disabled={disabled}
onChange={onChange}
schema={schema}
defaultValue={defaultValue}
/>
</div>
</Stack>
)
}
const ParameterField: React.FC<ParameterInputProps> = ({
disabled,
onChange,
schema,
defaultValue,
}) => {
if (schema.validation_contains && schema.validation_contains.length > 0) {
return (
<TextField
id={schema.name}
defaultValue={defaultValue ?? schema.default_source_value}
placeholder={schema.default_source_value}
disabled={disabled}
onChange={(event) => {
onChange(event.target.value)
}}
select
fullWidth
>
{schema.validation_contains.map((item) => (
<MenuItem key={item} value={item}>
{item}
</MenuItem>
))}
</TextField>
)
}
if (isBoolean(schema)) {
return (
<RadioGroup
id={schema.name}
defaultValue={schema.default_source_value}
onChange={(event) => {
onChange(event.target.value)
}}
>
<FormControlLabel
disabled={disabled}
value="true"
control={<Radio />}
label="True"
/>
<FormControlLabel
disabled={disabled}
value="false"
control={<Radio />}
label="False"
/>
</RadioGroup>
)
}
// A text field can technically handle all cases!
// As other cases become more prominent (like filtering for numbers),
// we should break this out into more finely scoped input fields.
return (
<TextField
id={schema.name}
disabled={disabled}
placeholder={schema.default_source_value}
defaultValue={defaultValue ?? schema.default_source_value}
onChange={(event) => {
onChange(event.target.value)
}}
/>
)
}
const useStyles = makeStyles((theme) => ({
labelName: {
fontSize: 14,
color: theme.palette.text.secondary,
display: "block",
},
labelDescription: {
fontSize: 16,
color: theme.palette.text.primary,
display: "block",
fontWeight: 600,
lineHeight: "24px", // Keep the same as ParameterInput
},
input: {
display: "flex",
flexDirection: "column",
},
checkbox: {
display: "flex",
alignItems: "center",
gap: theme.spacing(1),
},
}))
@@ -13,7 +13,7 @@ const Template: Story<TemplateVersionWarningsProps> = (args) => (
<TemplateVersionWarnings {...args} />
)
export const DeprecatedParameters = Template.bind({})
DeprecatedParameters.args = {
warnings: ["DEPRECATED_PARAMETERS"],
export const UnsupportedWorkspaces = Template.bind({})
UnsupportedWorkspaces.args = {
warnings: ["UNSUPPORTED_WORKSPACES"],
}
@@ -2,7 +2,6 @@ import { FC } from "react"
import * as TypesGen from "api/typesGenerated"
import { Alert } from "components/Alert/Alert"
import { Maybe } from "components/Conditionals/Maybe"
import Link from "@mui/material/Link"
export interface TemplateVersionWarningsProps {
warnings?: TypesGen.TemplateVersionWarning[]
@@ -16,15 +15,11 @@ export const TemplateVersionWarnings: FC<
}
return (
<Maybe condition={Boolean(warnings.includes("DEPRECATED_PARAMETERS"))}>
<div data-testid="warning-deprecated-parameters">
<Alert severity="warning">
This template uses legacy parameters which will be deprecated in the
next Coder release. Learn how to migrate in{" "}
<Link href="https://coder.com/docs/v2/latest/templates/parameters#migration">
our documentation
</Link>
.
<Maybe condition={Boolean(warnings.includes("UNSUPPORTED_WORKSPACES"))}>
<div data-testid="error-unsupported-workspaces">
<Alert severity="error">
This template uses legacy parameters which are not supported anymore.
Contact your administrator for assistance.
</Alert>
</div>
</Maybe>
@@ -697,9 +697,9 @@ function makeFailedBuildLogs(): ProvisionerJobLog[] {
]
}
export const WithDeprecatedParameters: Story = {
export const UnsupportedWorkspace: Story = {
args: {
...Running.args,
templateWarnings: ["DEPRECATED_PARAMETERS"],
templateWarnings: ["UNSUPPORTED_WORKSPACES"],
},
}
@@ -1,6 +1,5 @@
import { ComponentMeta, Story } from "@storybook/react"
import {
MockParameterSchemas,
MockTemplateExample,
MockTemplateVersionVariable1,
MockTemplateVersionVariable2,
@@ -33,11 +32,6 @@ WithStarterTemplate.args = {
starterTemplate: MockTemplateExample,
}
export const WithParameters = Template.bind({})
WithParameters.args = {
parameters: MockParameterSchemas,
}
export const WithVariables = Template.bind({})
WithVariables.args = {
variables: [
@@ -2,13 +2,11 @@ import Checkbox from "@mui/material/Checkbox"
import { makeStyles } from "@mui/styles"
import TextField from "@mui/material/TextField"
import {
ParameterSchema,
ProvisionerJobLog,
Template,
TemplateExample,
TemplateVersionVariable,
} from "api/typesGenerated"
import { ParameterInput } from "components/ParameterInput/ParameterInput"
import { Stack } from "components/Stack/Stack"
import {
TemplateUpload,
@@ -112,7 +110,6 @@ const defaultInitialValues: CreateTemplateData = {
type GetInitialValuesParams = {
fromExample?: TemplateExample
fromCopy?: Template
parameters?: ParameterSchema[]
variables?: TemplateVersionVariable[]
allowAdvancedScheduling: boolean
}
@@ -122,7 +119,6 @@ const getInitialValues = ({
fromCopy,
allowAdvancedScheduling,
variables,
parameters,
}: GetInitialValuesParams) => {
let initialValues = defaultInitialValues
@@ -166,16 +162,6 @@ const getInitialValues = ({
})
}
if (parameters) {
parameters.forEach((parameter) => {
if (!initialValues.parameter_values_by_name) {
initialValues.parameter_values_by_name = {}
}
initialValues.parameter_values_by_name[parameter.name] =
parameter.default_source_value
})
}
return initialValues
}
@@ -185,7 +171,6 @@ export interface CreateTemplateFormProps {
isSubmitting: boolean
upload: TemplateUploadProps
starterTemplate?: TemplateExample
parameters?: ParameterSchema[]
variables?: TemplateVersionVariable[]
error?: unknown
jobError?: string
@@ -199,7 +184,6 @@ export const CreateTemplateForm: FC<CreateTemplateFormProps> = ({
onSubmit,
starterTemplate,
copiedTemplate,
parameters,
variables,
isSubmitting,
upload,
@@ -215,7 +199,6 @@ export const CreateTemplateForm: FC<CreateTemplateFormProps> = ({
fromExample: starterTemplate,
fromCopy: copiedTemplate,
variables,
parameters,
}),
validationSchema,
onSubmit,
@@ -439,30 +422,6 @@ export const CreateTemplateForm: FC<CreateTemplateFormProps> = ({
</FormFields>
</FormSection>
{/* Parameters */}
{parameters && parameters.length > 0 && (
<FormSection
title={t("form.parameters.title")}
description={t("form.parameters.description")}
>
<FormFields>
{parameters.map((schema) => (
<ParameterInput
schema={schema}
disabled={isSubmitting}
key={schema.id}
onChange={async (value) => {
await form.setFieldValue(
`parameter_values_by_name.${schema.name}`,
value,
)
}}
/>
))}
</FormFields>
</FormSection>
)}
{/* Variables */}
{variables && variables.length > 0 && (
<FormSection
@@ -95,7 +95,6 @@ test("Create template with variables", async () => {
)
expect(API.createTemplateVersion).toHaveBeenCalledWith(MockOrganization.id, {
file_id: MockProvisionerJob.file_id,
parameter_values: [],
provisioner: "terraform",
storage_method: "file",
tags: {},
@@ -33,15 +33,8 @@ const CreateTemplatePage: FC = () => {
},
})
const {
starterTemplate,
parameters,
error,
file,
jobError,
jobLogs,
variables,
} = state.context
const { starterTemplate, error, file, jobError, jobLogs, variables } =
state.context
const shouldDisplayForm = !state.hasTag("loading")
const { entitlements } = useDashboard()
const allowAdvancedScheduling =
@@ -75,7 +68,6 @@ const CreateTemplatePage: FC = () => {
starterTemplate={starterTemplate}
isSubmitting={state.hasTag("submitting")}
variables={variables}
parameters={parameters}
onCancel={onCancel}
onSubmit={(data) => {
send({
@@ -3,7 +3,6 @@ import userEvent from "@testing-library/user-event"
import * as API from "api/api"
import i18next from "i18next"
import {
mockParameterSchema,
MockTemplate,
MockUser,
MockWorkspace,
@@ -79,7 +78,6 @@ describe("CreateWorkspacePage", () => {
})
it("succeeds with default owner", async () => {
jest.spyOn(API, "getTemplateVersionSchema").mockResolvedValueOnce([])
jest
.spyOn(API, "getUsers")
.mockResolvedValueOnce({ users: [MockUser], count: 1 })
@@ -114,39 +112,9 @@ describe("CreateWorkspacePage", () => {
)
})
it("uses default param values passed from the URL", async () => {
const param = "dotfile_uri"
const paramValue = "localhost:3000"
jest.spyOn(API, "getTemplateVersionSchema").mockResolvedValueOnce([
mockParameterSchema({
name: param,
redisplay_value: true,
default_source_value: "",
}),
])
jest
.spyOn(API, "getTemplateVersionRichParameters")
.mockResolvedValueOnce([MockTemplateVersionParameter1])
renderWithAuth(<CreateWorkspacePage />, {
route:
"/templates/" +
MockTemplate.name +
`/workspace?param.${param}=${paramValue}`,
path: "/templates/:template/workspace",
}),
await screen.findByDisplayValue(paramValue)
})
it("uses default rich param values passed from the URL", async () => {
const param = "first_parameter"
const paramValue = "It works!"
jest.spyOn(API, "getTemplateVersionSchema").mockResolvedValueOnce([
mockParameterSchema({
name: param,
default_source_value: "",
}),
])
jest
.spyOn(API, "getTemplateVersionRichParameters")
.mockResolvedValueOnce([MockTemplateVersionParameter1])
@@ -32,10 +32,8 @@ const CreateWorkspacePage: FC = () => {
const {
templates,
templateParameters,
templateSchema,
templateGitAuth,
selectedTemplate,
getTemplateSchemaError,
getTemplateGitAuthError,
getTemplatesError,
createWorkspaceError,
@@ -55,21 +53,15 @@ const CreateWorkspacePage: FC = () => {
name={name}
defaultParameterValues={defaultParameterValues}
loadingTemplates={createWorkspaceState.matches("gettingTemplates")}
loadingTemplateSchema={createWorkspaceState.matches(
"gettingTemplateSchema",
)}
creatingWorkspace={createWorkspaceState.matches("creatingWorkspace")}
hasTemplateErrors={createWorkspaceState.matches("error")}
templateName={templateName}
templates={templates}
selectedTemplate={selectedTemplate}
templateParameters={orderedTemplateParameters(templateParameters)}
templateSchema={templateSchema}
templateGitAuth={templateGitAuth}
createWorkspaceErrors={{
[CreateWorkspaceErrors.GET_TEMPLATES_ERROR]: getTemplatesError,
[CreateWorkspaceErrors.GET_TEMPLATE_SCHEMA_ERROR]:
getTemplateSchemaError,
[CreateWorkspaceErrors.CREATE_WORKSPACE_ERROR]: createWorkspaceError,
[CreateWorkspaceErrors.GET_TEMPLATE_GITAUTH_ERROR]:
getTemplateGitAuthError,
@@ -1,8 +1,6 @@
import { ComponentMeta, Story } from "@storybook/react"
import {
mockApiError,
mockParameterSchema,
MockParameterSchemas,
MockTemplate,
MockTemplateVersionParameter1,
MockTemplateVersionParameter2,
@@ -27,7 +25,6 @@ export const NoParameters = Template.bind({})
NoParameters.args = {
templates: [MockTemplate],
selectedTemplate: MockTemplate,
templateSchema: [],
createWorkspaceErrors: {},
}
@@ -35,7 +32,6 @@ export const Parameters = Template.bind({})
Parameters.args = {
templates: [MockTemplate],
selectedTemplate: MockTemplate,
templateSchema: MockParameterSchemas,
createWorkspaceErrors: {},
}
@@ -43,41 +39,6 @@ export const RedisplayParameters = Template.bind({})
RedisplayParameters.args = {
templates: [MockTemplate],
selectedTemplate: MockTemplate,
templateSchema: [
mockParameterSchema({
name: "region",
default_source_value: "🏈 US Central",
description: "Where would you like your workspace to live?",
redisplay_value: false,
validation_contains: [
"🏈 US Central",
"⚽ Brazil East",
"💶 EU West",
"🦘 Australia South",
],
}),
mockParameterSchema({
name: "instance_size",
default_source_value: "Big",
description: "How large should you instance be?",
validation_contains: ["Small", "Medium", "Big"],
redisplay_value: false,
}),
mockParameterSchema({
name: "instance_size",
default_source_value: "Big",
description: "How large should your instance be?",
validation_contains: ["Small", "Medium", "Big"],
redisplay_value: true,
}),
mockParameterSchema({
name: "disable_docker",
description: "Disable Docker?",
validation_value_type: "bool",
default_source_value: "false",
redisplay_value: true,
}),
],
createWorkspaceErrors: {},
}
@@ -93,18 +54,6 @@ GetTemplatesError.args = {
hasTemplateErrors: true,
}
export const GetTemplateSchemaError = Template.bind({})
GetTemplateSchemaError.args = {
...Parameters.args,
createWorkspaceErrors: {
[CreateWorkspaceErrors.GET_TEMPLATE_SCHEMA_ERROR]: mockApiError({
message: 'Failed to fetch template schema for "docker-amd64".',
detail: "You do not have permission to access this resource.",
}),
},
hasTemplateErrors: true,
}
export const CreateWorkspaceError = Template.bind({})
CreateWorkspaceError.args = {
...Parameters.args,
@@ -1,6 +1,5 @@
import TextField from "@mui/material/TextField"
import * as TypesGen from "api/typesGenerated"
import { ParameterInput } from "components/ParameterInput/ParameterInput"
import { Stack } from "components/Stack/Stack"
import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"
import { FormikContextType, FormikTouched, useFormik } from "formik"
@@ -32,7 +31,6 @@ import { ErrorAlert } from "components/Alert/ErrorAlert"
export enum CreateWorkspaceErrors {
GET_TEMPLATES_ERROR = "getTemplatesError",
GET_TEMPLATE_SCHEMA_ERROR = "getTemplateSchemaError",
GET_TEMPLATE_GITAUTH_ERROR = "getTemplateGitAuthError",
CREATE_WORKSPACE_ERROR = "createWorkspaceError",
}
@@ -40,14 +38,12 @@ export enum CreateWorkspaceErrors {
export interface CreateWorkspacePageViewProps {
name: string
loadingTemplates: boolean
loadingTemplateSchema: boolean
creatingWorkspace: boolean
hasTemplateErrors: boolean
templateName: string
templates?: TypesGen.Template[]
selectedTemplate?: TypesGen.Template
templateParameters?: TypesGen.TemplateVersionParameter[]
templateSchema?: TypesGen.ParameterSchema[]
templateGitAuth?: TypesGen.TemplateVersionGitAuth[]
createWorkspaceErrors: Partial<Record<CreateWorkspaceErrors, Error | unknown>>
canCreateForUser?: boolean
@@ -63,9 +59,6 @@ export interface CreateWorkspacePageViewProps {
export const CreateWorkspacePageView: FC<
React.PropsWithChildren<CreateWorkspacePageViewProps>
> = (props) => {
const [parameterValues, setParameterValues] = useState<
Record<string, string>
>(props.defaultParameterValues ?? {})
const initialRichParameterValues = selectInitialRichParametersValues(
props.templateParameters,
props.defaultParameterValues,
@@ -123,37 +116,14 @@ export const CreateWorkspacePageView: FC<
return
}
}
if (!props.templateSchema) {
throw new Error("No template schema loaded")
}
const createRequests: TypesGen.CreateParameterRequest[] = []
props.templateSchema.forEach((schema) => {
let value = schema.default_source_value
if (schema.name in parameterValues) {
value = parameterValues[schema.name]
}
createRequests.push({
name: schema.name,
destination_scheme: schema.default_destination_scheme,
source_scheme: "data",
source_value: value,
})
})
props.onSubmit({
...request,
parameter_values: createRequests,
})
form.setSubmitting(false)
},
})
const isLoading = props.loadingTemplateSchema || props.loadingTemplates
// We only want to show schema that have redisplay_value equals true
const schemaToBeDisplayed = props.templateSchema?.filter(
(schema) => schema.redisplay_value,
)
const isLoading = props.loadingTemplates
const getFieldHelpers = getFormHelpers<TypesGen.CreateWorkspaceRequest>(
form,
@@ -182,19 +152,6 @@ export const CreateWorkspacePageView: FC<
}
/>
)}
{Boolean(
props.createWorkspaceErrors[
CreateWorkspaceErrors.GET_TEMPLATE_SCHEMA_ERROR
],
) && (
<ErrorAlert
error={
props.createWorkspaceErrors[
CreateWorkspaceErrors.GET_TEMPLATE_SCHEMA_ERROR
]
}
/>
)}
{Boolean(
props.createWorkspaceErrors[
CreateWorkspaceErrors.GET_TEMPLATE_GITAUTH_ERROR
@@ -283,31 +240,6 @@ export const CreateWorkspacePageView: FC<
</FormSection>
)}
{/* Template params */}
{schemaToBeDisplayed && schemaToBeDisplayed.length > 0 && (
<FormSection
title="Template params"
description="These values are provided by your template's Terraform configuration."
>
<FormFields>
{schemaToBeDisplayed.map((schema) => (
<ParameterInput
disabled={form.isSubmitting}
key={schema.id}
defaultValue={parameterValues[schema.name]}
onChange={(value) => {
setParameterValues({
...parameterValues,
[schema.name]: value,
})
}}
schema={schema}
/>
))}
</FormFields>
</FormSection>
)}
{props.templateParameters && (
<>
<MutableTemplateParametersSection
@@ -394,7 +394,7 @@ describe("WorkspacePage", () => {
})
})
it("shows the template warnings", async () => {
it("shows the template warning", async () => {
server.use(
rest.get(
"/api/v2/templateversions/:templateVersionId",
@@ -405,6 +405,6 @@ describe("WorkspacePage", () => {
)
await renderWorkspacePage()
await screen.findByTestId("warning-deprecated-parameters")
await screen.findByTestId("error-unsupported-workspaces")
})
})
+1 -67
View File
@@ -352,7 +352,7 @@ export const MockTemplateVersion3: TypesGen.TemplateVersion = {
name: "test-version-3",
readme: "README",
created_by: MockUser,
warnings: ["DEPRECATED_PARAMETERS"],
warnings: ["UNSUPPORTED_WORKSPACES"],
}
export const MockTemplate: TypesGen.Template = {
@@ -997,7 +997,6 @@ export const MockTemplateVersionVariable5: TypesGen.TemplateVersionVariable = {
// requests the MockWorkspace
export const MockWorkspaceRequest: TypesGen.CreateWorkspaceRequest = {
name: "test",
parameter_values: [],
template_id: "test-template",
rich_parameter_values: [
{
@@ -1606,71 +1605,6 @@ export const MockWorkspaceBuildParameter5: TypesGen.WorkspaceBuildParameter = {
value: "5",
}
export const MockParameterSchema: TypesGen.ParameterSchema = {
id: "000000",
job_id: "000000",
allow_override_destination: false,
allow_override_source: true,
created_at: "",
default_destination_scheme: "none",
default_refresh: "",
default_source_scheme: "data",
default_source_value: "default-value",
name: "parameter name",
description: "Some description!",
redisplay_value: false,
validation_condition: "",
validation_contains: [],
validation_error: "",
validation_type_system: "",
validation_value_type: "",
}
export const mockParameterSchema = (
partial: Partial<TypesGen.ParameterSchema>,
): TypesGen.ParameterSchema => {
return {
...MockParameterSchema,
...partial,
}
}
export const MockParameterSchemas: TypesGen.ParameterSchema[] = [
mockParameterSchema({
name: "region",
default_source_value: "🏈 US Central",
description: "Where would you like your workspace to live?",
redisplay_value: true,
validation_contains: [
"🏈 US Central",
"⚽ Brazil East",
"💶 EU West",
"🦘 Australia South",
],
}),
mockParameterSchema({
name: "instance_size",
default_source_value: "Big",
description: "How large should you instance be?",
validation_contains: ["Small", "Medium", "Big"],
redisplay_value: true,
}),
mockParameterSchema({
name: "instance_size",
default_source_value: "Big",
description: "How large should your instance be?",
validation_contains: ["Small", "Medium", "Big"],
redisplay_value: true,
}),
mockParameterSchema({
name: "disable_docker",
description: "Disable Docker?",
validation_value_type: "bool",
default_source_value: "false",
redisplay_value: true,
}),
]
export const MockTemplateVersionGitAuth: TypesGen.TemplateVersionGitAuth = {
id: "github",
type: "github",
+1 -23
View File
@@ -3,7 +3,7 @@ import { WorkspaceBuildTransition } from "../api/types"
import { CreateWorkspaceBuildRequest } from "../api/typesGenerated"
import { permissionsToCheck } from "../xServices/auth/authXService"
import * as M from "./entities"
import { MockGroup, mockParameterSchema, MockWorkspaceQuota } from "./entities"
import { MockGroup, MockWorkspaceQuota } from "./entities"
import fs from "fs"
import path from "path"
@@ -84,28 +84,6 @@ export const handlers = [
return res(ctx.status(200), ctx.json(M.MockTemplateVersion))
},
),
rest.get(
"/api/v2/templateversions/:templateVersionId/schema",
async (req, res, ctx) => {
return res(
ctx.status(200),
ctx.json([
mockParameterSchema({
id: "1",
name: M.MockTemplateVersionParameter1.name,
}),
mockParameterSchema({
id: "2",
name: M.MockTemplateVersionParameter2.name,
}),
mockParameterSchema({
id: "3",
name: M.MockTemplateVersionParameter3.name,
}),
]),
)
},
),
rest.get(
"/api/v2/templateversions/:templateVersionId/resources",
async (req, res, ctx) => {
@@ -3,16 +3,12 @@ import {
createTemplateVersion,
getTemplateVersion,
createTemplate,
getTemplateVersionSchema,
uploadTemplateFile,
getTemplateVersionLogs,
getTemplateVersionVariables,
getTemplateByName,
getTemplateVersionParameters,
} from "api/api"
import {
CreateTemplateVersionRequest,
ParameterSchema,
ProvisionerJob,
ProvisionerJobLog,
Template,
@@ -59,7 +55,6 @@ interface CreateTemplateContext {
exampleId?: string | null // It can be null because it is being passed from query string
version?: TemplateVersion
templateData?: CreateTemplateData
parameters?: ParameterSchema[]
variables?: TemplateVersionVariable[]
// file is used in the FE to show the filename and some other visual stuff
// uploadedFile is the response from the server to use in the API
@@ -98,12 +93,8 @@ export const createTemplateMachine =
waitForJobToBeCompleted: {
data: TemplateVersion
}
loadParameterSchema: {
data: ParameterSchema[]
}
checkParametersAndVariables: {
data: {
parameters?: ParameterSchema[]
variables?: TemplateVersionVariable[]
}
}
@@ -117,7 +108,6 @@ export const createTemplateMachine =
data: {
template: Template
version: TemplateVersion
parameters: ParameterSchema[]
variables: TemplateVersionVariable[]
}
}
@@ -343,36 +333,14 @@ export const createTemplateMachine =
organizationId,
templateNameToCopy,
)
const [version, schemaParameters, computedParameters, variables] =
await Promise.all([
getTemplateVersion(template.active_version_id),
getTemplateVersionSchema(template.active_version_id),
getTemplateVersionParameters(template.active_version_id),
getTemplateVersionVariables(template.active_version_id),
])
// Recreate parameters with default_source_value from the already
// computed version parameters
const parameters: ParameterSchema[] = []
computedParameters.forEach((computedParameter) => {
const schema = schemaParameters.find(
(schema) => schema.name === computedParameter.name,
)
if (!schema) {
throw new Error(
`Parameter ${computedParameter.name} not found in schema`,
)
}
parameters.push({
...schema,
default_source_value: computedParameter.source_value,
})
})
const [version, variables] = await Promise.all([
getTemplateVersion(template.active_version_id),
getTemplateVersionVariables(template.active_version_id),
])
return {
template,
version,
parameters,
variables,
}
},
@@ -420,7 +388,6 @@ export const createTemplateMachine =
},
createVersionWithParametersAndVariables: async ({
organizationId,
parameters,
templateData,
version,
}) => {
@@ -431,27 +398,10 @@ export const createTemplateMachine =
throw new Error("No template data defined")
}
// Get parameter values if they are needed/present
const parameterValues: CreateTemplateVersionRequest["parameter_values"] =
[]
if (parameters) {
const { parameter_values_by_name } = templateData
parameters.forEach((schema) => {
const value = parameter_values_by_name?.[schema.name]
parameterValues.push({
name: schema.name,
source_value: value ?? schema.default_source_value,
destination_scheme: schema.default_destination_scheme,
source_scheme: "data",
})
})
}
return createTemplateVersion(organizationId, {
storage_method: "file",
file_id: version.job.file_id,
provisioner: "terraform",
parameter_values: parameterValues,
user_variable_values: templateData.user_variable_values,
tags: {},
})
@@ -481,26 +431,16 @@ export const createTemplateMachine =
throw new Error("Version not defined")
}
let promiseParameter: Promise<ParameterSchema[]> | undefined =
undefined
let promiseVariables: Promise<TemplateVersionVariable[]> | undefined =
undefined
if (isMissingParameter(version)) {
promiseParameter = getTemplateVersionSchema(version.id)
}
if (isMissingVariables(version)) {
promiseVariables = getTemplateVersionVariables(version.id)
}
const [parameters, variables] = await Promise.all([
promiseParameter,
promiseVariables,
])
const [variables] = await Promise.all([promiseVariables])
return {
parameters,
variables,
}
},
@@ -547,7 +487,6 @@ export const createTemplateMachine =
assignVersion: assign({ version: (_, { data }) => data }),
assignTemplateData: assign({ templateData: (_, { data }) => data }),
assignParametersAndVariables: assign({
parameters: (_, { data }) => data.parameters,
variables: (_, { data }) => data.variables,
}),
assignFile: assign({ file: (_, { file }) => file }),
@@ -560,7 +499,6 @@ export const createTemplateMachine =
assignCopiedTemplateData: assign({
copiedTemplate: (_, { data }) => data.template,
version: (_, { data }) => data.version,
parameters: (_, { data }) => data.parameters,
variables: (_, { data }) => data.variables,
}),
},
@@ -577,9 +515,9 @@ export const createTemplateMachine =
!isMissingVariables(data),
),
hasNoParametersOrVariables: (_, { data }) =>
data.parameters === undefined && data.variables === undefined,
data.variables === undefined,
hasParametersOrVariables: (_, { data }) => {
return data.parameters.length > 0 || data.variables.length > 0
return data.variables.length > 0
},
},
},
@@ -4,11 +4,9 @@ import {
getTemplates,
getTemplateVersionGitAuth,
getTemplateVersionRichParameters,
getTemplateVersionSchema,
} from "api/api"
import {
CreateWorkspaceRequest,
ParameterSchema,
Template,
TemplateVersionGitAuth,
TemplateVersionParameter,
@@ -26,7 +24,6 @@ type CreateWorkspaceContext = {
templates?: Template[]
selectedTemplate?: Template
templateParameters?: TemplateVersionParameter[]
templateSchema?: ParameterSchema[]
templateGitAuth?: TemplateVersionGitAuth[]
createWorkspaceRequest?: CreateWorkspaceRequest
createdWorkspace?: Workspace
@@ -34,7 +31,6 @@ type CreateWorkspaceContext = {
getTemplatesError?: Error | unknown
getTemplateParametersError?: Error | unknown
getTemplateGitAuthError?: Error | unknown
getTemplateSchemaError?: Error | unknown
permissions?: Record<string, boolean>
checkPermissionsError?: Error | unknown
}
@@ -77,9 +73,6 @@ export const createWorkspaceMachine =
getTemplateParameters: {
data: TemplateVersionParameter[]
}
getTemplateSchema: {
data: ParameterSchema[]
}
createWorkspace: {
data: Workspace
}
@@ -98,7 +91,7 @@ export const createWorkspaceMachine =
},
{
actions: ["assignTemplates", "assignSelectedTemplate"],
target: "gettingTemplateSchema",
target: "gettingTemplateParameters",
},
],
onError: {
@@ -107,20 +100,6 @@ export const createWorkspaceMachine =
},
},
},
gettingTemplateSchema: {
entry: "clearGetTemplateSchemaError",
invoke: {
src: "getTemplateSchema",
onDone: {
actions: ["assignTemplateSchema"],
target: "gettingTemplateParameters",
},
onError: {
actions: ["assignGetTemplateSchemaError"],
target: "error",
},
},
},
gettingTemplateParameters: {
entry: "clearGetTemplateParametersError",
invoke: {
@@ -232,15 +211,6 @@ export const createWorkspaceMachine =
selectedTemplate.active_version_id,
)
},
getTemplateSchema: (context) => {
const { selectedTemplate } = context
if (!selectedTemplate) {
throw new Error("No selected template")
}
return getTemplateVersionSchema(selectedTemplate.active_version_id)
},
checkPermissions: async (context) => {
if (!context.organizationId) {
throw new Error("No organization ID")
@@ -296,11 +266,6 @@ export const createWorkspaceMachine =
assignTemplateParameters: assign({
templateParameters: (_, event) => event.data,
}),
assignTemplateSchema: assign({
// Only show parameters that are allowed to be overridden.
// CLI code: https://github.com/coder/coder/blob/main/cli/create.go#L152-L155
templateSchema: (_, event) => event.data,
}),
assignPermissions: assign({
permissions: (_, event) => event.data as Record<string, boolean>,
}),
@@ -334,12 +299,6 @@ export const createWorkspaceMachine =
clearGetTemplateParametersError: assign({
getTemplateParametersError: (_) => undefined,
}),
assignGetTemplateSchemaError: assign({
getTemplateSchemaError: (_, event) => event.data,
}),
clearGetTemplateSchemaError: assign({
getTemplateSchemaError: (_) => undefined,
}),
clearTemplateGitAuthError: assign({
getTemplateGitAuthError: (_) => undefined,
}),