Skip to content

Commit a9a89fc

Browse files
committed
persistent naming strategy
1 parent 820a8dc commit a9a89fc

File tree

7 files changed

+84
-34
lines changed

7 files changed

+84
-34
lines changed

xset/api/xset_types.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ type XSetSpec struct {
5555
// +optional
5656
ScaleStrategy ScaleStrategy `json:"scaleStrategy,omitempty"`
5757

58+
// NamigPolicy indicates the strategy detail that will be used for replica naming
59+
// +optional
60+
NamingStrategy *NamingStrategy `json:"namingStrategy,omitempty"`
61+
5862
// Indicate the number of histories to be conserved
5963
// If unspecified, defaults to 20
6064
// +optional
@@ -120,6 +124,25 @@ type ScaleStrategy struct {
120124
OperationDelaySeconds *int32 `json:"operationDelaySeconds,omitempty"`
121125
}
122126

127+
// TargetNamingSuffixPolicy indicates how a new pod name suffix part is generated.
128+
type TargetNamingSuffixPolicy string
129+
130+
const (
131+
// TargetNamingSuffixPolicyPersistentSequence uses persistent sequential numbers as pod name suffix.
132+
TargetNamingSuffixPolicyPersistentSequence TargetNamingSuffixPolicy = "PersistentSequence"
133+
// TargetNamingSuffixPolicyRandom uses collaset name as pod generateName, which is the prefix
134+
// of pod name. Kubernetes then adds a random string as suffix after the generateName.
135+
// This is defaulting policy.
136+
TargetNamingSuffixPolicyRandom TargetNamingSuffixPolicy = "Random"
137+
)
138+
139+
type NamingStrategy struct {
140+
// TargetNamingSuffixPolicy is a string enumeration that determaines how pod name suffix will be generated.
141+
// A collaset pod name contains two parts to be placed in a string formation %s-%s; the prefix is collaset
142+
// name, and the suffix is determined by TargetNamingSuffixPolicy.
143+
TargetNamingSuffixPolicy TargetNamingSuffixPolicy `json:"TargetNamingSuffixPolicy,omitempty"`
144+
}
145+
123146
// UpdateStrategyType is a string enumeration type that enumerates
124147
// all possible ways we can update a Target when updating application
125148
type UpdateStrategyType string

xset/revisionowner/revision_owner.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ func (r *revisionOwner) GetInUsedRevisions(parent metav1.Object) (sets.String, e
6666
res.Insert(status.UpdatedRevision)
6767
res.Insert(status.CurrentRevision)
6868

69-
targets, err := r.TargetControl.GetFilteredTargets(context.TODO(), spec.Selector, xSetObject)
69+
targets, _, err := r.TargetControl.GetFilteredTargets(context.TODO(), spec.Selector, xSetObject)
7070
if err != nil {
7171
return nil, err
7272
}

xset/synccontrols/sync_control.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,19 @@ func (r *RealSyncControl) SyncTargets(ctx context.Context, instance api.XSetObje
135135
return false, fmt.Errorf("fail to get XSetSpec")
136136
}
137137

138-
var err error
139-
syncContext.FilteredTarget, err = r.xControl.GetFilteredTargets(ctx, xspec.Selector, instance)
138+
filteredTargets, allTargets, err := r.xControl.GetFilteredTargets(ctx, xspec.Selector, instance)
140139
if err != nil {
141140
return false, fmt.Errorf("fail to get filtered Targets: %w", err)
142141
}
143142

143+
if IsTargetNamingSuffixPolicyPersistentSequence(xspec) {
144+
// for naming with persistent sequences suffix, targets with same name should not exist at same time
145+
syncContext.FilteredTarget = allTargets
146+
} else {
147+
// for naming with random suffix, targets with random names can be created at same time
148+
syncContext.FilteredTarget = filteredTargets
149+
}
150+
144151
// sync subresource
145152
// 1. list pvcs using ownerReference
146153
// 2. adopt and retain orphaned pvcs according to PVC retention policy
@@ -199,7 +206,8 @@ func (r *RealSyncControl) SyncTargets(ctx context.Context, instance api.XSetObje
199206
}
200207
}
201208

202-
if target.GetDeletionTimestamp() != nil {
209+
// for naming with persistent sequences suffix, targets with same name should not exist at same time
210+
if target.GetDeletionTimestamp() != nil && !IsTargetNamingSuffixPolicyPersistentSequence(xspec) {
203211
// 1. Reclaim ID from Target which is scaling in and terminating.
204212
if contextDetail, exist := ownedIDs[id]; exist && r.resourceContextControl.Contains(contextDetail, api.EnumScaleInContextDataKey, "true") {
205213
idToReclaim.Insert(id)
@@ -897,7 +905,9 @@ func (r *RealSyncControl) CalculateStatus(_ context.Context, instance api.XSetOb
897905

898906
activeTargets := FilterOutActiveTargetWrappers(syncContext.TargetWrappers)
899907
for _, targetWrapper := range activeTargets {
900-
if targetWrapper.GetDeletionTimestamp() != nil {
908+
909+
// for naming with persistent sequences suffix, terminating targets can be shown in status
910+
if targetWrapper.GetDeletionTimestamp() != nil && !IsTargetNamingSuffixPolicyPersistentSequence(r.xsetController.GetXSetSpec(instance)) {
901911
continue
902912
}
903913

xset/synccontrols/x_replace.go

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -132,32 +132,13 @@ func (r *RealSyncControl) replaceOriginTargets(
132132

133133
replaceRevision := r.getReplaceRevision(originTarget, syncContext)
134134

135-
// create target using update revision if replaced by update, otherwise using current revision
136-
newTarget, err := NewTargetFrom(r.xsetController, r.xsetLabelAnnoMgr, instance, replaceRevision, originTargetId,
137-
r.xsetController.GetXSetTemplatePatcher(instance),
138-
func(object client.Object) error {
139-
if decorationAdapter, ok := r.xsetController.(api.DecorationAdapter); ok {
140-
// get current decoration patcher from origin target, and patch new target
141-
if fn, err := decorationAdapter.GetDecorationPatcherByRevisions(ctx, r.Client, originTarget, originWrapper.DecorationUpdatedRevisions); err != nil {
142-
return err
143-
} else {
144-
return fn(object)
145-
}
146-
}
147-
return nil
148-
},
149-
)
150-
if err != nil {
151-
return err
152-
}
153135
// add instance id and replace pair label
154136
var newInstanceId string
155137
var newTargetContext *api.ContextDetail
156138
if contextDetail, exist := mapNewToOriginTargetContext[originTargetId]; exist && contextDetail != nil {
157139
newTargetContext = contextDetail
158140
// reuse targetContext ID if pair-relation exists
159141
newInstanceId = fmt.Sprintf("%d", newTargetContext.ID)
160-
r.xsetLabelAnnoMgr.Set(newTarget, api.XInstanceIdLabelKey, newInstanceId)
161142
logger.Info("replaceOriginTargets", "try to reuse new pod resourceContext id", newInstanceId)
162143
} else {
163144
if availableContexts[i] == nil {
@@ -167,11 +148,30 @@ func (r *RealSyncControl) replaceOriginTargets(
167148
newTargetContext = availableContexts[i]
168149
// add replace pair-relation to targetContexts for originTarget and newTarget
169150
newInstanceId = fmt.Sprintf("%d", newTargetContext.ID)
170-
r.xsetLabelAnnoMgr.Set(newTarget, api.XInstanceIdLabelKey, newInstanceId)
171151
r.resourceContextControl.Put(ownedIDs[originTargetId], api.EnumReplaceNewTargetIDContextDataKey, newInstanceId)
172152
r.resourceContextControl.Put(ownedIDs[newTargetContext.ID], api.EnumReplaceOriginTargetIDContextDataKey, strconv.Itoa(originTargetId))
173153
r.resourceContextControl.Remove(ownedIDs[newTargetContext.ID], api.EnumJustCreateContextDataKey)
174154
}
155+
156+
// create target using update revision if replaced by update, otherwise using current revision
157+
newTarget, err := NewTargetFrom(r.xsetController, r.xsetLabelAnnoMgr, instance, replaceRevision, originTargetId,
158+
r.xsetController.GetXSetTemplatePatcher(instance),
159+
func(object client.Object) error {
160+
if decorationAdapter, ok := r.xsetController.(api.DecorationAdapter); ok {
161+
// get current decoration patcher from origin target, and patch new target
162+
if fn, err := decorationAdapter.GetDecorationPatcherByRevisions(ctx, r.Client, originTarget, originWrapper.DecorationUpdatedRevisions); err != nil {
163+
return err
164+
} else {
165+
return fn(object)
166+
}
167+
}
168+
return nil
169+
},
170+
)
171+
if err != nil {
172+
return err
173+
}
174+
175175
r.xsetLabelAnnoMgr.Set(newTarget, api.XReplacePairOriginName, originTarget.GetName())
176176
r.xsetLabelAnnoMgr.Set(newTarget, api.XCreatingLabel, strconv.FormatInt(time.Now().UnixNano(), 10))
177177
r.resourceContextControl.Put(newTargetContext, api.EnumRevisionContextDataKey, replaceRevision.GetName())

xset/synccontrols/x_utils.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ func NewTargetFrom(setController api.XSetController, xsetLabelAnnoMgr api.XSetLa
6565
targetObj.SetNamespace(owner.GetNamespace())
6666
targetObj.SetGenerateName(GetTargetsPrefix(owner.GetName()))
6767

68+
if IsTargetNamingSuffixPolicyPersistentSequence(setController.GetXSetSpec(owner)) {
69+
targetObj.SetName(fmt.Sprintf("%s-%d", targetObj.GetGenerateName(), id))
70+
}
71+
6872
xsetLabelAnnoMgr.Set(targetObj, api.XInstanceIdLabelKey, fmt.Sprintf("%d", id))
6973
targetObj.GetLabels()[appsv1.ControllerRevisionHashLabelKey] = revision.GetName()
7074
controlByXSet(xsetLabelAnnoMgr, targetObj)
@@ -172,3 +176,10 @@ func afterOrZero(t1, t2 *metav1.Time) bool {
172176
}
173177
return t1.After(t2.Time)
174178
}
179+
180+
func IsTargetNamingSuffixPolicyPersistentSequence(xsetSpec *api.XSetSpec) bool {
181+
if xsetSpec == nil || xsetSpec.NamingStrategy == nil {
182+
return false
183+
}
184+
return xsetSpec.NamingStrategy.TargetNamingSuffixPolicy == api.TargetNamingSuffixPolicyPersistentSequence
185+
}

xset/xcontrol/target_control.go

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const (
3939
)
4040

4141
type TargetControl interface {
42-
GetFilteredTargets(ctx context.Context, selector *metav1.LabelSelector, owner api.XSetObject) ([]client.Object, error)
42+
GetFilteredTargets(ctx context.Context, selector *metav1.LabelSelector, owner api.XSetObject) ([]client.Object, []client.Object, error)
4343
CreateTarget(ctx context.Context, target client.Object) (client.Object, error)
4444
DeleteTarget(ctx context.Context, target client.Object) error
4545
UpdateTarget(ctx context.Context, target client.Object) error
@@ -71,19 +71,19 @@ func NewTargetControl(mixin *mixin.ReconcilerMixin, xsetController api.XSetContr
7171
}, nil
7272
}
7373

74-
func (r *targetControl) GetFilteredTargets(ctx context.Context, selector *metav1.LabelSelector, owner api.XSetObject) ([]client.Object, error) {
74+
func (r *targetControl) GetFilteredTargets(ctx context.Context, selector *metav1.LabelSelector, owner api.XSetObject) ([]client.Object, []client.Object, error) {
7575
targetList := r.xsetController.NewXObjectList()
7676
if err := r.client.List(ctx, targetList, &client.ListOptions{
7777
Namespace: owner.GetNamespace(),
7878
FieldSelector: fields.OneTermEqualSelector(FieldIndexOwnerRefUID, string(owner.GetUID())),
7979
}); err != nil {
80-
return nil, err
80+
return nil, nil, err
8181
}
8282

8383
targetListVal := reflect.Indirect(reflect.ValueOf(targetList))
8484
itemsVal := targetListVal.FieldByName("Items")
8585
if !itemsVal.IsValid() {
86-
return nil, fmt.Errorf("target list items is invalid")
86+
return nil, nil, fmt.Errorf("target list items is invalid")
8787
}
8888

8989
var items []client.Object
@@ -94,12 +94,18 @@ func (r *targetControl) GetFilteredTargets(ctx context.Context, selector *metav1
9494
items[i] = itemVal.(client.Object)
9595
}
9696
} else {
97-
return nil, fmt.Errorf("target list items is invalid")
97+
return nil, nil, fmt.Errorf("target list items is invalid")
98+
}
99+
100+
allTargets, err := r.getTargets(items, selector, owner)
101+
if err != nil {
102+
return nil, nil, err
98103
}
99104

100105
items = filterOutInactiveTargets(r.xsetController, items)
101-
targets, err := r.getTargets(items, selector, owner)
102-
return targets, err
106+
filteredTargets, err := r.getTargets(items, selector, owner)
107+
108+
return filteredTargets, allTargets, err
103109
}
104110

105111
func (r *targetControl) CreateTarget(ctx context.Context, target client.Object) (client.Object, error) {

xset/xset_controller.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ func (r *xSetCommonReconciler) ensureReclaimPvcs(ctx context.Context, xset api.X
296296

297297
func (r *xSetCommonReconciler) ensureReclaimTargetsDeletion(ctx context.Context, instance api.XSetObject) (bool, error) {
298298
xSetSpec := r.XSetController.GetXSetSpec(instance)
299-
targets, err := r.targetControl.GetFilteredTargets(ctx, xSetSpec.Selector, instance)
299+
_, targets, err := r.targetControl.GetFilteredTargets(ctx, xSetSpec.Selector, instance)
300300
if err != nil {
301301
return false, fmt.Errorf("fail to get filtered Targets: %s", err.Error())
302302
}
@@ -322,7 +322,7 @@ func (r *xSetCommonReconciler) ensureReclaimOwnerReferences(ctx context.Context,
322322
return nil
323323
}
324324
xSetSpec := r.XSetController.GetXSetSpec(instance)
325-
filteredTargets, err := r.targetControl.GetFilteredTargets(ctx, xSetSpec.Selector, instance)
325+
_, filteredTargets, err := r.targetControl.GetFilteredTargets(ctx, xSetSpec.Selector, instance)
326326
if err != nil {
327327
return fmt.Errorf("fail to get filtered Targets: %s", err.Error())
328328
}

0 commit comments

Comments
 (0)