diff --git a/.github/workflows/e2e-1.24.yaml b/.github/workflows/e2e-1.24.yaml index bb425c1..4deb6de 100644 --- a/.github/workflows/e2e-1.24.yaml +++ b/.github/workflows/e2e-1.24.yaml @@ -47,7 +47,7 @@ jobs: make helm helm repo add openkruise https://openkruise.github.io/charts/ helm repo update - helm install kruise openkruise/kruise + helm install kruise openkruise/kruise --version 1.3.0 --set featureGates="PodProbeMarkerGate=true" for ((i=1;i<10;i++)); do set +e diff --git a/apis/v1alpha1/gameserver_types.go b/apis/v1alpha1/gameserver_types.go index 108ed31..406c0c0 100644 --- a/apis/v1alpha1/gameserver_types.go +++ b/apis/v1alpha1/gameserver_types.go @@ -58,9 +58,13 @@ const ( ) type ServiceQuality struct { - corev1.Probe `json:",inline"` - Name string `json:"name"` - ContainerName string `json:"containerName,omitempty"` + corev1.Probe `json:",inline"` + Name string `json:"name"` + ContainerName string `json:"containerName,omitempty"` + // Whether to make GameServerSpec not change after the ServiceQualityAction is executed. + // When Permanent is true, regardless of the detection results, ServiceQualityAction will only be executed once. + // When Permanent is false, ServiceQualityAction can be executed again even though ServiceQualityAction has been executed. + Permanent bool `json:"permanent"` ServiceQualityAction []ServiceQualityAction `json:"serviceQualityAction,omitempty"` } @@ -73,7 +77,6 @@ type ServiceQualityCondition struct { } type ServiceQualityAction struct { - Permanent bool `json:"permanent,omitempty"` // default: true State bool `json:"state"` GameServerSpec `json:",inline"` } diff --git a/apis/v1alpha1/gameserverset_types.go b/apis/v1alpha1/gameserverset_types.go index f32a30e..d66625f 100644 --- a/apis/v1alpha1/gameserverset_types.go +++ b/apis/v1alpha1/gameserverset_types.go @@ -29,10 +29,10 @@ import ( // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. const ( - GameServerOwnerGssKey = "game.kruise.io/owner-gss" - GameServerSetReserveIdsKey = "game.kruise.io/reserve-ids" - GameServerSetNotExistIdsKey = "game.kruise.io/not-exist-ids" - AstsHashKey = "game.kruise.io/asts-hash" + GameServerOwnerGssKey = "game.kruise.io/owner-gss" + GameServerSetReserveIdsKey = "game.kruise.io/reserve-ids" + AstsHashKey = "game.kruise.io/asts-hash" + PpmHashKey = "game.kruise.io/ppm-hash" ) // GameServerSetSpec defines the desired state of GameServerSet diff --git a/config/crd/bases/game.kruise.io_gameserversets.yaml b/config/crd/bases/game.kruise.io_gameserversets.yaml index ea9002c..77a5a30 100644 --- a/config/crd/bases/game.kruise.io_gameserversets.yaml +++ b/config/crd/bases/game.kruise.io_gameserversets.yaml @@ -472,6 +472,14 @@ spec: to 10 seconds. Minimum value is 1. format: int32 type: integer + permanent: + description: Whether to make GameServerSpec not change after + the ServiceQualityAction is executed. When Permanent is true, + regardless of the detection results, ServiceQualityAction + will only be executed once. When Permanent is false, ServiceQualityAction + can be executed again even though ServiceQualityAction has + been executed. + type: boolean serviceQualityAction: items: properties: @@ -484,8 +492,6 @@ spec: type: boolean opsState: type: string - permanent: - type: boolean state: type: boolean updatePriority: @@ -545,6 +551,7 @@ spec: type: integer required: - name + - permanent type: object type: array updateStrategy: diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 410e762..8f584d2 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -37,6 +37,18 @@ rules: - patch - update - watch +- apiGroups: + - apps.kruise.io + resources: + - podprobemarkers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - apps.kruise.io resources: diff --git a/go.mod b/go.mod index 65151d2..6343c10 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.18.1 - github.com/openkruise/kruise-api v1.2.0 + github.com/openkruise/kruise-api v1.3.0 k8s.io/api v0.24.0 k8s.io/apimachinery v0.24.0 k8s.io/client-go v0.24.0 diff --git a/go.sum b/go.sum index 351d460..21db659 100644 --- a/go.sum +++ b/go.sum @@ -41,19 +41,14 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM= github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= -github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q= github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= @@ -123,7 +118,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= @@ -139,7 +133,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= -github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -153,7 +146,6 @@ github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWp github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -170,16 +162,12 @@ github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/zapr v1.2.0 h1:n4JnPI1T3Qq1SFEi/F8rwLrZERp2bso19PJZDB9dayk= github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= @@ -263,12 +251,10 @@ github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -332,14 +318,12 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -380,7 +364,6 @@ github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= @@ -389,14 +372,13 @@ github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042 github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ= github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/openkruise/kruise-api v1.2.0 h1:MhoQtYT2tRdjrpb51xhn3lhEDWSlRGiMYQQ0Sh3zCkk= -github.com/openkruise/kruise-api v1.2.0/go.mod h1:BKMffjLFufZkj/yVpF5TjXG9gMU3Y9A3FxrVOJ5LJUI= +github.com/openkruise/kruise-api v1.3.0 h1:yfEy64uXgSuX/5RwePLbwUK/uX8RRM8fHJkccel5ZIQ= +github.com/openkruise/kruise-api v1.3.0/go.mod h1:9ZX+ycdHKNzcA5ezAf35xOa2Mwfa2BYagWr0lKgi5dU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -462,7 +444,6 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -470,7 +451,6 @@ github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5q github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -538,7 +518,6 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -672,7 +651,6 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -702,7 +680,6 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -743,7 +720,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -760,7 +736,6 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -965,37 +940,28 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.20.15/go.mod h1:X3JDf1BiTRQQ6xNAxTuhgi6yL2dHc6fSr9LGzE+Z3YU= k8s.io/api v0.24.0 h1:J0hann2hfxWr1hinZIDefw7Q96wmCBx6SSB8IY0MdDg= k8s.io/api v0.24.0/go.mod h1:5Jl90IUrJHUJYEMANRURMiVvJ0g7Ax7r3R1bqO8zx8I= k8s.io/apiextensions-apiserver v0.24.0 h1:JfgFqbA8gKJ/uDT++feAqk9jBIwNnL9YGdQvaI9DLtY= k8s.io/apiextensions-apiserver v0.24.0/go.mod h1:iuVe4aEpe6827lvO6yWQVxiPSpPoSKVjkq+MIdg84cM= -k8s.io/apimachinery v0.20.15/go.mod h1:4KFiDSxCoGviCiRk9kTXIROsIf4VSGkVYjVJjJln3pg= k8s.io/apimachinery v0.24.0 h1:ydFCyC/DjCvFCHK5OPMKBlxayQytB8pxy8YQInd5UyQ= k8s.io/apimachinery v0.24.0/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= k8s.io/apiserver v0.24.0/go.mod h1:WFx2yiOMawnogNToVvUYT9nn1jaIkMKj41ZYCVycsBA= -k8s.io/client-go v0.20.15/go.mod h1:q/vywQFfGT3jw+lXQGA9sEJDH0QEX7XUT2PwrQ2qm/I= k8s.io/client-go v0.24.0 h1:lbE4aB1gTHvYFSwm6eD3OF14NhFDKCejlnsGYlSJe5U= k8s.io/client-go v0.24.0/go.mod h1:VFPQET+cAFpYxh6Bq6f4xyMY80G6jKKktU6G0m00VDw= -k8s.io/code-generator v0.20.15/go.mod h1:MW85KuhTjX9nzhFYpRqUOYh4et0xeEBHTEjwBzFYGaM= k8s.io/code-generator v0.24.0 h1:7v52LjqCntfGxV9x8c57gkhDqkMHd0Z2jfRqGr6it6g= k8s.io/code-generator v0.24.0/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= k8s.io/component-base v0.24.0 h1:h5jieHZQoHrY/lHG+HyrSbJeyfuitheBvqvKwKHVC0g= k8s.io/component-base v0.24.0/go.mod h1:Dgazgon0i7KYUsS8krG8muGiMVtUZxG037l1MKyXgrA= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20211129171323-c02415ce4185 h1:TT1WdmqqXareKxZ/oNXEUSwKlLiHzPMyB0t8BaFeBYI= k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc= k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20211110013926-83f114cd0513/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 h1:Gii5eqf+GmIEwGNKQYQClCayuJCe2/4fZUvF7VG99sU= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= @@ -1008,10 +974,8 @@ sigs.k8s.io/controller-runtime v0.12.1/go.mod h1:BKhxlA4l7FPK4AQcsuL4X6vZeWnKDXe sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y= sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y= sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/main.go b/main.go index 0e41026..35da340 100644 --- a/main.go +++ b/main.go @@ -18,6 +18,7 @@ package main import ( "flag" + kruiseV1alpha1 "github.com/openkruise/kruise-api/apps/v1alpha1" kruiseV1beta1 "github.com/openkruise/kruise-api/apps/v1beta1" controller "github.com/openkruise/kruise-game/pkg/controllers" "github.com/openkruise/kruise-game/pkg/webhook" @@ -50,6 +51,7 @@ func init() { utilruntime.Must(gamekruiseiov1alpha1.AddToScheme(scheme)) utilruntime.Must(kruiseV1beta1.AddToScheme(scheme)) + utilruntime.Must(kruiseV1alpha1.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } diff --git a/pkg/controllers/gameserver/gameserver_controller.go b/pkg/controllers/gameserver/gameserver_controller.go index 62ad5fc..50c627c 100644 --- a/pkg/controllers/gameserver/gameserver_controller.go +++ b/pkg/controllers/gameserver/gameserver_controller.go @@ -39,6 +39,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" + "time" ) var ( @@ -185,12 +186,12 @@ func (r *GameServerReconciler) Reconcile(ctx context.Context, req ctrl.Request) return reconcile.Result{}, err } - podUpdated, err := gsm.SyncToPod() + podUpdated, err := gsm.SyncGsToPod() if err != nil || podUpdated { - return reconcile.Result{Requeue: podUpdated}, err + return reconcile.Result{Requeue: podUpdated, RequeueAfter: 3 * time.Second}, err } - err = gsm.SyncToGs(gss.Spec.ServiceQualities) + err = gsm.SyncPodToGs(gss) if err != nil { return reconcile.Result{}, err } diff --git a/pkg/controllers/gameserver/gameserver_manager.go b/pkg/controllers/gameserver/gameserver_manager.go index 8945141..e10a4ac 100644 --- a/pkg/controllers/gameserver/gameserver_manager.go +++ b/pkg/controllers/gameserver/gameserver_manager.go @@ -33,8 +33,12 @@ import ( ) type Control interface { - SyncToPod() (bool, error) - SyncToGs(qualities []gameKruiseV1alpha1.ServiceQuality) error + // SyncGsToPod compares the pod with GameServer, and decide whether to update the pod based on the results. + // When the fields of the pod is different from that of GameServer, + // pod will be updated and true is returned; otherwise, the pod won't be updated and false is returned. + SyncGsToPod() (bool, error) + // SyncPodToGs compares the GameServer with pod, and update the GameServer. + SyncPodToGs(*gameKruiseV1alpha1.GameServerSet) error } type GameServerManager struct { @@ -43,8 +47,7 @@ type GameServerManager struct { client client.Client } -func (manager GameServerManager) SyncToPod() (bool, error) { - // compare GameServer Spec With Pod +func (manager GameServerManager) SyncGsToPod() (bool, error) { pod := manager.pod gs := manager.gameServer podLabels := pod.GetLabels() @@ -83,15 +86,14 @@ func (manager GameServerManager) SyncToPod() (bool, error) { break } // GameServer Ready / NotReady - for _, con := range pod.Status.Conditions { - if con.Type == corev1.PodReady { - if con.Status == corev1.ConditionTrue { - gsState = gameKruiseV1alpha1.Ready - } else { - gsState = gameKruiseV1alpha1.NotReady - } - break + _, condition := util.GetPodConditionFromList(pod.Status.Conditions, corev1.PodReady) + if condition != nil { + if condition.Status == corev1.ConditionTrue { + gsState = gameKruiseV1alpha1.Ready + } else { + gsState = gameKruiseV1alpha1.NotReady } + break } case corev1.PodFailed: gsState = gameKruiseV1alpha1.Crash @@ -121,78 +123,32 @@ func (manager GameServerManager) SyncToPod() (bool, error) { return updated, nil } -func (manager GameServerManager) SyncToGs(qualities []gameKruiseV1alpha1.ServiceQuality) error { +func (manager GameServerManager) SyncPodToGs(gss *gameKruiseV1alpha1.GameServerSet) error { gs := manager.gameServer pod := manager.pod + + // sync DeletePriority/UpdatePriority/State podLabels := pod.GetLabels() podDeletePriority := intstr.FromString(podLabels[gameKruiseV1alpha1.GameServerDeletePriorityKey]) podUpdatePriority := intstr.FromString(podLabels[gameKruiseV1alpha1.GameServerUpdatePriorityKey]) podGsState := gameKruiseV1alpha1.GameServerState(podLabels[gameKruiseV1alpha1.GameServerStateKey]) - gsConditions := gs.Status.ServiceQualitiesCondition - podConditions := pod.Status.Conditions - var sqNames []string - for _, sq := range qualities { - sqNames = append(sqNames, sq.Name) - } - var toExec map[string]string - var newGsConditions []gameKruiseV1alpha1.ServiceQualityCondition - for _, pc := range podConditions { - if util.IsStringInList(string(pc.Type), sqNames) { - toExecAction := true - lastActionTransitionTime := metav1.Now() - for _, gsc := range gsConditions { - if gsc.Name == string(pc.Type) && gsc.Status == string(pc.Status) { - toExecAction = false - lastActionTransitionTime = gsc.LastActionTransitionTime - break - } - } - serviceQualityCondition := gameKruiseV1alpha1.ServiceQualityCondition{ - Name: string(pc.Type), - Status: string(pc.Status), - LastProbeTime: pc.LastProbeTime, - LastTransitionTime: pc.LastTransitionTime, - LastActionTransitionTime: lastActionTransitionTime, - } - newGsConditions = append(newGsConditions, serviceQualityCondition) - if toExecAction { - if toExec == nil { - toExec = make(map[string]string) - } - toExec[string(pc.Type)] = string(pc.Status) - } - } - } - if toExec != nil { - var spec gameKruiseV1alpha1.GameServerSpec - for _, sq := range qualities { - for name, state := range toExec { - if sq.Name == name { - for _, action := range sq.ServiceQualityAction { - if state == strconv.FormatBool(action.State) { - spec.DeletionPriority = action.DeletionPriority - spec.UpdatePriority = action.UpdatePriority - spec.OpsState = action.OpsState - spec.NetworkDisabled = action.NetworkDisabled - } - } - } - } - } + // sync Service Qualities + spec, newGsConditions := syncServiceQualities(gss.Spec.ServiceQualities, pod.Status.Conditions, gs.Status.ServiceQualitiesCondition) - patchSpec := map[string]interface{}{"spec": spec} - jsonPatchSpec, err := json.Marshal(patchSpec) - if err != nil { - return err - } - err = manager.client.Patch(context.TODO(), gs, client.RawPatch(types.MergePatchType, jsonPatchSpec)) - if err != nil && !errors.IsNotFound(err) { - klog.Errorf("failed to patch GameServer spec %s in %s,because of %s.", gs.GetName(), gs.GetNamespace(), err.Error()) - return err - } + // patch gs spec + patchSpec := map[string]interface{}{"spec": spec} + jsonPatchSpec, err := json.Marshal(patchSpec) + if err != nil { + return err + } + err = manager.client.Patch(context.TODO(), gs, client.RawPatch(types.MergePatchType, jsonPatchSpec)) + if err != nil && !errors.IsNotFound(err) { + klog.Errorf("failed to patch GameServer spec %s in %s,because of %s.", gs.GetName(), gs.GetNamespace(), err.Error()) + return err } + // patch gs status status := gameKruiseV1alpha1.GameServerStatus{ PodStatus: pod.Status, CurrentState: podGsState, @@ -216,6 +172,45 @@ func (manager GameServerManager) SyncToGs(qualities []gameKruiseV1alpha1.Service return nil } +func syncServiceQualities(serviceQualities []gameKruiseV1alpha1.ServiceQuality, podConditions []corev1.PodCondition, sqConditions []gameKruiseV1alpha1.ServiceQualityCondition) (gameKruiseV1alpha1.GameServerSpec, []gameKruiseV1alpha1.ServiceQualityCondition) { + var spec gameKruiseV1alpha1.GameServerSpec + var newGsConditions []gameKruiseV1alpha1.ServiceQualityCondition + sqConditionsMap := make(map[string]gameKruiseV1alpha1.ServiceQualityCondition) + for _, sqc := range sqConditions { + sqConditionsMap[sqc.Name] = sqc + } + 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 { + newSqCondition.Status = string(podCondition.Status) + 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)) { + // exec action + for _, action := range sq.ServiceQualityAction { + state, err := strconv.ParseBool(string(podCondition.Status)) + if err == nil && state == action.State { + spec.DeletionPriority = action.DeletionPriority + spec.UpdatePriority = action.UpdatePriority + spec.OpsState = action.OpsState + spec.NetworkDisabled = action.NetworkDisabled + lastActionTransitionTime = metav1.Now() + } + } + } else { + lastActionTransitionTime = sqCondition.LastActionTransitionTime + } + newSqCondition.LastActionTransitionTime = lastActionTransitionTime + } + newSqCondition.LastTransitionTime = metav1.Now() + newGsConditions = append(newGsConditions, newSqCondition) + } + return spec, newGsConditions +} + func NewGameServerManager(gs *gameKruiseV1alpha1.GameServer, pod *corev1.Pod, c client.Client) Control { return &GameServerManager{ gameServer: gs, diff --git a/pkg/controllers/gameserver/gameserver_manager_test.go b/pkg/controllers/gameserver/gameserver_manager_test.go new file mode 100644 index 0000000..7424039 --- /dev/null +++ b/pkg/controllers/gameserver/gameserver_manager_test.go @@ -0,0 +1,281 @@ +package gameserver + +import ( + gameKruiseV1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "reflect" + "testing" +) + +func TestSyncServiceQualities(t *testing.T) { + up := intstr.FromInt(20) + dp := intstr.FromInt(10) + fakeProbeTime := metav1.Now() + fakeActionTime := metav1.Now() + tests := []struct { + serviceQualities []gameKruiseV1alpha1.ServiceQuality + podConditions []corev1.PodCondition + sqConditions []gameKruiseV1alpha1.ServiceQualityCondition + spec gameKruiseV1alpha1.GameServerSpec + newSqConditions []gameKruiseV1alpha1.ServiceQualityCondition + }{ + { + serviceQualities: []gameKruiseV1alpha1.ServiceQuality{ + { + Name: "healthy", + Permanent: true, + ServiceQualityAction: []gameKruiseV1alpha1.ServiceQualityAction{ + { + State: true, + GameServerSpec: gameKruiseV1alpha1.GameServerSpec{ + UpdatePriority: &up, + }, + }, + { + State: false, + GameServerSpec: gameKruiseV1alpha1.GameServerSpec{ + DeletionPriority: &dp, + }, + }, + }, + }, + }, + podConditions: []corev1.PodCondition{ + { + Type: "game.kruise.io/healthy", + Status: corev1.ConditionTrue, + LastProbeTime: fakeProbeTime, + }, + { + Type: "otherA", + Status: corev1.ConditionFalse, + LastProbeTime: fakeProbeTime, + }, + }, + sqConditions: nil, + spec: gameKruiseV1alpha1.GameServerSpec{ + UpdatePriority: &up, + }, + newSqConditions: []gameKruiseV1alpha1.ServiceQualityCondition{ + { + Name: "healthy", + Status: string(corev1.ConditionTrue), + LastProbeTime: fakeProbeTime, + LastActionTransitionTime: fakeActionTime, + }, + }, + }, + { + serviceQualities: []gameKruiseV1alpha1.ServiceQuality{ + { + Name: "healthy", + Permanent: true, + ServiceQualityAction: []gameKruiseV1alpha1.ServiceQualityAction{ + { + State: true, + GameServerSpec: gameKruiseV1alpha1.GameServerSpec{ + UpdatePriority: &up, + }, + }, + { + State: false, + GameServerSpec: gameKruiseV1alpha1.GameServerSpec{ + DeletionPriority: &dp, + }, + }, + }, + }, + }, + podConditions: []corev1.PodCondition{ + { + Type: "game.kruise.io/healthy", + Status: corev1.ConditionTrue, + LastProbeTime: fakeProbeTime, + }, + { + Type: "otherA", + Status: corev1.ConditionFalse, + LastProbeTime: fakeProbeTime, + }, + }, + sqConditions: []gameKruiseV1alpha1.ServiceQualityCondition{ + { + Name: "healthy", + Status: string(corev1.ConditionFalse), + LastProbeTime: fakeProbeTime, + LastActionTransitionTime: fakeActionTime, + }, + }, + spec: gameKruiseV1alpha1.GameServerSpec{}, + newSqConditions: []gameKruiseV1alpha1.ServiceQualityCondition{ + { + Name: "healthy", + Status: string(corev1.ConditionTrue), + LastProbeTime: fakeProbeTime, + LastActionTransitionTime: fakeActionTime, + }, + }, + }, + { + serviceQualities: []gameKruiseV1alpha1.ServiceQuality{ + { + Name: "healthy", + Permanent: true, + ServiceQualityAction: []gameKruiseV1alpha1.ServiceQualityAction{ + { + State: true, + GameServerSpec: gameKruiseV1alpha1.GameServerSpec{ + UpdatePriority: &up, + }, + }, + { + State: false, + GameServerSpec: gameKruiseV1alpha1.GameServerSpec{ + DeletionPriority: &dp, + }, + }, + }, + }, + }, + podConditions: []corev1.PodCondition{ + { + Type: "otherA", + Status: corev1.ConditionFalse, + LastProbeTime: fakeProbeTime, + }, + }, + sqConditions: nil, + spec: gameKruiseV1alpha1.GameServerSpec{}, + newSqConditions: []gameKruiseV1alpha1.ServiceQualityCondition{ + { + Name: "healthy", + }, + }, + }, + { + serviceQualities: []gameKruiseV1alpha1.ServiceQuality{ + { + Name: "healthy", + Permanent: true, + ServiceQualityAction: []gameKruiseV1alpha1.ServiceQualityAction{ + { + State: true, + GameServerSpec: gameKruiseV1alpha1.GameServerSpec{ + UpdatePriority: &up, + }, + }, + }, + }, + }, + podConditions: []corev1.PodCondition{ + { + Type: "game.kruise.io/healthy", + Status: corev1.ConditionFalse, + LastProbeTime: fakeProbeTime, + }, + { + Type: "otherA", + Status: corev1.ConditionFalse, + LastProbeTime: fakeProbeTime, + }, + }, + sqConditions: nil, + spec: gameKruiseV1alpha1.GameServerSpec{}, + newSqConditions: []gameKruiseV1alpha1.ServiceQualityCondition{ + { + Name: "healthy", + Status: string(corev1.ConditionFalse), + LastProbeTime: fakeProbeTime, + }, + }, + }, + { + serviceQualities: []gameKruiseV1alpha1.ServiceQuality{ + { + Name: "healthy", + Permanent: false, + ServiceQualityAction: []gameKruiseV1alpha1.ServiceQualityAction{ + { + State: true, + GameServerSpec: gameKruiseV1alpha1.GameServerSpec{ + UpdatePriority: &up, + }, + }, + { + State: false, + GameServerSpec: gameKruiseV1alpha1.GameServerSpec{ + DeletionPriority: &dp, + }, + }, + }, + }, + }, + podConditions: []corev1.PodCondition{ + { + Type: "game.kruise.io/healthy", + Status: corev1.ConditionTrue, + LastProbeTime: fakeProbeTime, + }, + { + Type: "otherA", + Status: corev1.ConditionFalse, + LastProbeTime: fakeProbeTime, + }, + }, + sqConditions: []gameKruiseV1alpha1.ServiceQualityCondition{ + { + Name: "healthy", + Status: string(corev1.ConditionFalse), + LastProbeTime: fakeProbeTime, + LastActionTransitionTime: fakeActionTime, + }, + }, + spec: gameKruiseV1alpha1.GameServerSpec{ + UpdatePriority: &up, + }, + newSqConditions: []gameKruiseV1alpha1.ServiceQualityCondition{ + { + Name: "healthy", + Status: string(corev1.ConditionTrue), + LastProbeTime: fakeProbeTime, + LastActionTransitionTime: fakeActionTime, + }, + }, + }, + } + + for _, 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) + } + if len(actualNewSqConditions) != len(expectNewSqConditions) { + t.Errorf("expect sq conditions len %v but got %v", 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) + } + if actualNewSqCondition.LastProbeTime != expectNewSqCondition.LastProbeTime { + t.Errorf("expect sq condition LastProbeTime %v but got %v", 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()) + } + break + } + } + if !exist { + t.Errorf("expect sq condition %s exist, but actually not", expectNewSqCondition.Name) + } + } + } +} diff --git a/pkg/controllers/gameserverset/gameserverset_controller.go b/pkg/controllers/gameserverset/gameserverset_controller.go index c3b017f..cce1697 100644 --- a/pkg/controllers/gameserverset/gameserverset_controller.go +++ b/pkg/controllers/gameserverset/gameserverset_controller.go @@ -225,7 +225,6 @@ func (r *GameServerSetReconciler) Reconcile(ctx context.Context, req ctrl.Reques return reconcile.Result{}, nil } - // TODO sync PodProbeMarker err = gsm.SyncPodProbeMarker() if err != nil { klog.Errorf("GameServerSet %s failed to synchronize PodProbeMarker in %s,because of %s.", namespacedName.Name, namespacedName.Namespace, err.Error()) @@ -267,10 +266,10 @@ func (r *GameServerSetReconciler) initAsts(gss *gamekruiseiov1alpha1.GameServerS ors = append(ors, or) asts.SetOwnerReferences(ors) - // set label - astsLabels := make(map[string]string) - astsLabels[gamekruiseiov1alpha1.AstsHashKey] = util.GetAstsHash(gss) - asts.SetLabels(astsLabels) + // set annotations + astsAns := make(map[string]string) + astsAns[gamekruiseiov1alpha1.AstsHashKey] = util.GetAstsHash(gss) + asts.SetAnnotations(astsAns) // set label selector asts.Spec.Selector = &metav1.LabelSelector{ diff --git a/pkg/controllers/gameserverset/gameserverset_manager.go b/pkg/controllers/gameserverset/gameserverset_manager.go index 268ffab..45e14c9 100644 --- a/pkg/controllers/gameserverset/gameserverset_manager.go +++ b/pkg/controllers/gameserverset/gameserverset_manager.go @@ -18,10 +18,13 @@ package gameserverset import ( "context" + kruiseV1alpha1 "github.com/openkruise/kruise-api/apps/v1alpha1" kruiseV1beta1 "github.com/openkruise/kruise-api/apps/v1beta1" gameKruiseV1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1" "github.com/openkruise/kruise-game/pkg/util" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/json" "k8s.io/klog/v2" @@ -58,19 +61,15 @@ func NewGameServerSetManager(gss *gameKruiseV1alpha1.GameServerSet, asts *kruise func (manager *GameServerSetManager) IsNeedToScale() bool { gss := manager.gameServerSet asts := manager.asts - gsList := manager.podList - - currentReplicas := len(gsList) - workloadReplicas := int(*asts.Spec.Replicas) - expectedReplicas := int(*gss.Spec.Replicas) // workload is reconciling its replicas, don't interrupt - if currentReplicas != workloadReplicas { + if asts.Status.Replicas != *asts.Spec.Replicas { return false } // no need to scale - return !(expectedReplicas == currentReplicas && util.IsSliceEqual(util.StringToIntSlice(gss.GetAnnotations()[gameKruiseV1alpha1.GameServerSetReserveIdsKey], ","), gss.Spec.ReserveGameServerIds)) + return !(*gss.Spec.Replicas == *asts.Spec.Replicas && + util.IsSliceEqual(util.StringToIntSlice(gss.GetAnnotations()[gameKruiseV1alpha1.GameServerSetReserveIdsKey], ","), gss.Spec.ReserveGameServerIds)) } func (manager *GameServerSetManager) GameServerScale() error { @@ -84,7 +83,7 @@ func (manager *GameServerSetManager) GameServerScale() error { expectedReplicas := int(*gss.Spec.Replicas) as := gss.GetAnnotations() reserveIds := util.StringToIntSlice(as[gameKruiseV1alpha1.GameServerSetReserveIdsKey], ",") - notExistIds := util.StringToIntSlice(as[gameKruiseV1alpha1.GameServerSetNotExistIdsKey], ",") + notExistIds := util.GetSliceInANotInB(asts.Spec.ReserveOrdinals, reserveIds) gssReserveIds := gss.Spec.ReserveGameServerIds klog.Infof("GameServers %s/%s already has %d replicas, expect to have %d replicas.", gss.GetNamespace(), gss.GetName(), currentReplicas, expectedReplicas) @@ -104,7 +103,6 @@ func (manager *GameServerSetManager) GameServerScale() error { gssAnnotations := make(map[string]string) gssAnnotations[gameKruiseV1alpha1.GameServerSetReserveIdsKey] = util.IntSliceToString(gssReserveIds, ",") - gssAnnotations[gameKruiseV1alpha1.GameServerSetNotExistIdsKey] = util.IntSliceToString(newNotExistIds, ",") patchGss := map[string]interface{}{"metadata": map[string]map[string]string{"annotations": gssAnnotations}} patchGssBytes, _ := json.Marshal(patchGss) err = c.Patch(ctx, gss, client.RawPatch(types.MergePatchType, patchGssBytes)) @@ -182,7 +180,7 @@ func computeToScaleGs(gssReserveIds, reserveIds, notExistIds []int, expectedRepl } func (manager *GameServerSetManager) IsNeedToUpdateWorkload() bool { - return manager.asts.GetLabels()[gameKruiseV1alpha1.AstsHashKey] != util.GetAstsHash(manager.gameServerSet) + return manager.asts.GetAnnotations()[gameKruiseV1alpha1.AstsHashKey] != util.GetAstsHash(manager.gameServerSet) } func (manager *GameServerSetManager) UpdateWorkload() error { @@ -191,16 +189,94 @@ func (manager *GameServerSetManager) UpdateWorkload() error { // sync with Advanced StatefulSet asts = util.GetNewAstsFromGss(gss, asts) - astsLabels := asts.GetLabels() - astsLabels[gameKruiseV1alpha1.AstsHashKey] = util.GetAstsHash(manager.gameServerSet) - asts.SetLabels(astsLabels) + astsAns := asts.GetAnnotations() + astsAns[gameKruiseV1alpha1.AstsHashKey] = util.GetAstsHash(manager.gameServerSet) + asts.SetAnnotations(astsAns) return manager.client.Update(context.Background(), asts) } func (manager *GameServerSetManager) SyncPodProbeMarker() error { + gss := manager.gameServerSet + sqs := gss.Spec.ServiceQualities + c := manager.client + ctx := context.Background() + + // get ppm + ppm := &kruiseV1alpha1.PodProbeMarker{} + err := c.Get(ctx, types.NamespacedName{ + Namespace: gss.GetNamespace(), + Name: gss.GetName(), + }, ppm) + if err != nil { + if errors.IsNotFound(err) { + if sqs == nil { + return nil + } + // create ppm + return c.Create(ctx, createPpm(gss)) + } + return err + } + + // delete ppm + if sqs == nil { + return c.Delete(ctx, ppm) + } + + // update ppm + if util.GetHash(gss.Spec.ServiceQualities) != ppm.GetAnnotations()[gameKruiseV1alpha1.PpmHashKey] { + ppm.Spec.Probes = constructProbes(gss) + return c.Update(ctx, ppm) + } return nil } +func constructProbes(gss *gameKruiseV1alpha1.GameServerSet) []kruiseV1alpha1.PodContainerProbe { + var probes []kruiseV1alpha1.PodContainerProbe + for _, sq := range gss.Spec.ServiceQualities { + probe := kruiseV1alpha1.PodContainerProbe{ + Name: sq.Name, + ContainerName: sq.ContainerName, + Probe: kruiseV1alpha1.ContainerProbeSpec{ + Probe: sq.Probe, + }, + PodConditionType: util.AddPrefixGameKruise(sq.Name), + } + probes = append(probes, probe) + } + return probes +} + +func createPpm(gss *gameKruiseV1alpha1.GameServerSet) *kruiseV1alpha1.PodProbeMarker { + // set owner reference + ors := make([]metav1.OwnerReference, 0) + or := metav1.OwnerReference{ + APIVersion: gss.APIVersion, + Kind: gss.Kind, + Name: gss.GetName(), + UID: gss.GetUID(), + Controller: pointer.BoolPtr(true), + BlockOwnerDeletion: pointer.BoolPtr(true), + } + ors = append(ors, or) + return &kruiseV1alpha1.PodProbeMarker{ + ObjectMeta: metav1.ObjectMeta{ + Name: gss.GetName(), + Namespace: gss.GetNamespace(), + Annotations: map[string]string{ + gameKruiseV1alpha1.PpmHashKey: util.GetHash(gss.Spec.ServiceQualities), + }, + OwnerReferences: ors, + }, + Spec: kruiseV1alpha1.PodProbeMarkerSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{gameKruiseV1alpha1.GameServerOwnerGssKey: gss.GetName()}, + }, + Probes: constructProbes(gss), + }, + } +} + func (manager *GameServerSetManager) SyncStatus() error { gss := manager.gameServerSet asts := manager.asts diff --git a/pkg/util/gameserver.go b/pkg/util/gameserver.go index b69c556..3ef6c74 100644 --- a/pkg/util/gameserver.go +++ b/pkg/util/gameserver.go @@ -162,3 +162,11 @@ func GetAstsHash(gss *gameKruiseV1alpha1.GameServerSet) string { Template: gss.Spec.GameServerTemplate, }) } + +func AddPrefixGameKruise(s string) string { + return "game.kruise.io/" + s +} + +func RemovePrefixGameKruise(s string) string { + return strings.TrimPrefix(s, "game.kruise.io/") +} diff --git a/pkg/util/gameserver_test.go b/pkg/util/gameserver_test.go index d6014fa..373db85 100644 --- a/pkg/util/gameserver_test.go +++ b/pkg/util/gameserver_test.go @@ -108,3 +108,47 @@ func TestDeleteSequenceGs(t *testing.T) { } } } + +func TestAddPrefixGameKruise(t *testing.T) { + tests := []struct { + s string + result string + }{ + { + s: "healthy", + result: "game.kruise.io/healthy", + }, + } + + for _, test := range tests { + actual := AddPrefixGameKruise(test.s) + expect := test.result + if expect != actual { + t.Errorf("expect %v but got %v", expect, actual) + } + } +} + +func TestRemovePrefixGameKruise(t *testing.T) { + tests := []struct { + s string + result string + }{ + { + s: "game.kruise.io/healthy", + result: "healthy", + }, + { + s: "game/healthy", + result: "game/healthy", + }, + } + + for _, test := range tests { + actual := RemovePrefixGameKruise(test.s) + expect := test.result + if expect != actual { + t.Errorf("expect %v but got %v", expect, actual) + } + } +} diff --git a/pkg/util/pod.go b/pkg/util/pod.go new file mode 100644 index 0000000..38828a3 --- /dev/null +++ b/pkg/util/pod.go @@ -0,0 +1,33 @@ +/* +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 corev1 "k8s.io/api/core/v1" + +// GetPodConditionFromList extracts the provided condition from the given list of condition and +// returns the index of the condition and the condition. Returns -1 and nil if the condition is not present. +func GetPodConditionFromList(conditions []corev1.PodCondition, conditionType corev1.PodConditionType) (int, *corev1.PodCondition) { + if conditions == nil { + return -1, nil + } + for i := range conditions { + if conditions[i].Type == conditionType { + return i, &conditions[i] + } + } + return -1, nil +} diff --git a/pkg/util/pod_test.go b/pkg/util/pod_test.go new file mode 100644 index 0000000..b1ee0fb --- /dev/null +++ b/pkg/util/pod_test.go @@ -0,0 +1,61 @@ +/* +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 ( + corev1 "k8s.io/api/core/v1" + "reflect" + "testing" +) + +func TestGetPodConditionFromList(t *testing.T) { + tests := []struct { + podConditions []corev1.PodCondition + conditionType corev1.PodConditionType + index int + podCondition *corev1.PodCondition + }{ + { + podConditions: []corev1.PodCondition{ + { + Type: "game.kruise.io/healthy", + Status: corev1.ConditionTrue, + }, + { + Type: corev1.PodReady, + Status: corev1.ConditionFalse, + }, + }, + conditionType: corev1.PodReady, + index: 1, + podCondition: &corev1.PodCondition{ + Type: corev1.PodReady, + Status: corev1.ConditionFalse, + }, + }, + } + + for _, test := range tests { + actualIndex, actualPodCondition := GetPodConditionFromList(test.podConditions, test.conditionType) + if actualIndex != test.index { + t.Errorf("expect to get index %v but got %v", test.index, actualIndex) + } + if !reflect.DeepEqual(*test.podCondition, *actualPodCondition) { + t.Errorf("expect to get condition %v but got %v", *test.podCondition, *actualPodCondition) + } + } +} diff --git a/pkg/webhook/webhook.go b/pkg/webhook/webhook.go index c52b5ec..ab06eef 100644 --- a/pkg/webhook/webhook.go +++ b/pkg/webhook/webhook.go @@ -57,6 +57,7 @@ func init() { // +kubebuilder:rbac:groups=apps.kruise.io,resources=statefulsets,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=apps.kruise.io,resources=statefulsets/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=apps.kruise.io,resources=podprobemarkers,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=core,resources=pods/status,verbs=get;update;patch // +kubebuilder:rbac:groups=admissionregistration.k8s.io,resources=mutatingwebhookconfigurations,verbs=create;get;list;watch;update;patch diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go index 89cd65d..f943732 100644 --- a/test/e2e/framework/framework.go +++ b/test/e2e/framework/framework.go @@ -10,6 +10,7 @@ import ( corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" @@ -57,6 +58,42 @@ func (f *Framework) DeployGameServerSet() (*gamekruiseiov1alpha1.GameServerSet, return f.client.CreateGameServerSet(gss) } +func (f *Framework) DeployGssWithServiceQualities() (*gamekruiseiov1alpha1.GameServerSet, error) { + gss := f.client.DefaultGameServerSet() + up := intstr.FromInt(20) + dp := intstr.FromInt(10) + sqs := []gamekruiseiov1alpha1.ServiceQuality{ + { + Name: "healthy", + ContainerName: client.GameContainerName, + Probe: corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"/bin/sh", "-c", "ls /"}, + }, + }, + }, + Permanent: false, + ServiceQualityAction: []gamekruiseiov1alpha1.ServiceQualityAction{ + { + State: true, + GameServerSpec: gamekruiseiov1alpha1.GameServerSpec{ + UpdatePriority: &up, + }, + }, + { + State: false, + GameServerSpec: gamekruiseiov1alpha1.GameServerSpec{ + DeletionPriority: &dp, + }, + }, + }, + }, + } + gss.Spec.ServiceQualities = sqs + return f.client.CreateGameServerSet(gss) +} + func (f *Framework) GameServerScale(gss *gamekruiseiov1alpha1.GameServerSet, desireNum int, reserveGsId *int) (*gamekruiseiov1alpha1.GameServerSet, error) { // TODO: change patch type newReserves := gss.Spec.ReserveGameServerIds @@ -215,3 +252,18 @@ func (f *Framework) WaitForGsDeletionPriorityUpdated(gsName string, deletionPrio return false, nil }) } + +func (f *Framework) WaitForGsUpdatePriorityUpdated(gsName string, updatePriority string) error { + return wait.PollImmediate(5*time.Second, 1*time.Minute, + func() (done bool, err error) { + pod, err := f.client.GetPod(gsName) + if err != nil { + return false, err + } + currentPriority := pod.GetLabels()[gamekruiseiov1alpha1.GameServerUpdatePriorityKey] + if currentPriority == updatePriority { + return true, nil + } + return false, nil + }) +} diff --git a/test/e2e/testcase/testcase.go b/test/e2e/testcase/testcase.go index 700d4c2..c40fe05 100644 --- a/test/e2e/testcase/testcase.go +++ b/test/e2e/testcase/testcase.go @@ -74,5 +74,22 @@ func RunTestCases(f *framework.Framework) { err = f.WaitForUpdated(gss, client.GameContainerName, "nginx:latest") gomega.Expect(err).To(gomega.BeNil()) }) + + ginkgo.It("service qualities", func() { + + // deploy + gss, err := f.DeployGssWithServiceQualities() + gomega.Expect(err).To(gomega.BeNil()) + + err = f.ExpectGssCorrect(gss, []int{0, 1, 2}) + gomega.Expect(err).To(gomega.BeNil()) + + err = f.WaitForGsUpdatePriorityUpdated(gss.GetName()+"-0", "20") + gomega.Expect(err).To(gomega.BeNil()) + err = f.WaitForGsUpdatePriorityUpdated(gss.GetName()+"-1", "20") + gomega.Expect(err).To(gomega.BeNil()) + err = f.WaitForGsUpdatePriorityUpdated(gss.GetName()+"-2", "20") + gomega.Expect(err).To(gomega.BeNil()) + }) }) }