Skip to content

Commit

Permalink
NAS-132675: Remove nvidia state and event handlers (#11131)
Browse files Browse the repository at this point in the history
(cherry picked from commit 8936d21)

Co-authored-by: undsoft <[email protected]>
  • Loading branch information
bugclerk and undsoft authored Dec 3, 2024
1 parent 1478fb8 commit 8df9c74
Show file tree
Hide file tree
Showing 95 changed files with 54 additions and 550 deletions.
21 changes: 0 additions & 21 deletions src/app/enums/docker-nvidia-status.enum.ts

This file was deleted.

3 changes: 1 addition & 2 deletions src/app/interfaces/api/api-call-directory.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { CloudsyncTransferSetting } from 'app/enums/cloudsync-transfer-setting.e
import { DatasetRecordSize, DatasetType } from 'app/enums/dataset.enum';
import { DeviceType } from 'app/enums/device-type.enum';
import { DockerConfig, DockerStatusData } from 'app/enums/docker-config.interface';
import { DockerNvidiaStatusResponse } from 'app/enums/docker-nvidia-status.enum';
import { EnclosureSlotStatus } from 'app/enums/enclosure-slot-status.enum';
import { FailoverDisabledReason } from 'app/enums/failover-disabled-reason.enum';
import { FailoverStatus } from 'app/enums/failover-status.enum';
Expand Down Expand Up @@ -608,7 +607,7 @@ export interface ApiCallDirectory {
// Docker
'docker.config': { params: void; response: DockerConfig };
'docker.status': { params: void; response: DockerStatusData };
'docker.nvidia_status': { params: void; response: DockerNvidiaStatusResponse };
'docker.nvidia_present': { params: void; response: boolean };

// LDAP
'ldap.config': { params: void; response: LdapConfig };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,11 @@
}
</ix-list>

@if (showNvidiaCheckbox()) {
@if (hasNvidiaCard$ | async) {
<ix-checkbox
formControlName="nvidia"
[label]="'Install NVIDIA Drivers' | translate"
[tooltip]="tooltips.install_nvidia_driver| translate"
[hint]="'Current status: {status}' | translate: { status: dockerNvidiaStatus() | mapValue: dockerNvidiaStatusLabels }"
[tooltip]="tooltips.install_nvidia_driver | translate"
></ix-checkbox>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { fakeSuccessfulJob } from 'app/core/testing/utils/fake-job.utils';
import { mockAuth } from 'app/core/testing/utils/mock-auth.utils';
import { mockCall, mockJob, mockWebSocket } from 'app/core/testing/utils/mock-websocket.utils';
import { DockerConfig } from 'app/enums/docker-config.interface';
import { DockerNvidiaStatus } from 'app/enums/docker-nvidia-status.enum';
import { CatalogConfig } from 'app/interfaces/catalog.interface';
import { DialogService } from 'app/modules/dialog/dialog.service';
import { IxCheckboxListHarness } from 'app/modules/forms/ix-forms/components/ix-checkbox-list/ix-checkbox-list.harness';
Expand All @@ -26,6 +25,7 @@ import { WebSocketService } from 'app/services/ws.service';
describe('AppsSettingsComponent', () => {
let spectator: Spectator<AppsSettingsComponent>;
let loader: HarnessLoader;
let hasNvidiaCard = false;

const dockerConfig = {
address_pools: [
Expand All @@ -44,6 +44,7 @@ describe('AppsSettingsComponent', () => {
providers: [
mockWebSocket([
mockCall('catalog.update'),
mockCall('docker.nvidia_present', () => hasNvidiaCard),
mockCall('catalog.trains', ['stable', 'community', 'test']),
mockCall('catalog.config', {
label: 'TrueNAS',
Expand All @@ -62,23 +63,17 @@ describe('AppsSettingsComponent', () => {
mockProvider(IxSlideInRef),
mockProvider(FormErrorHandlerService),
mockAuth(),
mockProvider(DockerStore, {
dockerConfig$: of(dockerConfig),
reloadDockerConfig: jest.fn(() => of({})),
}),
],
});

describe('system has no nvidia card', () => {
beforeEach(() => {
spectator = createComponent({
providers: [
mockProvider(DockerStore, {
nvidiaDriversInstalled$: of(false),
hasNvidiaCard$: of(false),
dockerConfig$: of(dockerConfig),
dockerNvidiaStatus$: of(DockerNvidiaStatus.NotInstalled),
reloadDockerConfig: jest.fn(() => of({})),
reloadDockerNvidiaStatus: jest.fn(() => of({})),
}),
],
});
hasNvidiaCard = false;
spectator = createComponent();
loader = TestbedHarnessEnvironment.loader(spectator.fixture);
});

Expand Down Expand Up @@ -118,97 +113,51 @@ describe('AppsSettingsComponent', () => {
});
});

describe('has docker no nvidia drivers', () => {
describe('hasNvidiaCard is true', () => {
beforeEach(() => {
spectator = createComponent({
providers: [
mockProvider(DockerStore, {
nvidiaDriversInstalled$: of(false),
hasNvidiaCard$: of(true),
dockerConfig$: of(dockerConfig),
dockerNvidiaStatus$: of(DockerNvidiaStatus.NotInstalled),
setDockerNvidia: jest.fn(() => of(null)),
reloadDockerConfig: jest.fn(() => of({})),
reloadDockerNvidiaStatus: jest.fn(() => of({})),
}),
],
});
loader = TestbedHarnessEnvironment.loader(spectator.fixture);
});

it('shows Install NVIDIA Drivers checkbox when hasNvidiaCard is true', async () => {
const form = await loader.getHarness(IxFormHarness);
const values = await form.getValues();

expect(values).toMatchObject({
'Install NVIDIA Drivers': false,
'Preferred Trains': ['test'],
});
});

it('saves catalog updates and nvidia settings', async () => {
const form = await loader.getHarness(IxFormHarness);
await form.fillForm({
'Preferred Trains': ['stable'],
'Install NVIDIA Drivers': true,
});

const saveButton = await loader.getHarness(MatButtonHarness.with({ text: 'Save' }));
await saveButton.click();
describe('has nvidia card', () => {
beforeEach(() => {
hasNvidiaCard = true;
spectator = createComponent();
loader = TestbedHarnessEnvironment.loader(spectator.fixture);
});

expect(spectator.inject(WebSocketService).call).toHaveBeenCalledWith('catalog.update', [
{ preferred_trains: ['stable'] },
]);
it('shows Install NVIDIA Drivers checkbox when nvidia card is present', async () => {
const form = await loader.getHarness(IxFormHarness);
const values = await form.getValues();

expect(spectator.inject(DockerStore).setDockerNvidia).toHaveBeenCalled();
expect(spectator.inject(AppsStore).loadCatalog).toHaveBeenCalled();
expect(values).toMatchObject({
'Install NVIDIA Drivers': false,
'Preferred Trains': ['test'],
});
});

describe('hasNvidiaCard is false and nvidiaDriversInstalled is true', () => {
beforeEach(() => {
spectator = createComponent({
providers: [
mockProvider(DockerStore, {
nvidiaDriversInstalled$: of(true),
hasNvidiaCard$: of(false),
dockerConfig$: of(dockerConfig),
dockerNvidiaStatus$: of(DockerNvidiaStatus.Installed),
reloadDockerConfig: jest.fn(() => of({})),
reloadDockerNvidiaStatus: jest.fn(() => of({})),
}),
],
});
loader = TestbedHarnessEnvironment.loader(spectator.fixture);
it('saves catalog updates and nvidia settings', async () => {
const form = await loader.getHarness(IxFormHarness);
await form.fillForm({
'Preferred Trains': ['stable'],
'Install NVIDIA Drivers': true,
});

it('shows Install NVIDIA Drivers checkbox when docker.nvidia_status is not Absent OR when it is checked (so the user can uncheck it)', async () => {
const form = await loader.getHarness(IxFormHarness);
const values = await form.getValues();
const saveButton = await loader.getHarness(MatButtonHarness.with({ text: 'Save' }));
await saveButton.click();

expect(values).toMatchObject({
'Install NVIDIA Drivers': true,
'Preferred Trains': ['test'],
});
});
expect(spectator.inject(WebSocketService).job).toHaveBeenCalledWith('docker.update', [{
nvidia: true,
enable_image_updates: false,
address_pools: [
{
base: '172.17.0.0/12',
size: 12,
},
],
}]);

expect(spectator.inject(AppsStore).loadCatalog).toHaveBeenCalled();
});

describe('other docker settings', () => {
beforeEach(() => {
spectator = createComponent({
providers: [
mockProvider(DockerStore, {
nvidiaDriversInstalled$: of(true),
hasNvidiaCard$: of(true),
dockerConfig$: of(dockerConfig),
dockerNvidiaStatus$: of(DockerNvidiaStatus.Installed),
reloadDockerConfig: jest.fn(() => of({})),
reloadDockerNvidiaStatus: jest.fn(() => of({})),
setDockerNvidia: jest.fn(() => of(null)),
}),
],
});
hasNvidiaCard = false;
spectator = createComponent();
loader = TestbedHarnessEnvironment.loader(spectator.fixture);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import {
ChangeDetectionStrategy, Component, computed, OnInit, signal,
ChangeDetectionStrategy, Component, OnInit, signal,
} from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import {
FormArray, FormBuilder, FormControl, FormGroup, Validators,
} from '@angular/forms';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import {
combineLatest, filter, forkJoin, of, switchMap,
async,
combineLatest, filter, forkJoin, switchMap,
take,
} from 'rxjs';
import { dockerNvidiaStatusLabels } from 'app/enums/docker-nvidia-status.enum';
import { Role } from 'app/enums/role.enum';
import { singleArrayToOptions } from 'app/helpers/operators/options.operators';
import { helptextApps } from 'app/helptext/apps/apps';
Expand All @@ -30,12 +29,9 @@ import { WebSocketService } from 'app/services/ws.service';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppsSettingsComponent implements OnInit {
protected hasNvidiaCard = toSignal(this.dockerStore.hasNvidiaCard$);
protected nvidiaDriversInstalled = toSignal(this.dockerStore.nvidiaDriversInstalled$);
protected dockerNvidiaStatus = toSignal(this.dockerStore.dockerNvidiaStatus$);
protected hasNvidiaCard$ = this.ws.call('docker.nvidia_present');
protected isFormLoading = signal(false);
protected readonly requiredRoles = [Role.AppsWrite, Role.CatalogWrite];
protected readonly dockerNvidiaStatusLabels = dockerNvidiaStatusLabels;

protected form = this.fb.group({
preferred_trains: [[] as string[], Validators.required],
Expand All @@ -51,8 +47,6 @@ export class AppsSettingsComponent implements OnInit {
singleArrayToOptions(),
);

protected showNvidiaCheckbox = computed(() => this.hasNvidiaCard() || this.nvidiaDriversInstalled());

readonly tooltips = {
preferred_trains: helptextApps.catalogForm.preferredTrains.tooltip,
install_nvidia_driver: helptextApps.catalogForm.installNvidiaDriver.tooltip,
Expand Down Expand Up @@ -86,14 +80,9 @@ export class AppsSettingsComponent implements OnInit {
preferred_trains: catalogConfig.preferred_trains,
enable_image_updates: dockerConfig.enable_image_updates,
address_pools: dockerConfig.address_pools,
nvidia: dockerConfig.nvidia,
});
});

if (this.nvidiaDriversInstalled()) {
this.form.patchValue({
nvidia: this.nvidiaDriversInstalled(),
});
}
}

addAddressPool(): void {
Expand All @@ -118,13 +107,12 @@ export class AppsSettingsComponent implements OnInit {
this.ws.job('docker.update', [{
enable_image_updates: values.enable_image_updates,
address_pools: values.address_pools,
nvidia: values.nvidia,
}]),
])
.pipe(
switchMap(() => (values.nvidia !== null ? this.dockerStore.setDockerNvidia(values.nvidia) : of(values.nvidia))),
switchMap(() => forkJoin([
this.dockerStore.reloadDockerConfig(),
this.dockerStore.reloadDockerNvidiaStatus(),
this.appsStore.loadCatalog(),
])),
untilDestroyed(this),
Expand All @@ -142,4 +130,5 @@ export class AppsSettingsComponent implements OnInit {
}

protected readonly helptext = helptextApps;
protected readonly async = async;
}
22 changes: 1 addition & 21 deletions src/app/pages/apps/store/docker.store.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest';
import { MockWebSocketService } from 'app/core/testing/classes/mock-websocket.service';
import { mockCall, mockWebSocket } from 'app/core/testing/utils/mock-websocket.utils';
import { DockerConfig } from 'app/enums/docker-config.interface';
import { DockerNvidiaStatus } from 'app/enums/docker-nvidia-status.enum';
import { DockerStatus } from 'app/enums/docker-status.enum';
import { DockerStore } from 'app/pages/apps/store/docker.store';
import { WebSocketService } from 'app/services/ws.service';
Expand All @@ -18,7 +17,6 @@ describe('DockerStore', () => {
pool: 'pewl',
nvidia: true,
} as DockerConfig),
mockCall('docker.nvidia_status', { status: DockerNvidiaStatus.Installed }),
mockCall('docker.status', {
status: DockerStatus.Running,
description: 'Docker is running',
Expand All @@ -36,18 +34,15 @@ describe('DockerStore', () => {
spectator.service.initialize();

expect(spectator.inject(WebSocketService).call).toHaveBeenCalledWith('docker.config');
expect(spectator.inject(WebSocketService).call).toHaveBeenCalledWith('docker.nvidia_status');
expect(spectator.inject(WebSocketService).call).toHaveBeenCalledWith('docker.status');

expect(spectator.service.state()).toEqual({
dockerConfig: {
enable_image_updates: true,
nvidia: true,
pool: 'pewl',
nvidia: true,
},
isLoading: false,
nvidiaDriversInstalled: true,
nvidiaStatus: DockerNvidiaStatus.Installed,
statusData: {
description: 'Docker is running',
status: DockerStatus.Running,
Expand All @@ -68,24 +63,9 @@ describe('DockerStore', () => {
mockWebsocket.mockCall('docker.config', newDockerConfig);

spectator.service.reloadDockerConfig().subscribe();
spectator.service.reloadDockerNvidiaStatus().subscribe();

expect(mockWebsocket.call).toHaveBeenCalledWith('docker.config');
expect(spectator.service.state().dockerConfig).toEqual(newDockerConfig);
});
});

describe('reloadDockerNvidiaStatus', () => {
it('reloads docker nvidia status and updates the state', () => {
const mockWebsocket = spectator.inject(MockWebSocketService);
jest.resetAllMocks();
mockWebsocket.mockCall('docker.nvidia_status', { status: DockerNvidiaStatus.Installed });

spectator.service.reloadDockerConfig().subscribe();
spectator.service.reloadDockerNvidiaStatus().subscribe();

expect(mockWebsocket.call).toHaveBeenCalledWith('docker.nvidia_status');
expect(spectator.service.state().nvidiaStatus).toEqual(DockerNvidiaStatus.Installed);
});
});
});
Loading

0 comments on commit 8df9c74

Please sign in to comment.