232 lines
7.6 KiB
Go
232 lines
7.6 KiB
Go
/*
|
|
Copyright 2022 The Kruise Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package util
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
appspub "github.com/openkruise/kruise-api/apps/pub"
|
|
kruiseV1beta1 "github.com/openkruise/kruise-api/apps/v1beta1"
|
|
gameKruiseV1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
|
apps "k8s.io/api/apps/v1"
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type DeleteSequenceGs []corev1.Pod
|
|
|
|
func (dg DeleteSequenceGs) Len() int {
|
|
return len(dg)
|
|
}
|
|
|
|
func (dg DeleteSequenceGs) Swap(i, j int) {
|
|
dg[i], dg[j] = dg[j], dg[i]
|
|
}
|
|
|
|
func (dg DeleteSequenceGs) Less(i, j int) bool {
|
|
iLabels := dg[i].GetLabels()
|
|
jLabels := dg[j].GetLabels()
|
|
iOpsStatePriority := opsStateDeletePrority(iLabels[gameKruiseV1alpha1.GameServerOpsStateKey])
|
|
jOpsStatePriority := opsStateDeletePrority(jLabels[gameKruiseV1alpha1.GameServerOpsStateKey])
|
|
iDeletionPriority := iLabels[gameKruiseV1alpha1.GameServerDeletePriorityKey]
|
|
jDeletionPriority := jLabels[gameKruiseV1alpha1.GameServerDeletePriorityKey]
|
|
|
|
// OpsState
|
|
if iOpsStatePriority != jOpsStatePriority {
|
|
return iOpsStatePriority > jOpsStatePriority
|
|
}
|
|
// Deletion Priority
|
|
if iDeletionPriority != jDeletionPriority {
|
|
iDeletionPriorityInt, _ := strconv.Atoi(iDeletionPriority)
|
|
jDeletionPriorityInt, _ := strconv.Atoi(jDeletionPriority)
|
|
return iDeletionPriorityInt > jDeletionPriorityInt
|
|
}
|
|
// Index Number
|
|
return GetIndexFromGsName(dg[i].GetName()) > GetIndexFromGsName(dg[j].GetName())
|
|
}
|
|
|
|
func opsStateDeletePrority(opsState string) int {
|
|
switch opsState {
|
|
case string(gameKruiseV1alpha1.Kill):
|
|
return 100
|
|
case string(gameKruiseV1alpha1.WaitToDelete):
|
|
return 1
|
|
case string(gameKruiseV1alpha1.None):
|
|
return 0
|
|
case string(gameKruiseV1alpha1.Allocated):
|
|
return -1
|
|
case string(gameKruiseV1alpha1.Maintaining):
|
|
return -2
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func GetIndexFromGsName(gsName string) int {
|
|
temp := strings.Split(gsName, "-")
|
|
index, _ := strconv.Atoi(temp[len(temp)-1])
|
|
return index
|
|
}
|
|
|
|
func GetIndexListFromPodList(podList []corev1.Pod) []int {
|
|
var indexList []int
|
|
for i := 0; i < len(podList); i++ {
|
|
indexList = append(indexList, GetIndexFromGsName(podList[i].GetName()))
|
|
}
|
|
return indexList
|
|
}
|
|
|
|
func GetIndexListFromGsList(gsList []gameKruiseV1alpha1.GameServer) []int {
|
|
var indexList []int
|
|
for i := 0; i < len(gsList); i++ {
|
|
indexList = append(indexList, GetIndexFromGsName(gsList[i].GetName()))
|
|
}
|
|
return indexList
|
|
}
|
|
|
|
func GetNewAstsFromGss(gss *gameKruiseV1alpha1.GameServerSet, asts *kruiseV1beta1.StatefulSet) *kruiseV1beta1.StatefulSet {
|
|
// default: set ParallelPodManagement
|
|
asts.Spec.PodManagementPolicy = apps.ParallelPodManagement
|
|
|
|
// set pod labels
|
|
podLabels := gss.Spec.GameServerTemplate.GetLabels()
|
|
if podLabels == nil {
|
|
podLabels = make(map[string]string)
|
|
}
|
|
podLabels[gameKruiseV1alpha1.GameServerOwnerGssKey] = gss.GetName()
|
|
asts.Spec.Template.SetLabels(podLabels)
|
|
|
|
// set pod annotations
|
|
podAnnotations := gss.Spec.GameServerTemplate.GetAnnotations()
|
|
if gss.Spec.Network != nil {
|
|
if podAnnotations == nil {
|
|
podAnnotations = make(map[string]string)
|
|
}
|
|
networkConfig, _ := json.Marshal(gss.Spec.Network.NetworkConf)
|
|
podAnnotations[gameKruiseV1alpha1.GameServerNetworkConf] = string(networkConfig)
|
|
podAnnotations[gameKruiseV1alpha1.GameServerNetworkType] = gss.Spec.Network.NetworkType
|
|
}
|
|
asts.Spec.Template.SetAnnotations(podAnnotations)
|
|
|
|
// set template spec
|
|
asts.Spec.Template.Spec = gss.Spec.GameServerTemplate.Spec
|
|
// default: add InPlaceUpdateReady condition
|
|
readinessGates := gss.Spec.GameServerTemplate.Spec.ReadinessGates
|
|
readinessGates = append(readinessGates, corev1.PodReadinessGate{ConditionType: appspub.InPlaceUpdateReady})
|
|
asts.Spec.Template.Spec.ReadinessGates = readinessGates
|
|
|
|
// AllowNotReadyContainers
|
|
if gss.Spec.Network != nil && IsAllowNotReadyContainers(gss.Spec.Network.NetworkConf) {
|
|
// set lifecycle
|
|
asts.Spec.Lifecycle = &appspub.Lifecycle{
|
|
InPlaceUpdate: &appspub.LifecycleHook{
|
|
LabelsHandler: map[string]string{gameKruiseV1alpha1.InplaceUpdateNotReadyBlocker: "true"},
|
|
},
|
|
}
|
|
}
|
|
|
|
// set VolumeClaimTemplates
|
|
asts.Spec.VolumeClaimTemplates = gss.Spec.GameServerTemplate.VolumeClaimTemplates
|
|
|
|
// set ScaleStrategy
|
|
asts.Spec.ScaleStrategy = &kruiseV1beta1.StatefulSetScaleStrategy{
|
|
MaxUnavailable: gss.Spec.ScaleStrategy.MaxUnavailable,
|
|
}
|
|
|
|
// set UpdateStrategy
|
|
asts.Spec.UpdateStrategy.Type = gss.Spec.UpdateStrategy.Type
|
|
var rollingUpdateStatefulSetStrategy *kruiseV1beta1.RollingUpdateStatefulSetStrategy
|
|
if gss.Spec.UpdateStrategy.RollingUpdate != nil {
|
|
asts.Spec.UpdateStrategy.Type = apps.RollingUpdateStatefulSetStrategyType
|
|
rollingUpdateStatefulSetStrategy = &kruiseV1beta1.RollingUpdateStatefulSetStrategy{
|
|
Partition: gss.Spec.UpdateStrategy.RollingUpdate.Partition,
|
|
MaxUnavailable: gss.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable,
|
|
PodUpdatePolicy: gss.Spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy,
|
|
Paused: gss.Spec.UpdateStrategy.RollingUpdate.Paused,
|
|
InPlaceUpdateStrategy: gss.Spec.UpdateStrategy.RollingUpdate.InPlaceUpdateStrategy,
|
|
MinReadySeconds: gss.Spec.UpdateStrategy.RollingUpdate.MinReadySeconds,
|
|
UnorderedUpdate: &kruiseV1beta1.UnorderedUpdateStrategy{
|
|
PriorityStrategy: &appspub.UpdatePriorityStrategy{
|
|
OrderPriority: []appspub.UpdatePriorityOrderTerm{
|
|
{
|
|
OrderedKey: gameKruiseV1alpha1.GameServerUpdatePriorityKey,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
asts.Spec.UpdateStrategy.RollingUpdate = rollingUpdateStatefulSetStrategy
|
|
|
|
return asts
|
|
}
|
|
|
|
type astsToUpdate struct {
|
|
UpdateStrategy gameKruiseV1alpha1.UpdateStrategy
|
|
Template gameKruiseV1alpha1.GameServerTemplate
|
|
NetworkConfigs []gameKruiseV1alpha1.NetworkConfParams
|
|
}
|
|
|
|
func GetAstsHash(gss *gameKruiseV1alpha1.GameServerSet) string {
|
|
var networkConfigs []gameKruiseV1alpha1.NetworkConfParams
|
|
if gss.Spec.Network != nil {
|
|
networkConfigs = gss.Spec.Network.NetworkConf
|
|
}
|
|
return GetHash(astsToUpdate{
|
|
UpdateStrategy: gss.Spec.UpdateStrategy,
|
|
Template: gss.Spec.GameServerTemplate,
|
|
NetworkConfigs: networkConfigs,
|
|
})
|
|
}
|
|
|
|
func GetGsTemplateMetadataHash(gss *gameKruiseV1alpha1.GameServerSet) string {
|
|
return GetHash(metav1.ObjectMeta{
|
|
Labels: gss.Spec.GameServerTemplate.GetLabels(),
|
|
Annotations: gss.Spec.GameServerTemplate.GetAnnotations(),
|
|
})
|
|
}
|
|
|
|
func AddPrefixGameKruise(s string) string {
|
|
return "game.kruise.io/" + s
|
|
}
|
|
|
|
func RemovePrefixGameKruise(s string) string {
|
|
return strings.TrimPrefix(s, "game.kruise.io/")
|
|
}
|
|
|
|
func GetGameServerSetOfPod(pod *corev1.Pod, c client.Client, ctx context.Context) (*gameKruiseV1alpha1.GameServerSet, error) {
|
|
gssName := pod.GetLabels()[gameKruiseV1alpha1.GameServerOwnerGssKey]
|
|
gss := &gameKruiseV1alpha1.GameServerSet{}
|
|
err := c.Get(ctx, types.NamespacedName{
|
|
Namespace: pod.GetNamespace(),
|
|
Name: gssName,
|
|
}, gss)
|
|
return gss, err
|
|
}
|
|
|
|
func IsAllowNotReadyContainers(networkConfParams []gameKruiseV1alpha1.NetworkConfParams) bool {
|
|
for _, networkConfParam := range networkConfParams {
|
|
if networkConfParam.Name == gameKruiseV1alpha1.AllowNotReadyContainersNetworkConfName {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|