Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ServiceQuality supports multiple results returned by one probe #117

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions apis/v1alpha1/gameserver_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,20 @@ type ServiceQuality struct {
}

type ServiceQualityCondition struct {
Name string `json:"name"`
Status string `json:"status,omitempty"`
Name string `json:"name"`
Status string `json:"status,omitempty"`
// Result indicate the probe message returned by the script
Result string `json:"result,omitempty"`
LastProbeTime metav1.Time `json:"lastProbeTime,omitempty"`
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
LastActionTransitionTime metav1.Time `json:"lastActionTransitionTime,omitempty"`
}

type ServiceQualityAction struct {
State bool `json:"state"`
State bool `json:"state"`
// Result indicate the probe message returned by the script.
// When Result is defined, it would exec action only when the according Result is actually returns.
Result string `json:"result,omitempty"`
GameServerSpec `json:",inline"`
}

Expand Down
4 changes: 4 additions & 0 deletions config/crd/bases/game.kruise.io_gameservers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,10 @@ spec:
type: string
name:
type: string
result:
description: Result indicate the probe message returned by the
script
type: string
status:
type: string
required:
Expand Down
5 changes: 5 additions & 0 deletions config/crd/bases/game.kruise.io_gameserversets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,11 @@ spec:
type: boolean
opsState:
type: string
result:
description: Result indicate the probe message returned
by the script. When Result is defined, it would exec
action only when the according Result is actually returns.
type: string
state:
type: boolean
updatePriority:
Expand Down
19 changes: 15 additions & 4 deletions pkg/controllers/gameserver/gameserver_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"reflect"
"sigs.k8s.io/controller-runtime/pkg/client"
"strconv"
"strings"
"time"
)

Expand Down Expand Up @@ -316,33 +317,43 @@ func syncServiceQualities(serviceQualities []gameKruiseV1alpha1.ServiceQuality,
for _, sqc := range sqConditions {
sqConditionsMap[sqc.Name] = sqc
}
timeNow := metav1.Now()
for _, sq := range serviceQualities {
var newSqCondition gameKruiseV1alpha1.ServiceQualityCondition
newSqCondition.Name = sq.Name
index, podCondition := util.GetPodConditionFromList(podConditions, corev1.PodConditionType(util.AddPrefixGameKruise(sq.Name)))
if index != -1 {
podConditionMessage := strings.ReplaceAll(podCondition.Message, "|", "")
podConditionMessage = strings.ReplaceAll(podConditionMessage, "\n", "")
newSqCondition.Status = string(podCondition.Status)
newSqCondition.Result = podConditionMessage
newSqCondition.LastProbeTime = podCondition.LastProbeTime
var lastActionTransitionTime metav1.Time
sqCondition, exist := sqConditionsMap[sq.Name]
if !exist || (sqCondition.Status != string(podCondition.Status) && (sqCondition.LastActionTransitionTime.IsZero() || !sq.Permanent)) {
if !exist || ((sqCondition.Status != string(podCondition.Status) || (sqCondition.Result != podConditionMessage)) && (sqCondition.LastActionTransitionTime.IsZero() || !sq.Permanent)) {
// exec action
for _, action := range sq.ServiceQualityAction {
state, err := strconv.ParseBool(string(podCondition.Status))
if err == nil && state == action.State {
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
lastActionTransitionTime = metav1.Now()
lastActionTransitionTime = timeNow
}
}
} else {
lastActionTransitionTime = sqCondition.LastActionTransitionTime
}
newSqCondition.LastActionTransitionTime = lastActionTransitionTime
}
newSqCondition.LastTransitionTime = metav1.Now()

// Set LastTransitionTime, which depends on which value, the LastActionTransitionTime or LastProbeTime, is closer to the current time.
if timeNow.Sub(newSqCondition.LastActionTransitionTime.Time) < timeNow.Sub(newSqCondition.LastProbeTime.Time) {
newSqCondition.LastTransitionTime = newSqCondition.LastActionTransitionTime
} else {
newSqCondition.LastTransitionTime = newSqCondition.LastProbeTime
}
newGsConditions = append(newGsConditions, newSqCondition)
}
return spec, newGsConditions
Expand Down
133 changes: 126 additions & 7 deletions pkg/controllers/gameserver/gameserver_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func TestSyncServiceQualities(t *testing.T) {
spec gameKruiseV1alpha1.GameServerSpec
newSqConditions []gameKruiseV1alpha1.ServiceQualityCondition
}{
//case 0
{
serviceQualities: []gameKruiseV1alpha1.ServiceQuality{
{
Expand Down Expand Up @@ -88,6 +89,7 @@ func TestSyncServiceQualities(t *testing.T) {
},
},
},
// case 1
{
serviceQualities: []gameKruiseV1alpha1.ServiceQuality{
{
Expand Down Expand Up @@ -139,6 +141,7 @@ func TestSyncServiceQualities(t *testing.T) {
},
},
},
// case 2
{
serviceQualities: []gameKruiseV1alpha1.ServiceQuality{
{
Expand Down Expand Up @@ -175,6 +178,7 @@ func TestSyncServiceQualities(t *testing.T) {
},
},
},
// case 3
{
serviceQualities: []gameKruiseV1alpha1.ServiceQuality{
{
Expand Down Expand Up @@ -212,6 +216,7 @@ func TestSyncServiceQualities(t *testing.T) {
},
},
},
// case 4
{
serviceQualities: []gameKruiseV1alpha1.ServiceQuality{
{
Expand Down Expand Up @@ -265,37 +270,151 @@ func TestSyncServiceQualities(t *testing.T) {
},
},
},
// case 5
{
serviceQualities: []gameKruiseV1alpha1.ServiceQuality{
{
Name: "multi-return",
Permanent: false,
ServiceQualityAction: []gameKruiseV1alpha1.ServiceQualityAction{
{
State: true,
Result: "A",
GameServerSpec: gameKruiseV1alpha1.GameServerSpec{
OpsState: "A",
},
},
{
State: true,
Result: "B",
GameServerSpec: gameKruiseV1alpha1.GameServerSpec{
OpsState: "B",
},
},
{
State: true,
Result: "C",
GameServerSpec: gameKruiseV1alpha1.GameServerSpec{
OpsState: "C",
},
},
},
},
},
podConditions: []corev1.PodCondition{
{
Type: "game.kruise.io/multi-return",
Status: corev1.ConditionTrue,
Message: "B",
LastProbeTime: fakeProbeTime,
},
},
sqConditions: nil,
spec: gameKruiseV1alpha1.GameServerSpec{
OpsState: "B",
},
newSqConditions: []gameKruiseV1alpha1.ServiceQualityCondition{
{
Name: "multi-return",
Result: "B",
Status: string(corev1.ConditionTrue),
LastProbeTime: fakeProbeTime,
LastActionTransitionTime: fakeActionTime,
},
},
},
// case 6
{
serviceQualities: []gameKruiseV1alpha1.ServiceQuality{
{
Name: "multi-return",
Permanent: false,
ServiceQualityAction: []gameKruiseV1alpha1.ServiceQualityAction{
{
State: true,
Result: "A",
GameServerSpec: gameKruiseV1alpha1.GameServerSpec{
OpsState: "A",
},
},
{
State: true,
Result: "B",
GameServerSpec: gameKruiseV1alpha1.GameServerSpec{
OpsState: "B",
},
},
{
State: true,
Result: "C",
GameServerSpec: gameKruiseV1alpha1.GameServerSpec{
OpsState: "C",
},
},
},
},
},
podConditions: []corev1.PodCondition{
{
Type: "game.kruise.io/multi-return",
Status: corev1.ConditionTrue,
Message: "A",
LastProbeTime: fakeProbeTime,
},
},
sqConditions: []gameKruiseV1alpha1.ServiceQualityCondition{
{
Name: "multi-return",
Result: "B",
Status: string(corev1.ConditionTrue),
LastProbeTime: fakeProbeTime,
LastActionTransitionTime: fakeActionTime,
},
},
spec: gameKruiseV1alpha1.GameServerSpec{
OpsState: "A",
},
newSqConditions: []gameKruiseV1alpha1.ServiceQualityCondition{
{
Name: "multi-return",
Result: "A",
Status: string(corev1.ConditionTrue),
LastProbeTime: fakeProbeTime,
LastActionTransitionTime: fakeActionTime,
},
},
},
}

for _, test := range tests {
for i, test := range tests {
actualSpec, actualNewSqConditions := syncServiceQualities(test.serviceQualities, test.podConditions, test.sqConditions)
expectSpec := test.spec
expectNewSqConditions := test.newSqConditions
if !reflect.DeepEqual(actualSpec, expectSpec) {
t.Errorf("expect spec %v but got %v", expectSpec, actualSpec)
t.Errorf("case %d: expect spec %v but got %v", i, expectSpec, actualSpec)
}
if len(actualNewSqConditions) != len(expectNewSqConditions) {
t.Errorf("expect sq conditions len %v but got %v", len(expectNewSqConditions), len(actualNewSqConditions))
t.Errorf("case %d: expect sq conditions len %v but got %v", i, len(expectNewSqConditions), len(actualNewSqConditions))
}
for _, expectNewSqCondition := range expectNewSqConditions {
exist := false
for _, actualNewSqCondition := range actualNewSqConditions {
if actualNewSqCondition.Name == expectNewSqCondition.Name {
exist = true
if actualNewSqCondition.Status != expectNewSqCondition.Status {
t.Errorf("expect sq condition status %v but got %v", expectNewSqCondition.Status, actualNewSqCondition.Status)
t.Errorf("case %d: expect sq condition status %v but got %v", i, expectNewSqCondition.Status, actualNewSqCondition.Status)
}
if actualNewSqCondition.LastProbeTime != expectNewSqCondition.LastProbeTime {
t.Errorf("expect sq condition LastProbeTime %v but got %v", expectNewSqCondition.LastProbeTime, actualNewSqCondition.LastProbeTime)
t.Errorf("case %d: expect sq condition LastProbeTime %v but got %v", i, expectNewSqCondition.LastProbeTime, actualNewSqCondition.LastProbeTime)
}
if actualNewSqCondition.LastActionTransitionTime.IsZero() != expectNewSqCondition.LastActionTransitionTime.IsZero() {
t.Errorf("expect sq condition LastActionTransitionTime IsZero %v but got %v", expectNewSqCondition.LastActionTransitionTime.IsZero(), actualNewSqCondition.LastActionTransitionTime.IsZero())
t.Errorf("case %d: expect sq condition LastActionTransitionTime IsZero %v but got %v", i, expectNewSqCondition.LastActionTransitionTime.IsZero(), actualNewSqCondition.LastActionTransitionTime.IsZero())
}
break
}
}
if !exist {
t.Errorf("expect sq condition %s exist, but actually not", expectNewSqCondition.Name)
t.Errorf("case %d: expect sq condition %s exist, but actually not", i, expectNewSqCondition.Name)
}
}
}
Expand Down
Loading