Skip to content

Commit

Permalink
NAS-130470 / 24.10 / Adds back container functionality (#10410)
Browse files Browse the repository at this point in the history
* NAS-130470: Fixes `app.image.delete`

* NAS-130470: Added back `app.image.dockerhub_rate_limit`

* NAS-130470: Added back tests

* NAS-130470: Removed update dialog and references. Also fixes app.image.pull calls

* NAS-130470: Removes calls to update images

* NAS-130470: Remove docker images related comments

* NAS-130470: Changes role

* NAS-130470: Fix tag

* NAS-130470: Update app-containers-card.component.ts

* NAS-130470: Fix import order

* NAS-130470: Fix import order

* NAS-130470: Fix tests

* NAS-130470: Update apps.module.ts
  • Loading branch information
RehanY147 authored Aug 11, 2024
1 parent 9eea249 commit 6c4afbe
Show file tree
Hide file tree
Showing 117 changed files with 121 additions and 971 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface ApiCallAndSubscribeEventDirectory {
'user.query': { response: User };
'pool.query': { response: Pool };
'group.query': { response: Group };
'container.image.query': { response: ContainerImage };
'app.image.query': { response: ContainerImage };
}

export type ApiCallAndSubscribeMethod = keyof ApiCallAndSubscribeEventDirectory;
Expand Down
9 changes: 4 additions & 5 deletions src/app/interfaces/api/api-call-directory.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ import {
CloudSyncCredentialVerify, CloudSyncCredentialVerifyResult,
} from 'app/interfaces/cloudsync-credential.interface';
import { CloudSyncProvider, CloudSyncRestoreParams } from 'app/interfaces/cloudsync-provider.interface';
import { ContainerConfig, ContainerConfigUpdate } from 'app/interfaces/container-config.interface';
import { ContainerConfig } from 'app/interfaces/container-config.interface';
import {
ContainerImage, DeleteContainerImageParams,
} from 'app/interfaces/container-image.interface';
Expand Down Expand Up @@ -409,10 +409,9 @@ export interface ApiCallDirectory {

// Container
'container.config': { params: void; response: ContainerConfig };
'container.image.delete': { params: DeleteContainerImageParams; response: void };
'container.image.dockerhub_rate_limit': { params: void; response: DockerHubRateLimit };
'container.image.query': { params: QueryParams<ContainerImage>; response: ContainerImage[] };
'container.update': { params: [ContainerConfigUpdate]; response: ContainerConfig };
'app.image.delete': { params: DeleteContainerImageParams; response: boolean };
'app.image.dockerhub_rate_limit': { params: void; response: DockerHubRateLimit };
'app.image.query': { params: QueryParams<ContainerImage>; response: ContainerImage[] };

// Core
'core.download': { params: CoreDownloadQuery; response: CoreDownloadResponse };
Expand Down
5 changes: 2 additions & 3 deletions src/app/interfaces/api/api-event-directory.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { DockerStatusResponse } from 'app/enums/docker-config.interface';
import { FailoverStatus } from 'app/enums/failover-status.enum';
import { Alert } from 'app/interfaces/alert.interface';
import { App, ChartStatisticsUpdate } from 'app/interfaces/app.interface';
import { PullContainerImageResponse, PullContainerImageParams, ContainerImage } from 'app/interfaces/container-image.interface';
import { ContainerImage } from 'app/interfaces/container-image.interface';
import { DirectoryServicesState } from 'app/interfaces/directory-services-state.interface';
import { Disk } from 'app/interfaces/disk.interface';
import { FailoverDisabledReasonEvent } from 'app/interfaces/failover-disabled-reasons.interface';
Expand Down Expand Up @@ -33,11 +33,10 @@ export interface ApiEventDirectory {
'zfs.snapshot.query': { response: ZfsSnapshot };
'zfs.pool.scan': { response: PoolScan };
'user.query': { response: User };
'container.image.pull': { response: Job<PullContainerImageResponse, PullContainerImageParams> };
'disk.query': { response: Disk };
'pool.query': { response: Pool };
'group.query': { response: Group };
'container.image.query': { response: ContainerImage };
'app.image.query': { response: ContainerImage };
'reporting.realtime': { response: ReportingRealtimeUpdate };
'smart.test.progress': { response: SmartTestProgressUpdate };
'docker.state': { response: DockerStatusResponse };
Expand Down
2 changes: 1 addition & 1 deletion src/app/interfaces/api/api-job-directory.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export interface ApiJobDirectory {
'cloudsync.sync_onetime': { params: [task: CloudSyncTaskUpdate, params: { dry_run?: boolean }]; response: void };

// Container
'container.image.pull': { params: [PullContainerImageParams]; response: PullContainerImageResponse };
'app.image.pull': { params: [PullContainerImageParams]; response: PullContainerImageResponse };

// Config
'config.reset': { params: [ConfigResetParams]; response: void };
Expand Down
26 changes: 17 additions & 9 deletions src/app/interfaces/container-image.interface.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,39 @@
import { ApiTimestamp } from 'app/interfaces/api-date.interface';

export interface PullContainerImageParams {
authentication?: {
auth_config?: {
username: string;
password: string;
};
from_image: string;
tag?: string;
image: string;
}

export type DeleteContainerImageParams = [
id: string,
forceSetting?: { force: boolean },
];

export interface PullContainerImageResponse {
status: string;
}

export interface ParsedRepoTag {
image: string;
tag: string;
registry: string;
complete_tag: string;
}

export interface ContainerImage {
created: ApiTimestamp;
dangling: boolean;
id: string;
labels: Record<string, string>;
repo_digests: string[];
repo_tags: string[];
repo_digests: string[];
size: number;
system_image: boolean;
update_available: boolean;
dangling: boolean;
created: ApiTimestamp;
author: string;
comment: string;
parsed_repo_tags: ParsedRepoTag[];

state?: string;
}
8 changes: 4 additions & 4 deletions src/app/interfaces/dockerhub-rate-limit.interface.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export interface DockerHubRateLimit {
total_pull_limit: number;
total_time_limit_in_secs: number;
remaining_pull_limit: number;
remaining_time_limit_in_secs: number;
total_pull_limit?: number | null;
total_time_limit_in_secs?: number | null;
remaining_pull_limit?: number | null;
remaining_time_limit_in_secs?: number | null;
error?: string | null;
}
12 changes: 6 additions & 6 deletions src/app/pages/apps/apps-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { AppWizardComponent } from 'app/pages/apps/components/app-wizard/app-wiz
import { AppsScopeWrapperComponent } from 'app/pages/apps/components/apps-scope-wrapper.component';
import { AvailableAppsComponent } from 'app/pages/apps/components/available-apps/available-apps.component';
import { CategoryViewComponent } from 'app/pages/apps/components/available-apps/category-view/category-view.component';
import { DockerImagesListComponent } from 'app/pages/apps/components/docker-images/docker-images-list/docker-images-list.component';
import { InstalledAppsComponent } from 'app/pages/apps/components/installed-apps/installed-apps.component';
// import { PodShellComponent } from 'app/pages/apps/components/installed-apps/pod-shell/pod-shell.component';
import { appNameResolver } from 'app/pages/apps/resolvers/app-name.resolver';
Expand Down Expand Up @@ -67,12 +68,11 @@ const routes: Routes = [
},
],
},
// TODO: https://ixsystems.atlassian.net/browse/NAS-130379
// {
// path: 'manage-container-images',
// component: DockerImagesListComponent,
// data: { title: T('Manage Container Images') },
// },
{
path: 'manage-container-images',
component: DockerImagesListComponent,
data: { title: T('Manage Container Images') },
},
{
path: 'available',
component: AppRouterOutletComponent,
Expand Down
17 changes: 8 additions & 9 deletions src/app/pages/apps/apps.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ import {
import { AppWizardComponent } from 'app/pages/apps/components/app-wizard/app-wizard.component';
import { AppsScopeWrapperComponent } from 'app/pages/apps/components/apps-scope-wrapper.component';
import { CatalogSettingsComponent } from 'app/pages/apps/components/catalog-settings/catalog-settings.component';
import { DockerImageDeleteDialogComponent } from 'app/pages/apps/components/docker-images/docker-image-delete-dialog/docker-image-delete-dialog.component';
import { DockerImagesListComponent } from 'app/pages/apps/components/docker-images/docker-images-list/docker-images-list.component';
import { PullImageFormComponent } from 'app/pages/apps/components/docker-images/pull-image-form/pull-image-form.component';
import { DockerHubRateInfoDialogComponent } from 'app/pages/apps/components/dockerhub-rate-limit-info-dialog/dockerhub-rate-limit-info-dialog.component';
import { AppBulkUpgradeComponent } from 'app/pages/apps/components/installed-apps/app-bulk-upgrade/app-bulk-upgrade.component';
import { AppInfoCardComponent } from 'app/pages/apps/components/installed-apps/app-info-card/app-info-card.component';
Expand All @@ -58,9 +61,7 @@ import { AppRowComponent } from 'app/pages/apps/components/installed-apps/app-ro
import { AppSettingsButtonComponent } from 'app/pages/apps/components/installed-apps/app-settings-button/app-settings-button.component';
import { AppUpdateCellComponent } from 'app/pages/apps/components/installed-apps/app-update-cell/app-update-cell.component';
import { AppWorkloadsCardComponent } from 'app/pages/apps/components/installed-apps/app-workloads-card/app-workloads-card.component';
import {
VolumeMountsDialogComponent,
} from 'app/pages/apps/components/installed-apps/app-workloads-card/volume-mounts-dialog/volume-mounts-dialog.component';
import { VolumeMountsDialogComponent } from 'app/pages/apps/components/installed-apps/app-workloads-card/volume-mounts-dialog/volume-mounts-dialog.component';
import { PodSelectDialogComponent } from 'app/pages/apps/components/pod-select-dialog/pod-select-dialog.component';
import { SelectPoolDialogComponent } from 'app/pages/apps/components/select-pool-dialog/select-pool-dialog.component';
import { CustomFormsModule } from 'app/pages/apps/modules/custom-forms/custom-forms.module';
Expand Down Expand Up @@ -107,7 +108,6 @@ import { InstalledAppsComponent } from './components/installed-apps/installed-ap
AppDetailsHeaderComponent,
AppBulkUpgradeComponent,
AppRollbackModalComponent,
DockerHubRateInfoDialogComponent,
SelectPoolDialogComponent,
AppDetailsSimilarComponent,
AppSettingsButtonComponent,
Expand All @@ -117,11 +117,10 @@ import { InstalledAppsComponent } from './components/installed-apps/installed-ap
CustomAppButtonComponent,
DockerStatusComponent,
CatalogSettingsComponent,
// TODO: https://ixsystems.atlassian.net/browse/NAS-130379
// DockerImagesListComponent,
// DockerImageUpdateDialogComponent,
// DockerImageDeleteDialogComponent,
// PullImageFormComponent,
DockerImagesListComponent,
DockerImageDeleteDialogComponent,
PullImageFormComponent,
DockerHubRateInfoDialogComponent,
VolumeMountsDialogComponent,
],
imports: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,14 +289,13 @@ describe('AppWizardComponent', () => {
mockJob('app.update'),
mockCall('catalog.get_app_details', existingCatalogApp),
mockCall('app.query', [existingAppEdit]),
// TODO: https://ixsystems.atlassian.net/browse/NAS-130379
// mockCall('container.image.dockerhub_rate_limit', {
// total_pull_limit: 13,
// total_time_limit_in_secs: 21600,
// remaining_pull_limit: 3,
// remaining_time_limit_in_secs: 21600,
// error: null,
// }),
mockCall('app.image.dockerhub_rate_limit', {
total_pull_limit: 13,
total_time_limit_in_secs: 21600,
remaining_pull_limit: 3,
remaining_time_limit_in_secs: 21600,
error: null,
}),
]),
mockProvider(DockerStore, {
selectedPool$: of('pool set'),
Expand Down Expand Up @@ -482,18 +481,16 @@ describe('AppWizardComponent', () => {
});
});

// TODO: https://ixsystems.atlassian.net/browse/NAS-130379
// Add a test that shows Docker Hub Rate Limit Info Dialog when remaining_pull_limit is less then 5
// it('shows Docker Hub Rate Limit Info Dialog when remaining_pull_limit is less then 5', () => {
// expect(spectator.inject(MatDialog).open).toHaveBeenCalledWith(DockerHubRateInfoDialogComponent, {
// data: {
// total_pull_limit: 13,
// total_time_limit_in_secs: 21600,
// remaining_pull_limit: 3,
// remaining_time_limit_in_secs: 21600,
// error: null,
// },
// });
// });
it('shows Docker Hub Rate Limit Info Dialog when remaining_pull_limit is less then 5', () => {
expect(spectator.inject(MatDialog).open).toHaveBeenCalledWith(DockerHubRateInfoDialogComponent, {
data: {
total_pull_limit: 13,
total_time_limit_in_secs: 21600,
remaining_pull_limit: 3,
remaining_time_limit_in_secs: 21600,
error: null,
},
});
});
});
});
25 changes: 13 additions & 12 deletions src/app/pages/apps/components/app-wizard/app-wizard.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
OnInit,
} from '@angular/core';
import { FormBuilder, FormControl, Validators } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Router } from '@angular/router';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { TranslateService } from '@ngx-translate/core';
Expand Down Expand Up @@ -45,6 +46,7 @@ import { CustomUntypedFormField } from 'app/modules/forms/ix-dynamic-form/compon
import { IxValidatorsService } from 'app/modules/forms/ix-forms/services/ix-validators.service';
import { forbiddenAsyncValues, forbiddenValuesError } from 'app/modules/forms/ix-forms/validators/forbidden-values-validation/forbidden-values-validation';
import { AppLoaderService } from 'app/modules/loader/app-loader.service';
import { DockerHubRateInfoDialogComponent } from 'app/pages/apps/components/dockerhub-rate-limit-info-dialog/dockerhub-rate-limit-info-dialog.component';
import { ApplicationsService } from 'app/pages/apps/services/applications.service';
import { DockerStore } from 'app/pages/apps/store/docker.store';
import { AuthService } from 'app/services/auth/auth.service';
Expand Down Expand Up @@ -123,11 +125,11 @@ export class AppWizardComponent implements OnInit, OnDestroy {
private dockerStore: DockerStore,
private ws: WebSocketService,
private authService: AuthService,
private matDialog: MatDialog,
) {}

ngOnInit(): void {
// TODO: https://ixsystems.atlassian.net/browse/NAS-130379
// this.getDockerHubRateLimitInfo();
this.getDockerHubRateLimitInfo();
this.listenForRouteChanges();
this.handleSearchControl();
}
Expand Down Expand Up @@ -525,14 +527,13 @@ export class AppWizardComponent implements OnInit, OnDestroy {
});
}

// TODO: https://ixsystems.atlassian.net/browse/NAS-130379
// private getDockerHubRateLimitInfo(): void {
// this.ws.call('container.image.dockerhub_rate_limit').pipe(untilDestroyed(this)).subscribe((info) => {
// if (info.remaining_pull_limit < 5) {
// this.matDialog.open(DockerHubRateInfoDialogComponent, {
// data: info,
// });
// }
// });
// }
private getDockerHubRateLimitInfo(): void {
this.ws.call('app.image.dockerhub_rate_limit').pipe(untilDestroyed(this)).subscribe((info) => {
if (info.remaining_pull_limit < 5) {
this.matDialog.open(DockerHubRateInfoDialogComponent, {
data: info,
});
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ <h1 matDialogTitle>{{ 'Delete' | translate }}</h1>
[label]="'Confirm' | translate"
[required]="true"
></ix-checkbox>
<ix-checkbox
formControlName="force"
[label]="'Force' | translate"
[tooltip]="forceCheckboxTooltip | translate"
></ix-checkbox>
}
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ describe('DockerImageDeleteDialogComponent', () => {
}),
mockWebSocket([
mockJob('core.bulk'),
mockCall('container.image.delete'),
mockCall('app.image.delete'),
]),
],
});
Expand All @@ -77,10 +77,10 @@ describe('DockerImageDeleteDialogComponent', () => {

it('deletes selected docker images when form is submitted', async () => {
const jobArguments = [
'container.image.delete',
'app.image.delete',
[
['sha256:test1'],
['sha256:test2'],
['sha256:test1', { force: false }],
['sha256:test2', { force: false }],
],
];
spectator.inject(MockWebSocketService).mockJob('core.bulk', fakeSuccessfulJob(mockSuccessBulkResponse, jobArguments));
Expand All @@ -104,17 +104,18 @@ describe('DockerImageDeleteDialogComponent', () => {

it('checks force delete of docker images when form is submitted', async () => {
const jobArguments = [
'container.image.delete',
'app.image.delete',
[
['sha256:test1'],
['sha256:test2'],
['sha256:test1', { force: true }],
['sha256:test2', { force: true }],
],
];
spectator.inject(MockWebSocketService).mockJob('core.bulk', fakeSuccessfulJob(mockSuccessBulkResponse, jobArguments));

const form = await loader.getHarness(IxFormHarness);
await form.fillForm({
Confirm: true,
Force: true,
});

const deleteButton = await loader.getHarness(MatButtonHarness.with({ text: 'Delete' }));
Expand All @@ -129,10 +130,10 @@ describe('DockerImageDeleteDialogComponent', () => {

it('checks deleting failures of docker images when form is submitted', async () => {
const jobArguments: CoreBulkQuery = [
'container.image.delete',
'app.image.delete',
[
['sha256:test1'],
['sha256:test2'],
['sha256:test1', { force: false }],
['sha256:test2', { force: false }],
],
];
spectator.inject(MockWebSocketService).mockJob('core.bulk', fakeSuccessfulJob(mockFailedBulkResponse, jobArguments));
Expand Down
Loading

0 comments on commit 6c4afbe

Please sign in to comment.