Skip to content

Commit 85e556c

Browse files
committed
update
1 parent 12c56ec commit 85e556c

15 files changed

+241
-149
lines changed

controllers/k8score/event_controller.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"sigs.k8s.io/controller-runtime/pkg/log"
3434

3535
"github.com/apecloud/kubeblocks/pkg/controller/component"
36+
"github.com/apecloud/kubeblocks/pkg/controller/instance"
3637
"github.com/apecloud/kubeblocks/pkg/controller/instanceset"
3738
"github.com/apecloud/kubeblocks/pkg/controller/multicluster"
3839
intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil"
@@ -80,6 +81,7 @@ func (r *EventReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
8081
}
8182

8283
handlers := []eventHandler{
84+
&instance.PodRoleEventHandler{},
8385
&instanceset.PodRoleEventHandler{},
8486
&component.AvailableEventHandler{},
8587
&component.KBAgentTaskEventHandler{},

controllers/workloads/instance_controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ func (r *InstanceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
8484
Do(instance.NewFixMetaReconciler()).
8585
Do(instance.NewDeletionReconciler()).
8686
Do(instance.NewStatusReconciler()).
87+
Do(instance.NewRevisionUpdateReconciler()).
8788
Do(instance.NewAssistantObjectReconciler()).
8889
Do(instance.NewAlignmentReconciler()).
8990
Do(instance.NewUpdateReconciler()).

pkg/constant/annotations.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,7 @@ func InheritedAnnotations() []string {
7373
HostNetworkAnnotationKey,
7474
FeatureReconciliationInCompactModeAnnotationKey,
7575
KBAppMultiClusterPlacementKey,
76+
"enable-instance-api",
77+
"clone-assistant-objects",
7678
}
7779
}

pkg/controller/builder/builder_instance.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ func (builder *InstanceBuilder) SetFinalizers() *InstanceBuilder {
4242
return builder
4343
}
4444

45-
func (builder *InstanceBuilder) podSpec() *corev1.PodSpec {
46-
return &builder.get().Spec.Template.Spec
45+
func (builder *InstanceBuilder) SetPodTemplate(template corev1.PodTemplateSpec) *InstanceBuilder {
46+
builder.get().Spec.Template = template
47+
return builder
4748
}
4849

49-
func (builder *InstanceBuilder) SetPodSpec(podSpec corev1.PodSpec) *InstanceBuilder {
50-
*builder.podSpec() = podSpec
51-
return builder
50+
func (builder *InstanceBuilder) podSpec() *corev1.PodSpec {
51+
return &builder.get().Spec.Template.Spec
5252
}
5353

5454
func (builder *InstanceBuilder) SetContainers(containers []corev1.Container) *InstanceBuilder {
@@ -141,6 +141,20 @@ func (builder *InstanceBuilder) SetSelector(selector *metav1.LabelSelector) *Ins
141141
return builder
142142
}
143143

144+
func (builder *InstanceBuilder) SetSelectorMatchLabels(labels map[string]string) *InstanceBuilder {
145+
selector := builder.get().Spec.Selector
146+
if selector == nil {
147+
selector = &metav1.LabelSelector{}
148+
builder.get().Spec.Selector = selector
149+
}
150+
matchLabels := make(map[string]string, len(labels))
151+
for k, v := range labels {
152+
matchLabels[k] = v
153+
}
154+
builder.get().Spec.Selector.MatchLabels = matchLabels
155+
return builder
156+
}
157+
144158
func (builder *InstanceBuilder) SetMinReadySeconds(seconds int32) *InstanceBuilder {
145159
builder.get().Spec.MinReadySeconds = seconds
146160
return builder

pkg/controller/builder/builder_instance_set.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@ func (builder *InstanceSetBuilder) SetDisableDefaultHeadlessService(disable bool
165165
return builder
166166
}
167167

168+
func (builder *InstanceSetBuilder) SetEnableInstanceAPI(enableInstanceAPI *bool) *InstanceSetBuilder {
169+
builder.get().Spec.EnableInstanceAPI = enableInstanceAPI
170+
return builder
171+
}
172+
168173
func (builder *InstanceSetBuilder) SetAssistantObjects(objs []corev1.ObjectReference) *InstanceSetBuilder {
169174
builder.get().Spec.AssistantObjects = objs
170175
return builder

pkg/controller/factory/builder.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,16 @@ func BuildInstanceSet(synthesizedComp *component.SynthesizedComponent, compDef *
8686
SetTemplateVars(synthesizedComp.TemplateVars).
8787
SetAssistantObjects(synthesizedComp.AssistantObjects).
8888
SetCloneAssistantObjects(synthesizedComp.CloneAssistantObjects)
89+
if synthesizedComp.Annotations != nil {
90+
enable, ok1 := synthesizedComp.Annotations["enable-instance-api"]
91+
if ok1 && enable == "true" {
92+
itsBuilder.SetEnableInstanceAPI(ptr.To(true))
93+
}
94+
clone, ok2 := synthesizedComp.Annotations["clone-assistant-objects"]
95+
if ok2 && clone == "true" {
96+
itsBuilder.SetCloneAssistantObjects(true)
97+
}
98+
}
8999
if compDef != nil {
90100
itsBuilder.SetDisableDefaultHeadlessService(compDef.Spec.DisableDefaultHeadlessService)
91101
}

pkg/controller/instance/in_place_update_utils.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,9 @@ func equalResourcesInPlaceFields(old, new *corev1.Pod) bool {
285285

286286
func getPodUpdatePolicy(inst *workloads.Instance, pod *corev1.Pod) (PodUpdatePolicy, error) {
287287
if getPodRevision(pod) != inst.Status.UpdateRevision {
288+
if len(inst.Status.UpdateRevision) == 0 {
289+
return NoOpsPolicy, nil
290+
}
288291
return RecreatePolicy, nil
289292
}
290293

pkg/controller/instanceset2/pod_role_event_handler.go renamed to pkg/controller/instance/pod_role_event_handler.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ You should have received a copy of the GNU Affero General Public License
1717
along with this program. If not, see <http://www.gnu.org/licenses/>.
1818
*/
1919

20-
package instanceset2
20+
package instance
2121

2222
import (
2323
"encoding/json"
@@ -173,17 +173,17 @@ func handleRoleChangedEvent(cli client.Client, reqCtx intctrlutil.RequestCtx, _
173173

174174
var name string
175175
if pod.Labels != nil {
176-
if n, ok := pod.Labels[WorkloadsInstanceLabelKey]; ok {
176+
if n, ok := pod.Labels[constant.KBAppInstanceNameLabelKey]; ok {
177177
name = n
178178
}
179179
}
180-
its := &workloads.InstanceSet{}
181-
if err := cli.Get(reqCtx.Ctx, types.NamespacedName{Namespace: pod.Namespace, Name: name}, its); err != nil {
180+
inst := &workloads.Instance{}
181+
if err := cli.Get(reqCtx.Ctx, types.NamespacedName{Namespace: pod.Namespace, Name: name}, inst); err != nil {
182182
return "", err
183183
}
184184
reqCtx.Log.Info("handle role change event", "pod", pod.Name, "role", role, "originalRole", message.OriginalRole)
185185

186-
if err := updatePodRoleLabel(cli, reqCtx, *its, pod, pair.RoleName, snapshot.Version); err != nil {
186+
if err := updatePodRoleLabel(cli, reqCtx, inst, pod, pair.RoleName, snapshot.Version); err != nil {
187187
return "", err
188188
}
189189
}
@@ -239,9 +239,9 @@ func parseProbeEventMessage(reqCtx intctrlutil.RequestCtx, event *corev1.Event)
239239

240240
// updatePodRoleLabel updates pod role label when internal container role changed
241241
func updatePodRoleLabel(cli client.Client, reqCtx intctrlutil.RequestCtx,
242-
its workloads.InstanceSet, pod *corev1.Pod, roleName string, version string) error {
242+
inst *workloads.Instance, pod *corev1.Pod, roleName string, version string) error {
243243
ctx := reqCtx.Ctx
244-
roleMap := composeRoleMap(its)
244+
roleMap := composeRoleMap(inst)
245245
// role not defined in CR, ignore it
246246
roleName = strings.ToLower(roleName)
247247

@@ -250,9 +250,9 @@ func updatePodRoleLabel(cli client.Client, reqCtx intctrlutil.RequestCtx,
250250
role, ok := roleMap[roleName]
251251
switch ok {
252252
case true:
253-
newPod.Labels[RoleLabelKey] = role.Name
253+
newPod.Labels[constant.RoleLabelKey] = role.Name
254254
case false:
255-
delete(newPod.Labels, RoleLabelKey)
255+
delete(newPod.Labels, constant.RoleLabelKey)
256256
}
257257

258258
if newPod.Annotations == nil {
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
Copyright (C) 2022-2025 ApeCloud Co., Ltd
3+
4+
This file is part of KubeBlocks project
5+
6+
This program is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU Affero General Public License as published by
8+
the Free Software Foundation, either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
This program is distributed in the hope that it will be useful
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU Affero General Public License for more details.
15+
16+
You should have received a copy of the GNU Affero General Public License
17+
along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
package instance
21+
22+
import (
23+
workloads "github.com/apecloud/kubeblocks/apis/workloads/v1"
24+
"github.com/apecloud/kubeblocks/pkg/controller/kubebuilderx"
25+
"github.com/apecloud/kubeblocks/pkg/controller/model"
26+
)
27+
28+
func NewRevisionUpdateReconciler() kubebuilderx.Reconciler {
29+
return &revisionUpdateReconciler{}
30+
}
31+
32+
type revisionUpdateReconciler struct{}
33+
34+
var _ kubebuilderx.Reconciler = &revisionUpdateReconciler{}
35+
36+
func (r *revisionUpdateReconciler) PreCondition(tree *kubebuilderx.ObjectTree) *kubebuilderx.CheckResult {
37+
if tree.GetRoot() == nil || !model.IsObjectUpdating(tree.GetRoot()) {
38+
return kubebuilderx.ConditionUnsatisfied
39+
}
40+
return kubebuilderx.ConditionSatisfied
41+
}
42+
43+
func (r *revisionUpdateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kubebuilderx.Result, error) {
44+
inst := tree.GetRoot().(*workloads.Instance)
45+
revision, err := buildInstancePodRevision(&inst.Spec.Template, inst)
46+
if err != nil {
47+
return kubebuilderx.Continue, err
48+
}
49+
inst.Status.UpdateRevision = revision
50+
// The 'ObservedGeneration' field is used to indicate whether the revisions have been updated.
51+
// Computing these revisions in each reconciliation loop can be time-consuming, so we optimize it by
52+
// performing the computation only when the 'spec' is updated.
53+
inst.Status.ObservedGeneration = inst.Generation
54+
55+
return kubebuilderx.Continue, nil
56+
}

pkg/controller/instance/revision_utils.go

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"k8s.io/apimachinery/pkg/util/rand"
3737

3838
workloads "github.com/apecloud/kubeblocks/apis/workloads/v1"
39+
"github.com/apecloud/kubeblocks/pkg/controller/builder"
3940
"github.com/apecloud/kubeblocks/pkg/controller/model"
4041
)
4142

@@ -46,15 +47,15 @@ var Codecs = serializer.NewCodecFactory(model.GetScheme())
4647
var patchCodec = Codecs.LegacyCodec(workloads.SchemeGroupVersion)
4748
var controllerKind = appsv1.SchemeGroupVersion.WithKind("StatefulSet")
4849

49-
func NewRevision(its *workloads.InstanceSet) (*appsv1.ControllerRevision, error) {
50-
patch, err := getPatch(its)
50+
func NewRevision(inst *workloads.Instance) (*appsv1.ControllerRevision, error) {
51+
patch, err := getPatch(inst)
5152
if err != nil {
5253
return nil, err
5354
}
5455
collision := int32(0)
55-
cr, err := NewControllerRevision(its,
56+
cr, err := NewControllerRevision(inst,
5657
controllerKind,
57-
its.Spec.Template.Labels,
58+
inst.Spec.Template.Labels,
5859
runtime.RawExtension{Raw: patch},
5960
1,
6061
&collision)
@@ -64,7 +65,7 @@ func NewRevision(its *workloads.InstanceSet) (*appsv1.ControllerRevision, error)
6465
if cr.ObjectMeta.Annotations == nil {
6566
cr.ObjectMeta.Annotations = make(map[string]string)
6667
}
67-
for key, value := range its.Annotations {
68+
for key, value := range inst.Annotations {
6869
cr.ObjectMeta.Annotations[key] = value
6970
}
7071
return cr, nil
@@ -74,8 +75,8 @@ func NewRevision(its *workloads.InstanceSet) (*appsv1.ControllerRevision, error)
7475
// previous version. If the returned error is nil the patch is valid. The current state that we save is just the
7576
// PodSpecTemplate. We can modify this later to encompass more state (or less) and remain compatible with previously
7677
// recorded patches.
77-
func getPatch(its *workloads.InstanceSet) ([]byte, error) {
78-
data, err := runtime.Encode(patchCodec, its)
78+
func getPatch(inst *workloads.Instance) ([]byte, error) {
79+
data, err := runtime.Encode(patchCodec, inst)
7980
if err != nil {
8081
return nil, err
8182
}
@@ -166,3 +167,19 @@ func getPodRevision(pod *corev1.Pod) string {
166167
}
167168
return pod.Labels[appsv1.ControllerRevisionHashLabelKey]
168169
}
170+
171+
func buildInstancePodRevision(template *corev1.PodTemplateSpec, parent *workloads.Instance) (string, error) {
172+
podTemplate := filterInPlaceFields(template)
173+
inst := builder.NewInstanceBuilder(parent.Namespace, parent.Name).
174+
SetUID(parent.UID).
175+
AddAnnotationsInMap(parent.Annotations).
176+
SetSelectorMatchLabels(parent.Labels).
177+
SetPodTemplate(*podTemplate).
178+
GetObject()
179+
180+
cr, err := NewRevision(inst)
181+
if err != nil {
182+
return "", err
183+
}
184+
return cr.Labels[ControllerRevisionHashLabel], nil
185+
}

0 commit comments

Comments
 (0)