Merge pull request #11584 from jwangyangls/add-docker-pull-push-command

[feat] Add pull/push command in repo
This commit is contained in:
jwangyangls 2020-04-14 10:05:39 +08:00 committed by GitHub
commit fb3da503ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 149 additions and 55 deletions

View File

@ -6,7 +6,7 @@ import { HttpClient } from "@angular/common/http";
import { ScannerMetadata } from "./scanner-metadata";
import { CURRENT_BASE_HREF } from "../../../lib/utils/utils";
export const SCANNERS_DOC: string = "https://github.com/goharbor/harbor/blob/master/docs/harbor_compatibility_list.md";
export const SCANNERS_DOC: string = "https://goharbor.io/blog/harbor-1.10-release/#vulnerability-scanning-with-pluggable-scanners";
@Injectable()
export class ConfigScannerService {

View File

@ -148,6 +148,7 @@
<clr-dg-column class="flex-max-width">{{'REPOSITORY.ARTIFACTS_COUNT' | translate}}
</clr-dg-column>
<clr-dg-column>{{'REPOSITORY.PULL_COMMAND' | translate}}</clr-dg-column>
<clr-dg-column *ngIf="depth">{{'REPOSITORY.PLATFORM' | translate}}</clr-dg-column>
<clr-dg-column class="w-rem-4">{{'REPOSITORY.TAGS' | translate}}</clr-dg-column>
<clr-dg-column >{{'REPOSITORY.SIZE' | translate}}</clr-dg-column>
@ -180,6 +181,9 @@
</clr-tooltip>
</div>
</clr-dg-cell>
<clr-dg-cell class="truncated" title="{{artifact.pullCommand}}">
<hbr-copy-input *ngIf="artifact.pullCommand" #copyInput (onCopyError)="onCpError($event)" iconMode="true" defaultValue="{{artifact.pullCommand}}"></hbr-copy-input>
</clr-dg-cell>
<clr-dg-cell *ngIf="depth">
<div class="cell">
{{artifact.platform?.os}}/{{artifact.platform?.architecture}}{{artifact.platform?.variant?'/'+artifact.platform?.variant: ''}}

View File

@ -54,7 +54,7 @@ import {
} from "../../../../../../lib/entities/shared.const";
import { operateChanges, OperateInfo, OperationState } from "../../../../../../lib/components/operation/operate";
import { errorHandler } from "../../../../../../lib/utils/shared/shared.utils";
import { ArtifactFront as Artifact, mutipleFilter } from "../../../artifact/artifact";
import { ArtifactFront as Artifact, mutipleFilter, artifactPullCommands } from "../../../artifact/artifact";
import { Project } from "../../../../project";
import { ArtifactService as NewArtifactService } from "../../../../../../../ng-swagger-gen/services/artifact.service";
import { ADDITIONS } from "../../../artifact/artifact-additions/models";
@ -373,7 +373,7 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
this.artifactList.forEach((artifact, index) => {
artifact.platform = clone(platFormAttr[index].platform);
});
this.getArtifactAnnotationsArray(this.artifactList);
this.getPullCommand(this.artifactList);
}, error => {
this.errorHandlerService.error(error);
});
@ -400,7 +400,7 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
}
}
this.artifactList = res.body;
this.getArtifactAnnotationsArray(this.artifactList);
this.getPullCommand(this.artifactList);
}, error => {
// error
this.errorHandlerService.error(error);
@ -419,19 +419,16 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
}
this.clrLoad(st);
}
getArtifactAnnotationsArray(artifactList: Artifact[]) {
getPullCommand(artifactList: Artifact[]) {
artifactList.forEach(artifact => {
artifact.annotationsArray = [];
if (artifact.annotations) {
for (const key in artifact.annotations) {
if (artifact.annotations.hasOwnProperty(key)) {
const annotation = artifact.annotations[key];
artifact.annotationsArray.push(`${key} : ${annotation}`);
}
artifact.pullCommand = '';
artifactPullCommands.forEach(artifactPullCommand => {
if (artifactPullCommand.type === artifact.type) {
artifact.pullCommand =
`${artifactPullCommand.pullCommand} ${this.registryUrl}/${this.projectName}/${this.repoName}@${artifact.digest}`;
}
// todo : cannot support Object.entries
// artifact.annotationsArray = Object.entries(artifact.annotations).map(item => `${item[0]} : ${item[1]}`);
}
});
});
}
getAllLabels(): void {

View File

@ -33,7 +33,7 @@ export class ArtifactCommonPropertiesComponent implements OnInit, OnChanges {
ngOnChanges(changes: SimpleChanges) {
if (changes && changes["artifactDetails"]) {
if (this.artifactDetails) {
Object.assign(this.commonProperties, this.artifactDetails.extra_attrs);
Object.assign(this.commonProperties, this.artifactDetails.extra_attrs, this.artifactDetails.annotations);
for (let name in this.commonProperties) {
if (this.commonProperties.hasOwnProperty(name)) {
if (typeof (this.commonProperties[name]) === 'object') {

View File

@ -2,9 +2,9 @@ import { Artifact } from "../../../../../ng-swagger-gen/models/artifact";
import { Platform } from "../../../../../ng-swagger-gen/models/platform";
export interface ArtifactFront extends Artifact {
annotationsArray?: string[];
platform?: Platform;
showImage?: string;
pullCommand?: string;
}
export const mutipleFilter = [
@ -53,4 +53,18 @@ export const mutipleFilter = [
export const artifactImages = [
'IMAGE', 'CHART', 'CNAB', 'OPENPOLICYAGENT'
];
export const artifactPullCommands = [
{
type: artifactImages[0],
pullCommand: 'docker pull'
},
{
type: artifactImages[1],
pullCommand: 'helm chart pull'
},
{
type: artifactImages[2],
pullCommand: 'cnab-to-oci pull'
}
];
export const artifactDefault = "images/artifact-default.svg";

View File

@ -1018,8 +1018,14 @@
"SCAN_NOW": "Scan"
},
"PUSH_IMAGE": {
"TITLE": "Push Image Docker Command",
"TOOLTIP": "Command references for pushing an image to this project.",
"TITLE": "Push Command",
"DOCKER": "Docker",
"HELM": "Helm",
"CNAB": "CNAB",
"TAG_COMMAND_CHART": "Tag a chart for this project:",
"PUSH_COMMAND_CHART": "Push a chart to this project:",
"PUSH_COMMAND_CNAB": "Push a CNAB to this project:",
"TOOLTIP": "Command references for pushing an artifact to this project.",
"TAG_COMMAND": "Tag an image for this project:",
"PUSH_COMMAND": "Push an image to this project:",
"COPY_ERROR": "Copy failed, please try to manually copy the command references."

View File

@ -1018,8 +1018,14 @@
"SCAN_NOW": "Scan"
},
"PUSH_IMAGE": {
"TITLE": "Push Image Docker Command",
"TOOLTIP": "Command references for pushing an image to this project.",
"TITLE": "Push Command",
"DOCKER": "Docker",
"HELM": "Helm",
"CNAB": "CNAB",
"TAG_COMMAND_CHART": "Tag a chart for this project:",
"PUSH_COMMAND_CHART": "Push a chart to this project:",
"PUSH_COMMAND_CNAB": "Push a CNAB to this project:",
"TOOLTIP": "Command references for pushing an artifact to this project.",
"TAG_COMMAND": "Tag an image for this project:",
"PUSH_COMMAND": "Push an image to this project:",
"COPY_ERROR": "Copy failed, please try to manually copy the command references."

View File

@ -991,8 +991,14 @@
"SCAN_NOW": "Analyser"
},
"PUSH_IMAGE": {
"TITLE": "Pousser l'Image",
"TOOLTIP": "Commandes de références pour pousser une image vers ce projet.",
"TITLE": "Push Command",
"DOCKER": "Docker",
"HELM": "Helm",
"CNAB": "CNAB",
"TAG_COMMAND_CHART": "Tag a chart for this project:",
"PUSH_COMMAND_CHART": "Push a chart to this project:",
"PUSH_COMMAND_CNAB": "Push a CNAB to this project:",
"TOOLTIP": "Command references for pushing an artifact to this project.",
"TAG_COMMAND": "Tagger une image pour ce projet :",
"PUSH_COMMAND": "Pousser une image dans ce projet :",
"COPY_ERROR": "Copie échouée, veuillez essayer de copier manuellement les commandes de référence."

View File

@ -1014,8 +1014,14 @@
"SCAN_NOW": "Analisar"
},
"PUSH_IMAGE": {
"TITLE": "Enviar Imagem",
"TOOLTIP": "Referência de comando para enviar uma imagem para esse projeto.",
"TITLE": "Push Command",
"DOCKER": "Docker",
"HELM": "Helm",
"CNAB": "CNAB",
"TAG_COMMAND_CHART": "Tag a chart for this project:",
"PUSH_COMMAND_CHART": "Push a chart to this project:",
"PUSH_COMMAND_CNAB": "Push a CNAB to this project:",
"TOOLTIP": "Command references for pushing an artifact to this project.",
"TAG_COMMAND": "Taggeia uma imagem para esse projeto:",
"PUSH_COMMAND": "Envia uma imagem para esse projeto:",
"COPY_ERROR": "Copia falhou, por favor tente copiar o comando de referência manualmente."

View File

@ -1018,8 +1018,14 @@
"SCAN_NOW": "Tara"
},
"PUSH_IMAGE": {
"TITLE": "İmajı Yükle",
"TOOLTIP": "Bu projeye bir imaj yüklemek için komut referansları.",
"TITLE": "Push Command",
"DOCKER": "Docker",
"HELM": "Helm",
"CNAB": "CNAB",
"TAG_COMMAND_CHART": "Tag a chart for this project:",
"PUSH_COMMAND_CHART": "Push a chart to this project:",
"PUSH_COMMAND_CNAB": "Push a CNAB to this project:",
"TOOLTIP": "Command references for pushing an artifact to this project.",
"TAG_COMMAND": "Bu proje için bir imaj etiketleyin:",
"PUSH_COMMAND": "Bu projeye bir imaj gönder:",
"COPY_ERROR": "Kopyalama başarısız oldu, lütfen komut referanslarını el ile kopyalamayı deneyin."

View File

@ -648,7 +648,7 @@
"ARTIFACT_TOOTIP": "点击查看此 OCI 索引的 Artifact 列表",
"ARTIFACTS_COUNT": "Artifacts",
"PULL_COUNT": "下载数",
"PULL_COMMAND": "Pull命令",
"PULL_COMMAND": "拉取命令",
"PULL_TIME": "拉取时间",
"PUSH_TIME": "推送时间",
"IMMUTABLE": "不可变的",
@ -1018,8 +1018,14 @@
"SCAN_NOW": "扫描"
},
"PUSH_IMAGE": {
"TITLE": "推送镜像的Docker命令",
"TOOLTIP": "推送一个镜像到当前项目的参考命令。",
"TITLE": "推送命令",
"DOCKER": "Docker",
"HELM": "Helm",
"CNAB": "CNAB",
"TAG_COMMAND_CHART": "在项目中标记 chart",
"PUSH_COMMAND_CHART": "推送 chart 到当前项目",
"PUSH_COMMAND_CNAB": "推送 CNAB 到当前项目",
"TOOLTIP": "推送一个 artifact 到当前项目的参考命令。",
"TAG_COMMAND": "在项目中标记镜像:",
"PUSH_COMMAND": "推送镜像到当前项目:",
"COPY_ERROR": "拷贝失败,请尝试手动拷贝参考命令。"

View File

@ -7,25 +7,42 @@
<clr-dropdown-menu *clrIfOpen [clrPosition]="'bottom-right'" class="dropdown-width">
<div class="commands-container">
<section>
<span><h5 class="h5-override">{{ 'PUSH_IMAGE.TITLE' | translate }}</h5></span>
<span><h4 class="h5-override">{{ 'PUSH_IMAGE.TITLE' | translate }}</h4></span>
<span>
<clr-tooltip>
<clr-icon clrTooltipTrigger shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
<clr-tooltip-content [clrPosition]="'top-right'" [clrSize]="'md'" *clrIfOpen>
{{ 'PUSH_IMAGE.TOOLTIP' | translate }}
</clr-tooltip-content>
</clr-tooltip>
<clr-tooltip>
<clr-icon clrTooltipTrigger shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
<clr-tooltip-content [clrPosition]="'top-right'" [clrSize]="'md'" *clrIfOpen>
{{ 'PUSH_IMAGE.TOOLTIP' | translate }}
</clr-tooltip-content>
</clr-tooltip>
</span>
<div>- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -</div>
</section>
<section>
<hbr-inline-alert #copyAlert></hbr-inline-alert>
<hbr-inline-alert #copyAlert></hbr-inline-alert>
</section>
<section>
<h5 class="mt-0">{{ 'PUSH_IMAGE.DOCKER' | translate }} {{ 'PUSH_IMAGE.TITLE' | translate }}</h5>
<article class="commands-section">
<hbr-copy-input #tagCopy (onCopyError)="onCpError($event)" inputSize="50" headerTitle="{{ 'PUSH_IMAGE.TAG_COMMAND' | translate }}" defaultValue="{{tagCommand}}"></hbr-copy-input>
<hbr-copy-input #tagCopyImage (onCopyError)="onCpError($event)" inputSize="50" headerTitle="{{ 'PUSH_IMAGE.TAG_COMMAND' | translate }}" defaultValue="{{tagCommandImage}}"></hbr-copy-input>
</article>
<article class="commands-section">
<hbr-copy-input #pushCopy (onCopyError)="onCpError($event)" inputSize="50" headerTitle="{{ 'PUSH_IMAGE.PUSH_COMMAND' | translate }}" defaultValue="{{pushCommand}}"></hbr-copy-input>
<hbr-copy-input #pushCopyImage (onCopyError)="onCpError($event)" inputSize="50" headerTitle="{{ 'PUSH_IMAGE.PUSH_COMMAND' | translate }}" defaultValue="{{pushCommandImage}}"></hbr-copy-input>
</article>
</section>
<section>
<h5>{{ 'PUSH_IMAGE.HELM' | translate }} {{ 'PUSH_IMAGE.TITLE' | translate }}</h5>
<article class="commands-section">
<hbr-copy-input #tagCopyChart (onCopyError)="onCpError($event)" inputSize="50" headerTitle="{{ 'PUSH_IMAGE.TAG_COMMAND_CHART' | translate }}" defaultValue="{{tagCommandChart}}"></hbr-copy-input>
</article>
<article class="commands-section">
<hbr-copy-input #pushCopyChart (onCopyError)="onCpError($event)" inputSize="50" headerTitle="{{ 'PUSH_IMAGE.PUSH_COMMAND_CHART' | translate }}" defaultValue="{{pushCommandChart}}"></hbr-copy-input>
</article>
</section>
<section>
<h5>{{ 'PUSH_IMAGE.CNAB' | translate }} {{ 'PUSH_IMAGE.TITLE' | translate }}</h5>
<article class="commands-section">
<hbr-copy-input #pushCopyCnab (onCopyError)="onCpError($event)" inputSize="50" headerTitle="{{ 'PUSH_IMAGE.PUSH_COMMAND_CNAB' | translate }}" defaultValue="{{pushCommandCnab}}"></hbr-copy-input>
</article>
</section>
</div>

View File

@ -51,10 +51,10 @@ describe('PushImageButtonComponent (inline template)', () => {
let copyInputs: HTMLInputElement[] = fixture.nativeElement.querySelectorAll('.command-input');
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(copyInputs.length).toEqual(2);
expect(copyInputs.length).toEqual(5);
expect(copyInputs[0].value.trim())
.toEqual(`docker tag SOURCE_IMAGE[:TAG] ${component.registryUrl}/${component.projectName}/IMAGE[:TAG]`);
expect(copyInputs[1].value.trim()).toEqual(`docker push ${component.registryUrl}/${component.projectName}/IMAGE[:TAG]`);
.toEqual(`docker tag SOURCE_IMAGE[:TAG] ${component.registryUrl}/${component.projectName}/REPOSITORY[:TAG]`);
expect(copyInputs[1].value.trim()).toEqual(`docker push ${component.registryUrl}/${component.projectName}/REPOSITORY[:TAG]`);
});
});
});

View File

@ -13,27 +13,54 @@ export class PushImageButtonComponent {
@Input() registryUrl: string = "unknown";
@Input() projectName: string = "unknown";
@ViewChild("tagCopy", {static: false}) tagCopyInput: CopyInputComponent;
@ViewChild("pushCopy", {static: false}) pushCopyInput: CopyInputComponent;
@ViewChild("tagCopyImage", {static: false}) tagCopyImageInput: CopyInputComponent;
@ViewChild("pushCopyImage", {static: false}) pushCopImageyInput: CopyInputComponent;
@ViewChild("tagCopyChart", {static: false}) tagCopyChartInput: CopyInputComponent;
@ViewChild("pushCopyChart", {static: false}) pushCopyChartInput: CopyInputComponent;
@ViewChild("pushCopyCnab", {static: false}) pushCopCnabyInput: CopyInputComponent;
@ViewChild("copyAlert", {static: false}) copyAlert: InlineAlertComponent;
public get tagCommand(): string {
public get tagCommandImage(): string {
return `docker tag SOURCE_IMAGE[:TAG] ${this.registryUrl}/${
this.projectName
}/IMAGE[:TAG]`;
}/REPOSITORY[:TAG]`;
}
public get pushCommand(): string {
return `docker push ${this.registryUrl}/${this.projectName}/IMAGE[:TAG]`;
public get pushCommandImage(): string {
return `docker push ${this.registryUrl}/${this.projectName}/REPOSITORY[:TAG]`;
}
public get tagCommandChart(): string {
return `helm chart save CHART_PATH ${this.registryUrl}/${
this.projectName
}/REPOSITORY[:TAG]`;
}
public get pushCommandChart(): string {
return `helm chart push ${this.registryUrl}/${this.projectName}/REPOSITORY[:TAG]`;
}
public get pushCommandCnab(): string {
return `cnab-to-oci push CNAB_PATH --target ${this.registryUrl}/${this.projectName}/REPOSITORY[:TAG] --auto-update-bundle`;
}
onclick(): void {
if (this.tagCopyInput) {
this.tagCopyInput.reset();
if (this.tagCopyImageInput) {
this.tagCopyImageInput.reset();
}
if (this.pushCopyInput) {
this.pushCopyInput.reset();
if (this.pushCopImageyInput) {
this.pushCopImageyInput.reset();
}
if (this.tagCopyChartInput) {
this.tagCopyChartInput.reset();
}
if (this.pushCopyChartInput) {
this.pushCopyChartInput.reset();
}
if (this.pushCopCnabyInput) {
this.pushCopCnabyInput.reset();
}
if (this.copyAlert) {

View File

@ -26,7 +26,6 @@
.command-title {
font-size: 14px;
padding-left: 6px;
}
.command-input {
@ -51,7 +50,7 @@
width: 1px;
min-width: 0;
padding: 0;
opacity: .1;
opacity: .01;
}
.dropdown-width {