Skip to content

Commit

Permalink
fix(controllerrevision): add component into revision name (#6045)
Browse files Browse the repository at this point in the history
Signed-off-by: liubo02 <[email protected]>
  • Loading branch information
liubog2008 authored Jan 17, 2025
1 parent 47d6ecc commit ae78931
Show file tree
Hide file tree
Showing 17 changed files with 145 additions and 108 deletions.
4 changes: 2 additions & 2 deletions pkg/controllers/common/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ type GroupAndInstanceSliceState[
InstanceSliceState[I]
}

type RevisionStateInitializer interface {
RevisionInitializer() RevisionInitializer
type RevisionStateInitializer[G runtime.Group] interface {
RevisionInitializer() RevisionInitializer[G]
}

type RevisionState interface {
Expand Down
8 changes: 5 additions & 3 deletions pkg/controllers/common/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

package common

import "github.com/pingcap/tidb-operator/pkg/client"
import (
"github.com/pingcap/tidb-operator/pkg/runtime"
)

type Setter[T any] interface {
Set(T)
Expand Down Expand Up @@ -50,8 +52,8 @@ type CollisionCountOption interface {
CollisionCount() *int32
}

type ParentOption interface {
Parent() client.Object
type ParentOption[G runtime.Group] interface {
Parent() G
}

type (
Expand Down
55 changes: 31 additions & 24 deletions pkg/controllers/common/revision.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"k8s.io/apimachinery/pkg/labels"

"github.com/pingcap/tidb-operator/pkg/client"
"github.com/pingcap/tidb-operator/pkg/runtime"
revisionutil "github.com/pingcap/tidb-operator/pkg/utils/k8s/revision"
"github.com/pingcap/tidb-operator/pkg/utils/task/v3"
"github.com/pingcap/tidb-operator/third_party/kubernetes/pkg/controller/history"
Expand All @@ -35,78 +36,83 @@ func (f RevisionSetterFunc) Set(update, current string, collisionCount int32) {
f(update, current, collisionCount)
}

type Revision interface {
WithCurrentRevision(CurrentRevisionOption) Revision
WithCollisionCount(CollisionCountOption) Revision
WithParent(ParentOption) Revision
WithLabels(LabelsOption) Revision
Initializer() RevisionInitializer
type Revision[G runtime.Group] interface {
WithCurrentRevision(CurrentRevisionOption) Revision[G]
WithCollisionCount(CollisionCountOption) Revision[G]
WithParent(ParentOption[G]) Revision[G]
WithLabels(LabelsOption) Revision[G]
Initializer() RevisionInitializer[G]
}

type RevisionInitializer interface {
type RevisionInitializer[G runtime.Group] interface {
LabelsOption
ParentOption
ParentOption[G]
CurrentRevision() string
CollisionCount() *int32
RevisionSetter
}

type revision struct {
type revision[G runtime.Group] struct {
RevisionSetter

parent ParentOption
parent ParentOption[G]
currentRevision CurrentRevisionOption
collisionCount CollisionCountOption
labels LabelsOption
}

func NewRevision(setter RevisionSetter) Revision {
return &revision{
func NewRevision[G runtime.Group](setter RevisionSetter) Revision[G] {
return &revision[G]{
RevisionSetter: setter,
}
}

func (r *revision) WithParent(parent ParentOption) Revision {
func (r *revision[G]) WithParent(parent ParentOption[G]) Revision[G] {
r.parent = parent
return r
}

func (r *revision) WithCurrentRevision(rev CurrentRevisionOption) Revision {
func (r *revision[G]) WithCurrentRevision(rev CurrentRevisionOption) Revision[G] {
r.currentRevision = rev
return r
}

func (r *revision) WithCollisionCount(collisionCount CollisionCountOption) Revision {
func (r *revision[G]) WithCollisionCount(collisionCount CollisionCountOption) Revision[G] {
r.collisionCount = collisionCount
return r
}

func (r *revision) WithLabels(ls LabelsOption) Revision {
func (r *revision[G]) WithLabels(ls LabelsOption) Revision[G] {
r.labels = ls
return r
}

func (r *revision) Initializer() RevisionInitializer {
func (r *revision[G]) Initializer() RevisionInitializer[G] {
return r
}

func (r *revision) Parent() client.Object {
func (r *revision[G]) Parent() G {
return r.parent.Parent()
}

func (r *revision) CurrentRevision() string {
func (r *revision[G]) CurrentRevision() string {
return r.currentRevision.CurrentRevision()
}

func (r *revision) CollisionCount() *int32 {
func (r *revision[G]) CollisionCount() *int32 {
return r.collisionCount.CollisionCount()
}

func (r *revision) Labels() map[string]string {
func (r *revision[G]) Labels() map[string]string {
return r.labels.Labels()
}

func TaskRevision(state RevisionStateInitializer, c client.Client) task.Task {
func TaskRevision[
GT runtime.GroupTuple[OG, RG],
OG client.Object,
RG runtime.Group,
](state RevisionStateInitializer[RG], c client.Client) task.Task {
var gt GT
w := state.RevisionInitializer()
return task.NameTaskFunc("ContextRevision", func(ctx context.Context) task.Result {
historyCli := history.NewClient(c)
Expand All @@ -115,7 +121,7 @@ func TaskRevision(state RevisionStateInitializer, c client.Client) task.Task {
lbs := w.Labels()
selector := labels.SelectorFromSet(labels.Set(lbs))

revisions, err := historyCli.ListControllerRevisions(parent, selector)
revisions, err := historyCli.ListControllerRevisions(gt.To(parent), selector)
if err != nil {
return task.Fail().With("cannot list controller revisions: %w", err)
}
Expand All @@ -124,7 +130,8 @@ func TaskRevision(state RevisionStateInitializer, c client.Client) task.Task {
// Get the current(old) and update(new) ControllerRevisions.
currentRevision, updateRevision, collisionCount, err := revisionutil.GetCurrentAndUpdate(
ctx,
parent,
gt.To(parent),
parent.Component(),
lbs,
revisions,
historyCli,
Expand Down
64 changes: 44 additions & 20 deletions pkg/controllers/common/revision_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,23 @@ import (
"github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1"

"github.com/pingcap/tidb-operator/apis/core/v1alpha1"
"github.com/pingcap/tidb-operator/pkg/client"
"github.com/pingcap/tidb-operator/pkg/runtime"
"github.com/pingcap/tidb-operator/pkg/utils/fake"
"github.com/pingcap/tidb-operator/pkg/utils/task/v3"
)

type fakeRevisionStateInitializer struct {
type fakeRevisionStateInitializer[G runtime.Group] struct {
fakeRevisionState

currentRevision CurrentRevisionOption
collisionCount CollisionCountOption
parent ParentOption
parent ParentOption[G]
labels LabelsOption
}

func (f *fakeRevisionStateInitializer) RevisionInitializer() RevisionInitializer {
return NewRevision(&f.fakeRevisionState).
func (f *fakeRevisionStateInitializer[G]) RevisionInitializer() RevisionInitializer[G] {
return NewRevision[G](&f.fakeRevisionState).
WithCurrentRevision(f.currentRevision).
WithCollisionCount(f.collisionCount).
WithParent(f.parent).
Expand All @@ -53,7 +53,7 @@ const (
func TestTaskRevision(t *testing.T) {
cases := []struct {
desc string
state *fakeRevisionStateInitializer
state *fakeRevisionStateInitializer[*runtime.PDGroup]
objs []client.Object

expectedResult task.Status
Expand All @@ -63,15 +63,21 @@ func TestTaskRevision(t *testing.T) {
}{
{
desc: "no revisions",
state: &fakeRevisionStateInitializer{
state: &fakeRevisionStateInitializer[*runtime.PDGroup]{
currentRevision: Lazy[string](func() string {
return ""
}),
collisionCount: Lazy[*int32](func() *int32 {
return nil
}),
parent: Lazy[client.Object](func() client.Object {
return fake.FakeObj("aaa", fake.Label[v1alpha1.PDGroup]("aaa", "bbb"))
parent: Lazy[*runtime.PDGroup](func() *runtime.PDGroup {
return fake.Fake(func(obj *runtime.PDGroup) *runtime.PDGroup {
obj.SetName("aaa")
obj.Labels = map[string]string{
"aaa": "bbb",
}
return obj
})
}),
labels: Labels{
"ccc": "ddd",
Expand All @@ -82,15 +88,21 @@ func TestTaskRevision(t *testing.T) {
},
{
desc: "has a revision",
state: &fakeRevisionStateInitializer{
state: &fakeRevisionStateInitializer[*runtime.PDGroup]{
currentRevision: Lazy[string](func() string {
return "xxx"
}),
collisionCount: Lazy[*int32](func() *int32 {
return nil
}),
parent: Lazy[client.Object](func() client.Object {
return fake.FakeObj("aaa", fake.Label[v1alpha1.PDGroup]("aaa", "bbb"))
parent: Lazy[*runtime.PDGroup](func() *runtime.PDGroup {
return fake.Fake(func(obj *runtime.PDGroup) *runtime.PDGroup {
obj.SetName("aaa")
obj.Labels = map[string]string{
"aaa": "bbb",
}
return obj
})
}),
labels: Labels{
"ccc": "ddd",
Expand All @@ -104,15 +116,21 @@ func TestTaskRevision(t *testing.T) {
},
{
desc: "has a coflict revision",
state: &fakeRevisionStateInitializer{
state: &fakeRevisionStateInitializer[*runtime.PDGroup]{
currentRevision: Lazy[string](func() string {
return fakeOldRevision
}),
collisionCount: Lazy[*int32](func() *int32 {
return nil
}),
parent: Lazy[client.Object](func() client.Object {
return fake.FakeObj("aaa", fake.Label[v1alpha1.PDGroup]("aaa", "bbb"))
parent: Lazy[*runtime.PDGroup](func() *runtime.PDGroup {
return fake.Fake(func(obj *runtime.PDGroup) *runtime.PDGroup {
obj.SetName("aaa")
obj.Labels = map[string]string{
"aaa": "bbb",
}
return obj
})
}),
labels: Labels{
"ccc": "ddd",
Expand All @@ -127,15 +145,21 @@ func TestTaskRevision(t *testing.T) {
},
{
desc: "has two coflict revision",
state: &fakeRevisionStateInitializer{
state: &fakeRevisionStateInitializer[*runtime.PDGroup]{
currentRevision: Lazy[string](func() string {
return fakeOldRevision
}),
collisionCount: Lazy[*int32](func() *int32 {
return nil
}),
parent: Lazy[client.Object](func() client.Object {
return fake.FakeObj("aaa", fake.Label[v1alpha1.PDGroup]("aaa", "bbb"))
parent: Lazy[*runtime.PDGroup](func() *runtime.PDGroup {
return fake.Fake(func(obj *runtime.PDGroup) *runtime.PDGroup {
obj.SetName("aaa")
obj.Labels = map[string]string{
"aaa": "bbb",
}
return obj
})
}),
labels: Labels{
"ccc": "ddd",
Expand All @@ -158,7 +182,7 @@ func TestTaskRevision(t *testing.T) {

fc := client.NewFakeClient(c.objs...)

res, done := task.RunTask(context.Background(), TaskRevision(c.state, fc))
res, done := task.RunTask(context.Background(), TaskRevision[runtime.PDGroupTuple](c.state, fc))
assert.Equal(tt, c.expectedResult.String(), res.Status().String(), c.desc)
assert.False(tt, done, c.desc)
update, current, collisionCount := c.state.Revision()
Expand All @@ -175,7 +199,7 @@ func TestTaskRevision(t *testing.T) {
})

// rerun Revision task and make sure that status is unchanged
res2, _ := task.RunTask(context.Background(), TaskRevision(c.state, fc))
res2, _ := task.RunTask(context.Background(), TaskRevision[runtime.PDGroupTuple](c.state, fc))
assert.Equal(tt, c.expectedResult.String(), res2.Status().String(), c.desc)
update, current, collisionCount = c.state.Revision()
assert.Equal(tt, c.expectedUpdateRevision, update, c.desc)
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/pdgroup/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (r *Reconciler) NewRunner(state *tasks.ReconcileContext, reporter task.Task
common.TaskGroupStatusSuspend[runtime.PDGroupTuple](state, r.Client),
),
tasks.TaskContextPDClient(state, r.PDClientManager),
common.TaskRevision(state, r.Client),
common.TaskRevision[runtime.PDGroupTuple](state, r.Client),
tasks.TaskBoot(state, r.Client),
tasks.TaskService(state, r.Client),
tasks.TaskUpdater(state, r.Client),
Expand Down
20 changes: 10 additions & 10 deletions pkg/controllers/pdgroup/tasks/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"k8s.io/apimachinery/pkg/types"

"github.com/pingcap/tidb-operator/apis/core/v1alpha1"
"github.com/pingcap/tidb-operator/pkg/client"
"github.com/pingcap/tidb-operator/pkg/controllers/common"
"github.com/pingcap/tidb-operator/pkg/runtime"
)
Expand All @@ -39,7 +38,7 @@ type State interface {
common.PDGroupStateInitializer
common.ClusterStateInitializer
common.PDSliceStateInitializer
common.RevisionStateInitializer
common.RevisionStateInitializer[*runtime.PDGroup]

common.PDGroupState
common.ClusterState
Expand Down Expand Up @@ -100,23 +99,24 @@ func (s *state) PDSliceInitializer() common.PDSliceInitializer {
Initializer()
}

func (s *state) RevisionInitializer() common.RevisionInitializer {
return common.NewRevision(common.RevisionSetterFunc(func(update, current string, collisionCount int32) {
s.updateRevision = update
s.currentRevision = current
s.collisionCount = collisionCount
})).
func (s *state) RevisionInitializer() common.RevisionInitializer[*runtime.PDGroup] {
return common.NewRevision[*runtime.PDGroup](
common.RevisionSetterFunc(func(update, current string, collisionCount int32) {
s.updateRevision = update
s.currentRevision = current
s.collisionCount = collisionCount
})).
WithCurrentRevision(common.Lazy[string](func() string {
return s.pdg.Status.CurrentRevision
})).
WithCollisionCount(common.Lazy[*int32](func() *int32 {
return s.pdg.Status.CollisionCount
})).
WithParent(common.Lazy[client.Object](func() client.Object {
WithParent(common.Lazy[*runtime.PDGroup](func() *runtime.PDGroup {
pdg := s.pdg.DeepCopy()
// always ignore bootstrapped field in spec
pdg.Spec.Bootstrapped = false
return pdg
return runtime.FromPDGroup(pdg)
})).
WithLabels(s.Labels()).
Initializer()
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/tidbgroup/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (r *Reconciler) NewRunner(state *tasks.ReconcileContext, reporter task.Task
common.TaskGroupStatusSuspend[runtime.TiDBGroupTuple](state, r.Client),
),

common.TaskRevision(state, r.Client),
common.TaskRevision[runtime.TiDBGroupTuple](state, r.Client),
tasks.TaskService(state, r.Client),
tasks.TaskUpdater(state, r.Client),
tasks.TaskStatusAvailable(state, r.Client),
Expand Down
Loading

0 comments on commit ae78931

Please sign in to comment.