feat: extend the p2p preheat policy (#21115)

Add the field extra_attrs to the p2p preheat policy for the provider to
define their specified parameters when preheating.

Signed-off-by: chlins <chlins.zhang@gmail.com>
This commit is contained in:
Chlins Zhang 2024-12-18 10:30:36 +08:00 committed by GitHub
parent e417875377
commit a548ab705f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 2346 additions and 2166 deletions

View File

@ -7095,9 +7095,9 @@ definitions:
type: boolean
description: Whether the preheat policy enabled
x-omitempty: false
scope:
extra_attrs:
type: string
description: The scope of preheat policy
description: The extra attributes of preheat policy
creation_time:
type: string
format: date-time

View File

@ -0,0 +1,2 @@
ALTER TABLE p2p_preheat_policy DROP COLUMN IF EXISTS scope;
ALTER TABLE p2p_preheat_policy ADD COLUMN IF NOT EXISTS extra_attrs text;

View File

@ -246,4 +246,3 @@ cleanimage:
.PHONY: clean
clean: cleanimage

View File

@ -402,7 +402,7 @@ func (de *defaultEnforcer) launchExecutions(ctx context.Context, candidates []*s
// Start tasks
count := 0
for _, c := range candidates {
if _, err = de.startTask(ctx, eid, c, insData, pl.Scope); err != nil {
if _, err = de.startTask(ctx, eid, c, insData, pl.ExtraAttrs); err != nil {
// Just log the error and skip
log.Errorf("start task error for preheating image: %s/%s:%s@%s", c.Namespace, c.Repository, c.Tags[0], c.Digest)
continue
@ -421,7 +421,7 @@ func (de *defaultEnforcer) launchExecutions(ctx context.Context, candidates []*s
}
// startTask starts the preheat task(job) for the given candidate
func (de *defaultEnforcer) startTask(ctx context.Context, executionID int64, candidate *selector.Candidate, instance, scope string) (int64, error) {
func (de *defaultEnforcer) startTask(ctx context.Context, executionID int64, candidate *selector.Candidate, instance string, extraAttrs map[string]interface{}) (int64, error) {
u, err := de.fullURLGetter(candidate)
if err != nil {
return -1, err
@ -441,7 +441,7 @@ func (de *defaultEnforcer) startTask(ctx context.Context, executionID int64, can
ImageName: fmt.Sprintf("%s/%s", candidate.Namespace, candidate.Repository),
Tag: candidate.Tags[0],
Digest: candidate.Digest,
Scope: scope,
ExtraAttrs: extraAttrs,
}
piData, err := pi.ToJSON()

View File

@ -210,7 +210,6 @@ func mockPolicies() []*po.Schema {
Type: po.TriggerTypeManual,
},
Enabled: true,
Scope: "single_peer",
CreatedAt: time.Now().UTC(),
UpdatedTime: time.Now().UTC(),
}, {
@ -236,7 +235,6 @@ func mockPolicies() []*po.Schema {
Trigger: &po.Trigger{
Type: po.TriggerTypeEventBased,
},
Scope: "all_peers",
Enabled: true,
CreatedAt: time.Now().UTC(),
UpdatedTime: time.Now().UTC(),

View File

@ -30,9 +30,6 @@ func init() {
beego_orm.RegisterModel(&Schema{})
}
// ScopeType represents the preheat scope type.
type ScopeType = string
const (
// Filters:
// Repository : type=Repository value=name text (double star pattern used)
@ -58,11 +55,6 @@ const (
TriggerTypeScheduled TriggerType = "scheduled"
// TriggerTypeEventBased represents the event_based trigger type
TriggerTypeEventBased TriggerType = "event_based"
// ScopeTypeSinglePeer represents preheat image to single peer in p2p cluster.
ScopeTypeSinglePeer ScopeType = "single_peer"
// ScopeTypeAllPeers represents preheat image to all peers in p2p cluster.
ScopeTypeAllPeers ScopeType = "all_peers"
)
// Schema defines p2p preheat policy schema
@ -80,8 +72,9 @@ type Schema struct {
// Use JSON data format (query by trigger type should be supported)
TriggerStr string `orm:"column(trigger)" json:"-"`
Enabled bool `orm:"column(enabled)" json:"enabled"`
// Scope decides the preheat scope.
Scope string `orm:"column(scope)" json:"scope"`
// ExtraAttrs is used to store extra attributes provided by vendor.
ExtraAttrsStr string `orm:"column(extra_attrs)" json:"-"`
ExtraAttrs map[string]interface{} `orm:"-" json:"extra_attrs"`
CreatedAt time.Time `orm:"column(creation_time)" json:"creation_time"`
UpdatedTime time.Time `orm:"column(update_time)" json:"update_time"`
}
@ -136,11 +129,6 @@ func (s *Schema) ValidatePreheatPolicy() error {
}
}
// validate preheat scope
if s.Scope != "" && s.Scope != ScopeTypeSinglePeer && s.Scope != ScopeTypeAllPeers {
return errors.New(nil).WithCode(errors.BadRequestCode).WithMessagef("invalid scope for preheat policy: %s", s.Scope)
}
return nil
}
@ -162,6 +150,14 @@ func (s *Schema) Encode() error {
s.TriggerStr = string(triggerStr)
}
if s.ExtraAttrs != nil {
extraAttrsStr, err := json.Marshal(s.ExtraAttrs)
if err != nil {
return err
}
s.ExtraAttrsStr = string(extraAttrsStr)
}
return nil
}
@ -181,6 +177,13 @@ func (s *Schema) Decode() error {
}
s.Trigger = trigger
// parse extra attributes
extraAttrs, err := decodeExtraAttrs(s.ExtraAttrsStr)
if err != nil {
return err
}
s.ExtraAttrs = extraAttrs
return nil
}
@ -230,3 +233,17 @@ func decodeTrigger(triggerStr string) (*Trigger, error) {
return trigger, nil
}
// decodeExtraAttrs parse extraAttrsStr to extraAttrs.
func decodeExtraAttrs(extraAttrsStr string) (map[string]interface{}, error) {
if len(extraAttrsStr) == 0 {
return nil, nil
}
extraAttrs := make(map[string]interface{})
if err := json.Unmarshal([]byte(extraAttrsStr), &extraAttrs); err != nil {
return nil, err
}
return extraAttrs, nil
}

View File

@ -64,13 +64,6 @@ func (p *PolicyTestSuite) TestValidatePreheatPolicy() {
// valid cron string
p.schema.Trigger.Settings.Cron = "0 0 0 1 1 *"
p.NoError(p.schema.ValidatePreheatPolicy())
// invalid preheat scope
p.schema.Scope = "invalid scope"
p.Error(p.schema.ValidatePreheatPolicy())
// valid preheat scope
p.schema.Scope = "single_peer"
p.NoError(p.schema.ValidatePreheatPolicy())
}
// TestDecode tests decode.
@ -86,13 +79,13 @@ func (p *PolicyTestSuite) TestDecode() {
Trigger: nil,
TriggerStr: "{\"type\":\"event_based\",\"trigger_setting\":{\"cron\":\"\"}}",
Enabled: false,
Scope: "all_peers",
ExtraAttrsStr: "{\"key\":\"value\"}",
}
p.NoError(s.Decode())
p.Len(s.Filters, 3)
p.NotNil(s.Trigger)
p.Equal(ScopeTypeAllPeers, s.Scope)
p.Equal(map[string]interface{}{"key": "value"}, s.ExtraAttrs)
// invalid filter or trigger
s.FiltersStr = ""
@ -132,10 +125,12 @@ func (p *PolicyTestSuite) TestEncode() {
},
TriggerStr: "",
Enabled: false,
Scope: "single_peer",
ExtraAttrs: map[string]interface{}{
"key": "value",
},
}
p.NoError(s.Encode())
p.Equal(`[{"type":"repository","value":"**"},{"type":"tag","value":"**"},{"type":"label","value":"test"}]`, s.FiltersStr)
p.Equal(`{"type":"event_based","trigger_setting":{}}`, s.TriggerStr)
p.Equal(ScopeTypeSinglePeer, s.Scope)
p.Equal(`{"key":"value"}`, s.ExtraAttrsStr)
}

View File

@ -36,6 +36,15 @@ const (
// dragonflyJobPath is the job path for dragonfly openapi.
dragonflyJobPath = "/oapi/v1/jobs"
// scopeTypeSingleSeedPeer represents preheat image to single seed peer in p2p cluster.
scopeTypeSingleSeedPeer = "single_seed_peer"
// scopeTypeAllSeedPeers represents preheat image to all seed peers in p2p cluster.
scopeTypeAllSeedPeers = "all_seed_peers"
// scopeTypeAllPeers represents preheat image to all peers in p2p cluster.
scopeTypeAllPeers = "all_peers"
)
const (
@ -54,13 +63,13 @@ const (
type dragonflyCreateJobRequest struct {
// Type is the job type, support preheat.
Type string `json:"type" binding:"required"`
Type string `json:"type"`
// Args is the preheating args.
Args dragonflyCreateJobRequestArgs `json:"args" binding:"omitempty"`
Args dragonflyCreateJobRequestArgs `json:"args"`
// SchedulerClusterIDs is the scheduler cluster ids for preheating.
SchedulerClusterIDs []uint `json:"scheduler_cluster_ids" binding:"omitempty"`
SchedulerClusterIDs []uint `json:"scheduler_cluster_ids"`
}
type dragonflyCreateJobRequestArgs struct {
@ -150,6 +159,14 @@ type dragonflyJobResponse struct {
} `json:"result"`
}
// dragonflyExtraAttrs is the extra attributes model definition for dragonfly provider.
type dragonflyExtraAttrs struct {
// Scope is the scope for preheating, default behavior is single_peer.
Scope string `json:"scope"`
// ClusterIDs is the cluster ids for dragonfly provider.
ClusterIDs []uint `json:"cluster_ids"`
}
// DragonflyDriver implements the provider driver interface for Alibaba dragonfly.
// More details, please refer to https://github.com/alibaba/Dragonfly
type DragonflyDriver struct {
@ -201,6 +218,18 @@ func (dd *DragonflyDriver) Preheat(preheatingImage *PreheatImage) (*PreheatingSt
return nil, errors.New("no image specified")
}
var extraAttrs dragonflyExtraAttrs
if len(preheatingImage.ExtraAttrs) > 0 {
extraAttrsStr, err := json.Marshal(preheatingImage.ExtraAttrs)
if err != nil {
return nil, errors.Wrap(err, "failed to marshal extra attributes")
}
if err := json.Unmarshal(extraAttrsStr, &extraAttrs); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal extra attributes")
}
}
// Construct the preheat job request by the given parameters of the preheating image .
req := &dragonflyCreateJobRequest{
Type: "preheat",
@ -209,10 +238,23 @@ func (dd *DragonflyDriver) Preheat(preheatingImage *PreheatImage) (*PreheatingSt
Type: preheatingImage.Type,
URL: preheatingImage.URL,
Headers: headerToMapString(preheatingImage.Headers),
Scope: preheatingImage.Scope,
},
}
// Set the scope if it is specified.
if extraAttrs.Scope != "" {
if err := isScopeValid(extraAttrs.Scope); err != nil {
return nil, errors.Wrap(err, "specify the invalid scope")
}
req.Args.Scope = extraAttrs.Scope
}
// Set the cluster ids if it is specified.
if len(extraAttrs.ClusterIDs) > 0 {
req.SchedulerClusterIDs = extraAttrs.ClusterIDs
}
url := fmt.Sprintf("%s%s", strings.TrimSuffix(dd.instance.Endpoint, "/"), dragonflyJobPath)
data, err := client.GetHTTPClient(dd.instance.Insecure).Post(url, dd.getCred(), req, nil)
if err != nil {
@ -326,3 +368,15 @@ func headerToMapString(header map[string]interface{}) map[string]string {
return m
}
// isScopeValid checks whether the scope is valid.
func isScopeValid(scope string) error {
switch scope {
case scopeTypeSingleSeedPeer,
scopeTypeAllSeedPeers,
scopeTypeAllPeers:
return nil
default:
return errors.Errorf("invalid scope: %s", scope)
}
}

View File

@ -85,7 +85,10 @@ func (suite *DragonflyTestSuite) TestPreheat() {
Tag: "latest",
URL: "https://harbor.com",
Digest: "sha256:f3c97e3bd1e27393eb853a5c90b1132f2cda84336d5ba5d100c720dc98524c82",
Scope: "single_peer",
ExtraAttrs: map[string]interface{}{
"scope": "all_peers",
"cluster_ids": []uint{1, 2, 3},
},
})
require.NoError(suite.T(), err, "preheat image")
suite.Equal(provider.PreheatingStatusPending, st.Status, "preheat status")

View File

@ -46,8 +46,8 @@ type PreheatImage struct {
// Digest of the preheating image
Digest string `json:"digest"`
// Scope indicates the preheat scope.
Scope string `json:"scope,omitempty"`
// ExtraAttrs contains extra attributes for the preheating image.
ExtraAttrs map[string]interface{} `json:"extra_attrs,omitempty"`
}
// FromJSON build preheating image from the given data.

View File

@ -457,11 +457,16 @@
(inputvalue)="setCron($event)"></cron-selection>
</div>
</div>
<!-- dragonfly provider customization -->
<div *ngIf="isDragonflyProvider(policy.provider_id)">
<!-- scope -->
<div class="clr-form-control">
<clr-select-container>
<label class="clr-control-label width-6rem">
{{ 'P2P_PROVIDER.SCOPE' | translate }}
{{
'P2P_PROVIDER.DRAGONFLY.SCOPE'
| translate
}}
</label>
<select
class="width-380"
@ -471,7 +476,9 @@
id="scope"
[(ngModel)]="scope"
#ngScope="ngModel">
<option class="display-none" value=""></option>
<option
class="display-none"
value=""></option>
<option
[selected]="policy.scope === item"
*ngFor="let item of scopes"
@ -481,6 +488,36 @@
</select>
</clr-select-container>
</div>
<!-- cluster_ids -->
<div class="clr-form-control">
<label
for="clusterIDs"
class="clr-control-label width-6rem"
>{{
'P2P_PROVIDER.DRAGONFLY.CLUSTER_IDS'
| translate
}}</label
>
<div class="clr-control-container">
<div class="clr-input-wrapper">
<input
[disabled]="loading"
autocomplete="off"
class="clr-input width-380"
type="text"
id="clusterIDs"
[(ngModel)]="clusterIDs"
size="30"
name="clusterIDs"
#ngClusterIDs="ngModel" />
</div>
<clr-control-helper class="opacity-08">{{
'P2P_PROVIDER.DRAGONFLY.CLUSTER_IDS_SEPARATOR'
| translate
}}</clr-control-helper>
</div>
</div>
</div>
</section>
</form>
<div class="mt-1 bottom-btn" *ngIf="!isEdit">

View File

@ -12,6 +12,7 @@ import { NgForm } from '@angular/forms';
import { OriginCron, ProjectService } from '../../../../shared/services';
import { CronScheduleComponent } from '../../../../shared/components/cron-schedule';
import { PreheatService } from '../../../../../../ng-swagger-gen/services/preheat.service';
import { ExtraAttrs } from '../../../../../../ng-swagger-gen/models/extra-attrs';
import {
debounceTime,
distinctUntilChanged,
@ -29,8 +30,8 @@ import {
PROJECT_SEVERITY_LEVEL_MAP,
TRIGGER,
TRIGGER_I18N_MAP,
SCOPE,
SCOPE_I18N_MAP,
DRAGONFLY_SCOPE,
DRAGONFLY_SCOPE_I18N_MAP,
} from '../p2p-provider.service';
import { ProviderUnderProject } from '../../../../../../ng-swagger-gen/models/provider-under-project';
import { AppConfigService } from '../../../../services/app-config.service';
@ -75,7 +76,8 @@ export class AddP2pPolicyComponent implements OnInit, OnDestroy {
severity: number;
labels: string;
triggerType: string = TRIGGER.MANUAL;
scope: string = SCOPE.SINGLE_PEER;
scope: string = DRAGONFLY_SCOPE.SINGLE_SEED_PEER;
clusterIDs: string;
cron: string;
@ViewChild('policyForm', { static: true }) currentForm: NgForm;
loading: boolean = false;
@ -90,6 +92,8 @@ export class AddP2pPolicyComponent implements OnInit, OnDestroy {
originLabelsForEdit: string;
originTriggerTypeForEdit: string;
originCronForEdit: string;
originScopeForEdit: string;
originClusterIDsForEdit: string;
@Input()
providers: ProviderUnderProject[] = [];
preventVul: boolean = false;
@ -99,7 +103,11 @@ export class AddP2pPolicyComponent implements OnInit, OnDestroy {
TRIGGER.SCHEDULED,
TRIGGER.EVENT_BASED,
];
scopes: string[] = [SCOPE.SINGLE_PEER, SCOPE.ALL_PEERS];
scopes: string[] = [
DRAGONFLY_SCOPE.SINGLE_SEED_PEER,
DRAGONFLY_SCOPE.ALL_SEED_PEERS,
DRAGONFLY_SCOPE.ALL_PEERS,
];
enableContentTrust: boolean = false;
private _nameSubject: Subject<string> = new Subject<string>();
private _nameSubscription: Subscription;
@ -202,7 +210,7 @@ export class AddP2pPolicyComponent implements OnInit, OnDestroy {
}
this.currentForm.reset({
triggerType: 'manual',
scope: 'single_peer',
scope: DRAGONFLY_SCOPE.SINGLE_SEED_PEER,
severity: PROJECT_SEVERITY_LEVEL_MAP[this.projectSeverity],
onlySignedImages: this.enableContentTrust,
provider: this.policy.provider_id,
@ -308,7 +316,21 @@ export class AddP2pPolicyComponent implements OnInit, OnDestroy {
policy.trigger = JSON.stringify(trigger);
this.loading = true;
this.buttonStatus = ClrLoadingState.LOADING;
policy.scope = this.scope ? this.scope : SCOPE.SINGLE_PEER;
// assemble extra attrs for dragonfly provider
let extraAttrs: ExtraAttrs = {};
if (this.isDragonflyProvider(policy.provider_id)) {
if (this.scope) {
extraAttrs['scope'] = this.scope;
}
if (this.clusterIDs) {
extraAttrs['cluster_ids'] = this.clusterIDs
.split(',')
.map(Number);
}
}
if (Object.keys(extraAttrs).length) {
policy.extra_attrs = JSON.stringify(extraAttrs);
}
deleteEmptyKey(policy);
if (isAdd) {
policy.project_id = this.projectId;
@ -410,7 +432,11 @@ export class AddP2pPolicyComponent implements OnInit, OnDestroy {
return true;
}
// eslint-disable-next-line eqeqeq
if (this.policy.scope != this.scope) {
if (this.originScopeForEdit != this.scope) {
return true;
}
// eslint-disable-next-line eqeqeq
if (this.originClusterIDsForEdit != this.clusterIDs) {
return true;
}
// eslint-disable-next-line eqeqeq
@ -430,7 +456,7 @@ export class AddP2pPolicyComponent implements OnInit, OnDestroy {
getScopeI18n(scope): string {
if (scope) {
return SCOPE_I18N_MAP[scope];
return DRAGONFLY_SCOPE_I18N_MAP[scope];
}
return '';
}
@ -444,4 +470,15 @@ export class AddP2pPolicyComponent implements OnInit, OnDestroy {
showExplainForEventBased(): boolean {
return this.triggerType === TRIGGER.EVENT_BASED;
}
isDragonflyProvider(provider_id: number): boolean {
if (this.providers && this.providers.length) {
return this.providers.some(
provider =>
provider_id == provider.id &&
provider.provider.startsWith('dragonfly')
);
}
return false;
}
}

View File

@ -77,14 +77,16 @@ export const TRIGGER_I18N_MAP = {
'scheduled(paused)': 'JOB_SERVICE_DASHBOARD.SCHEDULE_PAUSED',
};
export enum SCOPE {
SINGLE_PEER = 'single_peer',
export enum DRAGONFLY_SCOPE {
SINGLE_SEED_PEER = 'single_seed_peer',
ALL_SEED_PEERS = 'all_seed_peers',
ALL_PEERS = 'all_peers',
}
export const SCOPE_I18N_MAP = {
single_peer: 'P2P_PROVIDER.SCOPE_SINGLE_PEER',
all_peers: 'P2P_PROVIDER.SCOPE_ALL_PEERS',
export const DRAGONFLY_SCOPE_I18N_MAP = {
single_seed_peer: 'P2P_PROVIDER.DRAGONFLY.SCOPE_SINGLE_SEED_PEER',
all_seed_peers: 'P2P_PROVIDER.DRAGONFLY.SCOPE_ALL_SEED_PEERS',
all_peers: 'P2P_PROVIDER.DRAGONFLY.SCOPE_ALL_PEERS',
};
export const TIME_OUT: number = 7000;

View File

@ -480,6 +480,13 @@ export class PolicyComponent implements OnInit, OnDestroy {
this.addP2pPolicyComponent.triggerType = trigger.type;
this.addP2pPolicyComponent.cron = trigger.trigger_setting.cron;
}
if (this.addP2pPolicyComponent.policy.extra_attrs) {
const { scope = '', cluster_ids = [] } = JSON.parse(
this.addP2pPolicyComponent.policy.extra_attrs
);
this.addP2pPolicyComponent.scope = scope;
this.addP2pPolicyComponent.clusterIDs = cluster_ids.join(',');
}
this.addP2pPolicyComponent.currentForm.reset({
provider: this.addP2pPolicyComponent.policy.provider_id,
name: this.addP2pPolicyComponent.policy.name,
@ -491,6 +498,7 @@ export class PolicyComponent implements OnInit, OnDestroy {
label: this.addP2pPolicyComponent.labels,
triggerType: this.addP2pPolicyComponent.triggerType,
scope: this.addP2pPolicyComponent.scope,
clusterIDs: this.addP2pPolicyComponent.clusterIDs,
});
this.addP2pPolicyComponent.originPolicyForEdit = clone(
this.selectedRow
@ -509,6 +517,10 @@ export class PolicyComponent implements OnInit, OnDestroy {
this.addP2pPolicyComponent.triggerType;
this.addP2pPolicyComponent.originCronForEdit =
this.addP2pPolicyComponent.cron;
this.addP2pPolicyComponent.originScopeForEdit =
this.addP2pPolicyComponent.scope;
this.addP2pPolicyComponent.originClusterIDsForEdit =
this.addP2pPolicyComponent.clusterIDs;
}
}

View File

@ -936,7 +936,6 @@
"LDAP_GROUP_MEMBERSHIP_INFO": "Dass Attribut, das die Mitglieder einer LDAP-Gruppe identifiziert. Standardwert ist memberof, in manchen LDAP Servern kann es \"ismemberof\" sein. Das Feld darf nicht leer sein, sofern eine LDAP Gruppen Funktion eingesetzt wird.",
"GROUP_SCOPE": "LDAP Gruppen Search Scope",
"GROUP_SCOPE_INFO": "Der Scope mit dem nach Gruppen gesucht wird. Standard ist Subtree."
},
"UAA": {
"ENDPOINT": "UAA Endpunkt",
@ -1310,7 +1309,6 @@
"ON": "am",
"AT": "um",
"NOSCHEDULE": "Ein Fehler ist aufgetreten beim setzen des Intervalls"
},
"GC": {
"CURRENT_SCHEDULE": "Speicherbereinigungs-Intervall",
@ -1623,6 +1621,14 @@
"CREATE_INSTANCE": "Instanz erstellen"
},
"P2P_PROVIDER": {
"DRAGONFLY": {
"SCOPE": "Scope",
"SCOPE_SINGLE_SEED_PEER": "Single Seed Peer",
"SCOPE_ALL_SEED_PEERS": "All Seed Peers",
"SCOPE_ALL_PEERS": "All Peers",
"CLUSTER_IDS": "Cluster IDs",
"CLUSTER_IDS_SEPARATOR": "Enter multiple comma separated cluster ids, eg., 1,2,3 (If empty, preheat all clusters)"
},
"P2P_PROVIDER": "P2P-Verteilung",
"POLICIES": "REGELWERKE",
"NEW_POLICY": "NEUES REGELWERK",
@ -1633,9 +1639,6 @@
"TRIGGER": "Trigger",
"CREATED": "Erzeugt am",
"DESCRIPTION": "Beschreibung",
"SCOPE": "Umfang",
"SCOPE_SINGLE_PEER": "Einzelner Peer",
"SCOPE_ALL_PEERS": "Alle Peers",
"NO_POLICY": "Keine Regelwerke",
"ENABLED_POLICY_SUMMARY": "Soll das Regelwerk {{name}} aktiviert werden?",
"DISABLED_POLICY_SUMMARY": "Soll das Regelwerk {{name}} deaktiviert werden?",

View File

@ -486,7 +486,6 @@
"CLOUD_EVENT": "CloudEvents",
"PAYLOAD_DATA": "Payload Data",
"SLACK_RATE_LIMIT": "Please be aware of Slack Rate Limits"
},
"GROUP": {
"GROUP": "Group",
@ -939,7 +938,6 @@
"GROUP_SCOPE_INFO": "The scope to search for groups, select Subtree by default.",
"GROUP_ATTACH_PARALLEL": "LDAP Group Attached In Parallel",
"GROUP_ATTACH_PARALLEL_INFO": "Enable this option to attach group in parallel to avoid timeout when there are too many groups. If disabled, the LDAP group information will be attached sequentially."
},
"UAA": {
"ENDPOINT": "UAA Endpoint",
@ -1313,7 +1311,6 @@
"ON": "on",
"AT": "at",
"NOSCHEDULE": "An error occurred in Get schedule"
},
"GC": {
"CURRENT_SCHEDULE": "Schedule to GC",
@ -1626,6 +1623,14 @@
"CREATE_INSTANCE": "Create instance"
},
"P2P_PROVIDER": {
"DRAGONFLY": {
"SCOPE": "Scope",
"SCOPE_SINGLE_SEED_PEER": "Single Seed Peer",
"SCOPE_ALL_SEED_PEERS": "All Seed Peers",
"SCOPE_ALL_PEERS": "All Peers",
"CLUSTER_IDS": "Cluster IDs",
"CLUSTER_IDS_SEPARATOR": "Enter multiple comma separated cluster ids, eg., 1,2,3 (If empty, preheat all clusters)"
},
"P2P_PROVIDER": "P2P Preheat",
"POLICIES": "Policies",
"NEW_POLICY": "NEW POLICY",
@ -1636,9 +1641,6 @@
"TRIGGER": "Trigger",
"CREATED": "Creation Time",
"DESCRIPTION": "Description",
"SCOPE": "Scope",
"SCOPE_SINGLE_PEER": "Single Peer",
"SCOPE_ALL_PEERS": "All Peers",
"NO_POLICY": "No policy",
"ENABLED_POLICY_SUMMARY": "Do you want to enable policy {{name}}?",
"DISABLED_POLICY_SUMMARY": "Do you want to deactivate policy {{name}}?",

View File

@ -913,7 +913,6 @@
"WEEKLY_CRON": "Run once a week, midnight between Sat/Sun. Equivalente a 0 0 0 * * 0.",
"DAILY_CRON": "Run once a day, midnight. Equivalente a 0 0 0 * * *.",
"SKIP_SCANNER_PULL_TIME_TOOLTIP": "Vulnerability scanner(e.g. Trivy) will not update the image \"last pull time\" when the image is scanned."
},
"LDAP": {
"URL": "LDAP URL",
@ -1196,7 +1195,6 @@
"ADD_TAG": "ADD TAG",
"REMOVE_TAG": "REMOVE TAG",
"NAME_ALREADY_EXISTS": "Tag already exists under the repository"
},
"LABEL": {
"LABEL": "Label",
@ -1307,7 +1305,6 @@
"ON": "on",
"AT": "at",
"NOSCHEDULE": "An error occurred in Get schedule"
},
"GC": {
"CURRENT_SCHEDULE": "Schedule to GC",
@ -1620,6 +1617,14 @@
"CREATE_INSTANCE": "Create instance"
},
"P2P_PROVIDER": {
"DRAGONFLY": {
"SCOPE": "Scope",
"SCOPE_SINGLE_SEED_PEER": "Single Seed Peer",
"SCOPE_ALL_SEED_PEERS": "All Seed Peers",
"SCOPE_ALL_PEERS": "All Peers",
"CLUSTER_IDS": "Cluster IDs",
"CLUSTER_IDS_SEPARATOR": "Enter multiple comma separated cluster ids, eg., 1,2,3 (If empty, preheat all clusters)"
},
"P2P_PROVIDER": "P2P Preheat",
"POLICIES": "Policies",
"NEW_POLICY": "NEW POLICY",
@ -1630,9 +1635,6 @@
"TRIGGER": "Trigger",
"CREATED": "Creation Time",
"DESCRIPTION": "Description",
"SCOPE": "Scope",
"SCOPE_SINGLE_PEER": "Single Peer",
"SCOPE_ALL_PEERS": "All Peers",
"NO_POLICY": "No policy",
"ENABLED_POLICY_SUMMARY": "Do you want to enable policy {{name}}?",
"DISABLED_POLICY_SUMMARY": "Do you want to disable policy {{name}}?",

View File

@ -1623,6 +1623,14 @@
"CREATE_INSTANCE": "Créer une instance"
},
"P2P_PROVIDER": {
"DRAGONFLY": {
"SCOPE": "Scope",
"SCOPE_SINGLE_SEED_PEER": "Single Seed Peer",
"SCOPE_ALL_SEED_PEERS": "All Seed Peers",
"SCOPE_ALL_PEERS": "All Peers",
"CLUSTER_IDS": "Cluster IDs",
"CLUSTER_IDS_SEPARATOR": "Enter multiple comma separated cluster ids, eg., 1,2,3 (If empty, preheat all clusters)"
},
"P2P_PROVIDER": "Préchauffage P2P",
"POLICIES": "Stratégies",
"NEW_POLICY": "Nouvelle stratégie",
@ -1633,9 +1641,6 @@
"TRIGGER": "Déclencheur",
"CREATED": "Date/Heure de création",
"DESCRIPTION": "Description",
"SCOPE": "Champ d'application",
"SCOPE_SINGLE_PEER": "Pair unique",
"SCOPE_ALL_PEERS": "Tous les pairs",
"NO_POLICY": "Aucune stratégie",
"ENABLED_POLICY_SUMMARY": "Voulez-vous activer la stratégie {{name}} ?",
"DISABLED_POLICY_SUMMARY": "Voulez-vous désactiver la stratégie {{name}} ?",

View File

@ -483,7 +483,6 @@
"CLOUD_EVENT": "클라우드이벤트",
"PAYLOAD_DATA": "페이로드 데이터",
"SLACK_RATE_LIMIT": "Slack 속도 제한에 유의하세요."
},
"GROUP": {
"GROUP": "그룹",
@ -934,7 +933,6 @@
"LDAP_GROUP_MEMBERSHIP_INFO": "속성은 LDAP 그룹의 멤버십을 나타내며 기본값은 memberof이며 일부 LDAP 서버에서는 \"ismemberof\"일 수 있습니다. LDAP 그룹 관련 기능을 활성화해야 하는 경우 이 필드를 비워둘 수 없습니다.",
"GROUP_SCOPE": "LDAP 그룹 검색 범위",
"GROUP_SCOPE_INFO": "그룹을 검색할 범위는 기본적으로 Subtree를 선택합니다."
},
"UAA": {
"ENDPOINT": "UAA 엔드포인트",
@ -1308,7 +1306,6 @@
"ON": "on",
"AT": "at",
"NOSCHEDULE": "예약내역을 가져오던 중 에러가 발생했습니다"
},
"GC": {
"CURRENT_SCHEDULE": "가비지 컬렉션 예약",
@ -1617,6 +1614,14 @@
"CREATE_INSTANCE": "인스턴스 생성"
},
"P2P_PROVIDER": {
"DRAGONFLY": {
"SCOPE": "Scope",
"SCOPE_SINGLE_SEED_PEER": "Single Seed Peer",
"SCOPE_ALL_SEED_PEERS": "All Seed Peers",
"SCOPE_ALL_PEERS": "All Peers",
"CLUSTER_IDS": "Cluster IDs",
"CLUSTER_IDS_SEPARATOR": "Enter multiple comma separated cluster ids, eg., 1,2,3 (If empty, preheat all clusters)"
},
"P2P_PROVIDER": "P2P 예열",
"POLICIES": "정책",
"NEW_POLICY": "새 정책",
@ -1627,9 +1632,6 @@
"TRIGGER": "트리거",
"CREATED": "생성 시간",
"DESCRIPTION": "설명",
"SCOPE": "범위",
"SCOPE_SINGLE_PEER": "싱글 피어",
"SCOPE_ALL_PEERS": "모든 피어",
"NO_POLICY": "정책 없음",
"ENABLED_POLICY_SUMMARY": "정책{{name}}을 활성화하시겠습니까?",
"DISABLED_POLICY_SUMMARY": "정책{{name}}을 비활성화하시겠습니까?",

View File

@ -933,7 +933,6 @@
"LDAP_GROUP_MEMBERSHIP_INFO": "Atributo que informa a lista de grupos do usuário. Se não informado, o nome \"memberof\" será usado. Alguns servidores LDAP utilizam o atributo \"ismemberof\". This field cannot be empty if you need to enable the LDAP group related feature.",
"GROUP_SCOPE": "LDAP Group Search Scope",
"GROUP_SCOPE_INFO": "O escopo que deve ser utilizado na busca por grupos, utiliza Subtree por padrão."
},
"UAA": {
"ENDPOINT": "Endereço UAA",
@ -1303,7 +1302,6 @@
"ON": "em",
"AT": "às",
"NOSCHEDULE": "Ocorreu um erro na rotina Get"
},
"GC": {
"CURRENT_SCHEDULE": "Agenda",
@ -1620,6 +1618,14 @@
"CREATE_INSTANCE": "Criar instância"
},
"P2P_PROVIDER": {
"DRAGONFLY": {
"SCOPE": "Scope",
"SCOPE_SINGLE_SEED_PEER": "Single Seed Peer",
"SCOPE_ALL_SEED_PEERS": "All Seed Peers",
"SCOPE_ALL_PEERS": "All Peers",
"CLUSTER_IDS": "Cluster IDs",
"CLUSTER_IDS_SEPARATOR": "Enter multiple comma separated cluster ids, eg., 1,2,3 (If empty, preheat all clusters)"
},
"P2P_PROVIDER": "Pré-análise P2P",
"POLICIES": "Políticas",
"NEW_POLICY": "NOVA POLÍTICA",
@ -1630,9 +1636,6 @@
"TRIGGER": "Disparo",
"CREATED": "Criado em",
"DESCRIPTION": "Descrição",
"SCOPE": "Escopo",
"SCOPE_SINGLE_PEER": "Par único",
"SCOPE_ALL_PEERS": "Todos os pares",
"NO_POLICY": "Nenhuma política",
"ENABLED_POLICY_SUMMARY": "Gostaria de habilitar a política {{name}}?",
"DISABLED_POLICY_SUMMARY": "Gostaria de desabilitar a política {{name}}?",

View File

@ -936,7 +936,6 @@
"LDAP_GROUP_MEMBERSHIP_INFO": "Öznitelik, LDAP grubunun üyeliğini gösterir, varsayılan değer memberof, bazı LDAP sunucularında \"ismemberof\" olabilir. This field cannot be empty if you need to enable the LDAP group related feature.",
"GROUP_SCOPE": "LDAP Group Search Scope",
"GROUP_SCOPE_INFO": "Grupları aramak için kapsamı, Varsayılan olarak Alt Ağaç'ı seçin."
},
"UAA": {
"ENDPOINT": "UAA Uç Noktası",
@ -1310,7 +1309,6 @@
"ON": "on",
"AT": "at",
"NOSCHEDULE": "Takvimlendirme de bir hata oluştu"
},
"GC": {
"CURRENT_SCHEDULE": "Schedule to GC",
@ -1623,6 +1621,14 @@
"CREATE_INSTANCE": "Create instance"
},
"P2P_PROVIDER": {
"DRAGONFLY": {
"SCOPE": "Scope",
"SCOPE_SINGLE_SEED_PEER": "Single Seed Peer",
"SCOPE_ALL_SEED_PEERS": "All Seed Peers",
"SCOPE_ALL_PEERS": "All Peers",
"CLUSTER_IDS": "Cluster IDs",
"CLUSTER_IDS_SEPARATOR": "Enter multiple comma separated cluster ids, eg., 1,2,3 (If empty, preheat all clusters)"
},
"P2P_PROVIDER": "P2P Preheat",
"POLICIES": "Policies",
"NEW_POLICY": "NEW POLICY",
@ -1633,9 +1639,6 @@
"TRIGGER": "Trigger",
"CREATED": "Creation Time",
"DESCRIPTION": "Description",
"SCOPE": "Scope",
"SCOPE_SINGLE_PEER": "Single Peer",
"SCOPE_ALL_PEERS": "All Peers",
"NO_POLICY": "No policy",
"ENABLED_POLICY_SUMMARY": "Do you want to enable policy {{name}}?",
"DISABLED_POLICY_SUMMARY": "Do you want to disable policy {{name}}?",

View File

@ -937,7 +937,6 @@
"GROUP_SCOPE_INFO": "搜索组的范围,默认值为\"子树\"",
"GROUP_ATTACH_PARALLEL": "LDAP组并行同步",
"GROUP_ATTACH_PARALLEL_INFO": "打开这个选项时LDAP组的信息是并行同步到Harbor, 这样可以防止用户组太多时造成的登录超时如果关闭这个选项LDAP组信息是顺序同步到Harbor"
},
"UAA": {
"ENDPOINT": "UAA Endpoint",
@ -1309,7 +1308,6 @@
"ON": " ",
"AT": " ",
"NOSCHEDULE": "获取schedule时出现错误"
},
"GC": {
"CURRENT_SCHEDULE": "当前定时任务",
@ -1622,6 +1620,14 @@
"CREATE_INSTANCE": "新建实例"
},
"P2P_PROVIDER": {
"DRAGONFLY": {
"SCOPE": "范围",
"SCOPE_SINGLE_SEED_PEER": "单个种子节点",
"SCOPE_ALL_SEED_PEERS": "所有种子节点",
"SCOPE_ALL_PEERS": "所有节点",
"CLUSTER_IDS": "集群 IDs",
"CLUSTER_IDS_SEPARATOR": "使用逗号分隔集群ID, 例如 1,2,3 (若为空则预热所有集群)"
},
"P2P_PROVIDER": "P2P 预热",
"POLICIES": "策略",
"NEW_POLICY": "新建策略",
@ -1632,9 +1638,6 @@
"TRIGGER": "触发器",
"CREATED": "创建时间",
"DESCRIPTION": "描述",
"SCOPE": "范围",
"SCOPE_SINGLE_PEER": "单节点",
"SCOPE_ALL_PEERS": "全节点",
"NO_POLICY": "暂无记录",
"ENABLED_POLICY_SUMMARY": "是否启用策略 {{name}}?",
"DISABLED_POLICY_SUMMARY": "是否禁用策略 {{name}}?",

View File

@ -1618,6 +1618,14 @@
"CREATE_INSTANCE": "建立實例"
},
"P2P_PROVIDER": {
"DRAGONFLY": {
"SCOPE": "範圍",
"SCOPE_SINGLE_SEED_PEER": "單一種子節點",
"SCOPE_ALL_SEED_PEERS": "所有種子節點",
"SCOPE_ALL_PEERS": "所有節點",
"CLUSTER_IDS": "叢集 IDs",
"CLUSTER_IDS_SEPARATOR": "用逗號分隔的叢集ID, 範例 1,2,3 (若為空則預熱所有叢集)"
},
"P2P_PROVIDER": "P2P 預載",
"POLICIES": "原則",
"NEW_POLICY": "新增原則",
@ -1628,9 +1636,6 @@
"TRIGGER": "觸發器",
"CREATED": "建立時間",
"DESCRIPTION": "描述",
"SCOPE": "範圍",
"SCOPE_SINGLE_PEER": "單節點",
"SCOPE_ALL_PEERS": "全節點",
"NO_POLICY": "無原則",
"ENABLED_POLICY_SUMMARY": "您是否要啟用原則 {{name}}",
"DISABLED_POLICY_SUMMARY": "您是否要停用原則 {{name}}",

View File

@ -483,7 +483,7 @@ func convertPolicyToPayload(policy *policy.Schema) (*models.PreheatPolicy, error
ProjectID: policy.ProjectID,
ProviderID: policy.ProviderID,
Trigger: policy.TriggerStr,
Scope: policy.Scope,
ExtraAttrs: policy.ExtraAttrsStr,
UpdateTime: strfmt.DateTime(policy.UpdatedTime),
}, nil
}
@ -512,7 +512,7 @@ func convertParamPolicyToModelPolicy(model *models.PreheatPolicy) (*policy.Schem
FiltersStr: model.Filters,
TriggerStr: model.Trigger,
Enabled: model.Enabled,
Scope: model.Scope,
ExtraAttrsStr: model.ExtraAttrs,
CreatedAt: time.Time(model.CreationTime),
UpdatedTime: time.Time(model.UpdateTime),
}, nil

View File

@ -79,7 +79,6 @@ func Test_convertPolicyToPayload(t *testing.T) {
Trigger: nil,
TriggerStr: "",
Enabled: false,
Scope: "all_peers",
CreatedAt: time.Time{},
UpdatedTime: time.Time{},
},
@ -93,7 +92,6 @@ func Test_convertPolicyToPayload(t *testing.T) {
ProjectID: 0,
ProviderID: 0,
Trigger: "",
Scope: "all_peers",
UpdateTime: strfmt.DateTime{},
},
},
@ -143,7 +141,6 @@ func Test_convertParamPolicyToModelPolicy(t *testing.T) {
ProjectID: 0,
ProviderID: 0,
Trigger: "",
Scope: "single_peer",
UpdateTime: strfmt.DateTime{},
},
expect: &policy.Schema{
@ -157,7 +154,6 @@ func Test_convertParamPolicyToModelPolicy(t *testing.T) {
Trigger: nil,
TriggerStr: "",
Enabled: false,
Scope: "single_peer",
CreatedAt: time.Time{},
UpdatedTime: time.Time{},
},