UI Changes for Configuring Proxy-Cache Speed Limit (#20946)

* Implemented proxy-cache bandwidth limit UI change

Signed-off-by: kunal-511 <yoyokvunal@gmail.com>

* Removed ducplicate space between words

Signed-off-by: kunal-511 <yoyokvunal@gmail.com>

* Fix UT issue

Signed-off-by: stonezdj <stone.zhang@broadcom.com>

---------

Signed-off-by: kunal-511 <yoyokvunal@gmail.com>
Signed-off-by: stonezdj <stone.zhang@broadcom.com>
Co-authored-by: stonezdj <stone.zhang@broadcom.com>
This commit is contained in:
kunal Dugar 2024-09-27 10:15:52 +05:30 committed by GitHub
parent e4fe61ddb7
commit ab400c9dd2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 147 additions and 2 deletions

View File

@ -223,6 +223,64 @@
</div> </div>
</div> </div>
</div> </div>
<div
class="clr-form-control mt-05"
[ngStyle]="{
visibility:
isSystemAdmin && enableProxyCache ? 'visible' : 'hidden'
}">
<label for="bandwidth" class="clr-control-label required">
{{ 'PROJECT.BANDWIDTH' | translate }}
<clr-tooltip>
<clr-icon
clrTooltipTrigger
shape="info-circle"
size="24"></clr-icon>
<clr-tooltip-content
clrPosition="bottom-left"
clrSize="lg"
*clrIfOpen>
<span>{{
'PROJECT.PROXY_CACHE_BANDWIDTH' | translate
}}</span>
</clr-tooltip-content>
</clr-tooltip>
</label>
<div
class="clr-control-container"
[class.clr-error]="bandwidthError">
<input
type="number"
id="bandwidth"
[(ngModel)]="speedLimit"
name="bandwidth"
class="clr-input width-164 mr-10"
placeholder="Enter bandwidth"
autocomplete="off"
(ngModelChange)="validateBandwidth()" />
<clr-icon
*ngIf="bandwidthError"
class="clr-validate-icon"
shape="exclamation-circle"></clr-icon>
<div class="clr-select-wrapper mr-10">
<select
id="bandwidth_unit"
name="bandwidth_unit"
[(ngModel)]="selectedSpeedLimitUnit">
<option
*ngFor="let unit of speedUnits"
[value]="unit.UNIT">
{{ unit.UNIT }}
</option>
</select>
</div>
<clr-control-error
*ngIf="bandwidthError"
class="tooltip-content">
{{ 'PROJECT.SPEED_LIMIT_TIP' | translate }}
</clr-control-error>
</div>
</div>
</form> </form>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">

View File

@ -39,6 +39,8 @@ import { Project } from '../../../project/project';
import { import {
QuotaUnits, QuotaUnits,
QuotaUnlimited, QuotaUnlimited,
BandwidthUnit,
KB_TO_MB,
} from '../../../../shared/entities/shared.const'; } from '../../../../shared/entities/shared.const';
import { QuotaHardInterface } from '../../../../shared/services'; import { QuotaHardInterface } from '../../../../shared/services';
import { import {
@ -72,7 +74,17 @@ export class CreateProjectComponent
storageDefaultLimit: number; storageDefaultLimit: number;
storageDefaultLimitUnit: string; storageDefaultLimitUnit: string;
initVal: Project = new Project(); initVal: Project = new Project();
speedLimit: number = -1;
speedLimitUnit: string = BandwidthUnit.KB;
selectedSpeedLimitUnit: string = BandwidthUnit.KB;
speedUnits = [
{
UNIT: BandwidthUnit.KB,
},
{
UNIT: BandwidthUnit.MB,
},
];
createProjectOpened: boolean; createProjectOpened: boolean;
hasChanged: boolean; hasChanged: boolean;
@ -97,6 +109,9 @@ export class CreateProjectComponent
supportedRegistryTypeQueryString: string = supportedRegistryTypeQueryString: string =
'type={docker-hub harbor azure-acr aws-ecr google-gcr quay docker-registry github-ghcr jfrog-artifactory}'; 'type={docker-hub harbor azure-acr aws-ecr google-gcr quay docker-registry github-ghcr jfrog-artifactory}';
// **Added property for bandwidth error message**
bandwidthError: string | null = null;
constructor( constructor(
private projectService: ProjectService, private projectService: ProjectService,
private translateService: TranslateService, private translateService: TranslateService,
@ -297,7 +312,39 @@ export class CreateProjectComponent
} }
} }
// **Added method for validating bandwidth input**
validateBandwidth(): void {
const value = Number(this.speedLimit);
if (
isNaN(value) ||
(!Number.isInteger(value) && value !== -1) ||
(value <= 0 && value !== -1)
) {
this.bandwidthError =
'Please enter -1 or an integer greater than 0.';
} else {
this.bandwidthError = null;
}
}
convertSpeedValue(realSpeed: number): number {
if (this.selectedSpeedLimitUnit == BandwidthUnit.MB) {
return realSpeed * KB_TO_MB;
} else {
return realSpeed ? realSpeed : -1;
}
}
onSubmit() { onSubmit() {
// **Invoke bandwidth validation before submission**
this.validateBandwidth();
if (this.bandwidthError) {
this.inlineAlert.showInlineError(this.bandwidthError);
return;
}
this.project.metadata.bandwidth = this.convertSpeedValue(
this.speedLimit
);
if (this.isSubmitOnGoing) { if (this.isSubmitOnGoing) {
return; return;
} }
@ -315,6 +362,8 @@ export class CreateProjectComponent
project_name: this.project.name, project_name: this.project.name,
metadata: { metadata: {
public: this.project.metadata.public ? 'true' : 'false', public: this.project.metadata.public ? 'true' : 'false',
proxy_speed_kb:
this.project.metadata.bandwidth.toString(),
}, },
storage_limit: +storageByte, storage_limit: +storageByte,
registry_id: registryId, registry_id: registryId,
@ -357,6 +406,8 @@ export class CreateProjectComponent
this.inlineAlert.close(); this.inlineAlert.close();
this.storageLimit = this.storageDefaultLimit; this.storageLimit = this.storageDefaultLimit;
this.storageLimitUnit = this.storageDefaultLimitUnit; this.storageLimitUnit = this.storageDefaultLimitUnit;
this.selectedSpeedLimitUnit = BandwidthUnit.KB;
this.speedLimit = -1;
} }
public get isValid(): boolean { public get isValid(): boolean {
@ -365,7 +416,8 @@ export class CreateProjectComponent
this.currentForm.valid && this.currentForm.valid &&
!this.isSubmitOnGoing && !this.isSubmitOnGoing &&
this.isNameValid && this.isNameValid &&
!this.checkOnGoing !this.checkOnGoing &&
!this.bandwidthError
); );
} }

View File

@ -35,6 +35,7 @@ export class Project {
auto_scan: string | boolean; auto_scan: string | boolean;
auto_sbom_generation: string | boolean; auto_sbom_generation: string | boolean;
retention_id: number; retention_id: number;
bandwidth: number;
}; };
constructor() { constructor() {
this.metadata = <any>{}; this.metadata = <any>{};

View File

@ -389,3 +389,10 @@ export enum ScanTypes {
SBOM = 'sbom', SBOM = 'sbom',
VULNERABILITY = 'vulnerability', VULNERABILITY = 'vulnerability',
} }
export const KB_TO_MB: number = 1024;
export enum BandwidthUnit {
MB = 'Mbps',
KB = 'Kbps',
}

View File

@ -246,6 +246,9 @@
"TOGGLED_SUCCESS": "Projekt erfolgreich geändert.", "TOGGLED_SUCCESS": "Projekt erfolgreich geändert.",
"FAILED_TO_DELETE_PROJECT": "Das Projekt enthält Repositories, Replikations-Regeln oder Helm-Charts und kann daher nicht gelöscht werden.", "FAILED_TO_DELETE_PROJECT": "Das Projekt enthält Repositories, Replikations-Regeln oder Helm-Charts und kann daher nicht gelöscht werden.",
"INLINE_HELP_PUBLIC": "Wenn ein Projekt öffentlich ist, hat jeder lesenden Zugriff auf die Repositories innerhalb des Projekts. Der Nutzer muss nicht \"docker login\" vor dem Pull eines Images durchführen.", "INLINE_HELP_PUBLIC": "Wenn ein Projekt öffentlich ist, hat jeder lesenden Zugriff auf die Repositories innerhalb des Projekts. Der Nutzer muss nicht \"docker login\" vor dem Pull eines Images durchführen.",
"PROXY_CACHE_BANDWIDTH":"Set the maximum network bandwidth to pull image from upstream for proxy-cache. For unlimited bandwidth, please enter -1. ",
"BANDWIDTH": "Bandwidth",
"SPEED_LIMIT_TIP": "Please enter -1 or an integer greater than 0. ",
"OF": "von", "OF": "von",
"COUNT_QUOTA": "Anzahlbeschränkung", "COUNT_QUOTA": "Anzahlbeschränkung",
"STORAGE_QUOTA": "Project quota limits", "STORAGE_QUOTA": "Project quota limits",

View File

@ -246,6 +246,9 @@
"TOGGLED_SUCCESS": "Toggled project successfully.", "TOGGLED_SUCCESS": "Toggled project successfully.",
"FAILED_TO_DELETE_PROJECT": "Project contains repositories or replication rules or helm-charts cannot be deleted.", "FAILED_TO_DELETE_PROJECT": "Project contains repositories or replication rules or helm-charts cannot be deleted.",
"INLINE_HELP_PUBLIC": "When a project is set to public, anyone has read permission to the repositories under this project, and the user does not need to run \"docker login\" before pulling images under this project.", "INLINE_HELP_PUBLIC": "When a project is set to public, anyone has read permission to the repositories under this project, and the user does not need to run \"docker login\" before pulling images under this project.",
"PROXY_CACHE_BANDWIDTH":"Set the maximum network bandwidth to pull image from upstream for proxy-cache. For unlimited bandwidth, please enter -1. ",
"BANDWIDTH": "Bandwidth",
"SPEED_LIMIT_TIP": "Please enter -1 or an integer greater than 0. ",
"OF": "of", "OF": "of",
"COUNT_QUOTA": "Count quota", "COUNT_QUOTA": "Count quota",
"STORAGE_QUOTA": "Project quota limits", "STORAGE_QUOTA": "Project quota limits",

View File

@ -247,6 +247,9 @@
"TOGGLED_SUCCESS": "Proyecto alternado satisfactoriamente.", "TOGGLED_SUCCESS": "Proyecto alternado satisfactoriamente.",
"FAILED_TO_DELETE_PROJECT": "Project contains repositories or replication rules or helm-charts cannot be deleted.", "FAILED_TO_DELETE_PROJECT": "Project contains repositories or replication rules or helm-charts cannot be deleted.",
"INLINE_HELP_PUBLIC": "Cuando un proyecto se marca como público, todo el mundo tiene permisos de lectura sobre los repositorio de dicho proyecto, y no hace falta hacer \"docker login\" antes de subir imágenes a ellos.", "INLINE_HELP_PUBLIC": "Cuando un proyecto se marca como público, todo el mundo tiene permisos de lectura sobre los repositorio de dicho proyecto, y no hace falta hacer \"docker login\" antes de subir imágenes a ellos.",
"PROXY_CACHE_BANDWIDTH":"Set the maximum network bandwidth to pull image from upstream for proxy-cache. For unlimited bandwidth, please enter -1. ",
"BANDWIDTH": "Bandwidth",
"SPEED_LIMIT_TIP": "Please enter -1 or an integer greater than 0. ",
"OF": "of", "OF": "of",
"COUNT_QUOTA": "Count quota", "COUNT_QUOTA": "Count quota",
"STORAGE_QUOTA": "Project quota limits", "STORAGE_QUOTA": "Project quota limits",

View File

@ -246,6 +246,9 @@
"TOGGLED_SUCCESS": "Projet basculé avec succès.", "TOGGLED_SUCCESS": "Projet basculé avec succès.",
"FAILED_TO_DELETE_PROJECT": "Le projet contient des dépôts, des règles de réplication ou des charts Helm et ne peut pas être supprimé.", "FAILED_TO_DELETE_PROJECT": "Le projet contient des dépôts, des règles de réplication ou des charts Helm et ne peut pas être supprimé.",
"INLINE_HELP_PUBLIC": "Lorsqu'un projet est mis en public, n'importe qui a l'autorisation de lire les dépôts sous ce projet, et l'utilisateur n'a pas besoin d'exécuter \"docker login\" avant de prendre des images de ce projet.", "INLINE_HELP_PUBLIC": "Lorsqu'un projet est mis en public, n'importe qui a l'autorisation de lire les dépôts sous ce projet, et l'utilisateur n'a pas besoin d'exécuter \"docker login\" avant de prendre des images de ce projet.",
"PROXY_CACHE_BANDWIDTH":"Set the maximum network bandwidth to pull image from upstream for proxy-cache. For unlimited bandwidth, please enter -1. ",
"BANDWIDTH": "Bandwidth",
"SPEED_LIMIT_TIP": "Please enter -1 or an integer greater than 0. ",
"OF": "sur", "OF": "sur",
"COUNT_QUOTA": "Quota de nombre", "COUNT_QUOTA": "Quota de nombre",
"STORAGE_QUOTA": "Quota du projet", "STORAGE_QUOTA": "Quota du projet",

View File

@ -246,6 +246,9 @@
"TOGGLED_SUCCESS": "프로젝트가 성공적으로 전환됐습니다.", "TOGGLED_SUCCESS": "프로젝트가 성공적으로 전환됐습니다.",
"FAILED_TO_DELETE_PROJECT": "프로젝트에 리포지토리 또는 복제 규칙이 포함되어 있거나 헬름 차트를 삭제할 수 없습니다.", "FAILED_TO_DELETE_PROJECT": "프로젝트에 리포지토리 또는 복제 규칙이 포함되어 있거나 헬름 차트를 삭제할 수 없습니다.",
"INLINE_HELP_PUBLIC": "프로젝트가 공개로 설정되면 누구나 이 프로젝트의 저장소에 대한 읽기 권한을 갖게 되며 사용자는 이 프로젝트에서 이미지를 가져오기 전에 \"docker login\"을 실행할 필요가 없습니다.", "INLINE_HELP_PUBLIC": "프로젝트가 공개로 설정되면 누구나 이 프로젝트의 저장소에 대한 읽기 권한을 갖게 되며 사용자는 이 프로젝트에서 이미지를 가져오기 전에 \"docker login\"을 실행할 필요가 없습니다.",
"PROXY_CACHE_BANDWIDTH":"Set the maximum network bandwidth to pull image from upstream for proxy-cache. For unlimited bandwidth, please enter -1. ",
"BANDWIDTH": "Bandwidth",
"SPEED_LIMIT_TIP": "Please enter -1 or an integer greater than 0. ",
"OF": "of", "OF": "of",
"COUNT_QUOTA": "할당량 수", "COUNT_QUOTA": "할당량 수",
"STORAGE_QUOTA": "프로젝트 할당량 제한", "STORAGE_QUOTA": "프로젝트 할당량 제한",

View File

@ -245,6 +245,9 @@
"TOGGLED_SUCCESS": "Projeto alterado com sucesso.", "TOGGLED_SUCCESS": "Projeto alterado com sucesso.",
"FAILED_TO_DELETE_PROJECT": "Projeto não pode ser removido porque ainda possui recursos em repositórios, regras de replicação ou helm charts.", "FAILED_TO_DELETE_PROJECT": "Projeto não pode ser removido porque ainda possui recursos em repositórios, regras de replicação ou helm charts.",
"INLINE_HELP_PUBLIC": "Quando o projeto é público, o acesso de leitura aos repositórios é liberado, incluindo usuários anônimos não autenticados. O usuário não precisa executar \"docker login\" para baixar imagens desse projeto.", "INLINE_HELP_PUBLIC": "Quando o projeto é público, o acesso de leitura aos repositórios é liberado, incluindo usuários anônimos não autenticados. O usuário não precisa executar \"docker login\" para baixar imagens desse projeto.",
"PROXY_CACHE_BANDWIDTH":"Set the maximum network bandwidth to pull image from upstream for proxy-cache. For unlimited bandwidth, please enter -1. ",
"BANDWIDTH": "Bandwidth",
"SPEED_LIMIT_TIP": "Please enter -1 or an integer greater than 0. ",
"OF": "de", "OF": "de",
"COUNT_QUOTA": "Limite de quantidade", "COUNT_QUOTA": "Limite de quantidade",
"STORAGE_QUOTA": "Project quota limits", "STORAGE_QUOTA": "Project quota limits",

View File

@ -246,6 +246,9 @@
"TOGGLED_SUCCESS": "Proje başarıyla değiştirildi.", "TOGGLED_SUCCESS": "Proje başarıyla değiştirildi.",
"FAILED_TO_DELETE_PROJECT": "Proje havuzları veya çoğaltma kurallarını içeriyor veya helm tabloları silinemiyor.", "FAILED_TO_DELETE_PROJECT": "Proje havuzları veya çoğaltma kurallarını içeriyor veya helm tabloları silinemiyor.",
"INLINE_HELP_PUBLIC": "Bir proje herkese açık olarak ayarlandığında, herkes bu proje altındaki depoları okuma iznine sahiptir ve kullanıcının bu proje altındaki imajları çekmeden önce \"docker login\" çalıştırması gerekmez.", "INLINE_HELP_PUBLIC": "Bir proje herkese açık olarak ayarlandığında, herkes bu proje altındaki depoları okuma iznine sahiptir ve kullanıcının bu proje altındaki imajları çekmeden önce \"docker login\" çalıştırması gerekmez.",
"PROXY_CACHE_BANDWIDTH":"Set the maximum network bandwidth to pull image from upstream for proxy-cache. For unlimited bandwidth, please enter -1. ",
"BANDWIDTH": "Bandwidth",
"SPEED_LIMIT_TIP": "Please enter -1 or an integer greater than 0. ",
"OF": "of", "OF": "of",
"COUNT_QUOTA": "Kota", "COUNT_QUOTA": "Kota",
"STORAGE_QUOTA": "Project quota limits", "STORAGE_QUOTA": "Project quota limits",

View File

@ -246,6 +246,9 @@
"TOGGLED_SUCCESS": "切换状态成功。", "TOGGLED_SUCCESS": "切换状态成功。",
"FAILED_TO_DELETE_PROJECT": "项目包含镜像仓库或复制规则或Helm Charts无法删除。", "FAILED_TO_DELETE_PROJECT": "项目包含镜像仓库或复制规则或Helm Charts无法删除。",
"INLINE_HELP_PUBLIC": "当项目设为公开后任何人都有此项目下镜像的读权限。命令行用户不需要“docker login”就可以拉取此项目下的镜像。", "INLINE_HELP_PUBLIC": "当项目设为公开后任何人都有此项目下镜像的读权限。命令行用户不需要“docker login”就可以拉取此项目下的镜像。",
"PROXY_CACHE_BANDWIDTH":"Set the maximum network bandwidth to pull image from upstream for proxy-cache. For unlimited bandwidth, please enter -1. ",
"BANDWIDTH": "Bandwidth",
"SPEED_LIMIT_TIP": "Please enter -1 or an integer greater than 0. ",
"COUNT_QUOTA": "存储数量", "COUNT_QUOTA": "存储数量",
"STORAGE_QUOTA": "项目配额限制", "STORAGE_QUOTA": "项目配额限制",
"COUNT_QUOTA_TIP": "请输入一个'1' ~ '100000000'之间的整数, '-1'表示不设置上限。", "COUNT_QUOTA_TIP": "请输入一个'1' ~ '100000000'之间的整数, '-1'表示不设置上限。",

View File

@ -245,6 +245,9 @@
"TOGGLED_SUCCESS": "專案切換成功。", "TOGGLED_SUCCESS": "專案切換成功。",
"FAILED_TO_DELETE_PROJECT": "由於專案包含儲存庫、複製規則或 helm-charts無法刪除。", "FAILED_TO_DELETE_PROJECT": "由於專案包含儲存庫、複製規則或 helm-charts無法刪除。",
"INLINE_HELP_PUBLIC": "當專案設為公開時,任何人都可讀取此專案下的儲存庫,使用者不需執行 \"docker login\" 即可拉取此專案下的映像檔。", "INLINE_HELP_PUBLIC": "當專案設為公開時,任何人都可讀取此專案下的儲存庫,使用者不需執行 \"docker login\" 即可拉取此專案下的映像檔。",
"PROXY_CACHE_BANDWIDTH":"Set the maximum network bandwidth to pull image from upstream for proxy-cache. For unlimited bandwidth, please enter -1. ",
"BANDWIDTH": "Bandwidth",
"SPEED_LIMIT_TIP": "Please enter -1 or an integer greater than 0. ",
"OF": "共計", "OF": "共計",
"COUNT_QUOTA": "數量配額", "COUNT_QUOTA": "數量配額",
"STORAGE_QUOTA": "儲存配額限制", "STORAGE_QUOTA": "儲存配額限制",