Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita4bd50c

Browse files
authored
chore: enable terraform provisioners in e2e by default (#13134)
* skip docker test for now, it leaks containers
1 parent1832a75 commita4bd50c

File tree

9 files changed

+150
-23
lines changed

9 files changed

+150
-23
lines changed

‎.vscode/settings.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,5 +222,7 @@
222222
"go.testFlags": ["-short","-coverpkg=./..."],
223223
// We often use a version of TypeScript that's ahead of the version shipped
224224
// with VS Code.
225-
"typescript.tsdk":"./site/node_modules/typescript/lib"
225+
"typescript.tsdk":"./site/node_modules/typescript/lib",
226+
// Playwright tests in VSCode will open a browser to live "view" the test.
227+
"playwright.reuseBrowser":true
226228
}

‎site/e2e/constants.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ export const requireEnterpriseTests = Boolean(
3939
);
4040
exportconstenterpriseLicense=process.env.CODER_E2E_ENTERPRISE_LICENSE??"";
4141

42+
// Disabling terraform tests is optional for environments without Docker + Terraform.
43+
// By default, we opt into these tests.
44+
exportconstrequireTerraformTests=!process.env.CODER_E2E_DISABLE_TERRAFORM;
45+
4246
// Fake experiments to verify that site presents them as enabled.
4347
exportconste2eFakeExperiment1="e2e-fake-experiment-1";
4448
exportconste2eFakeExperiment2="e2e-fake-experiment-2";

‎site/e2e/helpers.ts

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
enterpriseLicense,
2020
prometheusPort,
2121
requireEnterpriseTests,
22+
requireTerraformTests,
2223
}from"./constants";
2324
import{expectUrl}from"./expectUrl";
2425
import{
@@ -43,6 +44,11 @@ export function requiresEnterpriseLicense() {
4344
test.skip(!enterpriseLicense);
4445
}
4546

47+
// requireTerraformProvisioner by default is enabled.
48+
exportfunctionrequireTerraformProvisioner(){
49+
test.skip(!requireTerraformTests);
50+
}
51+
4652
// createWorkspace creates a workspace for a template.
4753
// It does not wait for it to be running, but it does navigate to the page.
4854
exportconstcreateWorkspace=async(
@@ -149,25 +155,46 @@ export const verifyParameters = async (
149155
}
150156
};
151157

158+
// StarterTemplates are ids of starter templates that can be used in place of
159+
// the responses payload. These starter templates will require real provisioners.
160+
exportenumStarterTemplates{
161+
STARTER_DOCKER="docker",
162+
}
163+
164+
functionisStarterTemplate(
165+
input:EchoProvisionerResponses|StarterTemplates|undefined,
166+
):input isStarterTemplates{
167+
if(!input){
168+
returnfalse;
169+
}
170+
returntypeofinput==="string";
171+
}
172+
152173
// createTemplate navigates to the /templates/new page and uploads a template
153174
// with the resources provided in the responses argument.
154175
exportconstcreateTemplate=async(
155176
page:Page,
156-
responses?:EchoProvisionerResponses,
177+
responses?:EchoProvisionerResponses|StarterTemplates,
157178
):Promise<string>=>{
158-
// Required to have templates submit their provisioner type as echo!
159-
awaitpage.addInitScript({
160-
content:"window.playwright = true",
161-
});
179+
letpath="/templates/new";
180+
if(isStarterTemplate(responses)){
181+
path+=`?exampleId=${responses}`;
182+
}else{
183+
// The form page will read this value and use it as the default type.
184+
path+="?provisioner_type=echo";
185+
}
162186

163-
awaitpage.goto("/templates/new",{waitUntil:"domcontentloaded"});
187+
awaitpage.goto(path,{waitUntil:"domcontentloaded"});
164188
awaitexpectUrl(page).toHavePathName("/templates/new");
165189

166-
awaitpage.getByTestId("file-upload").setInputFiles({
167-
buffer:awaitcreateTemplateVersionTar(responses),
168-
mimeType:"application/x-tar",
169-
name:"template.tar",
170-
});
190+
if(!isStarterTemplate(responses)){
191+
awaitpage.getByTestId("file-upload").setInputFiles({
192+
buffer:awaitcreateTemplateVersionTar(responses),
193+
mimeType:"application/x-tar",
194+
name:"template.tar",
195+
});
196+
}
197+
171198
constname=randomName();
172199
awaitpage.getByLabel("Name *").fill(name);
173200
awaitpage.getByTestId("form-submit").click();
@@ -868,6 +895,7 @@ export async function openTerminalWindow(
868895
page:Page,
869896
context:BrowserContext,
870897
workspaceName:string,
898+
agentName:string="dev",
871899
):Promise<Page>{
872900
// Wait for the web terminal to open in a new tab
873901
constpagePromise=context.waitForEvent("page");
@@ -879,7 +907,7 @@ export async function openTerminalWindow(
879907
// isn't POSIX compatible, such as Fish.
880908
constcommandQuery=`?command=${encodeURIComponent("/usr/bin/env bash")}`;
881909
awaitexpectUrl(terminal).toHavePathName(
882-
`/@admin/${workspaceName}.dev/terminal`,
910+
`/@admin/${workspaceName}.${agentName}/terminal`,
883911
);
884912
awaitterminal.goto(`/@admin/${workspaceName}.dev/terminal${commandQuery}`);
885913

‎site/e2e/playwright.config.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import{defineConfig}from"@playwright/test";
2+
import{execSync}from"child_process";
23
import*aspathfrom"path";
34
import{
45
coderMain,
@@ -7,13 +8,47 @@ import {
78
e2eFakeExperiment1,
89
e2eFakeExperiment2,
910
gitAuth,
11+
requireTerraformTests,
1012
}from"./constants";
1113

1214
exportconstwsEndpoint=process.env.CODER_E2E_WS_ENDPOINT;
1315

1416
// This is where auth cookies are stored!
1517
exportconststorageState=path.join(__dirname,".auth.json");
1618

19+
// If running terraform tests, verify the requirements exist in the
20+
// environment.
21+
//
22+
// These execs will throw an error if the status code is non-zero.
23+
// So if both these work, then we can launch terraform provisioners.
24+
lethasTerraform=false;
25+
lethasDocker=false;
26+
try{
27+
execSync("terraform --version");
28+
hasTerraform=true;
29+
}catch{
30+
/* empty */
31+
}
32+
33+
try{
34+
execSync("docker --version");
35+
hasDocker=true;
36+
}catch{
37+
/* empty */
38+
}
39+
40+
if(!hasTerraform||!hasDocker){
41+
constmsg=
42+
"Terraform provisioners require docker & terraform binaries to function. \n"+
43+
(hasTerraform
44+
?""
45+
:"\tThe `terraform` executable is not present in the runtime environment.\n")+
46+
(hasDocker
47+
?""
48+
:"\tThe `docker` executable is not present in the runtime environment.\n");
49+
thrownewError(msg);
50+
}
51+
1752
constlocalURL=(port:number,path:string):string=>{
1853
return`http://localhost:${port}${path}`;
1954
};
@@ -54,13 +89,14 @@ export default defineConfig({
5489
`go run -tags embed${coderMain} server`,
5590
"--global-config $(mktemp -d -t e2e-XXXXXXXXXX)",
5691
`--access-url=http://localhost:${coderPort}`,
57-
`--http-address=localhost:${coderPort}`,
92+
`--http-address=0.0.0.0:${coderPort}`,
5893
"--in-memory",
5994
"--telemetry=false",
6095
"--dangerous-disable-rate-limits",
6196
"--provisioner-daemons 10",
6297
// TODO: Enable some terraform provisioners
63-
"--provisioner-types=echo",
98+
`--provisioner-types=echo${requireTerraformTests ?",terraform" :""}`,
99+
`--provisioner-daemons=10`,
64100
"--web-terminal-renderer=dom",
65101
"--pprof-enable",
66102
]

‎site/e2e/tests/createWorkspace.spec.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import{test,expect}from"@playwright/test";
22
import{
3+
StarterTemplates,
34
createTemplate,
45
createWorkspace,
56
echoResponsesWithParameters,
7+
openTerminalWindow,
8+
requireTerraformProvisioner,
69
verifyParameters,
710
}from"../helpers";
811
import{beforeCoderTest}from"../hooks";
@@ -147,3 +150,42 @@ test("create workspace with disable_param search params", async ({ page }) => {
147150
awaitexpect(page.getByLabel(/Firstparameter/i)).toBeDisabled();
148151
awaitexpect(page.getByLabel(/Secondparameter/i)).toBeDisabled();
149152
});
153+
154+
test("create docker workspace",async({ context, page})=>{
155+
test.skip(
156+
true,
157+
"creating docker containers is currently leaky. They are not cleaned up when the tests are over.",
158+
);
159+
requireTerraformProvisioner();
160+
consttemplate=awaitcreateTemplate(page,StarterTemplates.STARTER_DOCKER);
161+
162+
constworkspaceName=awaitcreateWorkspace(page,template);
163+
164+
// The workspace agents must be ready before we try to interact with the workspace.
165+
awaitpage.waitForSelector(
166+
`//div[@role="status"][@data-testid="agent-status-ready"]`,
167+
{
168+
state:"visible",
169+
},
170+
);
171+
172+
// Wait for the terminal button to be visible, and click it.
173+
constterminalButton=
174+
"//a[@data-testid='terminal'][normalize-space()='Terminal']";
175+
awaitpage.waitForSelector(terminalButton,{
176+
state:"visible",
177+
});
178+
179+
constterminal=awaitopenTerminalWindow(
180+
page,
181+
context,
182+
workspaceName,
183+
"main",
184+
);
185+
awaitterminal.waitForSelector(
186+
`//textarea[contains(@class,"xterm-helper-textarea")]`,
187+
{
188+
state:"visible",
189+
},
190+
);
191+
});

‎site/src/pages/CreateTemplatePage/CreateTemplateForm.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import { useFormik } from "formik";
33
importcamelCasefrom"lodash/camelCase";
44
importcapitalizefrom"lodash/capitalize";
55
importtype{FC}from"react";
6+
import{useSearchParams}from"react-router-dom";
67
import*asYupfrom"yup";
78
importtype{
89
ProvisionerJobLog,
10+
ProvisionerType,
911
Template,
1012
TemplateExample,
1113
TemplateVersionVariable,
@@ -50,6 +52,7 @@ export interface CreateTemplateData {
5052
parameter_values_by_name?:Record<string,string>;
5153
user_variable_values?:VariableValue[];
5254
allow_everyone_group_access:boolean;
55+
provisioner_type:ProvisionerType;
5356
}
5457

5558
constvalidationSchema=Yup.object({
@@ -81,23 +84,31 @@ const defaultInitialValues: CreateTemplateData = {
8184
allow_user_autostart:false,
8285
allow_user_autostop:false,
8386
allow_everyone_group_access:true,
87+
provisioner_type:"terraform",
8488
};
8589

8690
typeGetInitialValuesParams={
8791
fromExample?:TemplateExample;
8892
fromCopy?:Template;
8993
variables?:TemplateVersionVariable[];
9094
allowAdvancedScheduling:boolean;
95+
searchParams:URLSearchParams;
9196
};
9297

9398
constgetInitialValues=({
9499
fromExample,
95100
fromCopy,
96101
allowAdvancedScheduling,
97102
variables,
103+
searchParams,
98104
}:GetInitialValuesParams)=>{
99105
letinitialValues=defaultInitialValues;
100106

107+
// Will assume the query param has a valid ProvisionerType, as this query param is only used
108+
// in testing.
109+
defaultInitialValues.provisioner_type=
110+
(searchParams.get("provisioner_type")asProvisionerType)||"terraform";
111+
101112
if(!allowAdvancedScheduling){
102113
initialValues={
103114
...initialValues,
@@ -164,6 +175,7 @@ export type CreateTemplateFormProps = (
164175
};
165176

166177
exportconstCreateTemplateForm:FC<CreateTemplateFormProps>=(props)=>{
178+
const[searchParams]=useSearchParams();
167179
const{
168180
onCancel,
169181
onSubmit,
@@ -176,13 +188,15 @@ export const CreateTemplateForm: FC<CreateTemplateFormProps> = (props) => {
176188
allowAdvancedScheduling,
177189
variablesSectionRef,
178190
}=props;
191+
179192
constform=useFormik<CreateTemplateData>({
180193
initialValues:getInitialValues({
181194
allowAdvancedScheduling,
182195
fromExample:
183196
"starterTemplate"inprops ?props.starterTemplate :undefined,
184197
fromCopy:"copiedTemplate"inprops ?props.copiedTemplate :undefined,
185198
variables,
199+
searchParams,
186200
}),
187201
validationSchema,
188202
onSubmit,

‎site/src/pages/CreateTemplatePage/DuplicateTemplateView.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export const DuplicateTemplateView: FC<CreateTemplatePageViewProps> = ({
8282
version:firstVersionFromFile(
8383
templateVersionQuery.data!.job.file_id,
8484
formData.user_variable_values,
85+
formData.provisioner_type,
8586
),
8687
template:newTemplate(formData),
8788
});

‎site/src/pages/CreateTemplatePage/UploadTemplateView.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export const UploadTemplateView: FC<CreateTemplatePageViewProps> = ({
6464
version:firstVersionFromFile(
6565
uploadedFile!.hash,
6666
formData.user_variable_values,
67+
formData.provisioner_type,
6768
),
6869
template:newTemplate(formData),
6970
});

‎site/src/pages/CreateTemplatePage/utils.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
importtype{
2+
CreateTemplateVersionRequest,
23
Entitlements,
34
ProvisionerType,
45
TemplateExample,
@@ -7,10 +8,6 @@ import type {
78
import{calculateAutostopRequirementDaysValue}from"utils/schedule";
89
importtype{CreateTemplateData}from"./CreateTemplateForm";
910

10-
constprovisioner:ProvisionerType=
11-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Playwright needs to use a different provisioner type!
12-
typeof(windowasany).playwright!=="undefined" ?"echo" :"terraform";
13-
1411
exportconstnewTemplate=(formData:CreateTemplateData)=>{
1512
const{ autostop_requirement_days_of_week, autostop_requirement_weeks}=
1613
formData;
@@ -56,10 +53,11 @@ export const getFormPermissions = (entitlements: Entitlements) => {
5653
exportconstfirstVersionFromFile=(
5754
fileId:string,
5855
variables:VariableValue[]|undefined,
59-
)=>{
56+
provisionerType:ProvisionerType,
57+
):CreateTemplateVersionRequest=>{
6058
return{
6159
storage_method:"file"asconst,
62-
provisioner:provisioner,
60+
provisioner:provisionerType,
6361
user_variable_values:variables,
6462
file_id:fileId,
6563
tags:{},
@@ -69,10 +67,11 @@ export const firstVersionFromFile = (
6967
exportconstfirstVersionFromExample=(
7068
example:TemplateExample,
7169
variables:VariableValue[]|undefined,
72-
)=>{
70+
):CreateTemplateVersionRequest=>{
7371
return{
7472
storage_method:"file"asconst,
75-
provisioner:provisioner,
73+
// All starter templates are for the terraform provisioner type.
74+
provisioner:"terraform",
7675
user_variable_values:variables,
7776
example_id:example.id,
7877
tags:{},

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp