mirror of
https://github.com/goharbor/harbor.git
synced 2025-02-16 11:51:47 +01:00
feat: extend the p2p preheat policy
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:
parent
91082af39f
commit
8c21bc8e22
@ -7098,6 +7098,9 @@ definitions:
|
||||
scope:
|
||||
type: string
|
||||
description: The scope of preheat policy
|
||||
extra_attrs:
|
||||
type: string
|
||||
description: The extra attributes of preheat policy
|
||||
creation_time:
|
||||
type: string
|
||||
format: date-time
|
||||
|
1
make/migrations/postgresql/0160_2.13.0_schema.up.sql
Normal file
1
make/migrations/postgresql/0160_2.13.0_schema.up.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE p2p_preheat_policy ADD COLUMN IF NOT EXISTS extra_attrs json;
|
@ -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.Scope, 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, scope string, extraAttrs map[string]interface{}) (int64, error) {
|
||||
u, err := de.fullURLGetter(candidate)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
@ -442,6 +442,7 @@ func (de *defaultEnforcer) startTask(ctx context.Context, executionID int64, can
|
||||
Tag: candidate.Tags[0],
|
||||
Digest: candidate.Digest,
|
||||
Scope: scope,
|
||||
ExtraAttrs: extraAttrs,
|
||||
}
|
||||
|
||||
piData, err := pi.ToJSON()
|
||||
|
@ -82,6 +82,9 @@ type Schema struct {
|
||||
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"`
|
||||
}
|
||||
@ -162,6 +165,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 +192,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 +248,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
|
||||
}
|
||||
|
@ -87,12 +87,14 @@ func (p *PolicyTestSuite) TestDecode() {
|
||||
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 = ""
|
||||
@ -133,9 +135,13 @@ 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)
|
||||
}
|
||||
|
@ -54,13 +54,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 +150,12 @@ type dragonflyJobResponse struct {
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
// dragonflyExtraAttrs is the extra attributes model definition for dragonfly provider.
|
||||
type dragonflyExtraAttrs struct {
|
||||
// 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 +207,18 @@ func (dd *DragonflyDriver) Preheat(preheatingImage *PreheatImage) (*PreheatingSt
|
||||
return nil, errors.New("no image specified")
|
||||
}
|
||||
|
||||
var extraAttrs dragonflyExtraAttrs
|
||||
if preheatingImage.ExtraAttrs != nil && 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",
|
||||
@ -213,6 +231,11 @@ func (dd *DragonflyDriver) Preheat(preheatingImage *PreheatImage) (*PreheatingSt
|
||||
},
|
||||
}
|
||||
|
||||
// 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 {
|
||||
|
@ -86,6 +86,9 @@ func (suite *DragonflyTestSuite) TestPreheat() {
|
||||
URL: "https://harbor.com",
|
||||
Digest: "sha256:f3c97e3bd1e27393eb853a5c90b1132f2cda84336d5ba5d100c720dc98524c82",
|
||||
Scope: "single_peer",
|
||||
ExtraAttrs: map[string]interface{}{
|
||||
"cluster_ids": []uint{1, 2, 3},
|
||||
},
|
||||
})
|
||||
require.NoError(suite.T(), err, "preheat image")
|
||||
suite.Equal(provider.PreheatingStatusPending, st.Status, "preheat status")
|
||||
|
@ -48,6 +48,9 @@ type PreheatImage struct {
|
||||
|
||||
// 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.
|
||||
|
@ -481,6 +481,23 @@
|
||||
</select>
|
||||
</clr-select-container>
|
||||
</div>
|
||||
<!-- extra_attrs -->
|
||||
<div class="clr-form-control">
|
||||
<label class="clr-control-label width-6rem">{{
|
||||
'P2P_PROVIDER.EXTRA_ATTRIBUTES' | translate
|
||||
}}</label>
|
||||
<div class="clr-control-container">
|
||||
<textarea
|
||||
autocomplete="off"
|
||||
class="clr-textarea width-380"
|
||||
type="text"
|
||||
id="extraAttrs"
|
||||
#ngExtraAttrs="ngModel"
|
||||
[disabled]="loading"
|
||||
[(ngModel)]="extraAttrs"
|
||||
name="extraAttrs"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
<div class="mt-1 bottom-btn" *ngIf="!isEdit">
|
||||
|
@ -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,
|
||||
@ -76,6 +77,7 @@ export class AddP2pPolicyComponent implements OnInit, OnDestroy {
|
||||
labels: string;
|
||||
triggerType: string = TRIGGER.MANUAL;
|
||||
scope: string = SCOPE.SINGLE_PEER;
|
||||
extraAttrs: 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;
|
||||
originExtraAttrsForEdit: string;
|
||||
@Input()
|
||||
providers: ProviderUnderProject[] = [];
|
||||
preventVul: boolean = false;
|
||||
@ -309,6 +313,7 @@ export class AddP2pPolicyComponent implements OnInit, OnDestroy {
|
||||
this.loading = true;
|
||||
this.buttonStatus = ClrLoadingState.LOADING;
|
||||
policy.scope = this.scope ? this.scope : SCOPE.SINGLE_PEER;
|
||||
policy.extra_attrs = this.extraAttrs;
|
||||
deleteEmptyKey(policy);
|
||||
if (isAdd) {
|
||||
policy.project_id = this.projectId;
|
||||
@ -410,7 +415,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.originExtraAttrsForEdit != this.extraAttrs) {
|
||||
return true;
|
||||
}
|
||||
// eslint-disable-next-line eqeqeq
|
||||
|
@ -166,6 +166,10 @@
|
||||
<clr-dg-column>{{ 'P2P_PROVIDER.PROVIDER' | translate }}</clr-dg-column>
|
||||
<clr-dg-column>{{ 'P2P_PROVIDER.FILTERS' | translate }}</clr-dg-column>
|
||||
<clr-dg-column>{{ 'P2P_PROVIDER.TRIGGER' | translate }}</clr-dg-column>
|
||||
<clr-dg-column>{{ 'P2P_PROVIDER.SCOPE' | translate }}</clr-dg-column>
|
||||
<clr-dg-column>{{
|
||||
'P2P_PROVIDER.EXTRA_ATTRIBUTES' | translate
|
||||
}}</clr-dg-column>
|
||||
<clr-dg-column [clrDgSortBy]="'creation_time'">{{
|
||||
'P2P_PROVIDER.CREATED' | translate
|
||||
}}</clr-dg-column>
|
||||
@ -284,6 +288,29 @@
|
||||
</clr-signpost-content>
|
||||
</clr-signpost>
|
||||
</clr-dg-cell>
|
||||
<clr-dg-cell>{{ getScopeI18n(p.scope) | translate }}</clr-dg-cell>
|
||||
<clr-dg-cell class="flex">
|
||||
<clr-signpost>
|
||||
<a class="btn btn-link link-normal" clrSignpostTrigger>
|
||||
<span>
|
||||
{{ toString(toJson(p?.extra_attrs)) }}
|
||||
</span>
|
||||
</a>
|
||||
<clr-signpost-content
|
||||
class="pre"
|
||||
[clrPosition]="'top-middle'"
|
||||
*clrIfOpen>
|
||||
<hbr-copy-input
|
||||
[iconMode]="true"
|
||||
[defaultValue]="
|
||||
toString(p?.extra_attrs)
|
||||
"></hbr-copy-input>
|
||||
<pre
|
||||
[innerHTML]="toJson(p?.extra_attrs) | json"
|
||||
class="abc"></pre>
|
||||
</clr-signpost-content>
|
||||
</clr-signpost>
|
||||
</clr-dg-cell>
|
||||
<clr-dg-cell>{{
|
||||
p.creation_time | harborDatetime : 'short'
|
||||
}}</clr-dg-cell>
|
||||
|
@ -58,3 +58,24 @@
|
||||
.no-wrapper {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.pre {
|
||||
min-width: 25rem;
|
||||
max-width: 40rem;
|
||||
}
|
||||
|
||||
pre {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.link-normal {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
max-width: 10rem;
|
||||
text-transform: unset;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import {
|
||||
TIME_OUT,
|
||||
TRIGGER,
|
||||
TRIGGER_I18N_MAP,
|
||||
SCOPE_I18N_MAP,
|
||||
} from '../p2p-provider.service';
|
||||
import { PreheatPolicy } from '../../../../../../ng-swagger-gen/models/preheat-policy';
|
||||
import { PreheatService } from '../../../../../../ng-swagger-gen/services/preheat.service';
|
||||
@ -490,7 +491,8 @@ export class PolicyComponent implements OnInit, OnDestroy {
|
||||
severity: this.addP2pPolicyComponent.severity,
|
||||
label: this.addP2pPolicyComponent.labels,
|
||||
triggerType: this.addP2pPolicyComponent.triggerType,
|
||||
scope: this.addP2pPolicyComponent.scope,
|
||||
scope: this.addP2pPolicyComponent.policy.scope,
|
||||
extraAttrs: this.addP2pPolicyComponent.policy.extra_attrs,
|
||||
});
|
||||
this.addP2pPolicyComponent.originPolicyForEdit = clone(
|
||||
this.selectedRow
|
||||
@ -509,6 +511,10 @@ export class PolicyComponent implements OnInit, OnDestroy {
|
||||
this.addP2pPolicyComponent.triggerType;
|
||||
this.addP2pPolicyComponent.originCronForEdit =
|
||||
this.addP2pPolicyComponent.cron;
|
||||
this.addP2pPolicyComponent.originScopeForEdit =
|
||||
this.addP2pPolicyComponent.scope;
|
||||
this.addP2pPolicyComponent.originExtraAttrsForEdit =
|
||||
this.addP2pPolicyComponent.extraAttrs;
|
||||
}
|
||||
}
|
||||
|
||||
@ -666,6 +672,13 @@ export class PolicyComponent implements OnInit, OnDestroy {
|
||||
return trigger;
|
||||
}
|
||||
|
||||
getScopeI18n(scope: string): string {
|
||||
if (scope) {
|
||||
return SCOPE_I18N_MAP[scope];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
isScheduled(trigger: string): boolean {
|
||||
return JSON.parse(trigger).type === TRIGGER.SCHEDULED;
|
||||
}
|
||||
@ -794,4 +807,17 @@ export class PolicyComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toString(v: any) {
|
||||
if (v) {
|
||||
return JSON.stringify(v);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
toJson(v: any) {
|
||||
if (v) {
|
||||
return JSON.parse(v);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -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",
|
||||
@ -1636,6 +1634,7 @@
|
||||
"SCOPE": "Umfang",
|
||||
"SCOPE_SINGLE_PEER": "Einzelner Peer",
|
||||
"SCOPE_ALL_PEERS": "Alle Peers",
|
||||
"EXTRA_ATTRIBUTES": "Extra Attributes",
|
||||
"NO_POLICY": "Keine Regelwerke",
|
||||
"ENABLED_POLICY_SUMMARY": "Soll das Regelwerk {{name}} aktiviert werden?",
|
||||
"DISABLED_POLICY_SUMMARY": "Soll das Regelwerk {{name}} deaktiviert werden?",
|
||||
|
@ -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",
|
||||
@ -1639,6 +1636,7 @@
|
||||
"SCOPE": "Scope",
|
||||
"SCOPE_SINGLE_PEER": "Single Peer",
|
||||
"SCOPE_ALL_PEERS": "All Peers",
|
||||
"EXTRA_ATTRIBUTES": "Extra Attributes",
|
||||
"NO_POLICY": "No policy",
|
||||
"ENABLED_POLICY_SUMMARY": "Do you want to enable policy {{name}}?",
|
||||
"DISABLED_POLICY_SUMMARY": "Do you want to deactivate policy {{name}}?",
|
||||
|
@ -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",
|
||||
@ -1633,6 +1630,7 @@
|
||||
"SCOPE": "Scope",
|
||||
"SCOPE_SINGLE_PEER": "Single Peer",
|
||||
"SCOPE_ALL_PEERS": "All Peers",
|
||||
"EXTRA_ATTRIBUTES": "Extra Attributes",
|
||||
"NO_POLICY": "No policy",
|
||||
"ENABLED_POLICY_SUMMARY": "Do you want to enable policy {{name}}?",
|
||||
"DISABLED_POLICY_SUMMARY": "Do you want to disable policy {{name}}?",
|
||||
|
@ -1636,6 +1636,7 @@
|
||||
"SCOPE": "Champ d'application",
|
||||
"SCOPE_SINGLE_PEER": "Pair unique",
|
||||
"SCOPE_ALL_PEERS": "Tous les pairs",
|
||||
"EXTRA_ATTRIBUTES": "Attributs supplémentaires",
|
||||
"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}} ?",
|
||||
|
@ -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": "가비지 컬렉션 예약",
|
||||
@ -1630,6 +1627,7 @@
|
||||
"SCOPE": "범위",
|
||||
"SCOPE_SINGLE_PEER": "싱글 피어",
|
||||
"SCOPE_ALL_PEERS": "모든 피어",
|
||||
"EXTRA_ATTRIBUTES": "추가 속성",
|
||||
"NO_POLICY": "정책 없음",
|
||||
"ENABLED_POLICY_SUMMARY": "정책{{name}}을 활성화하시겠습니까?",
|
||||
"DISABLED_POLICY_SUMMARY": "정책{{name}}을 비활성화하시겠습니까?",
|
||||
|
@ -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",
|
||||
@ -1633,6 +1631,7 @@
|
||||
"SCOPE": "Escopo",
|
||||
"SCOPE_SINGLE_PEER": "Par único",
|
||||
"SCOPE_ALL_PEERS": "Todos os pares",
|
||||
"EXTRA_ATTRIBUTES": "Atributos extras",
|
||||
"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}}?",
|
||||
|
@ -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",
|
||||
@ -1636,6 +1634,7 @@
|
||||
"SCOPE": "Scope",
|
||||
"SCOPE_SINGLE_PEER": "Single Peer",
|
||||
"SCOPE_ALL_PEERS": "All Peers",
|
||||
"EXTRA_ATTRIBUTES": "Extra Attributes",
|
||||
"NO_POLICY": "No policy",
|
||||
"ENABLED_POLICY_SUMMARY": "Do you want to enable policy {{name}}?",
|
||||
"DISABLED_POLICY_SUMMARY": "Do you want to disable policy {{name}}?",
|
||||
|
@ -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": "当前定时任务",
|
||||
@ -1635,6 +1633,7 @@
|
||||
"SCOPE": "范围",
|
||||
"SCOPE_SINGLE_PEER": "单节点",
|
||||
"SCOPE_ALL_PEERS": "全节点",
|
||||
"EXTRA_ATTRIBUTES": "额外属性",
|
||||
"NO_POLICY": "暂无记录",
|
||||
"ENABLED_POLICY_SUMMARY": "是否启用策略 {{name}}?",
|
||||
"DISABLED_POLICY_SUMMARY": "是否禁用策略 {{name}}?",
|
||||
|
@ -1631,6 +1631,7 @@
|
||||
"SCOPE": "範圍",
|
||||
"SCOPE_SINGLE_PEER": "單節點",
|
||||
"SCOPE_ALL_PEERS": "全節點",
|
||||
"EXTRA_ATTRIBUTES": "額外屬性",
|
||||
"NO_POLICY": "無原則",
|
||||
"ENABLED_POLICY_SUMMARY": "您是否要啟用原則 {{name}}?",
|
||||
"DISABLED_POLICY_SUMMARY": "您是否要停用原則 {{name}}?",
|
||||
|
@ -484,6 +484,7 @@ func convertPolicyToPayload(policy *policy.Schema) (*models.PreheatPolicy, error
|
||||
ProviderID: policy.ProviderID,
|
||||
Trigger: policy.TriggerStr,
|
||||
Scope: policy.Scope,
|
||||
ExtraAttrs: policy.ExtraAttrsStr,
|
||||
UpdateTime: strfmt.DateTime(policy.UpdatedTime),
|
||||
}, nil
|
||||
}
|
||||
@ -513,6 +514,7 @@ func convertParamPolicyToModelPolicy(model *models.PreheatPolicy) (*policy.Schem
|
||||
TriggerStr: model.Trigger,
|
||||
Enabled: model.Enabled,
|
||||
Scope: model.Scope,
|
||||
ExtraAttrsStr: model.ExtraAttrs,
|
||||
CreatedAt: time.Time(model.CreationTime),
|
||||
UpdatedTime: time.Time(model.UpdateTime),
|
||||
}, nil
|
||||
|
Loading…
Reference in New Issue
Block a user