Merge pull request #7265 from pureshine/move-scan/gc

Move GC and Vulnerability to Tasks
This commit is contained in:
Mia ZHOU 2019-04-03 16:41:57 +08:00 committed by GitHub
commit f73f926449
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 342 additions and 164 deletions

View File

@ -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>

View File

@ -0,0 +1,4 @@
.history-header {
color: #000;
margin:20px 0 6px 0;
}

View File

@ -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);
});
}
}

View File

@ -1,24 +1,4 @@
<div class="cron-selection"> <div class="cron-selection">
<cron-selection [labelCurrent]="getLabelCurrent" [labelEdit]='getText' [originCron]='originCron' (inputvalue)="scheduleGc($event)"></cron-selection> <cron-selection [labelCurrent]="getLabelCurrent" [labelEdit]='getText' [originCron]='originCron' (inputvalue)="scheduleGc($event)"></cron-selection>
</div> <button class="btn btn-outline btn-sm gc-start-btn" (click)="gcNow()" [disabled]="disableGC">{{'GC.GC_NOW' | translate}}</button>
<button class="btn btn-primary btn-sm gc-start-btn" (click)="gcNow()" [disabled]="disableGC">{{'GC.GC_NOW' | translate}}</button> </div>
<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>

View File

@ -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 { .cron-selection {
margin-top: 20px; margin-top: 20px;
} display: flex;
align-items: center;
.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;
}
} }
.gc-start-btn { .gc-start-btn {
width:150px; width:150px;
} margin-top: 47px;
.job-header {
margin:20px 0 -10px 0;
}
.day-selector-wrapper {
display: flex;
} }

View File

@ -4,3 +4,5 @@ export * from "./gc.api.repository";
export * from "./gc.service"; export * from "./gc.service";
export * from "./gc.viewmodel.factory"; export * from "./gc.viewmodel.factory";
export * from "./gcLog"; export * from "./gcLog";
export * from "./gc-history/gc-history.component";

View File

@ -5,7 +5,7 @@ import { SystemSettingsComponent } from './system/system-settings.component';
import { VulnerabilityConfigComponent } from './vulnerability/vulnerability-config.component'; import { VulnerabilityConfigComponent } from './vulnerability/vulnerability-config.component';
import { RegistryConfigComponent } from './registry-config.component'; import { RegistryConfigComponent } from './registry-config.component';
import { GcComponent } from './gc/gc.component'; import { GcComponent } from './gc/gc.component';
import { GcHistoryComponent } from './gc/gc-history/gc-history.component';
export * from './config'; export * from './config';
export * from './replication/replication-config.component'; export * from './replication/replication-config.component';
@ -16,6 +16,7 @@ export * from './gc/index';
export const CONFIGURATION_DIRECTIVES: Type<any>[] = [ export const CONFIGURATION_DIRECTIVES: Type<any>[] = [
ReplicationConfigComponent, ReplicationConfigComponent,
GcHistoryComponent,
GcComponent, GcComponent,
SystemSettingsComponent, SystemSettingsComponent,
VulnerabilityConfigComponent, VulnerabilityConfigComponent,

View File

@ -17,6 +17,7 @@
<button id="config-gc" clrTabLink>{{'CONFIG.GC' | translate}}</button> <button id="config-gc" clrTabLink>{{'CONFIG.GC' | translate}}</button>
<clr-tab-content id="gc" *clrIfActive> <clr-tab-content id="gc" *clrIfActive>
<gc-config #gcConfig></gc-config> <gc-config #gcConfig></gc-config>
<gc-history></gc-history>
</clr-tab-content> </clr-tab-content>
</clr-tab> </clr-tab>
</clr-tabs> </clr-tabs>

View File

@ -9,6 +9,7 @@ import { VulnerabilityConfigComponent } from './vulnerability/vulnerability-conf
import { RegistryConfigComponent } from './registry-config.component'; import { RegistryConfigComponent } from './registry-config.component';
import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component'; import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component';
import { GcComponent } from './gc/gc.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 { CronScheduleComponent } from '../cron-schedule/cron-schedule.component';
import { import {
@ -67,6 +68,7 @@ describe('RegistryConfigComponent (inline template)', () => {
RegistryConfigComponent, RegistryConfigComponent,
ConfirmationDialogComponent, ConfirmationDialogComponent,
GcComponent, GcComponent,
GcHistoryComponent,
CronScheduleComponent CronScheduleComponent
], ],
providers: [ providers: [

View File

@ -1,8 +1,8 @@
<form #systemConfigFrom="ngForm" class="compact"> <form #systemConfigFrom="ngForm" class="compact">
<section class="form-block"> <section class="form-block">
<label class="section-title" *ngIf="showSubTitle">{{ 'CONFIG.SCANNING.TITLE' | translate }}</label> <label class="section-title" *ngIf="showSubTitle">{{ 'CONFIG.SCANNING.TITLE' | translate }}</label>
<div class="form-group"> <div>
<label>{{ 'CONFIG.SCANNING.DB_REFRESH_TIME' | translate }}</label> <label class="update-time">{{ 'CONFIG.SCANNING.DB_REFRESH_TIME' | translate }}</label>
<clr-tooltip *ngIf="!isClairDBFullyReady"> <clr-tooltip *ngIf="!isClairDBFullyReady">
<clr-icon shape="warning" class="is-warning" size="22"></clr-icon> <clr-icon shape="warning" class="is-warning" size="22"></clr-icon>
<clr-tooltip-content [clrPosition]="'top-right'" [clrSize]="'md'" *clrIfOpen> <clr-tooltip-content [clrPosition]="'top-right'" [clrSize]="'md'" *clrIfOpen>
@ -23,9 +23,11 @@
</clr-dropdown> </clr-dropdown>
<span *ngIf="isClairDBFullyReady && !showScanningNamespaces">{{ updatedTimestamp | date:'MM/dd/y HH:mm:ss' }} AM</span> <span *ngIf="isClairDBFullyReady && !showScanningNamespaces">{{ updatedTimestamp | date:'MM/dd/y HH:mm:ss' }} AM</span>
</div> </div>
<cron-selection [labelCurrent]="getLabelCurrent" [labelEdit]='getLabelCurrent' [originCron]='originCron' (inputvalue)="scanAll($event)"></cron-selection> <div class="button-group">
<div class="btn-scan-right btn-scan"> <cron-selection [labelCurrent]="getLabelCurrent" [labelEdit]='getLabelCurrent' [originCron]='originCron' (inputvalue)="scanAll($event)"></cron-selection>
<button class="btn btn-primary btn-sm btn-scan" (click)="scanNow()" [disabled]="!scanAvailable">{{ 'CONFIG.SCANNING.SCAN_NOW' | translate }}</button><br> <div class="btn-scan-right btn-scan">
</div> <button class="btn btn-outline btn-sm btn-scan" (click)="scanNow()" [disabled]="!scanAvailable">{{ 'CONFIG.SCANNING.SCAN_NOW' | translate }}</button><br>
</div>
</div>
</section> </section>
</form> </form>

View File

@ -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{ .update-time {
width: 160px; color: #000;
margin-bottom: 0px; font-size: .541667rem;
margin-top: 5px; width: 200px;
} }
.btn-scan-right span{
margin-top: 4px;
}

View File

@ -1,21 +1,23 @@
<div class="normal-wrapper flex-layout" *ngIf="!isEditMode"> <div class="normal-wrapper flex-layout" *ngIf="!isEditMode">
<span class="font-style">{{ labelCurrent | translate }}</span> <div>
<span>{{(originScheduleType ? 'SCHEDULE.'+ originScheduleType.toUpperCase(): "") | translate}}</span> <span class="font-style">{{ labelCurrent | translate }}</span>
<a [hidden]="originScheduleType!==SCHEDULE_TYPE.HOURLY" href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right"> <span>{{(originScheduleType ? 'SCHEDULE.'+ originScheduleType.toUpperCase(): "") | translate}}</span>
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon> <a [hidden]="originScheduleType!==SCHEDULE_TYPE.HOURLY" href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right">
<span class="tooltip-content">{{'CONFIG.TOOLTIP.HOURLY_CRON' | translate}}</span> <clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
</a> <span class="tooltip-content">{{'CONFIG.TOOLTIP.HOURLY_CRON' | translate}}</span>
<a [hidden]="originScheduleType!==SCHEDULE_TYPE.WEEKLY" href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right"> </a>
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon> <a [hidden]="originScheduleType!==SCHEDULE_TYPE.WEEKLY" href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right">
<span class="tooltip-content">{{'CONFIG.TOOLTIP.WEEKLY_CRON' | translate}}</span> <clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
</a> <span class="tooltip-content">{{'CONFIG.TOOLTIP.WEEKLY_CRON' | translate}}</span>
<a [hidden]="originScheduleType!==SCHEDULE_TYPE.DAILY" href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right"> </a>
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon> <a [hidden]="originScheduleType!==SCHEDULE_TYPE.DAILY" href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right">
<span class="tooltip-content">{{'CONFIG.TOOLTIP.DAILY_CRON' | translate}}</span> <clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
</a> <span class="tooltip-content">{{'CONFIG.TOOLTIP.DAILY_CRON' | translate}}</span>
<span [hidden]="originScheduleType!==SCHEDULE_TYPE.CUSTOM">{{ "SCHEDULE.CRON" | translate }} :</span> </a>
<span [hidden]="originScheduleType!==SCHEDULE_TYPE.CUSTOM">{{ oriCron }}</span> <span [hidden]="originScheduleType!==SCHEDULE_TYPE.CUSTOM">{{ "SCHEDULE.CRON" | translate }} :</span>
<button class="btn btn-outline btn-sm" (click)="editSchedule()" id="editSchedule"> <span [hidden]="originScheduleType!==SCHEDULE_TYPE.CUSTOM">{{ oriCron }}</span>
</div>
<button class="btn btn-primary btn-sm" (click)="editSchedule()" id="editSchedule">
{{ "BUTTON.EDIT" | translate }} {{ "BUTTON.EDIT" | translate }}
</button> </button>
</div> </div>
@ -40,11 +42,13 @@
</span> </span>
</label> </label>
</div> </div>
<button class="btn btn-primary btn-sm" <div class="confirm-button">
<button class="btn btn-primary btn-sm"
(click)="save()" id="config-save"> (click)="save()" id="config-save">
{{ "BUTTON.SAVE" | translate }} {{ "BUTTON.SAVE" | translate }}
</button> </button>
<button class="btn btn-primary btn-sm" (click)="isEditMode=false"> <button class="btn btn-primary btn-sm" (click)="isEditMode=false">
{{ "BUTTON.CANCEL" | translate }} {{ "BUTTON.CANCEL" | translate }}
</button> </button>
</div>
</div> </div>

View File

@ -1,13 +1,11 @@
.flex-layout { .flex-layout {
display: flex;
align-items: center;
margin: 20px 0; margin: 20px 0;
font-size: .541667rem; font-size: .541667rem;
} }
.normal-wrapper { .normal-wrapper {
> span:first-child { > span:first-child {
width: 228px; width: 200px;
} }
> span:not(:first-child) { > span:not(:first-child) {
@ -17,13 +15,17 @@
margin-left: -10px; margin-left: -10px;
} }
button { button {
margin-left: 10px; margin: 20px 20px 0 200px;
} }
} }
.setting-wrapper { .setting-wrapper {
> span:first-child { > span:first-child {
width: 228px; width: 200px;
}
.confirm-button {
margin: 20px 0px 0 200px;
} }
*:not(:first-child) { *:not(:first-child) {
@ -39,7 +41,10 @@
width: 195px; width: 195px;
} }
} }
.font-style { .font-style {
display: inline-block;
color: #000; color: #000;
font-size: .541667rem; font-size: .541667rem;
} width: 200px;
}

View File

@ -31,6 +31,9 @@ import { ProjectConfigComponent } from './project/project-config/project-config.
import zh from '@angular/common/locales/zh-Hans'; import zh from '@angular/common/locales/zh-Hans';
import es from '@angular/common/locales/es'; import es from '@angular/common/locales/es';
import localeFr from '@angular/common/locales/fr'; 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'; import { OidcOnboardModule } from './oidc-onboard/oidc-onboard.module';
registerLocaleData(zh, 'zh-cn'); registerLocaleData(zh, 'zh-cn');
registerLocaleData(es, 'es-es'); registerLocaleData(es, 'es-es');
@ -51,7 +54,9 @@ export function getCurrentLanguage(translateService: TranslateService) {
@NgModule({ @NgModule({
declarations: [ declarations: [
AppComponent, AppComponent,
ProjectConfigComponent ProjectConfigComponent,
VulnerabilityPageComponent,
GcPageComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,

View File

@ -46,6 +46,19 @@
</a> </a>
</clr-vertical-nav-group-children> </clr-vertical-nav-group-children>
</clr-vertical-nav-group> </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>
<div class="vertical-nav-footer"> <div class="vertical-nav-footer">
<a clrVerticalNavLink target="_blank" routerLink="/devcenter"> <a clrVerticalNavLink target="_blank" routerLink="/devcenter">

View File

@ -32,22 +32,6 @@
</clr-tab-content> </clr-tab-content>
</ng-template> </ng-template>
</clr-tab> </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> </clr-tabs>
</div> </div>
</div> </div>

View File

@ -14,8 +14,8 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core'; import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { Subscription } from "rxjs"; import { Subscription } from "rxjs";
import { import {
Configuration, StringValueItem, SystemSettingsComponent, VulnerabilityConfigComponent, Configuration, StringValueItem, SystemSettingsComponent,
isEmpty, clone, getChanges, GcComponent, GcRepoService } from '@harbor/ui'; isEmpty, clone, getChanges, GcRepoService } from '@harbor/ui';
import { ConfirmationTargets, ConfirmationState } from '../shared/shared.const'; import { ConfirmationTargets, ConfirmationState } from '../shared/shared.const';
import { SessionService } from '../shared/session.service'; import { SessionService } from '../shared/session.service';
@ -34,8 +34,6 @@ const TabLinkContentMap = {
'config-replication': 'replication', 'config-replication': 'replication',
'config-email': 'email', 'config-email': 'email',
'config-system': 'system_settings', 'config-system': 'system_settings',
'config-vulnerability': 'vulnerability',
'config-gc': 'gc',
'config-label': 'system_label', 'config-label': 'system_label',
}; };
@ -52,8 +50,6 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
confirmSub: Subscription; confirmSub: Subscription;
@ViewChild(SystemSettingsComponent) systemSettingsConfig: SystemSettingsComponent; @ViewChild(SystemSettingsComponent) systemSettingsConfig: SystemSettingsComponent;
@ViewChild(VulnerabilityConfigComponent) vulnerabilityConfig: VulnerabilityConfigComponent;
@ViewChild(GcComponent) gcConfig: GcComponent;
@ViewChild(ConfigurationEmailComponent) mailConfig: ConfigurationEmailComponent; @ViewChild(ConfigurationEmailComponent) mailConfig: ConfigurationEmailComponent;
@ViewChild(ConfigurationAuthComponent) authConfig: ConfigurationAuthComponent; @ViewChild(ConfigurationAuthComponent) authConfig: ConfigurationAuthComponent;
@ -73,10 +69,6 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
return this.appConfigService.getConfig().has_ca_root; return this.appConfigService.getConfig().has_ca_root;
} }
public get withClair(): boolean {
return this.appConfigService.getConfig().with_clair;
}
public get withAdmiral(): boolean { public get withAdmiral(): boolean {
return this.appConfigService.getConfig().with_admiral; return this.appConfigService.getConfig().with_admiral;
} }

View 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>

View File

@ -0,0 +1,3 @@
.gc-title {
display: inline-block;
}

View 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();
});
});

View 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
);
}
}

View File

@ -24,6 +24,8 @@ import { PageNotFoundComponent } from './shared/not-found/not-found.component';
import { HarborShellComponent } from './base/harbor-shell/harbor-shell.component'; import { HarborShellComponent } from './base/harbor-shell/harbor-shell.component';
import { ConfigurationComponent } from './config/config.component'; import { ConfigurationComponent } from './config/config.component';
import { DevCenterComponent } from './dev-center/dev-center.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 { UserComponent } from './user/user.component';
import { SignInComponent } from './account/sign-in/sign-in.component'; import { SignInComponent } from './account/sign-in/sign-in.component';
@ -198,6 +200,16 @@ const harborRoutes: Routes = [
component: ConfigurationComponent, component: ConfigurationComponent,
canActivate: [SystemAdminGuard] canActivate: [SystemAdminGuard]
}, },
{
path: 'vulnerability',
component: VulnerabilityPageComponent,
canActivate: [SystemAdminGuard]
},
{
path: 'gc',
component: GcPageComponent,
canActivate: [SystemAdminGuard]
},
{ {
path: 'registry', path: 'registry',
component: DestinationPageComponent, component: DestinationPageComponent,

View File

@ -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>

View File

@ -0,0 +1,3 @@
.vul-title {
display: inline-block;
}

View File

@ -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();
});
});

View File

@ -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;
}
}

View File

@ -130,9 +130,12 @@
"GROUP": "Groups", "GROUP": "Groups",
"REGISTRY": "Registries", "REGISTRY": "Registries",
"REPLICATION": "Replications", "REPLICATION": "Replications",
"CONFIG": "Configuration" "CONFIG": "Configuration",
"VULNERABILITY": "Vulnerability",
"GARBAGE_COLLECTION": "Garbage Collection"
}, },
"LOGS": "Logs", "LOGS": "Logs",
"TASKS": "Tasks",
"API_EXPLORER": "API EXPLORER" "API_EXPLORER": "API EXPLORER"
}, },
"USER": { "USER": {
@ -596,6 +599,7 @@
"SUB_TITLE_SUFIX": "logs" "SUB_TITLE_SUFIX": "logs"
}, },
"CONFIG": { "CONFIG": {
"HISTORY": "History",
"TITLE": "Configuration", "TITLE": "Configuration",
"AUTH": "Authentication", "AUTH": "Authentication",
"REPLICATION": "Replication", "REPLICATION": "Replication",
@ -917,7 +921,7 @@
"GC": { "GC": {
"CURRENT_SCHEDULE": "Current Schedule", "CURRENT_SCHEDULE": "Current Schedule",
"GC_NOW": "GC NOW", "GC_NOW": "GC NOW",
"JOB_HISTORY": "GC Jobs History", "JOB_HISTORY": "GC History",
"JOB_ID": "Job ID", "JOB_ID": "Job ID",
"TRIGGER_TYPE": "Trigger Type", "TRIGGER_TYPE": "Trigger Type",
"LATEST_JOBS": "Latest {{param}} Jobs", "LATEST_JOBS": "Latest {{param}} Jobs",

View File

@ -130,9 +130,12 @@
"REGISTRY": "Registries", "REGISTRY": "Registries",
"GROUP": "Groups", "GROUP": "Groups",
"REPLICATION": "Replicacións", "REPLICATION": "Replicacións",
"CONFIG": "Configuración" "CONFIG": "Configuración",
"VULNERABILITY": "Vulnerability",
"GARBAGE_COLLECTION": "Garbage Collection"
}, },
"LOGS": "Logs", "LOGS": "Logs",
"TASKS": "Tasks",
"API_EXPLORER": "API EXPLORER" "API_EXPLORER": "API EXPLORER"
}, },
"USER": { "USER": {
@ -915,7 +918,7 @@
"GC": { "GC": {
"CURRENT_SCHEDULE": "Current Schedule", "CURRENT_SCHEDULE": "Current Schedule",
"GC_NOW": "GC NOW", "GC_NOW": "GC NOW",
"JOB_HISTORY": "GC Jobs History", "JOB_HISTORY": "GC History",
"JOB_ID": "Job ID", "JOB_ID": "Job ID",
"TRIGGER_TYPE": "Trigger Type", "TRIGGER_TYPE": "Trigger Type",
"LATEST_JOBS": "Latest {{param}} Jobs", "LATEST_JOBS": "Latest {{param}} Jobs",

View File

@ -116,9 +116,12 @@
"USER": "Utilisateurs", "USER": "Utilisateurs",
"GROUP": "Groups", "GROUP": "Groups",
"REPLICATION": "Réplication", "REPLICATION": "Réplication",
"CONFIG": "Configuration" "CONFIG": "Configuration",
"VULNERABILITY": "Vulnerability",
"GARBAGE_COLLECTION": "Garbage Collection"
}, },
"LOGS": "Logs", "LOGS": "Logs",
"TASKS": "Tasks",
"API_EXPLORER": "API EXPLORER" "API_EXPLORER": "API EXPLORER"
}, },
"USER": { "USER": {
@ -878,7 +881,7 @@
"GC": { "GC": {
"CURRENT_SCHEDULE": "Current Schedule", "CURRENT_SCHEDULE": "Current Schedule",
"GC_NOW": "GC NOW", "GC_NOW": "GC NOW",
"JOB_HISTORY": "GC Jobs History", "JOB_HISTORY": "GC History",
"JOB_ID": "Job ID", "JOB_ID": "Job ID",
"TRIGGER_TYPE": "Trigger Type", "TRIGGER_TYPE": "Trigger Type",
"LATEST_JOBS": "Latest {{param}} Jobs", "LATEST_JOBS": "Latest {{param}} Jobs",

View File

@ -128,9 +128,12 @@
"GROUP": "Grupos", "GROUP": "Grupos",
"REGISTRY": "Registros", "REGISTRY": "Registros",
"REPLICATION": "Replicações", "REPLICATION": "Replicações",
"CONFIG": "Configuração" "CONFIG": "Configuração",
"VULNERABILITY": "Vulnerability",
"GARBAGE_COLLECTION": "Garbage Collection"
}, },
"LOGS": "Logs", "LOGS": "Logs",
"TASKS": "Tasks",
"API_EXPLORER": "API EXPLORER" "API_EXPLORER": "API EXPLORER"
}, },
"USER": { "USER": {
@ -909,6 +912,7 @@
"ON": "em", "ON": "em",
"AT": "em", "AT": "em",
"GC_NOW": "GC AGORA", "GC_NOW": "GC AGORA",
"JOB_HISTORY": "GC History",
"JOB_LIST":"Lista de tarefas de Limpeza", "JOB_LIST":"Lista de tarefas de Limpeza",
"JOB_ID":"ID DA TAREFA", "JOB_ID":"ID DA TAREFA",
"TRIGGER_TYPE": "TIPO DE DISPARO", "TRIGGER_TYPE": "TIPO DE DISPARO",

View File

@ -129,9 +129,12 @@
"GROUP": "组管理", "GROUP": "组管理",
"REGISTRY": "仓库管理", "REGISTRY": "仓库管理",
"REPLICATION": "复制管理", "REPLICATION": "复制管理",
"CONFIG": "配置管理" "CONFIG": "配置管理",
"VULNERABILITY": "漏洞",
"GARBAGE_COLLECTION": "垃圾清理"
}, },
"LOGS": "日志", "LOGS": "日志",
"TASKS": "任务",
"API_EXPLORER": "API控制中心" "API_EXPLORER": "API控制中心"
}, },
"USER": { "USER": {

View File

@ -278,7 +278,7 @@ Delete A Label
## Garbage Collection ## Garbage Collection
Switch To Garbage Collection Switch To Garbage Collection
Sleep 1 Sleep 1
Click Element xpath=${configuration_xpath} Retry Element Click xpath=${gc_config_page}
Wait Until Page Contains Element ${garbage_collection_xpath} Wait Until Page Contains Element ${garbage_collection_xpath}
Click Element xpath=${garbage_collection_xpath} Click Element xpath=${garbage_collection_xpath}
@ -290,3 +290,8 @@ Click GC Now
View GC Details View GC Details
Click Element xpath=${gc_log_details_xpath} Click Element xpath=${gc_log_details_xpath}
Sleep 2 Sleep 2
Switch To GC History
Retry Element Click xpath=${gc_log_xpath}
Retry Wait Until Page Contains Job

View File

@ -27,5 +27,7 @@ ${vulnerbility_save_button_xpath} //*[@id='config-save']
${configuration_xpath} //clr-vertical-nav-group-children/a[contains(.,'Configuration')] ${configuration_xpath} //clr-vertical-nav-group-children/a[contains(.,'Configuration')]
${system_config_xpath} //*[@id='config-system'] ${system_config_xpath} //*[@id='config-system']
${garbage_collection_xpath} //*[@id='config-gc'] ${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 ${gc_log_details_xpath} //*[@id='clr-dg-row26']/clr-dg-cell[6]/a

View File

@ -173,7 +173,7 @@ Verify System Setting
Switch To System Settings Switch To System Settings
Page Should Contain @{creation}[0] Page Should Contain @{creation}[0]
Token Must Be Match @{token}[0] Token Must Be Match @{token}[0]
Go To Vulnerability Config Switch To Vulnerability Page
Page Should Contain None Page Should Contain None
Close Browser Close Browser

View File

@ -4,7 +4,8 @@ Resource ../../resources/Util.robot
*** Variables *** *** Variables ***
${HARBOR_VERSION} v1.1.1 ${HARBOR_VERSION} v1.1.1
${scan_now_button} //vulnerability-page//button[contains(.,'NOW')]
${vulnerability_page} //clr-vertical-nav-group-children/a[contains(.,'Vulnerability')]
*** Keywords *** *** Keywords ***
Disable Scan Schedule Disable Scan Schedule
Retry Element Click //vulnerability-config//cron-selection//button[contains(.,'EDIT')] 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 //vulnerability-config//cron-selection//select[@id='selectPolicy']//option[contains(.,'None')]
Retry Element Click //cron-selection//button[contains(.,'SAVE')] Retry Element Click //cron-selection//button[contains(.,'SAVE')]
Go To Vulnerability Config
Retry Element Click //config//button[contains(.,'Vulnerability')]
Trigger Scan Now Trigger Scan Now
Retry Element Click //config//button[contains(.,'NOW')] Retry Element Click xpath=${scan_now_button}
Sleep 10 Sleep 10
Switch To Vulnerability Page
Retry Element Click xpath=${vulnerability_page}
Retry Wait Element ${scan_now_button}
Set Vulnerabilty Serverity Set Vulnerabilty Serverity
#0 is high 1 is medium 2 is low 3 is negligible #0 is high 1 is medium 2 is low 3 is negligible
[Arguments] ${level} [Arguments] ${level}

View File

@ -34,8 +34,7 @@ Test Case - Vulnerability Data Not Ready
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
Go Into Project library has_image=${false} Go Into Project library has_image=${false}
Vulnerability Not Ready Project Hint Vulnerability Not Ready Project Hint
Switch To Configure Switch To Vulnerability Page
Go To Vulnerability Config
Vulnerability Not Ready Config Hint Vulnerability Not Ready Config Hint
Test Case - Garbage Collection Test Case - Garbage Collection
@ -56,7 +55,8 @@ Test Case - Garbage Collection
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
Switch To Garbage Collection Switch To Garbage Collection
Sleep 1 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" ${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} Log To Console ${output}
@ -265,13 +265,11 @@ Test Case - Delete Label
Test Case - Disable Scan Schedule Test Case - Disable Scan Schedule
Init Chrome Driver Init Chrome Driver
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
Switch To Configure Switch To Vulnerability Page
Go To Vulnerability Config
Disable Scan Schedule Disable Scan Schedule
Logout Harbor Logout Harbor
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
Switch To Configure Switch To Vulnerability Page
Go To Vulnerability Config
Retry Wait Until Page Contains None Retry Wait Until Page Contains None
Close Browser Close Browser
@ -545,8 +543,7 @@ Test Case - Manual Scan All
Init Chrome Driver Init Chrome Driver
Push Image ${ip} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} library redis Push Image ${ip} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} library redis
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
Switch To Configure Switch To Vulnerability Page
Go To Vulnerability Config
Trigger Scan Now Trigger Scan Now
Navigate To Projects Navigate To Projects
Go Into Project library Go Into Project library

View File

@ -35,8 +35,7 @@ Test Case - Vulnerability Data Not Ready
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
Go Into Project library has_image=${false} Go Into Project library has_image=${false}
Vulnerability Not Ready Project Hint Vulnerability Not Ready Project Hint
Switch To Configure Switch To Vulnerability Page
Go To Vulnerability Config
Vulnerability Not Ready Config Hint Vulnerability Not Ready Config Hint
Test Case - Read Only Mode Test Case - Read Only Mode
@ -438,13 +437,11 @@ Test Case - Scan Image With Empty Vul
Test Case - Disable Scan Schedule Test Case - Disable Scan Schedule
Init Chrome Driver Init Chrome Driver
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
Switch To Configure Switch To Vulnerability Page
Go To Vulnerability Config
Disable Scan Schedule Disable Scan Schedule
Logout Harbor Logout Harbor
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
Switch To Configure Switch To Vulnerability Page
Go To Vulnerability Config
Page Should Contain None Page Should Contain None
Close Browser Close Browser
### ###
@ -452,8 +449,7 @@ Test Case - Manual Scan All
Init Chrome Driver Init Chrome Driver
Push Image ${ip} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} library redis Push Image ${ip} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} library redis
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
Switch To Configure Switch To Vulnerability Page
Go To Vulnerability Config
Trigger Scan Now Trigger Scan Now
Navigate To Projects Navigate To Projects
Go Into Project library Go Into Project library