mirror of
https://github.com/goharbor/harbor.git
synced 2025-02-27 01:02:34 +01:00
Add copy_by-chunk checkbox for replication rule (#17617)
Signed-off-by: AllForNothing <sshijun@vmware.com> Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
parent
c330b8c63a
commit
0edc01a395
@ -537,7 +537,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<!--destination namespaces -->
|
||||
<div class="clr-form-control">
|
||||
<div class="clr-form-control flattening">
|
||||
<label
|
||||
for="dest_namespace_replace_count"
|
||||
class="clr-control-label"></label>
|
||||
@ -704,7 +704,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<!--speed-->
|
||||
<div class="clr-form-control">
|
||||
<div class="clr-form-control bandwidth">
|
||||
<label for="speed" class="required clr-control-label"
|
||||
>{{ 'REPLICATION.BANDWIDTH' | translate }}
|
||||
</label>
|
||||
@ -776,18 +776,21 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--override and enable-->
|
||||
<!--override and enable and chunk-->
|
||||
<div class="clr-form-control">
|
||||
<label class="clr-control-label"></label>
|
||||
<div class="clr-control-container">
|
||||
<div class="clr-checkbox-wrapper clr-form-control">
|
||||
<label class="clr-control-label">{{
|
||||
'SCANNER.OPTIONS' | translate
|
||||
}}</label>
|
||||
|
||||
<div class="clr-control-container clr-control-inline">
|
||||
<div class="clr-checkbox-wrapper">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="clr-checkbox"
|
||||
[checked]="true"
|
||||
id="overridePolicy"
|
||||
formControlName="override" />
|
||||
<label for="overridePolicy"
|
||||
<label for="overridePolicy" class="clr-control-label"
|
||||
>{{ 'REPLICATION.OVERRIDE_INFO' | translate }}
|
||||
<clr-tooltip class="override-tooltip">
|
||||
<clr-icon
|
||||
@ -806,8 +809,33 @@
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="clr-checkbox-wrapper clr-form-control"
|
||||
[hidden]="policyId < 0">
|
||||
class="clr-checkbox-wrapper"
|
||||
[hidden]="!showChunkOption">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="by-chunk"
|
||||
formControlName="copy_by_chunk"
|
||||
class="clr-checkbox" />
|
||||
<label for="by-chunk" class="clr-control-label"
|
||||
>{{ 'REPLICATION.COPY_BY_CHUNK' | translate }}
|
||||
<clr-tooltip class="override-tooltip">
|
||||
<clr-icon
|
||||
clrTooltipTrigger
|
||||
shape="info-circle"
|
||||
size="24"></clr-icon>
|
||||
<clr-tooltip-content
|
||||
clrPosition="top-left"
|
||||
clrSize="md"
|
||||
*clrIfOpen>
|
||||
<span>{{
|
||||
'REPLICATION.COPY_BY_CHUNK_TIP'
|
||||
| translate
|
||||
}}</span>
|
||||
</clr-tooltip-content>
|
||||
</clr-tooltip>
|
||||
</label>
|
||||
</div>
|
||||
<div class="clr-checkbox-wrapper" [hidden]="policyId < 0">
|
||||
<input
|
||||
type="checkbox"
|
||||
[checked]="true"
|
||||
|
@ -28,7 +28,7 @@ h4 {
|
||||
.filterSelect {
|
||||
position: relative;
|
||||
width: 315px;
|
||||
margin-bottom:0.5rem;
|
||||
margin-bottom:0.25rem;
|
||||
}
|
||||
|
||||
.filterSelect clr-icon {
|
||||
@ -315,3 +315,15 @@ clr-modal {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.clr-form-control {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.flattening {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.bandwidth {
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
@ -226,6 +226,9 @@ describe('CreateEditRuleComponent (inline template)', () => {
|
||||
listRegistries() {
|
||||
return of(mockEndpoints).pipe(delay(0));
|
||||
},
|
||||
getRegistryInfo() {
|
||||
return of(mockRegistryInfo).pipe(delay(0));
|
||||
},
|
||||
};
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
|
@ -53,6 +53,7 @@ import {
|
||||
} from '../../replication';
|
||||
import { errorHandler as errorHandlerFn } from '../../../../../shared/units/shared.utils';
|
||||
import { ReplicationPolicy } from '../../../../../../../ng-swagger-gen/models/replication-policy';
|
||||
import { RegistryInfo } from 'ng-swagger-gen/models';
|
||||
|
||||
const PREFIX: string = '0 ';
|
||||
const PAGE_SIZE: number = 100;
|
||||
@ -116,6 +117,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
||||
];
|
||||
selectedUnit: string = BandwidthUnit.KB;
|
||||
copySpeedUnit: string = BandwidthUnit.KB;
|
||||
showChunkOption: boolean = false;
|
||||
constructor(
|
||||
private fb: UntypedFormBuilder,
|
||||
private repService: ReplicationService,
|
||||
@ -128,18 +130,21 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
initRegistryInfo(id: number): void {
|
||||
this.onGoing = true;
|
||||
this.repService
|
||||
.getRegistryInfo(id)
|
||||
.pipe(finalize(() => (this.onGoing = false)))
|
||||
.subscribe(
|
||||
adapter => {
|
||||
this.inProgress = true;
|
||||
this.endpointService
|
||||
.getRegistryInfo({ id: id })
|
||||
.pipe(finalize(() => (this.inProgress = false)))
|
||||
.subscribe({
|
||||
next: adapter => {
|
||||
this.setFilterAndTrigger(adapter);
|
||||
if (id) {
|
||||
this.checkChunkOption(id, adapter);
|
||||
}
|
||||
},
|
||||
(error: any) => {
|
||||
error: error => {
|
||||
this.inlineAlert.showInlineError(error);
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
getAllRegistries() {
|
||||
this.endpointService
|
||||
@ -240,6 +245,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
||||
pushModeChange(): void {
|
||||
this.setFilter([]);
|
||||
this.initRegistryInfo(0);
|
||||
this.checkChunkOption(this.ruleForm?.get('dest_registry')?.value?.id);
|
||||
}
|
||||
|
||||
pullModeChange(): void {
|
||||
@ -247,6 +253,8 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
||||
if (selectId) {
|
||||
this.setFilter([]);
|
||||
this.initRegistryInfo(selectId.id);
|
||||
} else {
|
||||
this.checkChunkOption(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -316,6 +324,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
||||
deletion: false,
|
||||
override: true,
|
||||
speed: -1,
|
||||
copy_by_chunk: false,
|
||||
});
|
||||
}
|
||||
|
||||
@ -348,6 +357,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
||||
override: true,
|
||||
dest_namespace_replace_count: Flatten_Level.FLATTEN_LEVEl_1,
|
||||
speed: -1,
|
||||
copy_by_chunk: false,
|
||||
});
|
||||
this.isPushMode = true;
|
||||
this.selectedUnit = BandwidthUnit.KB;
|
||||
@ -355,6 +365,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
||||
|
||||
updateRuleFormAndCopyUpdateForm(rule: ReplicationPolicy): void {
|
||||
this.isPushMode = rule.dest_registry.id !== 0;
|
||||
this.checkChunkOption(rule.dest_registry.id || rule.src_registry.id);
|
||||
setTimeout(() => {
|
||||
// convert speed unit to KB or MB
|
||||
let speed: number = this.convertToInputValue(rule.speed);
|
||||
@ -374,6 +385,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
||||
enabled: rule.enabled,
|
||||
override: rule.override,
|
||||
speed: speed,
|
||||
copy_by_chunk: rule.copy_by_chunk,
|
||||
});
|
||||
let filtersArray = this.getFilterArray(rule);
|
||||
this.noSelectedEndpoint = false;
|
||||
@ -448,6 +460,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
||||
return;
|
||||
}
|
||||
this.noSelectedEndpoint = false;
|
||||
this.initRegistryInfo(this.ruleForm.get('dest_registry').value.id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -504,6 +517,10 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
||||
copyRuleForm.filters.splice(i, 1);
|
||||
}
|
||||
}
|
||||
if (!this.showChunkOption) {
|
||||
delete copyRuleForm?.copy_by_chunk;
|
||||
delete this.ruleForm?.value?.copy_by_chunk;
|
||||
}
|
||||
|
||||
if (this.policyId < 0) {
|
||||
this.repService.createReplicationRule(copyRuleForm).subscribe(
|
||||
@ -549,6 +566,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
||||
this.policyId = -1;
|
||||
this.createEditRuleOpened = true;
|
||||
this.noEndpointInfo = '';
|
||||
this.showChunkOption = false;
|
||||
if (this.targetList.length === 0) {
|
||||
this.noEndpointInfo = 'REPLICATION.NO_ENDPOINT_INFO';
|
||||
}
|
||||
@ -876,4 +894,19 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
||||
return label;
|
||||
}
|
||||
}
|
||||
checkChunkOption(id: number, info?: RegistryInfo) {
|
||||
this.showChunkOption = false;
|
||||
this.ruleForm.get('copy_by_chunk').reset(false);
|
||||
if (info) {
|
||||
this.showChunkOption = info.supported_copy_by_chunk;
|
||||
} else {
|
||||
if (id) {
|
||||
this.endpointService.getRegistryInfo({ id }).subscribe(res => {
|
||||
if (res) {
|
||||
this.showChunkOption = res.supported_copy_by_chunk;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -659,7 +659,9 @@
|
||||
"BANDWIDTH_TOOLTIP": "Legt die maximale Netzwerkbandbreite für jede Ausführung fest. Bitte auf die Anzahl der parallelen Ausführungen achten. Für umbegrenzte Bandbreite, bitte -1 eingeben",
|
||||
"UNLIMITED": "Unbegrenzt",
|
||||
"UNREACHABLE_SOURCE_REGISTRY": "Failed to connect to the source registry, please make sure the source registry is available before editing this rule: {{error}}",
|
||||
"CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field"
|
||||
"CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field",
|
||||
"COPY_BY_CHUNK": "Copy by chunk",
|
||||
"COPY_BY_CHUNK_TIP": "Specify whether to copy the blob by chunk. Transfer by chunk may increase the number of API requests."
|
||||
},
|
||||
"DESTINATION": {
|
||||
"NEW_ENDPOINT": "Neuer Endpunkt",
|
||||
|
@ -659,7 +659,9 @@
|
||||
"BANDWIDTH_TOOLTIP": "Set the maximum network bandwidth for each execution. Please pay attention to the number of concurrent executions. For unlimited bandwidth, please enter -1",
|
||||
"UNLIMITED": "Unlimited",
|
||||
"UNREACHABLE_SOURCE_REGISTRY": "Failed to connect to the source registry, please make sure the source registry is available before editing this rule: {{error}}",
|
||||
"CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field"
|
||||
"CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field",
|
||||
"COPY_BY_CHUNK": "Copy by chunk",
|
||||
"COPY_BY_CHUNK_TIP": "Specify whether to copy the blob by chunk. Transfer by chunk may increase the number of API requests."
|
||||
},
|
||||
"DESTINATION": {
|
||||
"NEW_ENDPOINT": "New Endpoint",
|
||||
|
@ -661,7 +661,9 @@
|
||||
"BANDWIDTH_TOOLTIP": "Set the maximum network bandwidth for each execution. Please pay attention to the number of concurrent executions. For unlimited bandwidth, please enter -1",
|
||||
"UNLIMITED": "Unlimited",
|
||||
"UNREACHABLE_SOURCE_REGISTRY": "Failed to connect to the source registry, please make sure the source registry is available before editing this rule: {{error}}",
|
||||
"CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field"
|
||||
"CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field",
|
||||
"COPY_BY_CHUNK": "Copy by chunk",
|
||||
"COPY_BY_CHUNK_TIP": "Specify whether to copy the blob by chunk. Transfer by chunk may increase the number of API requests."
|
||||
},
|
||||
"DESTINATION": {
|
||||
"NEW_ENDPOINT": "Nuevo Endpoint",
|
||||
|
@ -649,7 +649,9 @@
|
||||
"BANDWIDTH_TOOLTIP": "Définissez la bande passante réseau maximale pour chaque exécution. Veuillez faire attention au nombre d'exécutions simultanées. Pour une bande passante illimitée, veuillez entrer -1",
|
||||
"UNLIMITED": "Illimitée",
|
||||
"UNREACHABLE_SOURCE_REGISTRY": "Failed to connect to the source registry, please make sure the source registry is available before editing this rule: {{error}}",
|
||||
"CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field"
|
||||
"CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field",
|
||||
"COPY_BY_CHUNK": "Copy by chunk",
|
||||
"COPY_BY_CHUNK_TIP": "Specify whether to copy the blob by chunk. Transfer by chunk may increase the number of API requests."
|
||||
},
|
||||
"DESTINATION": {
|
||||
"NEW_ENDPOINT": "Nouveau Endpoint",
|
||||
|
@ -659,7 +659,9 @@
|
||||
"BANDWIDTH_TOOLTIP": "Informe o limite de banda para cada execução. Tome cuidado e observe a relação com o número de execuções simultâneas. Para remover qualquer limite, informe -1",
|
||||
"UNLIMITED": "Ilimitado",
|
||||
"UNREACHABLE_SOURCE_REGISTRY": "Failed to connect to the source registry, please make sure the source registry is available before editing this rule: {{error}}",
|
||||
"CRON_ERROR_TIP": "Field is required and \"*\"is not allowed for the \"Minutes\" field"
|
||||
"CRON_ERROR_TIP": "Field is required and \"*\"is not allowed for the \"Minutes\" field",
|
||||
"COPY_BY_CHUNK": "Copy by chunk",
|
||||
"COPY_BY_CHUNK_TIP": "Specify whether to copy the blob by chunk. Transfer by chunk may increase the number of API requests."
|
||||
},
|
||||
"DESTINATION": {
|
||||
"NEW_ENDPOINT": "Novo Endereço",
|
||||
|
@ -659,7 +659,9 @@
|
||||
"BANDWIDTH_TOOLTIP": "Set the maximum network bandwidth for each execution. Please pay attention to the number of concurrent executions. For unlimited bandwidth, please enter -1",
|
||||
"UNLIMITED": "Unlimited",
|
||||
"UNREACHABLE_SOURCE_REGISTRY": "Failed to connect to the source registry, please make sure the source registry is available before editing this rule: {{error}}",
|
||||
"CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field"
|
||||
"CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field",
|
||||
"COPY_BY_CHUNK": "Copy by chunk",
|
||||
"COPY_BY_CHUNK_TIP": "Specify whether to copy the blob by chunk. Transfer by chunk may increase the number of API requests."
|
||||
},
|
||||
"DESTINATION": {
|
||||
"NEW_ENDPOINT": "Yeni Uç Nokta",
|
||||
|
@ -661,7 +661,9 @@
|
||||
"BANDWIDTH_TOOLTIP": "设置执行该条同步规则时的最大网络带宽。实际总带宽需要考虑并发执行的情况。如无需限制,请输入-1",
|
||||
"UNLIMITED": "无限制",
|
||||
"UNREACHABLE_SOURCE_REGISTRY": "连接源仓库失败,在编辑此规则前请先确保源仓库可用: {{error}}",
|
||||
"CRON_ERROR_TIP": "此项必填且\"分钟\"项不能为\"*\""
|
||||
"CRON_ERROR_TIP": "此项必填且\"分钟\"项不能为\"*\"",
|
||||
"COPY_BY_CHUNK": "分块复制",
|
||||
"COPY_BY_CHUNK_TIP": "请指定是否开启分块复制。开启此项可能导致相应的 API 请求数量增加。"
|
||||
},
|
||||
"DESTINATION": {
|
||||
"NEW_ENDPOINT": "新建目标",
|
||||
|
@ -656,7 +656,9 @@
|
||||
"BANDWIDTH_TOOLTIP": "Set the maximum network bandwidth for each execution. Please pay attention to the number of concurrent executions. For unlimited bandwidth, please enter -1",
|
||||
"UNLIMITED": "Unlimited",
|
||||
"UNREACHABLE_SOURCE_REGISTRY": "Failed to connect to the source registry, please make sure the source registry is available before editing this rule: {{error}}",
|
||||
"CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field"
|
||||
"CRON_ERROR_TIP": "Field is required and \"*\" is not allowed for the \"Minutes\" field",
|
||||
"COPY_BY_CHUNK": "Copy by chunk",
|
||||
"COPY_BY_CHUNK_TIP": "Specify whether to copy the blob by chunk. Transfer by chunk may increase the number of API requests."
|
||||
},
|
||||
"DESTINATION":{
|
||||
"NEW_ENDPOINT": "新建目標",
|
||||
|
Loading…
Reference in New Issue
Block a user