mirror of
https://github.com/goharbor/harbor.git
synced 2024-08-21 03:22:50 +02:00
Merge pull request #7265 from pureshine/move-scan/gc
Move GC and Vulnerability to Tasks
This commit is contained in:
commit
f73f926449
|
@ -0,0 +1,20 @@
|
|||
<h5 class="history-header" id="history-header">{{'GC.JOB_HISTORY' | translate}}</h5>
|
||||
<clr-datagrid>
|
||||
<clr-dg-column>{{'GC.JOB_ID' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'GC.TRIGGER_TYPE' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'STATUS' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'START_TIME' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'UPDATE_TIME' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'LOGS' | translate}}</clr-dg-column>
|
||||
<clr-dg-row *ngFor="let job of jobs" [clrDgItem]='job'>
|
||||
<clr-dg-cell>{{job.id }}</clr-dg-cell>
|
||||
<clr-dg-cell>{{(job.type ? 'SCHEDULE.'+ job.type.toUpperCase() : '') | translate }}</clr-dg-cell>
|
||||
<clr-dg-cell>{{job.status.toUpperCase() | translate}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{job.createTime | date:'medium'}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{job.updateTime | date:'medium'}}</clr-dg-cell>
|
||||
<clr-dg-cell>
|
||||
<a *ngIf="job.status.toLowerCase() === 'finished' || job.status.toLowerCase() === 'error'" target="_blank" href="/api/system/gc/{{job.id}}/log"><clr-icon shape="list"></clr-icon></a>
|
||||
</clr-dg-cell>
|
||||
</clr-dg-row>
|
||||
<clr-dg-footer>{{'GC.LATEST_JOBS' | translate :{param: jobs.length} }}</clr-dg-footer>
|
||||
</clr-datagrid>
|
|
@ -0,0 +1,4 @@
|
|||
.history-header {
|
||||
color: #000;
|
||||
margin:20px 0 6px 0;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { GcRepoService } from "../gc.service";
|
||||
import { GcJobViewModel } from "../gcLog";
|
||||
import { GcViewModelFactory } from "../gc.viewmodel.factory";
|
||||
|
||||
@Component({
|
||||
selector: 'gc-history',
|
||||
templateUrl: './gc-history.component.html',
|
||||
styleUrls: ['./gc-history.component.scss']
|
||||
})
|
||||
export class GcHistoryComponent implements OnInit {
|
||||
jobs: Array<GcJobViewModel> = [];
|
||||
constructor(
|
||||
private gcRepoService: GcRepoService,
|
||||
private gcViewModelFactory: GcViewModelFactory,
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.getJobs();
|
||||
}
|
||||
|
||||
getJobs() {
|
||||
this.gcRepoService.getJobs().subscribe(jobs => {
|
||||
this.jobs = this.gcViewModelFactory.createJobViewModel(jobs);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +1,4 @@
|
|||
<div class="cron-selection">
|
||||
<cron-selection [labelCurrent]="getLabelCurrent" [labelEdit]='getText' [originCron]='originCron' (inputvalue)="scheduleGc($event)"></cron-selection>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-sm gc-start-btn" (click)="gcNow()" [disabled]="disableGC">{{'GC.GC_NOW' | translate}}</button>
|
||||
<div class="job-header font-style">{{'GC.JOB_HISTORY' | translate}}</div>
|
||||
<clr-datagrid>
|
||||
<clr-dg-column>{{'GC.JOB_ID' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'GC.TRIGGER_TYPE' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'STATUS' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'START_TIME' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'UPDATE_TIME' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'LOGS' | translate}}</clr-dg-column>
|
||||
<clr-dg-row *ngFor="let job of jobs" [clrDgItem]='job'>
|
||||
<clr-dg-cell>{{job.id }}</clr-dg-cell>
|
||||
<clr-dg-cell>{{(job.type ? 'SCHEDULE.'+ job.type.toUpperCase() : '') | translate }}</clr-dg-cell>
|
||||
<clr-dg-cell>{{job.status.toUpperCase() | translate}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{job.createTime | date:'medium'}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{job.updateTime | date:'medium'}}</clr-dg-cell>
|
||||
<clr-dg-cell>
|
||||
<a *ngIf="job.status.toLowerCase() === 'finished' || job.status.toLowerCase() === 'error'" target="_blank" href="/api/system/gc/{{job.id}}/log"><clr-icon shape="list"></clr-icon></a>
|
||||
</clr-dg-cell>
|
||||
</clr-dg-row>
|
||||
<clr-dg-footer>{{'GC.LATEST_JOBS' | translate :{param: jobs.length} }}</clr-dg-footer>
|
||||
</clr-datagrid>
|
||||
<button class="btn btn-outline btn-sm gc-start-btn" (click)="gcNow()" [disabled]="disableGC">{{'GC.GC_NOW' | translate}}</button>
|
||||
</div>
|
|
@ -1,45 +1,10 @@
|
|||
.flex-layout {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin:20px 0;
|
||||
font-size: .541667rem;
|
||||
}
|
||||
|
||||
.font-style {
|
||||
color: #000;
|
||||
font-size: .541667rem;
|
||||
}
|
||||
|
||||
.cron-selection {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.setting-wrapper {
|
||||
label {
|
||||
width: 228px;
|
||||
}
|
||||
*:not(:first-child), span {
|
||||
margin-right: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.normal-wrapper {
|
||||
> span:first-child {
|
||||
width: 228px;
|
||||
}
|
||||
> span:not(:first-child){
|
||||
margin-right: 18px;
|
||||
}
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.gc-start-btn {
|
||||
width:150px;
|
||||
}
|
||||
|
||||
.job-header {
|
||||
margin:20px 0 -10px 0;
|
||||
}
|
||||
|
||||
.day-selector-wrapper {
|
||||
display: flex;
|
||||
margin-top: 47px;
|
||||
}
|
|
@ -4,3 +4,5 @@ export * from "./gc.api.repository";
|
|||
export * from "./gc.service";
|
||||
export * from "./gc.viewmodel.factory";
|
||||
export * from "./gcLog";
|
||||
export * from "./gc-history/gc-history.component";
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import { SystemSettingsComponent } from './system/system-settings.component';
|
|||
import { VulnerabilityConfigComponent } from './vulnerability/vulnerability-config.component';
|
||||
import { RegistryConfigComponent } from './registry-config.component';
|
||||
import { GcComponent } from './gc/gc.component';
|
||||
|
||||
import { GcHistoryComponent } from './gc/gc-history/gc-history.component';
|
||||
|
||||
export * from './config';
|
||||
export * from './replication/replication-config.component';
|
||||
|
@ -16,6 +16,7 @@ export * from './gc/index';
|
|||
|
||||
export const CONFIGURATION_DIRECTIVES: Type<any>[] = [
|
||||
ReplicationConfigComponent,
|
||||
GcHistoryComponent,
|
||||
GcComponent,
|
||||
SystemSettingsComponent,
|
||||
VulnerabilityConfigComponent,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<button id="config-gc" clrTabLink>{{'CONFIG.GC' | translate}}</button>
|
||||
<clr-tab-content id="gc" *clrIfActive>
|
||||
<gc-config #gcConfig></gc-config>
|
||||
<gc-history></gc-history>
|
||||
</clr-tab-content>
|
||||
</clr-tab>
|
||||
</clr-tabs>
|
||||
|
|
|
@ -9,6 +9,7 @@ import { VulnerabilityConfigComponent } from './vulnerability/vulnerability-conf
|
|||
import { RegistryConfigComponent } from './registry-config.component';
|
||||
import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component';
|
||||
import { GcComponent } from './gc/gc.component';
|
||||
import { GcHistoryComponent } from './gc/gc-history/gc-history.component';
|
||||
import { CronScheduleComponent } from '../cron-schedule/cron-schedule.component';
|
||||
|
||||
import {
|
||||
|
@ -67,6 +68,7 @@ describe('RegistryConfigComponent (inline template)', () => {
|
|||
RegistryConfigComponent,
|
||||
ConfirmationDialogComponent,
|
||||
GcComponent,
|
||||
GcHistoryComponent,
|
||||
CronScheduleComponent
|
||||
],
|
||||
providers: [
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<form #systemConfigFrom="ngForm" class="compact">
|
||||
<section class="form-block">
|
||||
<label class="section-title" *ngIf="showSubTitle">{{ 'CONFIG.SCANNING.TITLE' | translate }}</label>
|
||||
<div class="form-group">
|
||||
<label>{{ 'CONFIG.SCANNING.DB_REFRESH_TIME' | translate }}</label>
|
||||
<div>
|
||||
<label class="update-time">{{ 'CONFIG.SCANNING.DB_REFRESH_TIME' | translate }}</label>
|
||||
<clr-tooltip *ngIf="!isClairDBFullyReady">
|
||||
<clr-icon shape="warning" class="is-warning" size="22"></clr-icon>
|
||||
<clr-tooltip-content [clrPosition]="'top-right'" [clrSize]="'md'" *clrIfOpen>
|
||||
|
@ -23,9 +23,11 @@
|
|||
</clr-dropdown>
|
||||
<span *ngIf="isClairDBFullyReady && !showScanningNamespaces">{{ updatedTimestamp | date:'MM/dd/y HH:mm:ss' }} AM</span>
|
||||
</div>
|
||||
<cron-selection [labelCurrent]="getLabelCurrent" [labelEdit]='getLabelCurrent' [originCron]='originCron' (inputvalue)="scanAll($event)"></cron-selection>
|
||||
<div class="btn-scan-right btn-scan">
|
||||
<button class="btn btn-primary btn-sm btn-scan" (click)="scanNow()" [disabled]="!scanAvailable">{{ 'CONFIG.SCANNING.SCAN_NOW' | translate }}</button><br>
|
||||
</div>
|
||||
<div class="button-group">
|
||||
<cron-selection [labelCurrent]="getLabelCurrent" [labelEdit]='getLabelCurrent' [originCron]='originCron' (inputvalue)="scanAll($event)"></cron-selection>
|
||||
<div class="btn-scan-right btn-scan">
|
||||
<button class="btn btn-outline btn-sm btn-scan" (click)="scanNow()" [disabled]="!scanAvailable">{{ 'CONFIG.SCANNING.SCAN_NOW' | translate }}</button><br>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
|
@ -31,12 +31,20 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.button-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.btn-scan-right {
|
||||
button{
|
||||
width: 160px;
|
||||
margin-bottom: 0px;
|
||||
margin-top: 41px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-scan-right button{
|
||||
width: 160px;
|
||||
margin-bottom: 0px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.btn-scan-right span{
|
||||
margin-top: 4px;
|
||||
}
|
||||
.update-time {
|
||||
color: #000;
|
||||
font-size: .541667rem;
|
||||
width: 200px;
|
||||
}
|
|
@ -1,21 +1,23 @@
|
|||
<div class="normal-wrapper flex-layout" *ngIf="!isEditMode">
|
||||
<span class="font-style">{{ labelCurrent | translate }}</span>
|
||||
<span>{{(originScheduleType ? 'SCHEDULE.'+ originScheduleType.toUpperCase(): "") | translate}}</span>
|
||||
<a [hidden]="originScheduleType!==SCHEDULE_TYPE.HOURLY" href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right">
|
||||
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
|
||||
<span class="tooltip-content">{{'CONFIG.TOOLTIP.HOURLY_CRON' | translate}}</span>
|
||||
</a>
|
||||
<a [hidden]="originScheduleType!==SCHEDULE_TYPE.WEEKLY" href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right">
|
||||
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
|
||||
<span class="tooltip-content">{{'CONFIG.TOOLTIP.WEEKLY_CRON' | translate}}</span>
|
||||
</a>
|
||||
<a [hidden]="originScheduleType!==SCHEDULE_TYPE.DAILY" href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right">
|
||||
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
|
||||
<span class="tooltip-content">{{'CONFIG.TOOLTIP.DAILY_CRON' | translate}}</span>
|
||||
</a>
|
||||
<span [hidden]="originScheduleType!==SCHEDULE_TYPE.CUSTOM">{{ "SCHEDULE.CRON" | translate }} :</span>
|
||||
<span [hidden]="originScheduleType!==SCHEDULE_TYPE.CUSTOM">{{ oriCron }}</span>
|
||||
<button class="btn btn-outline btn-sm" (click)="editSchedule()" id="editSchedule">
|
||||
<div>
|
||||
<span class="font-style">{{ labelCurrent | translate }}</span>
|
||||
<span>{{(originScheduleType ? 'SCHEDULE.'+ originScheduleType.toUpperCase(): "") | translate}}</span>
|
||||
<a [hidden]="originScheduleType!==SCHEDULE_TYPE.HOURLY" href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right">
|
||||
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
|
||||
<span class="tooltip-content">{{'CONFIG.TOOLTIP.HOURLY_CRON' | translate}}</span>
|
||||
</a>
|
||||
<a [hidden]="originScheduleType!==SCHEDULE_TYPE.WEEKLY" href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right">
|
||||
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
|
||||
<span class="tooltip-content">{{'CONFIG.TOOLTIP.WEEKLY_CRON' | translate}}</span>
|
||||
</a>
|
||||
<a [hidden]="originScheduleType!==SCHEDULE_TYPE.DAILY" href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right">
|
||||
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
|
||||
<span class="tooltip-content">{{'CONFIG.TOOLTIP.DAILY_CRON' | translate}}</span>
|
||||
</a>
|
||||
<span [hidden]="originScheduleType!==SCHEDULE_TYPE.CUSTOM">{{ "SCHEDULE.CRON" | translate }} :</span>
|
||||
<span [hidden]="originScheduleType!==SCHEDULE_TYPE.CUSTOM">{{ oriCron }}</span>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-sm" (click)="editSchedule()" id="editSchedule">
|
||||
{{ "BUTTON.EDIT" | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
@ -40,11 +42,13 @@
|
|||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-sm"
|
||||
<div class="confirm-button">
|
||||
<button class="btn btn-primary btn-sm"
|
||||
(click)="save()" id="config-save">
|
||||
{{ "BUTTON.SAVE" | translate }}
|
||||
</button>
|
||||
<button class="btn btn-primary btn-sm" (click)="isEditMode=false">
|
||||
{{ "BUTTON.CANCEL" | translate }}
|
||||
</button>
|
||||
</button>
|
||||
<button class="btn btn-primary btn-sm" (click)="isEditMode=false">
|
||||
{{ "BUTTON.CANCEL" | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
|
@ -1,13 +1,11 @@
|
|||
.flex-layout {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 20px 0;
|
||||
font-size: .541667rem;
|
||||
}
|
||||
}
|
||||
|
||||
.normal-wrapper {
|
||||
> span:first-child {
|
||||
width: 228px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
> span:not(:first-child) {
|
||||
|
@ -17,13 +15,17 @@
|
|||
margin-left: -10px;
|
||||
}
|
||||
button {
|
||||
margin-left: 10px;
|
||||
margin: 20px 20px 0 200px;
|
||||
}
|
||||
}
|
||||
|
||||
.setting-wrapper {
|
||||
> span:first-child {
|
||||
width: 228px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.confirm-button {
|
||||
margin: 20px 0px 0 200px;
|
||||
}
|
||||
|
||||
*:not(:first-child) {
|
||||
|
@ -39,7 +41,10 @@
|
|||
width: 195px;
|
||||
}
|
||||
}
|
||||
|
||||
.font-style {
|
||||
display: inline-block;
|
||||
color: #000;
|
||||
font-size: .541667rem;
|
||||
}
|
||||
width: 200px;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,9 @@ import { ProjectConfigComponent } from './project/project-config/project-config.
|
|||
import zh from '@angular/common/locales/zh-Hans';
|
||||
import es from '@angular/common/locales/es';
|
||||
import localeFr from '@angular/common/locales/fr';
|
||||
import { DevCenterComponent } from './dev-center/dev-center.component';
|
||||
import { VulnerabilityPageComponent } from './vulnerability-page/vulnerability-page.component';
|
||||
import { GcPageComponent } from './gc-page/gc-page.component';
|
||||
import { OidcOnboardModule } from './oidc-onboard/oidc-onboard.module';
|
||||
registerLocaleData(zh, 'zh-cn');
|
||||
registerLocaleData(es, 'es-es');
|
||||
|
@ -51,7 +54,9 @@ export function getCurrentLanguage(translateService: TranslateService) {
|
|||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
ProjectConfigComponent
|
||||
ProjectConfigComponent,
|
||||
VulnerabilityPageComponent,
|
||||
GcPageComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
|
|
|
@ -46,6 +46,19 @@
|
|||
</a>
|
||||
</clr-vertical-nav-group-children>
|
||||
</clr-vertical-nav-group>
|
||||
<clr-vertical-nav-group *ngIf="isSystemAdmin" routerLinkActive="active">
|
||||
<clr-icon shape="event" clrVerticalNavIcon></clr-icon>
|
||||
{{'SIDE_NAV.TASKS' | translate}}
|
||||
<a routerLink="#" hidden aria-hidden="true"></a>
|
||||
<clr-vertical-nav-group-children *clrIfExpanded="true">
|
||||
<a clrVerticalNavLink routerLink="/harbor/vulnerability" routerLinkActive="active">
|
||||
{{'SIDE_NAV.SYSTEM_MGMT.VULNERABILITY' | translate}}
|
||||
</a>
|
||||
<a clrVerticalNavLink routerLink="/harbor/gc" routerLinkActive="active">
|
||||
{{'SIDE_NAV.SYSTEM_MGMT.GARBAGE_COLLECTION' | translate}}
|
||||
</a>
|
||||
</clr-vertical-nav-group-children>
|
||||
</clr-vertical-nav-group>
|
||||
</div>
|
||||
<div class="vertical-nav-footer">
|
||||
<a clrVerticalNavLink target="_blank" routerLink="/devcenter">
|
||||
|
|
|
@ -32,22 +32,6 @@
|
|||
</clr-tab-content>
|
||||
</ng-template>
|
||||
</clr-tab>
|
||||
<clr-tab *ngIf="withClair">
|
||||
<button id="config-vulnerability" clrTabLink>{{'CONFIG.VULNERABILITY' | translate }}</button>
|
||||
<ng-template [(clrIfActive)]="vulnerabilityActive">
|
||||
<clr-tab-content id="vulnerability" *ngIf="withClair">
|
||||
<vulnerability-config></vulnerability-config>
|
||||
</clr-tab-content>
|
||||
</ng-template>
|
||||
</clr-tab>
|
||||
<clr-tab *ngIf="hasAdminRole">
|
||||
<button id="config-gc" clrTabLink>{{'CONFIG.GC' | translate }}</button>
|
||||
<ng-template [(clrIfActive)]="gcActive">
|
||||
<clr-tab-content id="gc" *ngIf="hasAdminRole">
|
||||
<gc-config></gc-config>
|
||||
</clr-tab-content>
|
||||
</ng-template>
|
||||
</clr-tab>
|
||||
</clr-tabs>
|
||||
</div>
|
||||
</div>
|
|
@ -14,8 +14,8 @@
|
|||
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
|
||||
import { Subscription } from "rxjs";
|
||||
import {
|
||||
Configuration, StringValueItem, SystemSettingsComponent, VulnerabilityConfigComponent,
|
||||
isEmpty, clone, getChanges, GcComponent, GcRepoService } from '@harbor/ui';
|
||||
Configuration, StringValueItem, SystemSettingsComponent,
|
||||
isEmpty, clone, getChanges, GcRepoService } from '@harbor/ui';
|
||||
|
||||
import { ConfirmationTargets, ConfirmationState } from '../shared/shared.const';
|
||||
import { SessionService } from '../shared/session.service';
|
||||
|
@ -34,8 +34,6 @@ const TabLinkContentMap = {
|
|||
'config-replication': 'replication',
|
||||
'config-email': 'email',
|
||||
'config-system': 'system_settings',
|
||||
'config-vulnerability': 'vulnerability',
|
||||
'config-gc': 'gc',
|
||||
'config-label': 'system_label',
|
||||
};
|
||||
|
||||
|
@ -52,8 +50,6 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||
confirmSub: Subscription;
|
||||
|
||||
@ViewChild(SystemSettingsComponent) systemSettingsConfig: SystemSettingsComponent;
|
||||
@ViewChild(VulnerabilityConfigComponent) vulnerabilityConfig: VulnerabilityConfigComponent;
|
||||
@ViewChild(GcComponent) gcConfig: GcComponent;
|
||||
@ViewChild(ConfigurationEmailComponent) mailConfig: ConfigurationEmailComponent;
|
||||
@ViewChild(ConfigurationAuthComponent) authConfig: ConfigurationAuthComponent;
|
||||
|
||||
|
@ -73,10 +69,6 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||
return this.appConfigService.getConfig().has_ca_root;
|
||||
}
|
||||
|
||||
public get withClair(): boolean {
|
||||
return this.appConfigService.getConfig().with_clair;
|
||||
}
|
||||
|
||||
public get withAdmiral(): boolean {
|
||||
return this.appConfigService.getConfig().with_admiral;
|
||||
}
|
||||
|
|
23
src/portal/src/app/gc-page/gc-page.component.html
Normal file
23
src/portal/src/app/gc-page/gc-page.component.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||
<h2 class="custom-h2 gc-title">{{'CONFIG.GC' | translate }}</h2>
|
||||
<clr-tabs>
|
||||
<clr-tab *ngIf="hasAdminRole">
|
||||
<button id="config-gc" clrTabLink>{{'CONFIG.GC' | translate }}</button>
|
||||
<ng-template [(clrIfActive)]="gcActive">
|
||||
<clr-tab-content id="gc" *ngIf="hasAdminRole">
|
||||
<gc-config></gc-config>
|
||||
</clr-tab-content>
|
||||
</ng-template>
|
||||
</clr-tab>
|
||||
<clr-tab *ngIf="hasAdminRole">
|
||||
<button id="gc-log" clrTabLink>{{'CONFIG.HISTORY' | translate }}</button>
|
||||
<ng-template [(clrIfActive)]="historyActive">
|
||||
<clr-tab-content id="history" *ngIf="hasAdminRole">
|
||||
<gc-history></gc-history>
|
||||
</clr-tab-content>
|
||||
</ng-template>
|
||||
</clr-tab>
|
||||
</clr-tabs>
|
||||
</div>
|
||||
</div>
|
3
src/portal/src/app/gc-page/gc-page.component.scss
Normal file
3
src/portal/src/app/gc-page/gc-page.component.scss
Normal file
|
@ -0,0 +1,3 @@
|
|||
.gc-title {
|
||||
display: inline-block;
|
||||
}
|
25
src/portal/src/app/gc-page/gc-page.component.spec.ts
Normal file
25
src/portal/src/app/gc-page/gc-page.component.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { GcPageComponent } from './gc-page.component';
|
||||
|
||||
describe('GcPageComponent', () => {
|
||||
let component: GcPageComponent;
|
||||
let fixture: ComponentFixture<GcPageComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ GcPageComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(GcPageComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
19
src/portal/src/app/gc-page/gc-page.component.ts
Normal file
19
src/portal/src/app/gc-page/gc-page.component.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { Component, OnInit } from "@angular/core";
|
||||
import { SessionService } from "../shared/session.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-gc-page",
|
||||
templateUrl: "./gc-page.component.html",
|
||||
styleUrls: ["./gc-page.component.scss"]
|
||||
})
|
||||
export class GcPageComponent implements OnInit {
|
||||
constructor(private session: SessionService) {}
|
||||
|
||||
ngOnInit() {}
|
||||
public get hasAdminRole(): boolean {
|
||||
return (
|
||||
this.session.getCurrentUser() &&
|
||||
this.session.getCurrentUser().has_admin_role
|
||||
);
|
||||
}
|
||||
}
|
|
@ -24,6 +24,8 @@ import { PageNotFoundComponent } from './shared/not-found/not-found.component';
|
|||
import { HarborShellComponent } from './base/harbor-shell/harbor-shell.component';
|
||||
import { ConfigurationComponent } from './config/config.component';
|
||||
import { DevCenterComponent } from './dev-center/dev-center.component';
|
||||
import { GcPageComponent } from './gc-page/gc-page.component';
|
||||
import { VulnerabilityPageComponent } from './vulnerability-page/vulnerability-page.component';
|
||||
|
||||
import { UserComponent } from './user/user.component';
|
||||
import { SignInComponent } from './account/sign-in/sign-in.component';
|
||||
|
@ -198,6 +200,16 @@ const harborRoutes: Routes = [
|
|||
component: ConfigurationComponent,
|
||||
canActivate: [SystemAdminGuard]
|
||||
},
|
||||
{
|
||||
path: 'vulnerability',
|
||||
component: VulnerabilityPageComponent,
|
||||
canActivate: [SystemAdminGuard]
|
||||
},
|
||||
{
|
||||
path: 'gc',
|
||||
component: GcPageComponent,
|
||||
canActivate: [SystemAdminGuard]
|
||||
},
|
||||
{
|
||||
path: 'registry',
|
||||
component: DestinationPageComponent,
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||
<h2 class="custom-h2 vul-title">{{'VULNERABILITY.SINGULAR' | translate }}</h2>
|
||||
<clr-tabs>
|
||||
<clr-tab *ngIf="withClair">
|
||||
<button id="config-vulnerability" clrTabLink>{{'CONFIG.VULNERABILITY' | translate }}</button>
|
||||
<ng-template [(clrIfActive)]="vulnerabilityActive">
|
||||
<clr-tab-content id="vulnerability" *ngIf="withClair">
|
||||
<vulnerability-config></vulnerability-config>
|
||||
</clr-tab-content>
|
||||
</ng-template>
|
||||
</clr-tab>
|
||||
</clr-tabs>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,3 @@
|
|||
.vul-title {
|
||||
display: inline-block;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { VulnerabilityPageComponent } from './vulnerability-page.component';
|
||||
|
||||
describe('VulnerabilityPageComponent', () => {
|
||||
let component: VulnerabilityPageComponent;
|
||||
let fixture: ComponentFixture<VulnerabilityPageComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ VulnerabilityPageComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(VulnerabilityPageComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,17 @@
|
|||
import { Component, OnInit } from "@angular/core";
|
||||
import { AppConfigService } from "../app-config.service";
|
||||
|
||||
@Component({
|
||||
selector: "vulnerability-page",
|
||||
templateUrl: "./vulnerability-page.component.html",
|
||||
styleUrls: ["./vulnerability-page.component.scss"]
|
||||
})
|
||||
export class VulnerabilityPageComponent implements OnInit {
|
||||
constructor(private appConfigService: AppConfigService) {}
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
public get withClair(): boolean {
|
||||
return this.appConfigService.getConfig().with_clair;
|
||||
}
|
||||
}
|
|
@ -130,9 +130,12 @@
|
|||
"GROUP": "Groups",
|
||||
"REGISTRY": "Registries",
|
||||
"REPLICATION": "Replications",
|
||||
"CONFIG": "Configuration"
|
||||
"CONFIG": "Configuration",
|
||||
"VULNERABILITY": "Vulnerability",
|
||||
"GARBAGE_COLLECTION": "Garbage Collection"
|
||||
},
|
||||
"LOGS": "Logs",
|
||||
"TASKS": "Tasks",
|
||||
"API_EXPLORER": "API EXPLORER"
|
||||
},
|
||||
"USER": {
|
||||
|
@ -596,6 +599,7 @@
|
|||
"SUB_TITLE_SUFIX": "logs"
|
||||
},
|
||||
"CONFIG": {
|
||||
"HISTORY": "History",
|
||||
"TITLE": "Configuration",
|
||||
"AUTH": "Authentication",
|
||||
"REPLICATION": "Replication",
|
||||
|
@ -917,7 +921,7 @@
|
|||
"GC": {
|
||||
"CURRENT_SCHEDULE": "Current Schedule",
|
||||
"GC_NOW": "GC NOW",
|
||||
"JOB_HISTORY": "GC Jobs History",
|
||||
"JOB_HISTORY": "GC History",
|
||||
"JOB_ID": "Job ID",
|
||||
"TRIGGER_TYPE": "Trigger Type",
|
||||
"LATEST_JOBS": "Latest {{param}} Jobs",
|
||||
|
|
|
@ -130,9 +130,12 @@
|
|||
"REGISTRY": "Registries",
|
||||
"GROUP": "Groups",
|
||||
"REPLICATION": "Replicacións",
|
||||
"CONFIG": "Configuración"
|
||||
"CONFIG": "Configuración",
|
||||
"VULNERABILITY": "Vulnerability",
|
||||
"GARBAGE_COLLECTION": "Garbage Collection"
|
||||
},
|
||||
"LOGS": "Logs",
|
||||
"TASKS": "Tasks",
|
||||
"API_EXPLORER": "API EXPLORER"
|
||||
},
|
||||
"USER": {
|
||||
|
@ -915,7 +918,7 @@
|
|||
"GC": {
|
||||
"CURRENT_SCHEDULE": "Current Schedule",
|
||||
"GC_NOW": "GC NOW",
|
||||
"JOB_HISTORY": "GC Jobs History",
|
||||
"JOB_HISTORY": "GC History",
|
||||
"JOB_ID": "Job ID",
|
||||
"TRIGGER_TYPE": "Trigger Type",
|
||||
"LATEST_JOBS": "Latest {{param}} Jobs",
|
||||
|
|
|
@ -116,9 +116,12 @@
|
|||
"USER": "Utilisateurs",
|
||||
"GROUP": "Groups",
|
||||
"REPLICATION": "Réplication",
|
||||
"CONFIG": "Configuration"
|
||||
"CONFIG": "Configuration",
|
||||
"VULNERABILITY": "Vulnerability",
|
||||
"GARBAGE_COLLECTION": "Garbage Collection"
|
||||
},
|
||||
"LOGS": "Logs",
|
||||
"TASKS": "Tasks",
|
||||
"API_EXPLORER": "API EXPLORER"
|
||||
},
|
||||
"USER": {
|
||||
|
@ -878,7 +881,7 @@
|
|||
"GC": {
|
||||
"CURRENT_SCHEDULE": "Current Schedule",
|
||||
"GC_NOW": "GC NOW",
|
||||
"JOB_HISTORY": "GC Jobs History",
|
||||
"JOB_HISTORY": "GC History",
|
||||
"JOB_ID": "Job ID",
|
||||
"TRIGGER_TYPE": "Trigger Type",
|
||||
"LATEST_JOBS": "Latest {{param}} Jobs",
|
||||
|
|
|
@ -128,9 +128,12 @@
|
|||
"GROUP": "Grupos",
|
||||
"REGISTRY": "Registros",
|
||||
"REPLICATION": "Replicações",
|
||||
"CONFIG": "Configuração"
|
||||
"CONFIG": "Configuração",
|
||||
"VULNERABILITY": "Vulnerability",
|
||||
"GARBAGE_COLLECTION": "Garbage Collection"
|
||||
},
|
||||
"LOGS": "Logs",
|
||||
"TASKS": "Tasks",
|
||||
"API_EXPLORER": "API EXPLORER"
|
||||
},
|
||||
"USER": {
|
||||
|
@ -909,6 +912,7 @@
|
|||
"ON": "em",
|
||||
"AT": "em",
|
||||
"GC_NOW": "GC AGORA",
|
||||
"JOB_HISTORY": "GC History",
|
||||
"JOB_LIST":"Lista de tarefas de Limpeza",
|
||||
"JOB_ID":"ID DA TAREFA",
|
||||
"TRIGGER_TYPE": "TIPO DE DISPARO",
|
||||
|
|
|
@ -129,9 +129,12 @@
|
|||
"GROUP": "组管理",
|
||||
"REGISTRY": "仓库管理",
|
||||
"REPLICATION": "复制管理",
|
||||
"CONFIG": "配置管理"
|
||||
"CONFIG": "配置管理",
|
||||
"VULNERABILITY": "漏洞",
|
||||
"GARBAGE_COLLECTION": "垃圾清理"
|
||||
},
|
||||
"LOGS": "日志",
|
||||
"TASKS": "任务",
|
||||
"API_EXPLORER": "API控制中心"
|
||||
},
|
||||
"USER": {
|
||||
|
|
|
@ -278,7 +278,7 @@ Delete A Label
|
|||
## Garbage Collection
|
||||
Switch To Garbage Collection
|
||||
Sleep 1
|
||||
Click Element xpath=${configuration_xpath}
|
||||
Retry Element Click xpath=${gc_config_page}
|
||||
Wait Until Page Contains Element ${garbage_collection_xpath}
|
||||
Click Element xpath=${garbage_collection_xpath}
|
||||
|
||||
|
@ -290,3 +290,8 @@ Click GC Now
|
|||
View GC Details
|
||||
Click Element xpath=${gc_log_details_xpath}
|
||||
Sleep 2
|
||||
|
||||
Switch To GC History
|
||||
Retry Element Click xpath=${gc_log_xpath}
|
||||
Retry Wait Until Page Contains Job
|
||||
|
||||
|
|
|
@ -27,5 +27,7 @@ ${vulnerbility_save_button_xpath} //*[@id='config-save']
|
|||
${configuration_xpath} //clr-vertical-nav-group-children/a[contains(.,'Configuration')]
|
||||
${system_config_xpath} //*[@id='config-system']
|
||||
${garbage_collection_xpath} //*[@id='config-gc']
|
||||
${gc_now_xpath} //*[@id='gc']/gc-config/button
|
||||
${gc_log_xpath} //*[@id='gc-log']
|
||||
${gc_config_page} //clr-vertical-nav-group-children/a[contains(.,'Garbage')]
|
||||
${gc_now_xpath} //*[@id='gc']/gc-config//button[contains(.,'GC')]
|
||||
${gc_log_details_xpath} //*[@id='clr-dg-row26']/clr-dg-cell[6]/a
|
|
@ -173,7 +173,7 @@ Verify System Setting
|
|||
Switch To System Settings
|
||||
Page Should Contain @{creation}[0]
|
||||
Token Must Be Match @{token}[0]
|
||||
Go To Vulnerability Config
|
||||
Switch To Vulnerability Page
|
||||
Page Should Contain None
|
||||
Close Browser
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@ Resource ../../resources/Util.robot
|
|||
|
||||
*** Variables ***
|
||||
${HARBOR_VERSION} v1.1.1
|
||||
|
||||
${scan_now_button} //vulnerability-page//button[contains(.,'NOW')]
|
||||
${vulnerability_page} //clr-vertical-nav-group-children/a[contains(.,'Vulnerability')]
|
||||
*** Keywords ***
|
||||
Disable Scan Schedule
|
||||
Retry Element Click //vulnerability-config//cron-selection//button[contains(.,'EDIT')]
|
||||
|
@ -12,13 +13,15 @@ Disable Scan Schedule
|
|||
Retry Element Click //vulnerability-config//cron-selection//select[@id='selectPolicy']//option[contains(.,'None')]
|
||||
Retry Element Click //cron-selection//button[contains(.,'SAVE')]
|
||||
|
||||
Go To Vulnerability Config
|
||||
Retry Element Click //config//button[contains(.,'Vulnerability')]
|
||||
|
||||
Trigger Scan Now
|
||||
Retry Element Click //config//button[contains(.,'NOW')]
|
||||
Retry Element Click xpath=${scan_now_button}
|
||||
Sleep 10
|
||||
|
||||
Switch To Vulnerability Page
|
||||
Retry Element Click xpath=${vulnerability_page}
|
||||
Retry Wait Element ${scan_now_button}
|
||||
|
||||
|
||||
Set Vulnerabilty Serverity
|
||||
#0 is high 1 is medium 2 is low 3 is negligible
|
||||
[Arguments] ${level}
|
||||
|
|
|
@ -34,8 +34,7 @@ Test Case - Vulnerability Data Not Ready
|
|||
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
|
||||
Go Into Project library has_image=${false}
|
||||
Vulnerability Not Ready Project Hint
|
||||
Switch To Configure
|
||||
Go To Vulnerability Config
|
||||
Switch To Vulnerability Page
|
||||
Vulnerability Not Ready Config Hint
|
||||
|
||||
Test Case - Garbage Collection
|
||||
|
@ -56,7 +55,8 @@ Test Case - Garbage Collection
|
|||
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
|
||||
Switch To Garbage Collection
|
||||
Sleep 1
|
||||
Wait Until Page Contains Finished
|
||||
Switch To GC History
|
||||
Retry Wait Until Page Contains Finished
|
||||
|
||||
${rc} ${output}= Run And Return Rc And Output curl -u ${HARBOR_ADMIN}:${HARBOR_PASSWORD} -i --insecure -H "Content-Type: application/json" -X GET "https://${ip}/api/system/gc/1/log"
|
||||
Log To Console ${output}
|
||||
|
@ -265,13 +265,11 @@ Test Case - Delete Label
|
|||
Test Case - Disable Scan Schedule
|
||||
Init Chrome Driver
|
||||
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
|
||||
Switch To Configure
|
||||
Go To Vulnerability Config
|
||||
Switch To Vulnerability Page
|
||||
Disable Scan Schedule
|
||||
Logout Harbor
|
||||
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
|
||||
Switch To Configure
|
||||
Go To Vulnerability Config
|
||||
Switch To Vulnerability Page
|
||||
Retry Wait Until Page Contains None
|
||||
Close Browser
|
||||
|
||||
|
@ -545,8 +543,7 @@ Test Case - Manual Scan All
|
|||
Init Chrome Driver
|
||||
Push Image ${ip} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} library redis
|
||||
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
|
||||
Switch To Configure
|
||||
Go To Vulnerability Config
|
||||
Switch To Vulnerability Page
|
||||
Trigger Scan Now
|
||||
Navigate To Projects
|
||||
Go Into Project library
|
||||
|
|
|
@ -35,8 +35,7 @@ Test Case - Vulnerability Data Not Ready
|
|||
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
|
||||
Go Into Project library has_image=${false}
|
||||
Vulnerability Not Ready Project Hint
|
||||
Switch To Configure
|
||||
Go To Vulnerability Config
|
||||
Switch To Vulnerability Page
|
||||
Vulnerability Not Ready Config Hint
|
||||
|
||||
Test Case - Read Only Mode
|
||||
|
@ -438,13 +437,11 @@ Test Case - Scan Image With Empty Vul
|
|||
Test Case - Disable Scan Schedule
|
||||
Init Chrome Driver
|
||||
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
|
||||
Switch To Configure
|
||||
Go To Vulnerability Config
|
||||
Switch To Vulnerability Page
|
||||
Disable Scan Schedule
|
||||
Logout Harbor
|
||||
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
|
||||
Switch To Configure
|
||||
Go To Vulnerability Config
|
||||
Switch To Vulnerability Page
|
||||
Page Should Contain None
|
||||
Close Browser
|
||||
###
|
||||
|
@ -452,8 +449,7 @@ Test Case - Manual Scan All
|
|||
Init Chrome Driver
|
||||
Push Image ${ip} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} library redis
|
||||
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
|
||||
Switch To Configure
|
||||
Go To Vulnerability Config
|
||||
Switch To Vulnerability Page
|
||||
Trigger Scan Now
|
||||
Navigate To Projects
|
||||
Go Into Project library
|
||||
|
|
Loading…
Reference in New Issue
Block a user