mirror of
https://github.com/goharbor/harbor.git
synced 2024-09-29 22:07:32 +02:00
Add new client Podman to the pull command (#18857)
1.Fixes #18832 Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
parent
1d6c02f52d
commit
d36ca805b4
@ -126,6 +126,12 @@
|
|||||||
</clr-dropdown>
|
</clr-dropdown>
|
||||||
</div>
|
</div>
|
||||||
<div class="right-pos">
|
<div class="right-pos">
|
||||||
|
<app-pull-command
|
||||||
|
[registryUrl]="registryUrl"
|
||||||
|
[projectName]="projectName"
|
||||||
|
[repoName]="repoName"
|
||||||
|
[selectedRow]="selectedRow"
|
||||||
|
class="mr-1"></app-pull-command>
|
||||||
<app-artifact-filter
|
<app-artifact-filter
|
||||||
[withDivider]="true"
|
[withDivider]="true"
|
||||||
(filterEvent)="filterEvent($event)"
|
(filterEvent)="filterEvent($event)"
|
||||||
@ -142,11 +148,6 @@
|
|||||||
{{ 'REPOSITORY.ARTIFACTS_COUNT' | translate }}
|
{{ 'REPOSITORY.ARTIFACTS_COUNT' | translate }}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</clr-dg-column>
|
</clr-dg-column>
|
||||||
<clr-dg-column class="pull-command-column">
|
|
||||||
<ng-template [clrDgHideableColumn]="{ hidden: hiddenArray[1] }">
|
|
||||||
{{ 'REPOSITORY.PULL_COMMAND' | translate }}
|
|
||||||
</ng-template>
|
|
||||||
</clr-dg-column>
|
|
||||||
<clr-dg-column *ngIf="depth">
|
<clr-dg-column *ngIf="depth">
|
||||||
<ng-template [clrDgHideableColumn]="{ hidden: hiddenArray[2] }">
|
<ng-template [clrDgHideableColumn]="{ hidden: hiddenArray[2] }">
|
||||||
{{ 'REPOSITORY.PLATFORM' | translate }}
|
{{ 'REPOSITORY.PLATFORM' | translate }}
|
||||||
@ -244,15 +245,6 @@
|
|||||||
</clr-tooltip>
|
</clr-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</clr-dg-cell>
|
</clr-dg-cell>
|
||||||
<clr-dg-cell>
|
|
||||||
<hbr-copy-input
|
|
||||||
[title]="getPullCommand(artifact)"
|
|
||||||
*ngIf="getPullCommand(artifact)"
|
|
||||||
[iconMode]="true"
|
|
||||||
[defaultValue]="
|
|
||||||
getPullCommand(artifact)
|
|
||||||
"></hbr-copy-input>
|
|
||||||
</clr-dg-cell>
|
|
||||||
<clr-dg-cell *ngIf="depth">
|
<clr-dg-cell *ngIf="depth">
|
||||||
<div class="cell">
|
<div class="cell">
|
||||||
{{ artifact.platform?.os }}
|
{{ artifact.platform?.os }}
|
||||||
|
@ -57,9 +57,6 @@ import {
|
|||||||
ArtifactFilterEvent,
|
ArtifactFilterEvent,
|
||||||
ArtifactFront as Artifact,
|
ArtifactFront as Artifact,
|
||||||
ArtifactFront,
|
ArtifactFront,
|
||||||
ArtifactType,
|
|
||||||
getPullCommandByDigest,
|
|
||||||
getPullCommandByTag,
|
|
||||||
} from '../../../artifact';
|
} from '../../../artifact';
|
||||||
import { Project } from '../../../../../project';
|
import { Project } from '../../../../../project';
|
||||||
import { ArtifactService as NewArtifactService } from '../../../../../../../../../ng-swagger-gen/services/artifact.service';
|
import { ArtifactService as NewArtifactService } from '../../../../../../../../../ng-swagger-gen/services/artifact.service';
|
||||||
@ -458,32 +455,6 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
|
|||||||
this.clrLoad(st);
|
this.clrLoad(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPullCommand(artifact: Artifact): string {
|
|
||||||
let pullCommand: string = '';
|
|
||||||
if (
|
|
||||||
artifact.type === ArtifactType.CHART &&
|
|
||||||
artifact.tags &&
|
|
||||||
artifact.tags[0]
|
|
||||||
) {
|
|
||||||
pullCommand = getPullCommandByTag(
|
|
||||||
artifact.type,
|
|
||||||
`${this.registryUrl ? this.registryUrl : location.hostname}/${
|
|
||||||
this.projectName
|
|
||||||
}/${this.repoName}`,
|
|
||||||
artifact.tags[0]?.name
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
pullCommand = getPullCommandByDigest(
|
|
||||||
artifact.type,
|
|
||||||
`${this.registryUrl ? this.registryUrl : location.hostname}/${
|
|
||||||
this.projectName
|
|
||||||
}/${this.repoName}`,
|
|
||||||
artifact.digest
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return pullCommand;
|
|
||||||
}
|
|
||||||
|
|
||||||
canAddLabel(): boolean {
|
canAddLabel(): boolean {
|
||||||
if (this.selectedRow && this.selectedRow.length === 1) {
|
if (this.selectedRow && this.selectedRow.length === 1) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -0,0 +1,131 @@
|
|||||||
|
<clr-dropdown [clrCloseMenuOnItemClick]="false" class="mr-1" *ngIf="!isTagMode">
|
||||||
|
<button
|
||||||
|
[disabled]="
|
||||||
|
selectedRow?.length !== 1 || !hasPullCommand(selectedRow[0])
|
||||||
|
"
|
||||||
|
class="btn btn-link copy-pull-command"
|
||||||
|
clrDropdownTrigger>
|
||||||
|
{{ 'PUSH_IMAGE.COPY_PULL_COMMAND' | translate }}
|
||||||
|
<cds-icon shape="angle" direction="down"></cds-icon>
|
||||||
|
</button>
|
||||||
|
<clr-dropdown-menu clrPosition="bottom-right" *clrIfOpen>
|
||||||
|
<ng-container *ngIf="isImage(selectedRow[0])">
|
||||||
|
<div
|
||||||
|
class="flex"
|
||||||
|
aria-label="Dropdown header Action"
|
||||||
|
clrDropdownItem>
|
||||||
|
<hbr-copy-input
|
||||||
|
[title]="getPullCommandForDocker(selectedRow[0])"
|
||||||
|
[iconMode]="true"
|
||||||
|
[defaultValue]="
|
||||||
|
getPullCommandForDocker(selectedRow[0])
|
||||||
|
"></hbr-copy-input>
|
||||||
|
<span>{{ 'PUSH_IMAGE.DOCKER' | translate }}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex"
|
||||||
|
aria-label="Dropdown header Action"
|
||||||
|
clrDropdownItem>
|
||||||
|
<hbr-copy-input
|
||||||
|
[title]="getPullCommandForPadMan(selectedRow[0])"
|
||||||
|
[iconMode]="true"
|
||||||
|
[defaultValue]="
|
||||||
|
getPullCommandForPadMan(selectedRow[0])
|
||||||
|
"></hbr-copy-input>
|
||||||
|
<span>{{ 'PUSH_IMAGE.PODMAN' | translate }}</span>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
<div
|
||||||
|
*ngIf="isCNAB(selectedRow[0])"
|
||||||
|
class="flex"
|
||||||
|
aria-label="Dropdown header Action"
|
||||||
|
clrDropdownItem>
|
||||||
|
<hbr-copy-input
|
||||||
|
[title]="getPullCommandForCNAB(selectedRow[0])"
|
||||||
|
[iconMode]="true"
|
||||||
|
[defaultValue]="
|
||||||
|
getPullCommandForCNAB(selectedRow[0])
|
||||||
|
"></hbr-copy-input>
|
||||||
|
<span>{{ 'PUSH_IMAGE.CNAB' | translate }}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
*ngIf="isChart(selectedRow[0])"
|
||||||
|
class="flex"
|
||||||
|
aria-label="Dropdown header Action"
|
||||||
|
clrDropdownItem>
|
||||||
|
<hbr-copy-input
|
||||||
|
[title]="getPullCommandForChart(selectedRow[0])"
|
||||||
|
[iconMode]="true"
|
||||||
|
[defaultValue]="
|
||||||
|
getPullCommandForChart(selectedRow[0])
|
||||||
|
"></hbr-copy-input>
|
||||||
|
<span>{{ 'PUSH_IMAGE.HELM' | translate }}</span>
|
||||||
|
</div>
|
||||||
|
</clr-dropdown-menu>
|
||||||
|
</clr-dropdown>
|
||||||
|
|
||||||
|
<clr-dropdown [clrCloseMenuOnItemClick]="false" class="mr-1" *ngIf="isTagMode">
|
||||||
|
<button
|
||||||
|
[disabled]="
|
||||||
|
selectedTags?.length !== 1 || !hasPullCommandForTag(artifact)
|
||||||
|
"
|
||||||
|
class="btn btn-link copy-pull-command"
|
||||||
|
clrDropdownTrigger>
|
||||||
|
{{ 'PUSH_IMAGE.COPY_PULL_COMMAND' | translate }}
|
||||||
|
<cds-icon shape="angle" direction="down"></cds-icon>
|
||||||
|
</button>
|
||||||
|
<clr-dropdown-menu clrPosition="bottom-right" *clrIfOpen>
|
||||||
|
<ng-container *ngIf="isImage(artifact)">
|
||||||
|
<div
|
||||||
|
class="flex"
|
||||||
|
aria-label="Dropdown header Action"
|
||||||
|
clrDropdownItem>
|
||||||
|
<hbr-copy-input
|
||||||
|
[title]="getPullCommandForDockerByTag(artifact)"
|
||||||
|
[iconMode]="true"
|
||||||
|
[defaultValue]="
|
||||||
|
getPullCommandForDockerByTag(artifact)
|
||||||
|
"></hbr-copy-input>
|
||||||
|
<span>{{ 'PUSH_IMAGE.DOCKER' | translate }}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex"
|
||||||
|
aria-label="Dropdown header Action"
|
||||||
|
clrDropdownItem>
|
||||||
|
<hbr-copy-input
|
||||||
|
[title]="getPullCommandForPadManByTag(artifact)"
|
||||||
|
[iconMode]="true"
|
||||||
|
[defaultValue]="
|
||||||
|
getPullCommandForPadManByTag(artifact)
|
||||||
|
"></hbr-copy-input>
|
||||||
|
<span>{{ 'PUSH_IMAGE.PODMAN' | translate }}</span>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
<div
|
||||||
|
*ngIf="isCNAB(artifact)"
|
||||||
|
class="flex"
|
||||||
|
aria-label="Dropdown header Action"
|
||||||
|
clrDropdownItem>
|
||||||
|
<hbr-copy-input
|
||||||
|
[title]="getPullCommandForCNABByTag(artifact)"
|
||||||
|
[iconMode]="true"
|
||||||
|
[defaultValue]="
|
||||||
|
getPullCommandForCNABByTag(artifact)
|
||||||
|
"></hbr-copy-input>
|
||||||
|
<span>{{ 'PUSH_IMAGE.CNAB' | translate }}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
*ngIf="isChart(artifact)"
|
||||||
|
class="flex"
|
||||||
|
aria-label="Dropdown header Action"
|
||||||
|
clrDropdownItem>
|
||||||
|
<hbr-copy-input
|
||||||
|
[title]="getPullCommandForChartByTag(artifact)"
|
||||||
|
[iconMode]="true"
|
||||||
|
[defaultValue]="
|
||||||
|
getPullCommandForChartByTag(artifact)
|
||||||
|
"></hbr-copy-input>
|
||||||
|
<span>{{ 'PUSH_IMAGE.HELM' | translate }}</span>
|
||||||
|
</div>
|
||||||
|
</clr-dropdown-menu>
|
||||||
|
</clr-dropdown>
|
@ -0,0 +1,8 @@
|
|||||||
|
.copy-pull-command {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
import { PullCommandComponent } from './pull-command.component';
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { SharedTestingModule } from '../../../../../../../../shared/shared.module';
|
||||||
|
|
||||||
|
describe('PullCommandComponent', () => {
|
||||||
|
let component: PullCommandComponent;
|
||||||
|
let fixture: ComponentFixture<PullCommandComponent>;
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [PullCommandComponent],
|
||||||
|
imports: [SharedTestingModule],
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(PullCommandComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,152 @@
|
|||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
import {
|
||||||
|
AccessoryType,
|
||||||
|
ArtifactFront as Artifact,
|
||||||
|
ArtifactType,
|
||||||
|
Clients,
|
||||||
|
getPullCommandByDigest,
|
||||||
|
getPullCommandByTag,
|
||||||
|
hasPullCommand,
|
||||||
|
} from '../../../../artifact';
|
||||||
|
import { Tag } from '../../../../../../../../../../ng-swagger-gen/models/tag';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-pull-command',
|
||||||
|
templateUrl: './pull-command.component.html',
|
||||||
|
styleUrls: ['./pull-command.component.scss'],
|
||||||
|
})
|
||||||
|
export class PullCommandComponent {
|
||||||
|
@Input()
|
||||||
|
isTagMode: boolean = false; // tagMode is for tag list datagrid,
|
||||||
|
@Input()
|
||||||
|
projectName: string;
|
||||||
|
@Input()
|
||||||
|
registryUrl: string;
|
||||||
|
@Input()
|
||||||
|
repoName: string;
|
||||||
|
@Input()
|
||||||
|
selectedRow: Artifact[];
|
||||||
|
|
||||||
|
// for tagMode
|
||||||
|
@Input()
|
||||||
|
selectedTags: Tag[];
|
||||||
|
@Input()
|
||||||
|
artifact: Artifact;
|
||||||
|
@Input()
|
||||||
|
accessoryType: string;
|
||||||
|
|
||||||
|
hasPullCommand(artifact: Artifact): boolean {
|
||||||
|
return hasPullCommand(artifact);
|
||||||
|
}
|
||||||
|
|
||||||
|
isImage(artifact: Artifact): boolean {
|
||||||
|
return artifact.type === ArtifactType.IMAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
isCNAB(artifact: Artifact): boolean {
|
||||||
|
return artifact.type === ArtifactType.CNAB;
|
||||||
|
}
|
||||||
|
|
||||||
|
isChart(artifact: Artifact): boolean {
|
||||||
|
return artifact.type === ArtifactType.CHART;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPullCommandForDocker(artifact: Artifact): string {
|
||||||
|
return getPullCommandByDigest(
|
||||||
|
artifact.type,
|
||||||
|
`${this.registryUrl ? this.registryUrl : location.hostname}/${
|
||||||
|
this.projectName
|
||||||
|
}/${this.repoName}`,
|
||||||
|
artifact.digest,
|
||||||
|
Clients.DOCKER
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPullCommandForPadMan(artifact: Artifact): string {
|
||||||
|
return getPullCommandByDigest(
|
||||||
|
artifact.type,
|
||||||
|
`${this.registryUrl ? this.registryUrl : location.hostname}/${
|
||||||
|
this.projectName
|
||||||
|
}/${this.repoName}`,
|
||||||
|
artifact.digest,
|
||||||
|
Clients.PODMAN
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPullCommandForCNAB(artifact: Artifact): string {
|
||||||
|
return getPullCommandByDigest(
|
||||||
|
artifact.type,
|
||||||
|
`${this.registryUrl ? this.registryUrl : location.hostname}/${
|
||||||
|
this.projectName
|
||||||
|
}/${this.repoName}`,
|
||||||
|
artifact.digest,
|
||||||
|
Clients.CNAB
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPullCommandForChart(artifact: Artifact): string {
|
||||||
|
return getPullCommandByTag(
|
||||||
|
artifact.type,
|
||||||
|
`${this.registryUrl ? this.registryUrl : location.hostname}/${
|
||||||
|
this.projectName
|
||||||
|
}/${this.repoName}`,
|
||||||
|
artifact.tags[0].name,
|
||||||
|
Clients.CHART
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For tagMode
|
||||||
|
hasPullCommandForTag(artifact): boolean {
|
||||||
|
return (
|
||||||
|
(artifact?.type === ArtifactType.IMAGE ||
|
||||||
|
artifact?.type === ArtifactType.CHART ||
|
||||||
|
artifact?.type === ArtifactType.CNAB) &&
|
||||||
|
this.accessoryType !== AccessoryType.COSIGN &&
|
||||||
|
this.accessoryType !== AccessoryType.NYDUS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPullCommandForDockerByTag(artifact: Artifact): string {
|
||||||
|
return getPullCommandByTag(
|
||||||
|
artifact.type,
|
||||||
|
`${this.registryUrl ? this.registryUrl : location.hostname}/${
|
||||||
|
this.projectName
|
||||||
|
}/${this.repoName}`,
|
||||||
|
this.selectedTags[0].name,
|
||||||
|
Clients.DOCKER
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPullCommandForPadManByTag(artifact: Artifact): string {
|
||||||
|
return getPullCommandByTag(
|
||||||
|
artifact.type,
|
||||||
|
`${this.registryUrl ? this.registryUrl : location.hostname}/${
|
||||||
|
this.projectName
|
||||||
|
}/${this.repoName}`,
|
||||||
|
this.selectedTags[0].name,
|
||||||
|
Clients.PODMAN
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPullCommandForCNABByTag(artifact: Artifact): string {
|
||||||
|
return getPullCommandByTag(
|
||||||
|
artifact.type,
|
||||||
|
`${this.registryUrl ? this.registryUrl : location.hostname}/${
|
||||||
|
this.projectName
|
||||||
|
}/${this.repoName}`,
|
||||||
|
this.selectedTags[0].name,
|
||||||
|
Clients.CNAB
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPullCommandForChartByTag(artifact: Artifact): string {
|
||||||
|
return getPullCommandByTag(
|
||||||
|
artifact.type,
|
||||||
|
`${this.registryUrl ? this.registryUrl : location.hostname}/${
|
||||||
|
this.projectName
|
||||||
|
}/${this.repoName}`,
|
||||||
|
this.selectedTags[0].name,
|
||||||
|
Clients.CHART
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -5,36 +5,52 @@
|
|||||||
(clrDgRefresh)="getCurrentArtifactTags($event)"
|
(clrDgRefresh)="getCurrentArtifactTags($event)"
|
||||||
[(clrDgSelected)]="selectedRow">
|
[(clrDgSelected)]="selectedRow">
|
||||||
<clr-dg-action-bar>
|
<clr-dg-action-bar>
|
||||||
<button
|
<div class="action-bar">
|
||||||
*ngIf="!isProxyCacheProject"
|
<div>
|
||||||
id="new-tag"
|
<button
|
||||||
type="button"
|
*ngIf="!isProxyCacheProject"
|
||||||
[disabled]="!hasCreateTagPermission"
|
id="new-tag"
|
||||||
class="btn btn-secondary"
|
type="button"
|
||||||
(click)="addTag()">
|
[disabled]="!hasCreateTagPermission"
|
||||||
<clr-icon shape="plus" size="16"></clr-icon> {{
|
class="btn btn-secondary"
|
||||||
'TAG.ADD_TAG' | translate
|
(click)="addTag()">
|
||||||
}}
|
<clr-icon shape="plus" size="16"></clr-icon> {{
|
||||||
</button>
|
'TAG.ADD_TAG' | translate
|
||||||
<button
|
}}
|
||||||
id="delete-tag"
|
</button>
|
||||||
type="button"
|
<button
|
||||||
class="btn btn-secondary"
|
id="delete-tag"
|
||||||
[disabled]="
|
type="button"
|
||||||
!(
|
class="btn btn-secondary"
|
||||||
selectedRow.length >= 1 &&
|
[disabled]="
|
||||||
!hasImmutableOnTag() &&
|
!(
|
||||||
hasDeleteTagPermission
|
selectedRow.length >= 1 &&
|
||||||
)
|
!hasImmutableOnTag() &&
|
||||||
"
|
hasDeleteTagPermission
|
||||||
(click)="removeTag()">
|
)
|
||||||
<clr-icon shape="trash" size="16"></clr-icon> {{
|
"
|
||||||
'TAG.REMOVE_TAG' | translate
|
(click)="removeTag()">
|
||||||
}}
|
<clr-icon shape="trash" size="16"></clr-icon> {{
|
||||||
</button>
|
'TAG.REMOVE_TAG' | translate
|
||||||
<span class="refresh-btn" (click)="refresh()">
|
}}
|
||||||
<clr-icon shape="refresh"></clr-icon>
|
</button>
|
||||||
</span>
|
</div>
|
||||||
|
<div class="right-pos">
|
||||||
|
<app-pull-command
|
||||||
|
[isTagMode]="true"
|
||||||
|
[artifact]="artifactDetails"
|
||||||
|
[accessoryType]="accessoryType"
|
||||||
|
[registryUrl]="registryUrl"
|
||||||
|
[projectName]="projectName"
|
||||||
|
[repoName]="repositoryName"
|
||||||
|
[selectedTags]="selectedRow"
|
||||||
|
class="mr-1"></app-pull-command>
|
||||||
|
<span class="refresh-btn" (click)="refresh()">
|
||||||
|
<clr-icon shape="refresh"></clr-icon>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
#tagForm="ngForm"
|
#tagForm="ngForm"
|
||||||
[hidden]="!newTagformShow"
|
[hidden]="!newTagformShow"
|
||||||
@ -102,9 +118,6 @@
|
|||||||
<clr-dg-column [clrDgField]="'name'">{{
|
<clr-dg-column [clrDgField]="'name'">{{
|
||||||
'TAG.NAME' | translate
|
'TAG.NAME' | translate
|
||||||
}}</clr-dg-column>
|
}}</clr-dg-column>
|
||||||
<clr-dg-column *ngIf="hasPullCommand()">{{
|
|
||||||
'REPOSITORY.PULL_COMMAND' | translate
|
|
||||||
}}</clr-dg-column>
|
|
||||||
<clr-dg-column [clrDgSortBy]="'pull_time'">{{
|
<clr-dg-column [clrDgSortBy]="'pull_time'">{{
|
||||||
'TAG.PULL_TIME' | translate
|
'TAG.PULL_TIME' | translate
|
||||||
}}</clr-dg-column>
|
}}</clr-dg-column>
|
||||||
@ -128,13 +141,6 @@
|
|||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
</clr-dg-cell>
|
</clr-dg-cell>
|
||||||
<clr-dg-cell *ngIf="hasPullCommand()">
|
|
||||||
<hbr-copy-input
|
|
||||||
[title]="getPullCommand(tag)"
|
|
||||||
*ngIf="getPullCommand(tag)"
|
|
||||||
[iconMode]="true"
|
|
||||||
[defaultValue]="getPullCommand(tag)"></hbr-copy-input>
|
|
||||||
</clr-dg-cell>
|
|
||||||
<clr-dg-cell>{{
|
<clr-dg-cell>{{
|
||||||
tag.pull_time !== availableTime
|
tag.pull_time !== availableTime
|
||||||
? (tag.pull_time | harborDatetime : 'short')
|
? (tag.pull_time | harborDatetime : 'short')
|
||||||
|
@ -39,9 +39,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.refresh-btn {
|
.refresh-btn {
|
||||||
float: right;
|
|
||||||
margin-top: 15px;
|
|
||||||
margin-right: 20px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,3 +47,15 @@
|
|||||||
right: -.7rem;
|
right: -.7rem;
|
||||||
top: 1.2rem;
|
top: 1.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-pos {
|
||||||
|
margin-right: 35px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
@ -23,13 +23,7 @@ import {
|
|||||||
OperateInfo,
|
OperateInfo,
|
||||||
OperationState,
|
OperationState,
|
||||||
} from '../../../../../shared/components/operation/operate';
|
} from '../../../../../shared/components/operation/operate';
|
||||||
import {
|
import { AccessoryQueryParams, ArtifactFront as Artifact } from '../artifact';
|
||||||
AccessoryQueryParams,
|
|
||||||
AccessoryType,
|
|
||||||
ArtifactFront as Artifact,
|
|
||||||
ArtifactType,
|
|
||||||
getPullCommandByTag,
|
|
||||||
} from '../artifact';
|
|
||||||
import { ArtifactService } from '../../../../../../../ng-swagger-gen/services/artifact.service';
|
import { ArtifactService } from '../../../../../../../ng-swagger-gen/services/artifact.service';
|
||||||
import { Tag } from '../../../../../../../ng-swagger-gen/models/tag';
|
import { Tag } from '../../../../../../../ng-swagger-gen/models/tag';
|
||||||
import {
|
import {
|
||||||
@ -49,7 +43,6 @@ import {
|
|||||||
PageSizeMapKeys,
|
PageSizeMapKeys,
|
||||||
setPageSizeToLocalStorage,
|
setPageSizeToLocalStorage,
|
||||||
} from '../../../../../shared/units/utils';
|
} from '../../../../../shared/units/utils';
|
||||||
import { AppConfigService } from '../../../../../services/app-config.service';
|
|
||||||
import { errorHandler } from '../../../../../shared/units/shared.utils';
|
import { errorHandler } from '../../../../../shared/units/shared.utils';
|
||||||
import { ConfirmationDialogComponent } from '../../../../../shared/components/confirmation-dialog';
|
import { ConfirmationDialogComponent } from '../../../../../shared/components/confirmation-dialog';
|
||||||
import { ConfirmationMessage } from '../../../../global-confirmation-dialog/confirmation-message';
|
import { ConfirmationMessage } from '../../../../global-confirmation-dialog/confirmation-message';
|
||||||
@ -59,8 +52,6 @@ import { ActivatedRoute } from '@angular/router';
|
|||||||
class InitTag {
|
class InitTag {
|
||||||
name = '';
|
name = '';
|
||||||
}
|
}
|
||||||
const DeleteTagWithNotoryCommand1 = 'notary -s https://';
|
|
||||||
const DeleteTagWithNotoryCommand2 = ':4443 -d ~/.docker/trust remove -p ';
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'artifact-tag',
|
selector: 'artifact-tag',
|
||||||
templateUrl: './artifact-tag.component.html',
|
templateUrl: './artifact-tag.component.html',
|
||||||
@ -73,7 +64,6 @@ export class ArtifactTagComponent implements OnInit, OnDestroy {
|
|||||||
@Input() projectId: number;
|
@Input() projectId: number;
|
||||||
@Input() repositoryName: string;
|
@Input() repositoryName: string;
|
||||||
newTagName = new InitTag();
|
newTagName = new InitTag();
|
||||||
newTagForm: NgForm;
|
|
||||||
@ViewChild('newTagForm', { static: true }) currentForm: NgForm;
|
@ViewChild('newTagForm', { static: true }) currentForm: NgForm;
|
||||||
selectedRow: Tag[] = [];
|
selectedRow: Tag[] = [];
|
||||||
isTagNameExist = false;
|
isTagNameExist = false;
|
||||||
@ -87,7 +77,6 @@ export class ArtifactTagComponent implements OnInit, OnDestroy {
|
|||||||
hasCreateTagPermission: boolean;
|
hasCreateTagPermission: boolean;
|
||||||
|
|
||||||
totalCount: number = 0;
|
totalCount: number = 0;
|
||||||
allTags: Tag[] = [];
|
|
||||||
currentTags: Tag[] = [];
|
currentTags: Tag[] = [];
|
||||||
pageSize: number = getPageSizeFromLocalStorage(
|
pageSize: number = getPageSizeFromLocalStorage(
|
||||||
PageSizeMapKeys.ARTIFACT_TAGS_COMPONENT
|
PageSizeMapKeys.ARTIFACT_TAGS_COMPONENT
|
||||||
@ -341,12 +330,6 @@ export class ArtifactTagComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
deletePort(url): string {
|
|
||||||
if (url && url.indexOf(':') !== -1) {
|
|
||||||
return url.split(':')[0];
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
delOperate(tag: Tag): Observable<any> | null {
|
delOperate(tag: Tag): Observable<any> | null {
|
||||||
// init operation info
|
// init operation info
|
||||||
let operMessage = new OperateInfo();
|
let operMessage = new OperateInfo();
|
||||||
@ -387,10 +370,6 @@ export class ArtifactTagComponent implements OnInit, OnDestroy {
|
|||||||
this.isTagNameExist = false;
|
this.isTagNameExist = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toggleTagListOpenOrClose() {
|
|
||||||
this.openTag = !this.openTag;
|
|
||||||
this.newTagformShow = false;
|
|
||||||
}
|
|
||||||
hasImmutableOnTag(): boolean {
|
hasImmutableOnTag(): boolean {
|
||||||
return this.selectedRow.some(artifact => artifact.immutable);
|
return this.selectedRow.some(artifact => artifact.immutable);
|
||||||
}
|
}
|
||||||
@ -413,25 +392,4 @@ export class ArtifactTagComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
return location.hostname;
|
return location.hostname;
|
||||||
}
|
}
|
||||||
hasPullCommand(): boolean {
|
|
||||||
return (
|
|
||||||
this.artifactDetails &&
|
|
||||||
(this.artifactDetails.type === ArtifactType.IMAGE ||
|
|
||||||
this.artifactDetails.type === ArtifactType.CHART ||
|
|
||||||
this.artifactDetails.type === ArtifactType.CNAB) &&
|
|
||||||
this.accessoryType !== AccessoryType.COSIGN &&
|
|
||||||
this.accessoryType !== AccessoryType.NYDUS
|
|
||||||
);
|
|
||||||
}
|
|
||||||
getPullCommand(tag: Tag): string {
|
|
||||||
let pullCommand: string = '';
|
|
||||||
if (tag && tag.name && this.artifactDetails) {
|
|
||||||
pullCommand = getPullCommandByTag(
|
|
||||||
this.artifactDetails?.type,
|
|
||||||
`${this.registryUrl}/${this.projectName}/${this.repositoryName}`,
|
|
||||||
tag.name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return pullCommand;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import { ArtifactListPageService } from './artifact-list-page/artifact-list-page
|
|||||||
import { CopyArtifactComponent } from './artifact-list-page/artifact-list/artifact-list-tab/copy-artifact/copy-artifact.component';
|
import { CopyArtifactComponent } from './artifact-list-page/artifact-list/artifact-list-tab/copy-artifact/copy-artifact.component';
|
||||||
import { CopyDigestComponent } from './artifact-list-page/artifact-list/artifact-list-tab/copy-digest/copy-digest.component';
|
import { CopyDigestComponent } from './artifact-list-page/artifact-list/artifact-list-tab/copy-digest/copy-digest.component';
|
||||||
import { ArtifactFilterComponent } from './artifact-list-page/artifact-list/artifact-list-tab/artifact-filter/artifact-filter.component';
|
import { ArtifactFilterComponent } from './artifact-list-page/artifact-list/artifact-list-tab/artifact-filter/artifact-filter.component';
|
||||||
|
import { PullCommandComponent } from './artifact-list-page/artifact-list/artifact-list-tab/pull-command/pull-command.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
@ -88,6 +89,7 @@ const routes: Routes = [
|
|||||||
CopyArtifactComponent,
|
CopyArtifactComponent,
|
||||||
CopyDigestComponent,
|
CopyDigestComponent,
|
||||||
ArtifactFilterComponent,
|
ArtifactFilterComponent,
|
||||||
|
PullCommandComponent,
|
||||||
],
|
],
|
||||||
imports: [RouterModule.forChild(routes), SharedModule],
|
imports: [RouterModule.forChild(routes), SharedModule],
|
||||||
providers: [
|
providers: [
|
||||||
|
@ -89,41 +89,59 @@ export enum AccessoryQueryParams {
|
|||||||
ACCESSORY_TYPE = 'accessoryType',
|
ACCESSORY_TYPE = 'accessoryType',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function hasPullCommand(artifact: Artifact): boolean {
|
||||||
|
return (
|
||||||
|
artifact.type === ArtifactType.IMAGE ||
|
||||||
|
artifact.type === ArtifactType.CNAB ||
|
||||||
|
artifact.type === ArtifactType.CHART
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function getPullCommandByDigest(
|
export function getPullCommandByDigest(
|
||||||
artifactType: string,
|
artifactType: string,
|
||||||
url: string,
|
url: string,
|
||||||
digest: string
|
digest: string,
|
||||||
|
client: Clients
|
||||||
): string {
|
): string {
|
||||||
let pullCommand: string = '';
|
|
||||||
if (artifactType && url && digest) {
|
if (artifactType && url && digest) {
|
||||||
if (artifactType === ArtifactType.IMAGE) {
|
if (artifactType === ArtifactType.IMAGE) {
|
||||||
pullCommand = `docker pull ${url}@${digest}`;
|
if (client === Clients.DOCKER) {
|
||||||
|
return `${Clients.DOCKER} pull ${url}@${digest}`;
|
||||||
|
}
|
||||||
|
if (client === Clients.PODMAN) {
|
||||||
|
return `${Clients.PODMAN} pull ${url}@${digest}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (artifactType === ArtifactType.CNAB) {
|
if (artifactType === ArtifactType.CNAB) {
|
||||||
pullCommand = `cnab-to-oci pull ${url}@${digest}`;
|
return `${Clients.CNAB} pull ${url}@${digest}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pullCommand;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPullCommandByTag(
|
export function getPullCommandByTag(
|
||||||
artifactType: string,
|
artifactType: string,
|
||||||
url: string,
|
url: string,
|
||||||
tag: string
|
tag: string,
|
||||||
|
client: Clients
|
||||||
): string {
|
): string {
|
||||||
let pullCommand: string = '';
|
|
||||||
if (artifactType && url && tag) {
|
if (artifactType && url && tag) {
|
||||||
if (artifactType === ArtifactType.IMAGE) {
|
if (artifactType === ArtifactType.IMAGE) {
|
||||||
pullCommand = `docker pull ${url}:${tag}`;
|
if (client === Clients.DOCKER) {
|
||||||
|
return `${Clients.DOCKER} pull ${url}:${tag}`;
|
||||||
|
}
|
||||||
|
if (client === Clients.PODMAN) {
|
||||||
|
return `${Clients.PODMAN} pull ${url}:${tag}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (artifactType === ArtifactType.CNAB) {
|
if (artifactType === ArtifactType.CNAB) {
|
||||||
pullCommand = `cnab-to-oci pull ${url}:${tag}`;
|
return `cnab-to-oci pull ${url}:${tag}`;
|
||||||
}
|
}
|
||||||
if (artifactType === ArtifactType.CHART) {
|
if (artifactType === ArtifactType.CHART) {
|
||||||
pullCommand = `helm pull oci://${url} --version ${tag}`;
|
return `helm pull oci://${url} --version ${tag}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pullCommand;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ArtifactFilterEvent {
|
export interface ArtifactFilterEvent {
|
||||||
@ -133,3 +151,17 @@ export interface ArtifactFilterEvent {
|
|||||||
isInputTag?: boolean;
|
isInputTag?: boolean;
|
||||||
label?: Label;
|
label?: Label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum Clients {
|
||||||
|
DOCKER = 'docker',
|
||||||
|
PODMAN = 'podman',
|
||||||
|
CHART = 'helm',
|
||||||
|
CNAB = 'cnab-to-oci',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ClientNames {
|
||||||
|
DOCKER = 'Docker',
|
||||||
|
PODMAN = 'Podman',
|
||||||
|
CHART = 'Helm',
|
||||||
|
CNAB = 'CNAB',
|
||||||
|
}
|
||||||
|
@ -1044,7 +1044,8 @@
|
|||||||
"TOOLTIP": "Befehlreferenz um ein Artefakt in das Projekt zu pushen.",
|
"TOOLTIP": "Befehlreferenz um ein Artefakt in das Projekt zu pushen.",
|
||||||
"TAG_COMMAND": "Tag ein Image für dieses Projekt:",
|
"TAG_COMMAND": "Tag ein Image für dieses Projekt:",
|
||||||
"PUSH_COMMAND": "Push ein Image für dieses Projekt:",
|
"PUSH_COMMAND": "Push ein Image für dieses Projekt:",
|
||||||
"COPY_ERROR": "Kopieren fehlgeschlagen, bitte die Befehlsreferenz manuell kopieren."
|
"COPY_ERROR": "Kopieren fehlgeschlagen, bitte die Befehlsreferenz manuell kopieren.",
|
||||||
|
"COPY_PULL_COMMAND": "COPY PULL COMMAND"
|
||||||
},
|
},
|
||||||
"ARTIFACT": {
|
"ARTIFACT": {
|
||||||
"FILTER_FOR_ARTIFACTS": "Filter Artefakte",
|
"FILTER_FOR_ARTIFACTS": "Filter Artefakte",
|
||||||
|
@ -1045,7 +1045,8 @@
|
|||||||
"TOOLTIP": "Command references for pushing an artifact to this project.",
|
"TOOLTIP": "Command references for pushing an artifact to this project.",
|
||||||
"TAG_COMMAND": "Tag an image for this project:",
|
"TAG_COMMAND": "Tag an image for this project:",
|
||||||
"PUSH_COMMAND": "Push an image to this project:",
|
"PUSH_COMMAND": "Push an image to this project:",
|
||||||
"COPY_ERROR": "Copy failed, please try to manually copy the command references."
|
"COPY_ERROR": "Copy failed, please try to manually copy the command references.",
|
||||||
|
"COPY_PULL_COMMAND": "COPY PULL COMMAND"
|
||||||
},
|
},
|
||||||
"ARTIFACT": {
|
"ARTIFACT": {
|
||||||
"FILTER_FOR_ARTIFACTS": "Filter Artifacts",
|
"FILTER_FOR_ARTIFACTS": "Filter Artifacts",
|
||||||
|
@ -1043,7 +1043,8 @@
|
|||||||
"TOOLTIP": "Command references for pushing an artifact to this project.",
|
"TOOLTIP": "Command references for pushing an artifact to this project.",
|
||||||
"TAG_COMMAND": "Tag an image for this project:",
|
"TAG_COMMAND": "Tag an image for this project:",
|
||||||
"PUSH_COMMAND": "Push an image to this project:",
|
"PUSH_COMMAND": "Push an image to this project:",
|
||||||
"COPY_ERROR": "Copy failed, please try to manually copy the command references."
|
"COPY_ERROR": "Copy failed, please try to manually copy the command references.",
|
||||||
|
"COPY_PULL_COMMAND": "COPY PULL COMMAND"
|
||||||
},
|
},
|
||||||
"ARTIFACT": {
|
"ARTIFACT": {
|
||||||
"FILTER_FOR_ARTIFACTS": "Filter Artifacts",
|
"FILTER_FOR_ARTIFACTS": "Filter Artifacts",
|
||||||
|
@ -1016,7 +1016,8 @@
|
|||||||
"TOOLTIP": "Commandes pour push un artefact dans ce projet.",
|
"TOOLTIP": "Commandes pour push un artefact dans ce projet.",
|
||||||
"TAG_COMMAND": "Taguer une image pour ce projet :",
|
"TAG_COMMAND": "Taguer une image pour ce projet :",
|
||||||
"PUSH_COMMAND": "Push une image dans ce projet :",
|
"PUSH_COMMAND": "Push une image dans ce projet :",
|
||||||
"COPY_ERROR": "Copie échouée, veuillez essayer de copier manuellement les commandes de référence."
|
"COPY_ERROR": "Copie échouée, veuillez essayer de copier manuellement les commandes de référence.",
|
||||||
|
"COPY_PULL_COMMAND": "COPY PULL COMMAND"
|
||||||
},
|
},
|
||||||
"ARTIFACT": {
|
"ARTIFACT": {
|
||||||
"FILTER_FOR_ARTIFACTS": "Filtrer les artefacts",
|
"FILTER_FOR_ARTIFACTS": "Filtrer les artefacts",
|
||||||
|
@ -1041,7 +1041,8 @@
|
|||||||
"TOOLTIP": "Referência de comandos para enviar artefatos a este projeto.",
|
"TOOLTIP": "Referência de comandos para enviar artefatos a este projeto.",
|
||||||
"TAG_COMMAND": "Colocar tag em uma imagem deste projeto:",
|
"TAG_COMMAND": "Colocar tag em uma imagem deste projeto:",
|
||||||
"PUSH_COMMAND": "Envia uma imagem a esse projeto:",
|
"PUSH_COMMAND": "Envia uma imagem a esse projeto:",
|
||||||
"COPY_ERROR": "Cópia falhou, por favor tente copiar o comando de referência manualmente."
|
"COPY_ERROR": "Cópia falhou, por favor tente copiar o comando de referência manualmente.",
|
||||||
|
"COPY_PULL_COMMAND": "COPY PULL COMMAND"
|
||||||
},
|
},
|
||||||
"ARTIFACT": {
|
"ARTIFACT": {
|
||||||
"FILTER_FOR_ARTIFACTS": "Filtrar",
|
"FILTER_FOR_ARTIFACTS": "Filtrar",
|
||||||
|
@ -1044,7 +1044,8 @@
|
|||||||
"TOOLTIP": "Command references for pushing an artifact to this project.",
|
"TOOLTIP": "Command references for pushing an artifact to this project.",
|
||||||
"TAG_COMMAND": "Bu proje için bir imaj etiketleyin:",
|
"TAG_COMMAND": "Bu proje için bir imaj etiketleyin:",
|
||||||
"PUSH_COMMAND": "Bu projeye bir imaj gönder:",
|
"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."
|
"COPY_ERROR": "Kopyalama başarısız oldu, lütfen komut referanslarını el ile kopyalamayı deneyin.",
|
||||||
|
"COPY_PULL_COMMAND": "COPY PULL COMMAND"
|
||||||
},
|
},
|
||||||
"ARTIFACT": {
|
"ARTIFACT": {
|
||||||
"FILTER_FOR_ARTIFACTS": "Filter Artifacts",
|
"FILTER_FOR_ARTIFACTS": "Filter Artifacts",
|
||||||
|
@ -1043,7 +1043,8 @@
|
|||||||
"TOOLTIP": "推送一个 artifact 到当前项目的参考命令。",
|
"TOOLTIP": "推送一个 artifact 到当前项目的参考命令。",
|
||||||
"TAG_COMMAND": "在项目中标记镜像:",
|
"TAG_COMMAND": "在项目中标记镜像:",
|
||||||
"PUSH_COMMAND": "推送镜像到当前项目:",
|
"PUSH_COMMAND": "推送镜像到当前项目:",
|
||||||
"COPY_ERROR": "拷贝失败,请尝试手动拷贝参考命令。"
|
"COPY_ERROR": "拷贝失败,请尝试手动拷贝参考命令。",
|
||||||
|
"COPY_PULL_COMMAND": "复制拉取命令"
|
||||||
},
|
},
|
||||||
"ARTIFACT": {
|
"ARTIFACT": {
|
||||||
"FILTER_FOR_ARTIFACTS": "Filter Artifacts",
|
"FILTER_FOR_ARTIFACTS": "Filter Artifacts",
|
||||||
|
@ -1038,7 +1038,8 @@
|
|||||||
"TOOLTIP": "將映像檔推送至此專案的參考命令。",
|
"TOOLTIP": "將映像檔推送至此專案的參考命令。",
|
||||||
"TAG_COMMAND": "在項目中標記映像檔:",
|
"TAG_COMMAND": "在項目中標記映像檔:",
|
||||||
"PUSH_COMMAND": "推送映像檔到目前項目:",
|
"PUSH_COMMAND": "推送映像檔到目前項目:",
|
||||||
"COPY_ERROR": "複製失敗,請嘗試手動複製參考命令。"
|
"COPY_ERROR": "複製失敗,請嘗試手動複製參考命令。",
|
||||||
|
"COPY_PULL_COMMAND": "COPY PULL COMMAND"
|
||||||
},
|
},
|
||||||
"ARTIFACT": {
|
"ARTIFACT": {
|
||||||
"FILTER_FOR_ARTIFACTS": "篩選器",
|
"FILTER_FOR_ARTIFACTS": "篩選器",
|
||||||
|
Loading…
Reference in New Issue
Block a user