Skip to content

Commit 7e81ead

Browse files
committed
Restored null fields in user settings; removed deprecated user settings fields
1 parent 9a36e63 commit 7e81ead

File tree

5 files changed

+23
-223
lines changed

5 files changed

+23
-223
lines changed

__tests__/v2/UserEditor.test.js

Lines changed: 6 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,15 @@ describe('UserEditor', () => {
4646
/** @type {import('fractal-components/types/api').UserSettings} */
4747
const initialSettings = {
4848
slurm_accounts: [],
49-
project_dir: null,
50-
slurm_user: null,
51-
ssh_host: null,
52-
ssh_username: null,
53-
ssh_private_key_path: null,
54-
ssh_tasks_dir: null,
55-
ssh_jobs_dir: null
49+
project_dir: null
5650
};
5751

5852
/**
5953
* @type {() => Promise<Response>}
6054
*/
6155
const mockSaveUser = vi.fn();
6256

63-
it('Update settings with slurm_sudo runner backend - success', async () => {
57+
it('Update settings - success', async () => {
6458
const mockRequest = /** @type {import('vitest').Mock} */ (fetch)
6559
.mockResolvedValueOnce({
6660
ok: true,
@@ -105,22 +99,21 @@ describe('UserEditor', () => {
10599
});
106100

107101
await user.type(screen.getByRole('textbox', { name: 'Project dir' }), '/path/to/project/dir');
108-
await user.type(screen.getByRole('textbox', { name: 'SLURM user' }), 'user');
109102
await user.click(screen.getByRole('button', { name: 'Save' }));
110103
await screen.findByText('User successfully updated');
111104

112105
expect(mockRequest).toHaveBeenCalledWith(
113106
expect.anything(),
114107
expect.objectContaining({
115108
body: JSON.stringify({
116-
project_dir: '/path/to/project/dir',
117-
slurm_user: 'user'
109+
slurm_accounts: [],
110+
project_dir: '/path/to/project/dir'
118111
})
119112
})
120113
);
121114
});
122115

123-
it('Update settings with slurm_sudo runner backend - validation error', async () => {
116+
it('Update settings - validation error', async () => {
124117
const mockRequest = /** @type {import('vitest').Mock} */ (fetch)
125118
.mockResolvedValueOnce({
126119
ok: true,
@@ -176,122 +169,10 @@ describe('UserEditor', () => {
176169
expect.anything(),
177170
expect.objectContaining({
178171
body: JSON.stringify({
172+
slurm_accounts: [],
179173
project_dir: 'xxx'
180174
})
181175
})
182176
);
183177
});
184-
185-
it('Update settings with slurm_ssh runner backend - success', async () => {
186-
const user = userEvent.setup();
187-
188-
render(UserEditor, {
189-
props: {
190-
runnerBackend: 'slurm_ssh',
191-
user: selectedUser,
192-
settings: { ...initialSettings },
193-
saveUser: mockSaveUser
194-
}
195-
});
196-
197-
const mockRequest = /** @type {import('vitest').Mock} */ (fetch).mockResolvedValue({
198-
ok: true,
199-
status: 200,
200-
json: () =>
201-
new Promise((resolve) =>
202-
resolve({
203-
...initialSettings,
204-
ssh_host: 'localhost',
205-
ssh_username: 'username',
206-
ssh_private_key_path: '/path/to/private/key'
207-
})
208-
)
209-
});
210-
211-
await user.type(screen.getByRole('textbox', { name: 'SSH host' }), 'localhost');
212-
await user.type(screen.getByRole('textbox', { name: 'SSH username' }), 'username');
213-
await user.type(screen.getByRole('textbox', { name: 'SSH Private Key Path' }), 'xxx');
214-
await user.click(screen.getByRole('button', { name: 'Save' }));
215-
await screen.findByText('User successfully updated');
216-
217-
expect(mockRequest).toHaveBeenCalledWith(
218-
expect.anything(),
219-
expect.objectContaining({
220-
body: JSON.stringify({
221-
ssh_host: 'localhost',
222-
ssh_username: 'username',
223-
ssh_private_key_path: 'xxx'
224-
})
225-
})
226-
);
227-
});
228-
229-
it('Update settings with slurm_ssh runner backend - validation error', async () => {
230-
const mockRequest = /** @type {import('vitest').Mock} */ (fetch)
231-
.mockResolvedValueOnce({
232-
ok: true,
233-
status: 200,
234-
// mock profile
235-
json: () => new Promise((resolve) => resolve({ id: 1, resource_id: 1 }))
236-
})
237-
.mockResolvedValueOnce({
238-
ok: true,
239-
status: 200,
240-
// mock resources
241-
json: () => new Promise((resolve) => resolve([{ id: 1 }]))
242-
})
243-
.mockResolvedValueOnce({
244-
ok: true,
245-
status: 200,
246-
// mock profiles
247-
json: () => new Promise((resolve) => resolve([{ id: 1 }]))
248-
})
249-
.mockResolvedValueOnce({
250-
ok: false,
251-
status: 422,
252-
json: () =>
253-
new Promise((resolve) =>
254-
resolve({
255-
detail: [
256-
{
257-
loc: ['body', 'ssh_private_key_path'],
258-
msg: 'mock_error_ssh_private_key_path',
259-
type: 'value_error'
260-
}
261-
]
262-
})
263-
)
264-
});
265-
266-
const user = userEvent.setup();
267-
268-
render(UserEditor, {
269-
props: {
270-
runnerBackend: 'slurm_ssh',
271-
user: selectedUser,
272-
settings: { ...initialSettings },
273-
saveUser: mockSaveUser
274-
}
275-
});
276-
277-
await user.type(screen.getByRole('textbox', { name: 'SSH host' }), 'localhost');
278-
await user.type(screen.getByRole('textbox', { name: 'SSH username' }), 'username');
279-
await user.type(
280-
screen.getByRole('textbox', { name: 'SSH Private Key Path' }),
281-
'/path/to/private/key'
282-
);
283-
await user.click(screen.getByRole('button', { name: 'Save' }));
284-
await screen.findByText('mock_error_ssh_private_key_path');
285-
286-
expect(mockRequest).toHaveBeenCalledWith(
287-
expect.anything(),
288-
expect.objectContaining({
289-
body: JSON.stringify({
290-
ssh_host: 'localhost',
291-
ssh_username: 'username',
292-
ssh_private_key_path: '/path/to/private/key'
293-
})
294-
})
295-
);
296-
});
297178
});

components/src/lib/types/api.d.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,6 @@ export type User = {
2121
export type UserSettings = {
2222
slurm_accounts: string[];
2323
project_dir: string | null;
24-
// Slurm
25-
slurm_user: string | null;
26-
// Slurm SSH
27-
ssh_host: string | null;
28-
ssh_username: string | null;
29-
ssh_private_key_path: string | null;
30-
ssh_tasks_dir: string | null;
31-
ssh_jobs_dir: string | null;
3224
};
3325

3426
export type ProfileInfo = {

src/lib/components/v2/admin/ProfileEditor.svelte

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,17 @@
117117
class:is-invalid={profileFormSubmitted && $profileValidationErrors['username']}
118118
required
119119
/>
120+
{#if resource.type === 'slurm_sudo'}
121+
<div class="form-text">
122+
The user on the local SLURM cluster who will be impersonated by Fractal through
123+
<code>sudo -u</code>
124+
</div>
125+
{:else}
126+
<div class="form-text">
127+
The user on the remote SLURM cluster who will be impersonated by Fractal through
128+
<code>ssh</code>
129+
</div>
130+
{/if}
120131
<span class="invalid-feedback">{$profileValidationErrors['username']}</span>
121132
</div>
122133
</div>
@@ -136,6 +147,9 @@
136147
class:is-invalid={profileFormSubmitted && $profileValidationErrors['ssh_key_path']}
137148
required
138149
/>
150+
<div class="form-text">
151+
Path of private SSH key for <code>username</code>
152+
</div>
139153
<span class="invalid-feedback">{$profileValidationErrors['ssh_key_path']}</span>
140154
</div>
141155
</div>

src/lib/components/v2/admin/UserSettingsEditor.svelte

Lines changed: 2 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,7 @@
4646
4747
const settingsFormErrorHandler = new FormErrorHandler('genericSettingsError', [
4848
'slurm_accounts',
49-
'project_dir',
50-
'slurm_user',
51-
'ssh_host',
52-
'ssh_username',
53-
'ssh_private_key_path'
49+
'project_dir'
5450
]);
5551
const settingsValidationErrors = settingsFormErrorHandler.getValidationErrorStore();
5652
@@ -74,7 +70,7 @@
7470
method: 'PATCH',
7571
credentials: 'include',
7672
headers,
77-
body: normalizePayload({ ...editableSettings, id: undefined }, { stripEmptyElements: true })
73+
body: normalizePayload({ ...editableSettings, id: undefined }, { nullifyEmptyStrings: true })
7874
});
7975
if (!response.ok) {
8076
await settingsFormErrorHandler.handleErrorResponse(response);
@@ -107,83 +103,6 @@
107103
<span class="invalid-feedback">{$settingsValidationErrors['project_dir']}</span>
108104
</div>
109105
</div>
110-
{#if runnerBackend === 'slurm_sudo'}
111-
<div class="row mb-3 has-validation">
112-
<label for="slurmUser" class="col-sm-3 col-form-label text-end">
113-
<strong>SLURM user</strong>
114-
</label>
115-
<div class="col-sm-9">
116-
<input
117-
type="text"
118-
class="form-control"
119-
id="slurmUser"
120-
bind:value={editableSettings.slurm_user}
121-
class:is-invalid={settingsFormSubmitted && $settingsValidationErrors['slurm_user']}
122-
/>
123-
<div class="form-text">
124-
The user on the local SLURM cluster who will be impersonated by Fractal through
125-
<code>sudo -u</code>
126-
</div>
127-
<span class="invalid-feedback">{$settingsValidationErrors['slurm_user']}</span>
128-
</div>
129-
</div>
130-
{:else if runnerBackend === 'slurm_ssh'}
131-
<div class="row mb-3 has-validation">
132-
<label for="sshHost" class="col-sm-3 col-form-label text-end">
133-
<strong>SSH host</strong>
134-
</label>
135-
<div class="col-sm-9">
136-
<input
137-
type="text"
138-
class="form-control"
139-
id="sshHost"
140-
bind:value={editableSettings.ssh_host}
141-
class:is-invalid={settingsFormSubmitted && $settingsValidationErrors['ssh_host']}
142-
/>
143-
<div class="form-text">SSH-reachable host where a SLURM client is available</div>
144-
<span class="invalid-feedback">{$settingsValidationErrors['ssh_host']}</span>
145-
</div>
146-
</div>
147-
<div class="row mb-3 has-validation">
148-
<label for="sshUsername" class="col-sm-3 col-form-label text-end">
149-
<strong>SSH username</strong>
150-
</label>
151-
<div class="col-sm-9">
152-
<input
153-
type="text"
154-
class="form-control"
155-
id="sshUsername"
156-
bind:value={editableSettings.ssh_username}
157-
class:is-invalid={settingsFormSubmitted && $settingsValidationErrors['ssh_username']}
158-
/>
159-
<div class="form-text">
160-
The user on the remote SLURM cluster who will be impersonated by Fractal through
161-
<code>ssh</code>
162-
</div>
163-
<span class="invalid-feedback">{$settingsValidationErrors['ssh_username']}</span>
164-
</div>
165-
</div>
166-
<div class="row mb-3 has-validation">
167-
<label for="sshPrivateKeyPath" class="col-sm-3 col-form-label text-end">
168-
<strong>SSH Private Key Path</strong>
169-
</label>
170-
<div class="col-sm-9">
171-
<input
172-
type="text"
173-
class="form-control"
174-
id="sshPrivateKeyPath"
175-
bind:value={editableSettings.ssh_private_key_path}
176-
class:is-invalid={settingsFormSubmitted &&
177-
$settingsValidationErrors['ssh_private_key_path']}
178-
/>
179-
<div class="form-text">
180-
Path of private SSH key for <code>ssh_username</code>
181-
</div>
182-
<span class="invalid-feedback">{$settingsValidationErrors['ssh_private_key_path']}</span
183-
>
184-
</div>
185-
</div>
186-
{/if}
187106
{#if runnerBackend !== 'local'}
188107
<div class="row mb-3 has-validation">
189108
<label for="slurmAccount-0" class="col-sm-3 col-form-label text-end">

src/routes/v2/admin/groups/[groupId]/edit/+page.svelte

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -181,13 +181,7 @@
181181
function createEmptySettings() {
182182
return {
183183
slurm_accounts: [],
184-
project_dir: '',
185-
slurm_user: '',
186-
ssh_host: '',
187-
ssh_username: '',
188-
ssh_private_key_path: '',
189-
ssh_tasks_dir: '',
190-
ssh_jobs_dir: ''
184+
project_dir: ''
191185
};
192186
}
193187

0 commit comments

Comments
 (0)