mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-24 01:27:49 +01:00
Merge pull request #11584 from jwangyangls/add-docker-pull-push-command
[feat] Add pull/push command in repo
This commit is contained in:
commit
fb3da503ea
@ -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 {
|
||||
|
@ -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: ''}}
|
||||
|
@ -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 {
|
||||
|
@ -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') {
|
||||
|
@ -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";
|
||||
|
@ -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."
|
||||
|
@ -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."
|
||||
|
@ -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."
|
||||
|
@ -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."
|
||||
|
@ -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."
|
||||
|
@ -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": "拷贝失败,请尝试手动拷贝参考命令。"
|
||||
|
@ -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>
|
||||
|
@ -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]`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user