Skip to content

Commit

Permalink
enhance: service quality support patch labels & annotations
Browse files Browse the repository at this point in the history
Signed-off-by: ChrisLiu <[email protected]>
  • Loading branch information
chrisliu1995 committed Jul 4, 2024
1 parent f946700 commit dffdc78
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 44 deletions.
2 changes: 2 additions & 0 deletions apis/v1alpha1/gameserver_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ type ServiceQualityAction struct {
// When Result is defined, it would exec action only when the according Result is actually returns.
Result string `json:"result,omitempty"`
GameServerSpec `json:",inline"`
Annotations map[string]string `json:"annotations,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
}

// GameServerStatus defines the observed state of GameServer
Expand Down
14 changes: 14 additions & 0 deletions apis/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions config/crd/bases/game.kruise.io_gameserversets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,10 @@ spec:
serviceQualityAction:
items:
properties:
annotations:
additionalProperties:
type: string
type: object
containers:
description: Containers can be used to make the corresponding
GameServer container fields different from the fields
Expand Down Expand Up @@ -594,6 +598,10 @@ spec:
- type: integer
- type: string
x-kubernetes-int-or-string: true
labels:
additionalProperties:
type: string
type: object
networkDisabled:
type: boolean
opsState:
Expand Down
38 changes: 23 additions & 15 deletions pkg/controllers/gameserver/gameserver_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ func (manager GameServerManager) SyncGsToPod() error {
func (manager GameServerManager) SyncPodToGs(gss *gameKruiseV1alpha1.GameServerSet) error {
gs := manager.gameServer
pod := manager.pod
oldGsSpec := gs.Spec.DeepCopy()
oldGsLabels := gs.GetLabels()
oldGsAnnotations := gs.GetAnnotations()
oldGsStatus := *gs.Status.DeepCopy()

// sync DeletePriority/UpdatePriority/State
podLabels := pod.GetLabels()
Expand All @@ -221,14 +225,18 @@ func (manager GameServerManager) SyncPodToGs(gss *gameKruiseV1alpha1.GameServerS
podGsState := gameKruiseV1alpha1.GameServerState(podLabels[gameKruiseV1alpha1.GameServerStateKey])

// sync Service Qualities
spec, sqConditions := syncServiceQualities(gss.Spec.ServiceQualities, pod.Status.Conditions, gs.Status.ServiceQualitiesCondition)
sqConditions := syncServiceQualities(gss.Spec.ServiceQualities, pod.Status.Conditions, gs)

if isNeedToSyncMetadata(gss, gs) || !reflect.DeepEqual(spec, gs.Spec) {
// sync metadata
// sync Metadata from Gss
if isNeedToSyncMetadata(gss, gs) {
gsMetadata := syncMetadataFromGss(gss)
gs.SetLabels(util.MergeMapString(gs.GetLabels(), gsMetadata.GetLabels()))
gs.SetAnnotations(util.MergeMapString(gs.GetAnnotations(), gsMetadata.GetAnnotations()))
}

if !reflect.DeepEqual(oldGsSpec, gs.Spec) || !reflect.DeepEqual(oldGsLabels, gs.GetLabels()) || !reflect.DeepEqual(oldGsAnnotations, gs.GetAnnotations()) {
// patch gs spec & metadata
patchSpec := map[string]interface{}{"spec": spec, "metadata": gsMetadata}
patchSpec := map[string]interface{}{"spec": gs.Spec, "metadata": map[string]interface{}{"labels": gs.GetLabels(), "annotations": gs.GetAnnotations()}}
jsonPatchSpec, err := json.Marshal(patchSpec)
if err != nil {
return err
Expand All @@ -248,7 +256,6 @@ func (manager GameServerManager) SyncPodToGs(gss *gameKruiseV1alpha1.GameServerS
}

// patch gs status
oldStatus := *gs.Status.DeepCopy()
newStatus := gameKruiseV1alpha1.GameServerStatus{
PodStatus: pod.Status,
CurrentState: podGsState,
Expand All @@ -257,10 +264,10 @@ func (manager GameServerManager) SyncPodToGs(gss *gameKruiseV1alpha1.GameServerS
DeletionPriority: &podDeletePriority,
ServiceQualitiesCondition: sqConditions,
NetworkStatus: manager.syncNetworkStatus(),
LastTransitionTime: oldStatus.LastTransitionTime,
LastTransitionTime: oldGsStatus.LastTransitionTime,
Conditions: conditions,
}
if !reflect.DeepEqual(oldStatus, newStatus) {
if !reflect.DeepEqual(oldGsStatus, newStatus) {
newStatus.LastTransitionTime = metav1.Now()
patchStatus := map[string]interface{}{"status": newStatus}
jsonPatchStatus, err := json.Marshal(patchStatus)
Expand Down Expand Up @@ -333,11 +340,10 @@ func desiredNetworkState(disabled bool) gameKruiseV1alpha1.NetworkState {
return gameKruiseV1alpha1.NetworkReady
}

func syncServiceQualities(serviceQualities []gameKruiseV1alpha1.ServiceQuality, podConditions []corev1.PodCondition, sqConditions []gameKruiseV1alpha1.ServiceQualityCondition) (gameKruiseV1alpha1.GameServerSpec, []gameKruiseV1alpha1.ServiceQualityCondition) {
var spec gameKruiseV1alpha1.GameServerSpec
func syncServiceQualities(serviceQualities []gameKruiseV1alpha1.ServiceQuality, podConditions []corev1.PodCondition, gs *gameKruiseV1alpha1.GameServer) []gameKruiseV1alpha1.ServiceQualityCondition {
var newGsConditions []gameKruiseV1alpha1.ServiceQualityCondition
sqConditionsMap := make(map[string]gameKruiseV1alpha1.ServiceQualityCondition)
for _, sqc := range sqConditions {
for _, sqc := range gs.Status.ServiceQualitiesCondition {
sqConditionsMap[sqc.Name] = sqc
}
timeNow := metav1.Now()
Expand All @@ -358,10 +364,12 @@ func syncServiceQualities(serviceQualities []gameKruiseV1alpha1.ServiceQuality,
for _, action := range sq.ServiceQualityAction {
state, err := strconv.ParseBool(string(podCondition.Status))
if err == nil && state == action.State && (action.Result == "" || podConditionMessage == action.Result) {
spec.DeletionPriority = action.DeletionPriority
spec.UpdatePriority = action.UpdatePriority
spec.OpsState = action.OpsState
spec.NetworkDisabled = action.NetworkDisabled
gs.Spec.DeletionPriority = action.DeletionPriority
gs.Spec.UpdatePriority = action.UpdatePriority
gs.Spec.OpsState = action.OpsState
gs.Spec.NetworkDisabled = action.NetworkDisabled
gs.SetLabels(util.MergeMapString(gs.GetLabels(), action.Labels))
gs.SetAnnotations(util.MergeMapString(gs.GetAnnotations(), action.Annotations))
lastActionTransitionTime = timeNow
}
}
Expand All @@ -379,7 +387,7 @@ func syncServiceQualities(serviceQualities []gameKruiseV1alpha1.ServiceQuality,
}
newGsConditions = append(newGsConditions, newSqCondition)
}
return spec, newGsConditions
return newGsConditions
}

func (manager GameServerManager) syncPodContainers(gsContainers []gameKruiseV1alpha1.GameServerContainer, podContainers []corev1.Container) []corev1.Container {
Expand Down
107 changes: 78 additions & 29 deletions pkg/controllers/gameserver/gameserver_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ func TestSyncServiceQualities(t *testing.T) {
tests := []struct {
serviceQualities []gameKruiseV1alpha1.ServiceQuality
podConditions []corev1.PodCondition
sqConditions []gameKruiseV1alpha1.ServiceQualityCondition
gs *gameKruiseV1alpha1.GameServer
spec gameKruiseV1alpha1.GameServerSpec
labels map[string]string
annotations map[string]string
newSqConditions []gameKruiseV1alpha1.ServiceQualityCondition
}{
//case 0
Expand Down Expand Up @@ -77,7 +79,12 @@ func TestSyncServiceQualities(t *testing.T) {
LastProbeTime: fakeProbeTime,
},
},
sqConditions: nil,
gs: &gameKruiseV1alpha1.GameServer{
Spec: gameKruiseV1alpha1.GameServerSpec{},
Status: gameKruiseV1alpha1.GameServerStatus{
ServiceQualitiesCondition: nil,
},
},
spec: gameKruiseV1alpha1.GameServerSpec{
UpdatePriority: &up,
},
Expand Down Expand Up @@ -124,12 +131,17 @@ func TestSyncServiceQualities(t *testing.T) {
LastProbeTime: fakeProbeTime,
},
},
sqConditions: []gameKruiseV1alpha1.ServiceQualityCondition{
{
Name: "healthy",
Status: string(corev1.ConditionFalse),
LastProbeTime: fakeProbeTime,
LastActionTransitionTime: fakeActionTime,
gs: &gameKruiseV1alpha1.GameServer{
Spec: gameKruiseV1alpha1.GameServerSpec{},
Status: gameKruiseV1alpha1.GameServerStatus{
ServiceQualitiesCondition: []gameKruiseV1alpha1.ServiceQualityCondition{
{
Name: "healthy",
Status: string(corev1.ConditionFalse),
LastProbeTime: fakeProbeTime,
LastActionTransitionTime: fakeActionTime,
},
},
},
},
spec: gameKruiseV1alpha1.GameServerSpec{},
Expand Down Expand Up @@ -171,8 +183,13 @@ func TestSyncServiceQualities(t *testing.T) {
LastProbeTime: fakeProbeTime,
},
},
sqConditions: nil,
spec: gameKruiseV1alpha1.GameServerSpec{},
gs: &gameKruiseV1alpha1.GameServer{
Spec: gameKruiseV1alpha1.GameServerSpec{},
Status: gameKruiseV1alpha1.GameServerStatus{
ServiceQualitiesCondition: nil,
},
},
spec: gameKruiseV1alpha1.GameServerSpec{},
newSqConditions: []gameKruiseV1alpha1.ServiceQualityCondition{
{
Name: "healthy",
Expand Down Expand Up @@ -207,8 +224,13 @@ func TestSyncServiceQualities(t *testing.T) {
LastProbeTime: fakeProbeTime,
},
},
sqConditions: nil,
spec: gameKruiseV1alpha1.GameServerSpec{},
gs: &gameKruiseV1alpha1.GameServer{
Spec: gameKruiseV1alpha1.GameServerSpec{},
Status: gameKruiseV1alpha1.GameServerStatus{
ServiceQualitiesCondition: nil,
},
},
spec: gameKruiseV1alpha1.GameServerSpec{},
newSqConditions: []gameKruiseV1alpha1.ServiceQualityCondition{
{
Name: "healthy",
Expand All @@ -229,6 +251,9 @@ func TestSyncServiceQualities(t *testing.T) {
GameServerSpec: gameKruiseV1alpha1.GameServerSpec{
UpdatePriority: &up,
},
Annotations: map[string]string{
"case-4": "new",
},
},
{
State: false,
Expand All @@ -251,17 +276,25 @@ func TestSyncServiceQualities(t *testing.T) {
LastProbeTime: fakeProbeTime,
},
},
sqConditions: []gameKruiseV1alpha1.ServiceQualityCondition{
{
Name: "healthy",
Status: string(corev1.ConditionFalse),
LastProbeTime: fakeProbeTime,
LastActionTransitionTime: fakeActionTime,
gs: &gameKruiseV1alpha1.GameServer{
Spec: gameKruiseV1alpha1.GameServerSpec{},
Status: gameKruiseV1alpha1.GameServerStatus{
ServiceQualitiesCondition: []gameKruiseV1alpha1.ServiceQualityCondition{
{
Name: "healthy",
Status: string(corev1.ConditionFalse),
LastProbeTime: fakeProbeTime,
LastActionTransitionTime: fakeActionTime,
},
},
},
},
spec: gameKruiseV1alpha1.GameServerSpec{
UpdatePriority: &up,
},
annotations: map[string]string{
"case-4": "new",
},
newSqConditions: []gameKruiseV1alpha1.ServiceQualityCondition{
{
Name: "healthy",
Expand Down Expand Up @@ -310,7 +343,12 @@ func TestSyncServiceQualities(t *testing.T) {
LastProbeTime: fakeProbeTime,
},
},
sqConditions: nil,
gs: &gameKruiseV1alpha1.GameServer{
Spec: gameKruiseV1alpha1.GameServerSpec{},
Status: gameKruiseV1alpha1.GameServerStatus{
ServiceQualitiesCondition: nil,
},
},
spec: gameKruiseV1alpha1.GameServerSpec{
OpsState: "B",
},
Expand Down Expand Up @@ -363,13 +401,18 @@ func TestSyncServiceQualities(t *testing.T) {
LastProbeTime: fakeProbeTime,
},
},
sqConditions: []gameKruiseV1alpha1.ServiceQualityCondition{
{
Name: "multi-return",
Result: "B",
Status: string(corev1.ConditionTrue),
LastProbeTime: fakeProbeTime,
LastActionTransitionTime: fakeActionTime,
gs: &gameKruiseV1alpha1.GameServer{
Spec: gameKruiseV1alpha1.GameServerSpec{},
Status: gameKruiseV1alpha1.GameServerStatus{
ServiceQualitiesCondition: []gameKruiseV1alpha1.ServiceQualityCondition{
{
Name: "multi-return",
Result: "B",
Status: string(corev1.ConditionTrue),
LastProbeTime: fakeProbeTime,
LastActionTransitionTime: fakeActionTime,
},
},
},
},
spec: gameKruiseV1alpha1.GameServerSpec{
Expand All @@ -388,11 +431,17 @@ func TestSyncServiceQualities(t *testing.T) {
}

for i, test := range tests {
actualSpec, actualNewSqConditions := syncServiceQualities(test.serviceQualities, test.podConditions, test.sqConditions)
actualNewSqConditions := syncServiceQualities(test.serviceQualities, test.podConditions, test.gs)
expectSpec := test.spec
expectNewSqConditions := test.newSqConditions
if !reflect.DeepEqual(actualSpec, expectSpec) {
t.Errorf("case %d: expect spec %v but got %v", i, expectSpec, actualSpec)
if !reflect.DeepEqual(test.gs.Spec, expectSpec) {
t.Errorf("case %d: expect spec %v but got %v", i, expectSpec, test.gs.Spec)
}
if !reflect.DeepEqual(test.gs.GetLabels(), test.labels) {
t.Errorf("case %d: expect labels %v but got %v", i, test.labels, test.gs.GetLabels())
}
if !reflect.DeepEqual(test.gs.GetAnnotations(), test.annotations) {
t.Errorf("case %d: expect annotations %v but got %v", i, test.annotations, test.gs.GetAnnotations())
}
if len(actualNewSqConditions) != len(expectNewSqConditions) {
t.Errorf("case %d: expect sq conditions len %v but got %v", i, len(expectNewSqConditions), len(actualNewSqConditions))
Expand Down
18 changes: 18 additions & 0 deletions pkg/util/map.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package util

func MergeMapString(map1, map2 map[string]string) map[string]string {
if map1 == nil && map2 == nil {
return nil
}
mergedMap := make(map[string]string)

for key, value := range map1 {
mergedMap[key] = value
}

for key, value := range map2 {
mergedMap[key] = value
}

return mergedMap
}
Loading

0 comments on commit dffdc78

Please sign in to comment.