diff --git a/build/build-image/Dockerfile b/build/build-image/Dockerfile index 6e180218ec..8e863e9289 100644 --- a/build/build-image/Dockerfile +++ b/build/build-image/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# ForceUpdate 6 -- change here if you need to force a rebuild +# ForceUpdate 7 -- change here if you need to force a rebuild # compiling proto + grpc takes an exceptionally long time # so we'll use a base from `base` - which is manually built using the below tag. @@ -140,11 +140,12 @@ RUN echo "export PATH=/usr/local/go/bin:/go/bin/:\$PATH" >> /root/.bashrc # make nano the editor RUN echo "export EDITOR=nano" >> /root/.bashrc +# update CMake +RUN wget https://github.com/Kitware/CMake/releases/download/v3.14.0/cmake-3.14.0-Linux-x86_64.sh && mkdir /opt/cmake && \ + sh ./cmake-3.14.0-Linux-x86_64.sh --skip-license --prefix=/opt/cmake && export PATH=$PATH:/opt/cmake/bin + # code generation scripts COPY *.sh /root/ RUN chmod +x /root/*.sh -RUN wget https://github.com/Kitware/CMake/releases/download/v3.14.0/cmake-3.14.0-Linux-x86_64.sh && mkdir /opt/cmake && \ - sh ./cmake-3.14.0-Linux-x86_64.sh --skip-license --prefix=/opt/cmake && export PATH=$PATH:/opt/cmake/bin - WORKDIR /go \ No newline at end of file diff --git a/build/build-image/gen-crd-client.sh b/build/build-image/gen-crd-client.sh index 1ea6e0bd55..827fe589ed 100644 --- a/build/build-image/gen-crd-client.sh +++ b/build/build-image/gen-crd-client.sh @@ -14,9 +14,14 @@ # See the License for the specific language governing permissions and # limitations under the License. +set -x + +# not sure why the modules break things, but they do. +export GO111MODULE=off +rm -r $GOPATH/src/agones.dev/agones/pkg/client rsync -r /go/src/agones.dev/agones/vendor/k8s.io/ /go/src/k8s.io/ cd /go/src/k8s.io/code-generator ./generate-groups.sh "all" \ agones.dev/agones/pkg/client \ - agones.dev/agones/pkg/apis stable:v1alpha1 \ + agones.dev/agones/pkg/apis "allocation:v1alpha1 stable:v1alpha1" \ --go-header-file=/go/src/agones.dev/agones/build/boilerplate.go.txt diff --git a/cmd/controller/main.go b/cmd/controller/main.go index dac103e539..87e03a10f5 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -142,9 +142,7 @@ func main() { // https server and the items that share the Mux for routing httpsServer := https.NewServer(ctlConf.CertFile, ctlConf.KeyFile) wh := webhooks.NewWebHook(httpsServer.Mux) - // will register openapi endpoint, which is currently not used - // but gets the code ready for usage in a later PR. - _ = apiserver.NewAPIServer(httpsServer.Mux) + api := apiserver.NewAPIServer(httpsServer.Mux) agonesInformerFactory := externalversions.NewSharedInformerFactory(agonesClient, defaultResync) kubeInformerFactory := informers.NewSharedInformerFactory(kubeClient, defaultResync) @@ -201,8 +199,8 @@ func main() { fleetController := fleets.NewController(wh, health, kubeClient, extClient, agonesClient, agonesInformerFactory) faController := fleetallocation.NewController(wh, allocationMutex, kubeClient, extClient, agonesClient, agonesInformerFactory) - gasController := gameserverallocations.NewController(wh, health, gsCounter, topNGSForAllocation, - kubeClient, extClient, agonesClient, agonesInformerFactory) + gasController := gameserverallocations.NewController(api, health, gsCounter, topNGSForAllocation, + kubeClient, agonesClient, agonesInformerFactory) fasController := fleetautoscalers.NewController(wh, health, kubeClient, extClient, agonesClient, agonesInformerFactory) diff --git a/examples/gameserverallocation.yaml b/examples/gameserverallocation.yaml index 80347045b2..aa75ccb467 100644 --- a/examples/gameserverallocation.yaml +++ b/examples/gameserverallocation.yaml @@ -20,12 +20,8 @@ # multiple Fleets, or a self managed group of GameServers. # -apiVersion: "stable.agones.dev/v1alpha1" +apiVersion: "allocation.agones.dev/v1alpha1" kind: GameServerAllocation -metadata: - # We recommend using the following to generate a unique name when creating Allocations - # This will need to be created with `kubectl create` if using the command line tooling - generateName: simple-udp- spec: # GameServer selector from which to choose GameServers from. # GameServers still have the hard requirement to be `Ready` to be allocated from diff --git a/examples/simple-udp/gameserverallocation.yaml b/examples/simple-udp/gameserverallocation.yaml index b902947957..9eabb4af1d 100644 --- a/examples/simple-udp/gameserverallocation.yaml +++ b/examples/simple-udp/gameserverallocation.yaml @@ -12,14 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +# +# A GameServerAllocation against a Fleet named 'simple-udp' # (GameServerAllocation is currently experimental, and likely to change in upcoming releases) +# -apiVersion: "stable.agones.dev/v1alpha1" +apiVersion: "allocation.agones.dev/v1alpha1" kind: GameServerAllocation -metadata: - # We recommend using the following to generate a unique name when creating Allocations - # This will need to be created with `kubectl create` if using the command line tooling - generateName: simple-udp- spec: # GameServer selector from which to choose GameServers from. # GameServers still have the hard requirement to be `Ready` to be allocated from diff --git a/examples/xonotic/gameserverallocation.yaml b/examples/xonotic/gameserverallocation.yaml index 6384fa6e29..6ce3b222aa 100644 --- a/examples/xonotic/gameserverallocation.yaml +++ b/examples/xonotic/gameserverallocation.yaml @@ -14,12 +14,8 @@ # (GameServerAllocation is currently experimental, and likely to change in upcoming releases) -apiVersion: "stable.agones.dev/v1alpha1" +apiVersion: "allocation.agones.dev/v1alpha1" kind: GameServerAllocation -metadata: - # We recommend using the following to generate a unique name when creating Allocations - # This will need to be created with `kubectl create` if using the command line tooling - generateName: xonotic- spec: # GameServer selector from which to choose GameServers from. # GameServers still have the hard requirement to be `Ready` to be allocated from diff --git a/install/helm/agones/scripts/delete_agones_resources.sh b/install/helm/agones/scripts/delete_agones_resources.sh index 5c1f503833..dd1e0021b0 100755 --- a/install/helm/agones/scripts/delete_agones_resources.sh +++ b/install/helm/agones/scripts/delete_agones_resources.sh @@ -32,7 +32,6 @@ for ns in $namespaces; do kubectl -n $ns delete gameserversets --all kubectl -n $ns delete gameservers --all kubectl -n $ns delete fleetallocations --all - kubectl -n $ns delete gameserverallocations --all # Since we don't have the nifty kubectl wait yet, hack one in the meantime for p in $pods; do diff --git a/install/helm/agones/templates/crds/_selector.yaml b/install/helm/agones/templates/crds/_selector.yaml deleted file mode 100644 index 2158d704da..0000000000 --- a/install/helm/agones/templates/crds/_selector.yaml +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright 2018 Google Inc. All Rights Reserved. -# -# 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. - -{{/* definition of a Kubernetes selector */}} -{{- define "agones.selector" }} -properties: - matchLabels: - type: object - matchExpressions: - type: array - items: - type: object - required: - - key - - operator - properties: - key: - type: string - operator: - type: string - values: - type: array - items: - type: string -{{- end }} \ No newline at end of file diff --git a/install/helm/agones/templates/crds/gameserverallocation.yaml b/install/helm/agones/templates/crds/gameserverallocation.yaml deleted file mode 100644 index 18cae28c5b..0000000000 --- a/install/helm/agones/templates/crds/gameserverallocation.yaml +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright 2018 Google Inc. All Rights Reserved. -# -# 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. - -{{- if .Values.agones.crds.install }} -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: gameserverallocations.stable.agones.dev - labels: - component: crd - app: {{ template "agones.name" . }} - chart: {{ template "agones.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - group: stable.agones.dev - version: v1alpha1 - scope: Namespaced - additionalPrinterColumns: - - JSONPath: .status.state - name: State - type: string - - JSONPath: .status.gameServerName - name: GameServer - type: string - - JSONPath: .status.address - name: Address - type: string - priority: 1 - - JSONPath: .status.ports[0].port - name: Port - type: string - priority: 1 - - JSONPath: .status.nodeName - name: Node - type: string - priority: 1 - - JSONPath: .metadata.creationTimestamp - name: Age - type: date - names: - kind: GameServerAllocation - plural: gameserverallocations - shortNames: - - gsa - singular: gameserverallocation - validation: - openAPIV3Schema: - properties: - spec: - required: - - required - properties: - required: - {{- include "agones.selector" . | indent 14 }} - preferred: - type: array - items: - type: object - {{- include "agones.selector" . | indent 16 }} - scheduling: - type: string - enum: - - Packed - - Distributed - metadata: - type: object - -{{- end }} - diff --git a/install/helm/agones/templates/admissionregistration.yaml b/install/helm/agones/templates/extensions.yaml similarity index 76% rename from install/helm/agones/templates/admissionregistration.yaml rename to install/helm/agones/templates/extensions.yaml index bb038310e1..19ec5d4b7a 100644 --- a/install/helm/agones/templates/admissionregistration.yaml +++ b/install/helm/agones/templates/extensions.yaml @@ -16,12 +16,44 @@ {{- $altName1 := printf "agones-controller-service.%s" .Release.Namespace }} {{- $altName2 := printf "agones-controller-service.%s.svc" .Release.Namespace }} {{- $cert := genSignedCert $cn nil (list $altName1 $altName2) 3650 $ca }} +--- +{{- if .Values.agones.registerApiService }} +apiVersion: apiregistration.k8s.io/v1beta1 +kind: APIService +metadata: + name: v1alpha1.allocation.agones.dev + labels: + component: controller + app: {{ template "agones.name" . }} + chart: {{ template "agones.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + group: allocation.agones.dev + groupPriorityMinimum: 1000 + versionPriority: 15 + service: + name: agones-controller-service + namespace: {{ .Release.Namespace }} + {{- if .Values.agones.controller.generateTLS }} + caBundle: {{ b64enc $ca.Cert }} + {{- else }} + caBundle: {{ .Files.Get "certs/server.crt" | b64enc }} + {{- end }} + version: v1alpha1 +{{- end}} {{- if .Values.agones.registerWebhooks }} --- apiVersion: admissionregistration.k8s.io/v1beta1 kind: ValidatingWebhookConfiguration metadata: name: agones-validation-webhook + labels: + component: controller + app: {{ template "agones.name" . }} + chart: {{ template "agones.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} webhooks: - name: validations.stable.agones.dev failurePolicy: Fail @@ -55,7 +87,6 @@ webhooks: - "gameserversets" - "fleetallocations" - "fleetautoscalers" - - "gameserverallocations" apiVersions: - "v1alpha1" operations: @@ -91,7 +122,6 @@ webhooks: - "gameservers" - "fleets" - "fleetallocations" - - "gameserverallocations" apiVersions: - "v1alpha1" operations: diff --git a/install/helm/agones/templates/hooks/sa.yaml b/install/helm/agones/templates/hooks/sa.yaml index ca02392edf..f46746c677 100644 --- a/install/helm/agones/templates/hooks/sa.yaml +++ b/install/helm/agones/templates/hooks/sa.yaml @@ -45,7 +45,7 @@ metadata: "helm.sh/hook-delete-policy": before-hook-creation rules: - apiGroups: ["stable.agones.dev"] - resources: ["fleets", "fleetallocations", "fleetautoscalers", "gameservers", "gameserversets", "gameserverallocations"] + resources: ["fleets", "fleetallocations", "fleetautoscalers", "gameservers", "gameserversets"] verbs: ["delete", "list" ] - apiGroups: [""] resources: ["pods"] diff --git a/install/helm/agones/templates/serviceaccounts/controller.yaml b/install/helm/agones/templates/serviceaccounts/controller.yaml index 2489ce3547..0af375f5a5 100644 --- a/install/helm/agones/templates/serviceaccounts/controller.yaml +++ b/install/helm/agones/templates/serviceaccounts/controller.yaml @@ -64,9 +64,6 @@ rules: - apiGroups: ["stable.agones.dev"] resources: ["fleets/status"] verbs: ["update"] -- apiGroups: ["stable.agones.dev"] - resources: ["gameserverallocations"] - verbs: ["list", "watch", "delete"] --- apiVersion: rbac.authorization.k8s.io/v1 @@ -87,4 +84,34 @@ roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: {{ .Values.agones.serviceaccount.controller }} +--- +# +# RBACs for APIService +# +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ .Values.agones.serviceaccount.controller }}:system:auth-delegator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: + - kind: ServiceAccount + name: apiserver + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ .Values.agones.serviceaccount.controller }}-auth-reader + namespace: kube-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: + - kind: ServiceAccount + name: apiserver + namespace: {{ .Release.Namespace }} {{- end }} diff --git a/install/helm/agones/values.yaml b/install/helm/agones/values.yaml index f45caea609..0d1b197056 100644 --- a/install/helm/agones/values.yaml +++ b/install/helm/agones/values.yaml @@ -23,6 +23,7 @@ agones: rbacEnabled: true registerServiceAccounts: true registerWebhooks: true + registerApiService: true crds: install: true cleanupOnDelete: true diff --git a/install/yaml/install.yaml b/install/yaml/install.yaml index 53587aee7d..bee15d02d1 100644 --- a/install/yaml/install.yaml +++ b/install/yaml/install.yaml @@ -62,9 +62,6 @@ rules: - apiGroups: ["stable.agones.dev"] resources: ["fleets/status"] verbs: ["update"] -- apiGroups: ["stable.agones.dev"] - resources: ["gameserverallocations"] - verbs: ["list", "watch", "delete"] --- apiVersion: rbac.authorization.k8s.io/v1 @@ -85,6 +82,36 @@ roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: agones-controller +--- +# +# RBACs for APIService +# +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: agones-controller:system:auth-delegator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: + - kind: ServiceAccount + name: apiserver + namespace: agones-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: agones-controller-auth-reader + namespace: kube-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: + - kind: ServiceAccount + name: apiserver + namespace: agones-system --- # Source: agones/templates/serviceaccounts/sdk.yaml @@ -650,122 +677,6 @@ spec: minimum: 1 maximum: 2147483648 ---- -# Source: agones/templates/crds/gameserverallocation.yaml -# Copyright 2018 Google Inc. All Rights Reserved. -# -# 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. -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: gameserverallocations.stable.agones.dev - labels: - component: crd - app: agones - chart: agones-0.9.0-rc - release: agones-manual - heritage: Tiller -spec: - group: stable.agones.dev - version: v1alpha1 - scope: Namespaced - additionalPrinterColumns: - - JSONPath: .status.state - name: State - type: string - - JSONPath: .status.gameServerName - name: GameServer - type: string - - JSONPath: .status.address - name: Address - type: string - priority: 1 - - JSONPath: .status.ports[0].port - name: Port - type: string - priority: 1 - - JSONPath: .status.nodeName - name: Node - type: string - priority: 1 - - JSONPath: .metadata.creationTimestamp - name: Age - type: date - names: - kind: GameServerAllocation - plural: gameserverallocations - shortNames: - - gsa - singular: gameserverallocation - validation: - openAPIV3Schema: - properties: - spec: - required: - - required - properties: - required: - properties: - matchLabels: - type: object - matchExpressions: - type: array - items: - type: object - required: - - key - - operator - properties: - key: - type: string - operator: - type: string - values: - type: array - items: - type: string - preferred: - type: array - items: - type: object - properties: - matchLabels: - type: object - matchExpressions: - type: array - items: - type: object - required: - - key - - operator - properties: - key: - type: string - operator: - type: string - values: - type: array - items: - type: string - scheduling: - type: string - enum: - - Packed - - Distributed - metadata: - type: object - - --- # Source: agones/templates/crds/gameserverset.yaml # Copyright 2018 Google Inc. All Rights Reserved. @@ -1235,29 +1146,7 @@ spec: protocol: UDP type: LoadBalancer --- -# Source: agones/templates/priority-class.yaml - -apiVersion: scheduling.k8s.io/v1beta1 -kind: PriorityClass -metadata: - name: agones-system -value: 1000000 -globalDefault: false -description: "This priority class should be used for Agones service pods only." ---- -# Source: agones/templates/hooks/pre_delete_hook.yaml - - ---- -# Source: agones/templates/hooks/sa.yaml - - ---- -# Source: agones/templates/hooks/scripts.yaml - - ---- -# Source: agones/templates/admissionregistration.yaml +# Source: agones/templates/extensions.yaml # Copyright 2018 Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -1272,10 +1161,36 @@ description: "This priority class should be used for Agones service pods only." # See the License for the specific language governing permissions and # limitations under the License. --- +apiVersion: apiregistration.k8s.io/v1beta1 +kind: APIService +metadata: + name: v1alpha1.allocation.agones.dev + labels: + component: controller + app: agones + chart: agones-0.9.0-rc + release: agones-manual + heritage: Tiller +spec: + group: allocation.agones.dev + groupPriorityMinimum: 1000 + versionPriority: 15 + service: + name: agones-controller-service + namespace: agones-system + caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVLVENDQXhHZ0F3SUJBZ0lKQU9KUDY0MTB3dkdTTUEwR0NTcUdTSWIzRFFFQkN3VUFNSUdxTVFzd0NRWUQKVlFRR0V3SlZVekVUTUJFR0ExVUVDQXdLVTI5dFpTMVRkR0YwWlRFUE1BMEdBMVVFQ2d3R1FXZHZibVZ6TVE4dwpEUVlEVlFRTERBWkJaMjl1WlhNeE5EQXlCZ05WQkFNTUsyRm5iMjVsY3kxamIyNTBjbTlzYkdWeUxYTmxjblpwClkyVXVZV2R2Ym1WekxYTjVjM1JsYlM1emRtTXhMakFzQmdrcWhraUc5dzBCQ1FFV0gyRm5iMjVsY3kxa2FYTmoKZFhOelFHZHZiMmRzWldkeWIzVndjeTVqYjIwd0hoY05NVGd3TWpFME1EUTBORFEyV2hjTk1qZ3dNakV5TURRMApORFEyV2pDQnFqRUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdNQ2xOdmJXVXRVM1JoZEdVeER6QU5CZ05WCkJBb01Ca0ZuYjI1bGN6RVBNQTBHQTFVRUN3d0dRV2R2Ym1Wek1UUXdNZ1lEVlFRRERDdGhaMjl1WlhNdFkyOXUKZEhKdmJHeGxjaTF6WlhKMmFXTmxMbUZuYjI1bGN5MXplWE4wWlcwdWMzWmpNUzR3TEFZSktvWklodmNOQVFrQgpGaDloWjI5dVpYTXRaR2x6WTNWemMwQm5iMjluYkdWbmNtOTFjSE11WTI5dE1JSUJJakFOQmdrcWhraUc5dzBCCkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXpnVlQ5MGVqeE5ud0NvL09qTUQyNmZVNGRya1NlZndkUWd3aWJpZmEKbDhyazZZMFZ2T0lWMUgrbFJvd2UwNm1XTnVSNUZPWEZBMGZYbHZ4Q0tLWVZRcFNQRUsyWVN5aC9hU25KUUw2cQpvOGVBWVRKQmtPWUxCNUNiekl6aVdlb1FmT1lOOE1sRW44YlhKZGllSmhISDhVbnlqdHlvVGx4emhabVgrcGZ0CmhVZGVhM1Zrek8yMW40K1FFM1JYNWYxMzJGVEZjdXFYT1VBL3BpOGNjQU5HYzN6akxlWkp2QTlvZFBFaEdmN2cKQzhleUE2OFNWY3NoK1BqejBsdzk1QVB2bE12MWptcVVSRldjRVNUTGFRMEZ4NUt3UnlWMHppWm1VdkFBRjJaeApEWmhIVWNvRlBIQXdUbDc1TkFobkhwTWxMTnA1TDd0Y1ZkeVQ4QjJHUnMrc2xRSURBUUFCbzFBd1RqQWRCZ05WCkhRNEVGZ1FVZ3YxblRQYVFKU04zTHFtNWpJalc0eEhtZEcwd0h3WURWUjBqQkJnd0ZvQVVndjFuVFBhUUpTTjMKTHFtNWpJalc0eEhtZEcwd0RBWURWUjBUQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBSEtFQwprdEVqWU5VQ0ErbXlzejRvclc3cFJVdmhCSERWU2dzWTZlRVZSTHpmLzF5SVpFMHU2NTZrcEs2T1Q3TWhKR2xVCkt3R1NTb1VCQnpWZ1VzWmpEbTdQZ2JrNGlZem40TTF4THpiTFFCcjNNYzV6WEhlZlB2YmltaEQ1NWNMenBWRnUKVlFtQm1aVjJOalU1RHVTZFJuZGxjUGFOY2cvdU9jdlpLNEtZMUtDQkEzRW9BUUlrcHpIWDJpVU1veGlSdlpWTgpORXdnRlR0SUdCWW4wSGZML3ZnT3NIOGZWck1Va3VHMnZoR2RlWEJwWmlxL0JaSmJaZU4yckNmMmdhWDFRSXYwCkVLYmN1RnFNOThXVDVaVlpSdFgxWTNSd2V2ZzRteFlKWEN1SDZGRjlXOS9TejI5NEZ5Mk9CS0I4SkFWYUV4OW4KMS9pNmZJZmZHbkhUWFdIc1ZRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + version: v1alpha1 +--- apiVersion: admissionregistration.k8s.io/v1beta1 kind: ValidatingWebhookConfiguration metadata: name: agones-validation-webhook + labels: + component: controller + app: agones + chart: agones-0.9.0-rc + release: agones-manual + heritage: Tiller webhooks: - name: validations.stable.agones.dev failurePolicy: Fail @@ -1305,7 +1220,6 @@ webhooks: - "gameserversets" - "fleetallocations" - "fleetautoscalers" - - "gameserverallocations" apiVersions: - "v1alpha1" operations: @@ -1337,7 +1251,6 @@ webhooks: - "gameservers" - "fleets" - "fleetallocations" - - "gameserverallocations" apiVersions: - "v1alpha1" operations: @@ -1358,3 +1271,25 @@ data: server.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVLVENDQXhHZ0F3SUJBZ0lKQU9KUDY0MTB3dkdTTUEwR0NTcUdTSWIzRFFFQkN3VUFNSUdxTVFzd0NRWUQKVlFRR0V3SlZVekVUTUJFR0ExVUVDQXdLVTI5dFpTMVRkR0YwWlRFUE1BMEdBMVVFQ2d3R1FXZHZibVZ6TVE4dwpEUVlEVlFRTERBWkJaMjl1WlhNeE5EQXlCZ05WQkFNTUsyRm5iMjVsY3kxamIyNTBjbTlzYkdWeUxYTmxjblpwClkyVXVZV2R2Ym1WekxYTjVjM1JsYlM1emRtTXhMakFzQmdrcWhraUc5dzBCQ1FFV0gyRm5iMjVsY3kxa2FYTmoKZFhOelFHZHZiMmRzWldkeWIzVndjeTVqYjIwd0hoY05NVGd3TWpFME1EUTBORFEyV2hjTk1qZ3dNakV5TURRMApORFEyV2pDQnFqRUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdNQ2xOdmJXVXRVM1JoZEdVeER6QU5CZ05WCkJBb01Ca0ZuYjI1bGN6RVBNQTBHQTFVRUN3d0dRV2R2Ym1Wek1UUXdNZ1lEVlFRRERDdGhaMjl1WlhNdFkyOXUKZEhKdmJHeGxjaTF6WlhKMmFXTmxMbUZuYjI1bGN5MXplWE4wWlcwdWMzWmpNUzR3TEFZSktvWklodmNOQVFrQgpGaDloWjI5dVpYTXRaR2x6WTNWemMwQm5iMjluYkdWbmNtOTFjSE11WTI5dE1JSUJJakFOQmdrcWhraUc5dzBCCkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXpnVlQ5MGVqeE5ud0NvL09qTUQyNmZVNGRya1NlZndkUWd3aWJpZmEKbDhyazZZMFZ2T0lWMUgrbFJvd2UwNm1XTnVSNUZPWEZBMGZYbHZ4Q0tLWVZRcFNQRUsyWVN5aC9hU25KUUw2cQpvOGVBWVRKQmtPWUxCNUNiekl6aVdlb1FmT1lOOE1sRW44YlhKZGllSmhISDhVbnlqdHlvVGx4emhabVgrcGZ0CmhVZGVhM1Zrek8yMW40K1FFM1JYNWYxMzJGVEZjdXFYT1VBL3BpOGNjQU5HYzN6akxlWkp2QTlvZFBFaEdmN2cKQzhleUE2OFNWY3NoK1BqejBsdzk1QVB2bE12MWptcVVSRldjRVNUTGFRMEZ4NUt3UnlWMHppWm1VdkFBRjJaeApEWmhIVWNvRlBIQXdUbDc1TkFobkhwTWxMTnA1TDd0Y1ZkeVQ4QjJHUnMrc2xRSURBUUFCbzFBd1RqQWRCZ05WCkhRNEVGZ1FVZ3YxblRQYVFKU04zTHFtNWpJalc0eEhtZEcwd0h3WURWUjBqQkJnd0ZvQVVndjFuVFBhUUpTTjMKTHFtNWpJalc0eEhtZEcwd0RBWURWUjBUQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBSEtFQwprdEVqWU5VQ0ErbXlzejRvclc3cFJVdmhCSERWU2dzWTZlRVZSTHpmLzF5SVpFMHU2NTZrcEs2T1Q3TWhKR2xVCkt3R1NTb1VCQnpWZ1VzWmpEbTdQZ2JrNGlZem40TTF4THpiTFFCcjNNYzV6WEhlZlB2YmltaEQ1NWNMenBWRnUKVlFtQm1aVjJOalU1RHVTZFJuZGxjUGFOY2cvdU9jdlpLNEtZMUtDQkEzRW9BUUlrcHpIWDJpVU1veGlSdlpWTgpORXdnRlR0SUdCWW4wSGZML3ZnT3NIOGZWck1Va3VHMnZoR2RlWEJwWmlxL0JaSmJaZU4yckNmMmdhWDFRSXYwCkVLYmN1RnFNOThXVDVaVlpSdFgxWTNSd2V2ZzRteFlKWEN1SDZGRjlXOS9TejI5NEZ5Mk9CS0I4SkFWYUV4OW4KMS9pNmZJZmZHbkhUWFdIc1ZRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= server.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBemdWVDkwZWp4Tm53Q28vT2pNRDI2ZlU0ZHJrU2Vmd2RRZ3dpYmlmYWw4cms2WTBWCnZPSVYxSCtsUm93ZTA2bVdOdVI1Rk9YRkEwZlhsdnhDS0tZVlFwU1BFSzJZU3loL2FTbkpRTDZxbzhlQVlUSkIKa09ZTEI1Q2J6SXppV2VvUWZPWU44TWxFbjhiWEpkaWVKaEhIOFVueWp0eW9UbHh6aFptWCtwZnRoVWRlYTNWawp6TzIxbjQrUUUzUlg1ZjEzMkZURmN1cVhPVUEvcGk4Y2NBTkdjM3pqTGVaSnZBOW9kUEVoR2Y3Z0M4ZXlBNjhTClZjc2grUGp6MGx3OTVBUHZsTXYxam1xVVJGV2NFU1RMYVEwRng1S3dSeVYwemlabVV2QUFGMlp4RFpoSFVjb0YKUEhBd1RsNzVOQWhuSHBNbExOcDVMN3RjVmR5VDhCMkdScytzbFFJREFRQUJBb0lCQUVvVTVHS1E0alRRNFY0Swo1QXo4L2t5V254MGg0NkQxcFZld29WalcvK1dCVWRzaG5tVnpMc0pndS8rb054V0piN2lCWTRDK05wKzlYNnF0ClB1VDdBNzRUU1hhSDFiR0ErSC9LUk5JQlBiN3k2QmtMUjBSaFZDbitOK2ZQNlR6SHkvSDlqNW03NWU5R1F1c2EKLzVOVTVYN0FSblpVcGppM1Nkc0twZm00VS9LT1YrcDJqV1NQWDdIT0J1L0tZYTFqdmVDdDZKTVBRMzZLQlhrUgpNbFZDa0FEY3ZBQUd1T2JwYS9zbTBNQTYzK2loZGVTWWhrRVhLcXhINEF6M1BWREx3UDgwVDhmNVZxd1dZbW5xCkwvQmc2SG5WNUdIbmxUWEErV2VwTmJIa29rTjlHMEg2bTBJdGo0YWwzYkdUQjRqZUJDSlpwNUZIVzVvYko0cVAKV2tjZlhjRUNnWUVBOFVJWnZkTlNzU3BSWlZUZTRoaHRYbmNPcHRGVGRvVktJelR1VVZLZktlOU9CNWkzMkI5dQo0aEROcEJEcWtnRWt0ZzRSOC9jbjU3ejZaVWRVQ2NvYmpXUWJKTFhFNXdwN0h0ZjdqQ0duTDJRbUljcDIwcmJGCkhyRTJsSHIwb05yM01MVXJ1QnZBclZCM0xMR21PRWduM05RdzlhSndnLzU0MkVEUzd4NXYzWGtDZ1lFQTJwd0cKSGlHWVhUSmZZTmcvK1NtRHVTRFdGZTRpTVBUUncxVFQ4NXVHRTlVRXJZUFFkOE9xWVFRT2dJQVQ3eHAxejBvcQo2cG1zalBPNkhabmc5b0hLZUFPL0pQZVN1WEUrYko4SFlLcDdXOTI5RitMR0pvcWl0T0xQTW0vOU9vdllEQ3ZoCjYrcURZNUxOUkhkQWVUcXd3STJ5dWdmNFluQmpZNnpJZkJwNUxQMENnWUVBeXJydjVKcVNienVQUUdaTUVKUFUKTzhBeCtLNEh3NTJIeWdQdGl6cXhjc3lidGpoM3JFM2xvR1BjV2RTNU9FMXJxdXd4Mjk5QmtqTXoraTB4Q2pUaQphRExKdUZSaURIKzdMQlQwVlRIbVNpV1BBWEFmM3pza2M0RVl5elp6SUVRLzJaYzBFTGFKZDFvWmV0NGhQa1FyCjh4My9zamw0OFFIQ1RINVVnZ2tDbVlrQ2dZQWZLL3BQVjVrRFNRaUNwYk5Sa3hMZVZnbFE3VGpnNURmNDgyS1oKclFhTVUyYXNXMHhobDN2M0EzNFI0ckYwK2Ivc3cvV2txQzhMbGtGbXNTZDczdndBNnYvWmhKZmVhNEJzT3F6eApvcjJlVnRyOHlmQlpWSkZvMjZLUjNaZ3RQZjJibHJKTFVwQlRwWDR4a2hPV2RjRDRZL3dsUExlMVNiTlNaalBjClJtWWEvUUtCZ1FDNmE3ek5BU1AwQTBxTVBocXlKWmxiZzRGOFdNUnRnSEZmc3kvaUx3ZGlFVUd1Q2hRV1VMa2MKaHpQV3BqRDB6d3JTeFp0eWhTTDBiNlRIbnFUaWluMjNPdnRJTmxWaVptb3M1bVdXMFZlR3NiSG5KdVJhM1RIeQpFalNrU1A0bVI3dEpsSm9rYm9aK2xZTDdnQUJIbjJFUm5Ec3FYOG9FVTZRcERQMXJaaFlTemc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= +--- +# Source: agones/templates/priority-class.yaml + +apiVersion: scheduling.k8s.io/v1beta1 +kind: PriorityClass +metadata: + name: agones-system +value: 1000000 +globalDefault: false +description: "This priority class should be used for Agones service pods only." +--- +# Source: agones/templates/hooks/pre_delete_hook.yaml + + +--- +# Source: agones/templates/hooks/sa.yaml + + +--- +# Source: agones/templates/hooks/scripts.yaml + + diff --git a/pkg/apis/allocation/register.go b/pkg/apis/allocation/register.go new file mode 100644 index 0000000000..2408567142 --- /dev/null +++ b/pkg/apis/allocation/register.go @@ -0,0 +1,20 @@ +// Copyright 2019 Google Inc. All Rights Reserved. +// +// 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 allocation + +const ( + // GroupName is the Scheme Group Name for Agones allocation + GroupName = "allocation.agones.dev" +) diff --git a/pkg/apis/allocation/v1alpha1/doc.go b/pkg/apis/allocation/v1alpha1/doc.go new file mode 100644 index 0000000000..ae6c83d244 --- /dev/null +++ b/pkg/apis/allocation/v1alpha1/doc.go @@ -0,0 +1,19 @@ +// Copyright 2019 Google Inc. All Rights Reserved. +// +// 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. + +// +k8s:deepcopy-gen=package,register + +// Package v1alpha1 is the v1alpha1 version of the API. +// +groupName=allocation.agones.dev +package v1alpha1 diff --git a/pkg/apis/stable/v1alpha1/gameserverallocation.go b/pkg/apis/allocation/v1alpha1/gameserverallocation.go similarity index 73% rename from pkg/apis/stable/v1alpha1/gameserverallocation.go rename to pkg/apis/allocation/v1alpha1/gameserverallocation.go index 127d056b25..ec45dce4fa 100644 --- a/pkg/apis/stable/v1alpha1/gameserverallocation.go +++ b/pkg/apis/allocation/v1alpha1/gameserverallocation.go @@ -1,4 +1,4 @@ -// Copyright 2018 Google Inc. All Rights Reserved. +// Copyright 2019 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,8 +15,11 @@ package v1alpha1 import ( + "fmt" + + "agones.dev/agones/pkg/apis" + "agones.dev/agones/pkg/apis/stable/v1alpha1" "github.com/pkg/errors" - "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" ) @@ -35,6 +38,7 @@ const ( type GameServerAllocationState string // +genclient +// +genclient:onlyVerbs=create // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // GameServerAllocation is the data structure for allocating against a set of @@ -67,13 +71,19 @@ type GameServerAllocationSpec struct { Preferred []metav1.LabelSelector `json:"preferred,omitempty"` // Scheduling strategy. Defaults to "Packed". - Scheduling SchedulingStrategy `json:"scheduling"` + Scheduling apis.SchedulingStrategy `json:"scheduling"` // MetaPatch is optional custom metadata that is added to the game server at allocation // You can use this to tell the server necessary session data MetaPatch MetaPatch `json:"metadata,omitempty"` } +// MetaPatch is the metadata used to patch the GameServer metadata on allocation +type MetaPatch struct { + Labels map[string]string `json:"labels,omitempty"` + Annotations map[string]string `json:"annotations,omitempty"` +} + // PreferredSelectors converts all the the preferred label selectors into an array of // labels.Selectors. This is useful as they all have `Match()` functions! func (gsas *GameServerAllocationSpec) PreferredSelectors() ([]labels.Selector, error) { @@ -93,30 +103,34 @@ func (gsas *GameServerAllocationSpec) PreferredSelectors() ([]labels.Selector, e // GameServerAllocationStatus is the status for an GameServerAllocation resource type GameServerAllocationStatus struct { // GameServerState is the current state of an GameServerAllocation, e.g. Allocated, or UnAllocated - State GameServerAllocationState `json:"state"` - GameServerName string `json:"gameServerName"` - Ports []GameServerStatusPort `json:"ports,omitempty"` - Address string `json:"address,omitempty"` - NodeName string `json:"nodeName,omitempty"` + State GameServerAllocationState `json:"state"` + GameServerName string `json:"gameServerName"` + Ports []v1alpha1.GameServerStatusPort `json:"ports,omitempty"` + Address string `json:"address,omitempty"` + NodeName string `json:"nodeName,omitempty"` } // ApplyDefaults applies the default values to this GameServerAllocation func (gsa *GameServerAllocation) ApplyDefaults() { if gsa.Spec.Scheduling == "" { - gsa.Spec.Scheduling = Packed + gsa.Spec.Scheduling = apis.Packed } } -// ValidateUpdate validates when an update occurs -func (gsa *GameServerAllocation) ValidateUpdate(new *GameServerAllocation) ([]metav1.StatusCause, bool) { +// Validate validation for the GameServerAllocation +func (gsa *GameServerAllocation) Validate() ([]metav1.StatusCause, bool) { var causes []metav1.StatusCause - if !equality.Semantic.DeepEqual(gsa.Spec, new.Spec) { - causes = append(causes, metav1.StatusCause{ - Type: metav1.CauseTypeFieldValueInvalid, - Field: "spec", - Message: "spec cannot be updated", - }) + valid := false + for _, v := range []apis.SchedulingStrategy{apis.Packed, apis.Distributed} { + if gsa.Spec.Scheduling == v { + valid = true + } + } + if !valid { + causes = append(causes, metav1.StatusCause{Type: metav1.CauseTypeFieldValueInvalid, + Field: "spec.scheduling", + Message: fmt.Sprintf("Invalid value: %s, value must be either Packed or Distributed", gsa.Spec.Scheduling)}) } return causes, len(causes) == 0 diff --git a/pkg/apis/stable/v1alpha1/gameserverallocation_test.go b/pkg/apis/allocation/v1alpha1/gameserverallocation_test.go similarity index 74% rename from pkg/apis/stable/v1alpha1/gameserverallocation_test.go rename to pkg/apis/allocation/v1alpha1/gameserverallocation_test.go index 551e9421df..ac2d2afc9b 100644 --- a/pkg/apis/stable/v1alpha1/gameserverallocation_test.go +++ b/pkg/apis/allocation/v1alpha1/gameserverallocation_test.go @@ -1,4 +1,4 @@ -// Copyright 2018 Google Inc. All Rights Reserved. +// Copyright 2019 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,39 +17,30 @@ package v1alpha1 import ( "testing" + "agones.dev/agones/pkg/apis" + "agones.dev/agones/pkg/apis/stable/v1alpha1" + "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" ) func TestGameServerAllocationApplyDefaults(t *testing.T) { + t.Parallel() + gsa := &GameServerAllocation{} gsa.ApplyDefaults() - assert.Equal(t, Packed, gsa.Spec.Scheduling) + assert.Equal(t, apis.Packed, gsa.Spec.Scheduling) - gsa = &GameServerAllocation{Spec: GameServerAllocationSpec{Scheduling: Distributed}} + gsa = &GameServerAllocation{Spec: GameServerAllocationSpec{Scheduling: apis.Distributed}} gsa.ApplyDefaults() - assert.Equal(t, Distributed, gsa.Spec.Scheduling) -} - -func TestGameServerAllocationValidateUpdate(t *testing.T) { - new := &GameServerAllocation{Spec: GameServerAllocationSpec{Scheduling: Packed}} - old := &GameServerAllocation{Spec: GameServerAllocationSpec{Scheduling: Distributed}} - - causes, ok := old.ValidateUpdate(old) - assert.True(t, ok) - assert.Empty(t, causes) - - causes, ok = old.ValidateUpdate(new) - assert.False(t, ok) - assert.Len(t, causes, 1) - - assert.Equal(t, metav1.CauseTypeFieldValueInvalid, causes[0].Type) - assert.Equal(t, "spec", causes[0].Field) + assert.Equal(t, apis.Distributed, gsa.Spec.Scheduling) } func TestGameServerAllocationSpecPreferredSelectors(t *testing.T) { + t.Parallel() + gsas := &GameServerAllocationSpec{ Preferred: []metav1.LabelSelector{ {MatchLabels: map[string]string{"check": "blue"}}, @@ -61,7 +52,7 @@ func TestGameServerAllocationSpecPreferredSelectors(t *testing.T) { assert.Nil(t, err) assert.Len(t, selectors, 2) - gs := &GameServer{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{}}} + gs := &v1alpha1.GameServer{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{}}} for _, s := range selectors { assert.False(t, s.Matches(labels.Set(gs.ObjectMeta.Labels))) @@ -75,3 +66,23 @@ func TestGameServerAllocationSpecPreferredSelectors(t *testing.T) { assert.False(t, selectors[0].Matches(labels.Set(gs.ObjectMeta.Labels))) assert.True(t, selectors[1].Matches(labels.Set(gs.ObjectMeta.Labels))) } + +func TestGameServerAllocationValidate(t *testing.T) { + t.Parallel() + + gsa := &GameServerAllocation{} + gsa.ApplyDefaults() + + causes, ok := gsa.Validate() + assert.True(t, ok) + assert.Empty(t, causes) + + gsa.Spec.Scheduling = "FLERG" + + causes, ok = gsa.Validate() + assert.False(t, ok) + assert.Len(t, causes, 1) + + assert.Equal(t, metav1.CauseTypeFieldValueInvalid, causes[0].Type) + assert.Equal(t, "spec.scheduling", causes[0].Field) +} diff --git a/pkg/apis/allocation/v1alpha1/register.go b/pkg/apis/allocation/v1alpha1/register.go new file mode 100644 index 0000000000..f036485809 --- /dev/null +++ b/pkg/apis/allocation/v1alpha1/register.go @@ -0,0 +1,58 @@ +// Copyright 2019 Google Inc. All Rights Reserved. +// +// 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 v1alpha1 + +import ( + "agones.dev/agones/pkg/apis/allocation" + "agones.dev/agones/pkg/util/runtime" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8sruntime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/kubernetes/scheme" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: allocation.GroupName, Version: "v1alpha1"} + +// Kind takes an unqualified kind and returns back a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // SchemeBuilder registers our types + SchemeBuilder = k8sruntime.NewSchemeBuilder(addKnownTypes) + // AddToScheme local alias for SchemeBuilder.AddToScheme + AddToScheme = SchemeBuilder.AddToScheme +) + +func init() { + runtime.Must(AddToScheme(scheme.Scheme)) +} + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *k8sruntime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &GameServerAllocation{}, + &GameServerAllocationList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/pkg/apis/allocation/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/allocation/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..495090ad32 --- /dev/null +++ b/pkg/apis/allocation/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,164 @@ +// +build !ignore_autogenerated + +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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. + +// This code was autogenerated. Do not edit directly. + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + stable_v1alpha1 "agones.dev/agones/pkg/apis/stable/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GameServerAllocation) DeepCopyInto(out *GameServerAllocation) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServerAllocation. +func (in *GameServerAllocation) DeepCopy() *GameServerAllocation { + if in == nil { + return nil + } + out := new(GameServerAllocation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GameServerAllocation) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GameServerAllocationList) DeepCopyInto(out *GameServerAllocationList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]GameServerAllocation, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServerAllocationList. +func (in *GameServerAllocationList) DeepCopy() *GameServerAllocationList { + if in == nil { + return nil + } + out := new(GameServerAllocationList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GameServerAllocationList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GameServerAllocationSpec) DeepCopyInto(out *GameServerAllocationSpec) { + *out = *in + in.Required.DeepCopyInto(&out.Required) + if in.Preferred != nil { + in, out := &in.Preferred, &out.Preferred + *out = make([]v1.LabelSelector, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.MetaPatch.DeepCopyInto(&out.MetaPatch) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServerAllocationSpec. +func (in *GameServerAllocationSpec) DeepCopy() *GameServerAllocationSpec { + if in == nil { + return nil + } + out := new(GameServerAllocationSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GameServerAllocationStatus) DeepCopyInto(out *GameServerAllocationStatus) { + *out = *in + if in.Ports != nil { + in, out := &in.Ports, &out.Ports + *out = make([]stable_v1alpha1.GameServerStatusPort, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServerAllocationStatus. +func (in *GameServerAllocationStatus) DeepCopy() *GameServerAllocationStatus { + if in == nil { + return nil + } + out := new(GameServerAllocationStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MetaPatch) DeepCopyInto(out *MetaPatch) { + *out = *in + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetaPatch. +func (in *MetaPatch) DeepCopy() *MetaPatch { + if in == nil { + return nil + } + out := new(MetaPatch) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/apis/stable/v1alpha1/scheduling.go b/pkg/apis/scheduling.go similarity index 95% rename from pkg/apis/stable/v1alpha1/scheduling.go rename to pkg/apis/scheduling.go index 9f17579427..817b832ef3 100644 --- a/pkg/apis/stable/v1alpha1/scheduling.go +++ b/pkg/apis/scheduling.go @@ -1,4 +1,4 @@ -// Copyright 2018 Google Inc. All Rights Reserved. +// Copyright 2019 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package v1alpha1 +package apis const ( // Packed scheduling strategy will prioritise allocating GameServers diff --git a/pkg/apis/stable/v1alpha1/fleet.go b/pkg/apis/stable/v1alpha1/fleet.go index cc8c21475a..4a87473a91 100644 --- a/pkg/apis/stable/v1alpha1/fleet.go +++ b/pkg/apis/stable/v1alpha1/fleet.go @@ -18,6 +18,7 @@ import ( "fmt" "agones.dev/agones/pkg" + "agones.dev/agones/pkg/apis" "agones.dev/agones/pkg/apis/stable" appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -62,7 +63,7 @@ type FleetSpec struct { // Deployment strategy Strategy appsv1.DeploymentStrategy `json:"strategy"` // Scheduling strategy. Defaults to "Packed". - Scheduling SchedulingStrategy `json:"scheduling"` + Scheduling apis.SchedulingStrategy `json:"scheduling"` // Template the GameServer template to apply for this Fleet Template GameServerTemplateSpec `json:"template"` } @@ -114,7 +115,7 @@ func (f *Fleet) ApplyDefaults() { } if f.Spec.Scheduling == "" { - f.Spec.Scheduling = Packed + f.Spec.Scheduling = apis.Packed } if f.Spec.Strategy.Type == appsv1.RollingUpdateDeploymentStrategyType { diff --git a/pkg/apis/stable/v1alpha1/fleet_test.go b/pkg/apis/stable/v1alpha1/fleet_test.go index f690ac811f..685a886653 100644 --- a/pkg/apis/stable/v1alpha1/fleet_test.go +++ b/pkg/apis/stable/v1alpha1/fleet_test.go @@ -17,6 +17,7 @@ package v1alpha1 import ( "testing" + "agones.dev/agones/pkg/apis" "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -33,7 +34,7 @@ func TestFleetGameServerSetGameServer(t *testing.T) { }, Spec: FleetSpec{ Replicas: 10, - Scheduling: Packed, + Scheduling: apis.Packed, Template: GameServerTemplateSpec{ Spec: GameServerSpec{ Ports: []GameServerPort{{ContainerPort: 1234}}, @@ -69,7 +70,7 @@ func TestFleetApplyDefaults(t *testing.T) { assert.Equal(t, appsv1.RollingUpdateDeploymentStrategyType, f.Spec.Strategy.Type) assert.Equal(t, "25%", f.Spec.Strategy.RollingUpdate.MaxUnavailable.String()) assert.Equal(t, "25%", f.Spec.Strategy.RollingUpdate.MaxSurge.String()) - assert.Equal(t, Packed, f.Spec.Scheduling) + assert.Equal(t, apis.Packed, f.Spec.Scheduling) } func TestFleetUpperBoundReplicas(t *testing.T) { diff --git a/pkg/apis/stable/v1alpha1/gameserver.go b/pkg/apis/stable/v1alpha1/gameserver.go index c0e3872762..ccd4f63421 100644 --- a/pkg/apis/stable/v1alpha1/gameserver.go +++ b/pkg/apis/stable/v1alpha1/gameserver.go @@ -22,6 +22,7 @@ import ( "github.com/mattbaird/jsonpatch" "agones.dev/agones/pkg" + "agones.dev/agones/pkg/apis" "agones.dev/agones/pkg/apis/stable" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" @@ -124,7 +125,7 @@ type GameServerSpec struct { // Health configures health checking Health Health `json:"health,omitempty"` // Scheduling strategy. Defaults to "Packed". - Scheduling SchedulingStrategy `json:"scheduling,omitempty"` + Scheduling apis.SchedulingStrategy `json:"scheduling,omitempty"` // Template describes the Pod that will be created for the GameServer Template corev1.PodTemplateSpec `json:"template"` } @@ -241,7 +242,7 @@ func (gs *GameServer) applyPortDefaults() { func (gs *GameServer) applySchedulingDefaults() { if gs.Spec.Scheduling == "" { - gs.Spec.Scheduling = Packed + gs.Spec.Scheduling = apis.Packed } } @@ -423,7 +424,7 @@ func (gs *GameServer) podObjectMeta(pod *corev1.Pod) { ref := metav1.NewControllerRef(gs, SchemeGroupVersion.WithKind("GameServer")) pod.ObjectMeta.OwnerReferences = append(pod.ObjectMeta.OwnerReferences, *ref) - if gs.Spec.Scheduling == Packed { + if gs.Spec.Scheduling == apis.Packed { // This means that the autoscaler cannot remove the Node that this Pod is on. // (and evict the Pod in the process) pod.ObjectMeta.Annotations["cluster-autoscaler.kubernetes.io/safe-to-evict"] = "false" @@ -444,7 +445,7 @@ func (gs *GameServer) podObjectMeta(pod *corev1.Pod) { // pods to a host topology. Basically doing a half decent job of packing GameServer // pods together. func (gs *GameServer) podScheduling(pod *corev1.Pod) { - if gs.Spec.Scheduling == Packed { + if gs.Spec.Scheduling == apis.Packed { if pod.Spec.Affinity == nil { pod.Spec.Affinity = &corev1.Affinity{} } diff --git a/pkg/apis/stable/v1alpha1/gameserver_test.go b/pkg/apis/stable/v1alpha1/gameserver_test.go index 10d7f4a954..070b743d4b 100644 --- a/pkg/apis/stable/v1alpha1/gameserver_test.go +++ b/pkg/apis/stable/v1alpha1/gameserver_test.go @@ -18,6 +18,7 @@ import ( "fmt" "testing" + "agones.dev/agones/pkg/apis" "agones.dev/agones/pkg/apis/stable" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" @@ -63,7 +64,7 @@ func TestGameServerApplyDefaults(t *testing.T) { state GameServerState policy PortPolicy health Health - scheduling SchedulingStrategy + scheduling apis.SchedulingStrategy } data := map[string]struct { gameServer GameServer @@ -84,7 +85,7 @@ func TestGameServerApplyDefaults(t *testing.T) { protocol: "UDP", state: GameServerStatePortAllocation, policy: Dynamic, - scheduling: Packed, + scheduling: apis.Packed, health: Health{ Disabled: false, FailureThreshold: 3, @@ -120,7 +121,7 @@ func TestGameServerApplyDefaults(t *testing.T) { protocol: "TCP", state: "TestState", policy: Static, - scheduling: Packed, + scheduling: apis.Packed, health: Health{ Disabled: false, FailureThreshold: 10, @@ -141,7 +142,7 @@ func TestGameServerApplyDefaults(t *testing.T) { protocol: "UDP", state: GameServerStateCreating, policy: Static, - scheduling: Packed, + scheduling: apis.Packed, health: Health{ Disabled: false, FailureThreshold: 3, @@ -163,7 +164,7 @@ func TestGameServerApplyDefaults(t *testing.T) { protocol: "UDP", state: GameServerStatePortAllocation, policy: Dynamic, - scheduling: Packed, + scheduling: apis.Packed, health: Health{ Disabled: true, }, @@ -189,7 +190,7 @@ func TestGameServerApplyDefaults(t *testing.T) { protocol: corev1.ProtocolTCP, state: GameServerStateCreating, policy: Static, - scheduling: Packed, + scheduling: apis.Packed, health: Health{Disabled: true}, }, }, @@ -356,7 +357,7 @@ func TestGameServerPodObjectMeta(t *testing.T) { t.Run("packed", func(t *testing.T) { gs := fixture.DeepCopy() - gs.Spec.Scheduling = Packed + gs.Spec.Scheduling = apis.Packed pod := &corev1.Pod{} gs.podObjectMeta(pod) @@ -367,7 +368,7 @@ func TestGameServerPodObjectMeta(t *testing.T) { t.Run("distributed", func(t *testing.T) { gs := fixture.DeepCopy() - gs.Spec.Scheduling = Distributed + gs.Spec.Scheduling = apis.Distributed pod := &corev1.Pod{} gs.podObjectMeta(pod) @@ -381,7 +382,7 @@ func TestGameServerPodScheduling(t *testing.T) { fixture := &corev1.Pod{Spec: corev1.PodSpec{}} t.Run("packed", func(t *testing.T) { - gs := &GameServer{Spec: GameServerSpec{Scheduling: Packed}} + gs := &GameServer{Spec: GameServerSpec{Scheduling: apis.Packed}} pod := fixture.DeepCopy() gs.podScheduling(pod) @@ -393,7 +394,7 @@ func TestGameServerPodScheduling(t *testing.T) { }) t.Run("distributed", func(t *testing.T) { - gs := &GameServer{Spec: GameServerSpec{Scheduling: Distributed}} + gs := &GameServer{Spec: GameServerSpec{Scheduling: apis.Distributed}} pod := fixture.DeepCopy() gs.podScheduling(pod) assert.Empty(t, pod.Spec.Affinity) diff --git a/pkg/apis/stable/v1alpha1/gameserverset.go b/pkg/apis/stable/v1alpha1/gameserverset.go index 51d6849272..574f8b3c11 100644 --- a/pkg/apis/stable/v1alpha1/gameserverset.go +++ b/pkg/apis/stable/v1alpha1/gameserverset.go @@ -18,6 +18,7 @@ import ( "fmt" "reflect" + "agones.dev/agones/pkg/apis" "agones.dev/agones/pkg/apis/stable" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/validation" @@ -60,7 +61,7 @@ type GameServerSetSpec struct { // Replicas are the number of GameServers that should be in this set Replicas int32 `json:"replicas"` // Scheduling strategy. Defaults to "Packed". - Scheduling SchedulingStrategy `json:"scheduling,omitempty"` + Scheduling apis.SchedulingStrategy `json:"scheduling,omitempty"` // Template the GameServer template to apply for this GameServerSet Template GameServerTemplateSpec `json:"template"` } diff --git a/pkg/apis/stable/v1alpha1/register.go b/pkg/apis/stable/v1alpha1/register.go index d62bc80465..d7a8413586 100644 --- a/pkg/apis/stable/v1alpha1/register.go +++ b/pkg/apis/stable/v1alpha1/register.go @@ -58,8 +58,6 @@ func addKnownTypes(scheme *k8sruntime.Scheme) error { &FleetList{}, &FleetAllocation{}, &FleetAllocationList{}, - &GameServerAllocation{}, - &GameServerAllocationList{}, &FleetAutoscaler{}, &FleetAutoscalerList{}, ) diff --git a/pkg/apis/stable/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/stable/v1alpha1/zz_generated.deepcopy.go index 4fc56d4bc4..afab19b497 100644 --- a/pkg/apis/stable/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/stable/v1alpha1/zz_generated.deepcopy.go @@ -22,7 +22,6 @@ package v1alpha1 import ( v1beta1 "k8s.io/api/admissionregistration/v1beta1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -472,113 +471,6 @@ func (in *GameServer) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GameServerAllocation) DeepCopyInto(out *GameServerAllocation) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServerAllocation. -func (in *GameServerAllocation) DeepCopy() *GameServerAllocation { - if in == nil { - return nil - } - out := new(GameServerAllocation) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GameServerAllocation) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GameServerAllocationList) DeepCopyInto(out *GameServerAllocationList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]GameServerAllocation, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServerAllocationList. -func (in *GameServerAllocationList) DeepCopy() *GameServerAllocationList { - if in == nil { - return nil - } - out := new(GameServerAllocationList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *GameServerAllocationList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GameServerAllocationSpec) DeepCopyInto(out *GameServerAllocationSpec) { - *out = *in - in.Required.DeepCopyInto(&out.Required) - if in.Preferred != nil { - in, out := &in.Preferred, &out.Preferred - *out = make([]v1.LabelSelector, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - in.MetaPatch.DeepCopyInto(&out.MetaPatch) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServerAllocationSpec. -func (in *GameServerAllocationSpec) DeepCopy() *GameServerAllocationSpec { - if in == nil { - return nil - } - out := new(GameServerAllocationSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GameServerAllocationStatus) DeepCopyInto(out *GameServerAllocationStatus) { - *out = *in - if in.Ports != nil { - in, out := &in.Ports, &out.Ports - *out = make([]GameServerStatusPort, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServerAllocationStatus. -func (in *GameServerAllocationStatus) DeepCopy() *GameServerAllocationStatus { - if in == nil { - return nil - } - out := new(GameServerAllocationStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GameServerList) DeepCopyInto(out *GameServerList) { *out = *in diff --git a/pkg/client/clientset/versioned/clientset.go b/pkg/client/clientset/versioned/clientset.go index b0397438b1..44a8b52212 100644 --- a/pkg/client/clientset/versioned/clientset.go +++ b/pkg/client/clientset/versioned/clientset.go @@ -19,6 +19,7 @@ package versioned import ( + allocationv1alpha1 "agones.dev/agones/pkg/client/clientset/versioned/typed/allocation/v1alpha1" stablev1alpha1 "agones.dev/agones/pkg/client/clientset/versioned/typed/stable/v1alpha1" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" @@ -27,6 +28,9 @@ import ( type Interface interface { Discovery() discovery.DiscoveryInterface + AllocationV1alpha1() allocationv1alpha1.AllocationV1alpha1Interface + // Deprecated: please explicitly pick a version if possible. + Allocation() allocationv1alpha1.AllocationV1alpha1Interface StableV1alpha1() stablev1alpha1.StableV1alpha1Interface // Deprecated: please explicitly pick a version if possible. Stable() stablev1alpha1.StableV1alpha1Interface @@ -36,7 +40,19 @@ type Interface interface { // version included in a Clientset. type Clientset struct { *discovery.DiscoveryClient - stableV1alpha1 *stablev1alpha1.StableV1alpha1Client + allocationV1alpha1 *allocationv1alpha1.AllocationV1alpha1Client + stableV1alpha1 *stablev1alpha1.StableV1alpha1Client +} + +// AllocationV1alpha1 retrieves the AllocationV1alpha1Client +func (c *Clientset) AllocationV1alpha1() allocationv1alpha1.AllocationV1alpha1Interface { + return c.allocationV1alpha1 +} + +// Deprecated: Allocation retrieves the default version of AllocationClient. +// Please explicitly pick a version. +func (c *Clientset) Allocation() allocationv1alpha1.AllocationV1alpha1Interface { + return c.allocationV1alpha1 } // StableV1alpha1 retrieves the StableV1alpha1Client @@ -66,6 +82,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { } var cs Clientset var err error + cs.allocationV1alpha1, err = allocationv1alpha1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } cs.stableV1alpha1, err = stablev1alpha1.NewForConfig(&configShallowCopy) if err != nil { return nil, err @@ -82,6 +102,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { // panics if there is an error in the config. func NewForConfigOrDie(c *rest.Config) *Clientset { var cs Clientset + cs.allocationV1alpha1 = allocationv1alpha1.NewForConfigOrDie(c) cs.stableV1alpha1 = stablev1alpha1.NewForConfigOrDie(c) cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) @@ -91,6 +112,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset { // New creates a new Clientset for the given RESTClient. func New(c rest.Interface) *Clientset { var cs Clientset + cs.allocationV1alpha1 = allocationv1alpha1.New(c) cs.stableV1alpha1 = stablev1alpha1.New(c) cs.DiscoveryClient = discovery.NewDiscoveryClient(c) diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index d48e8c7d16..ff65cedadc 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -20,6 +20,8 @@ package fake import ( clientset "agones.dev/agones/pkg/client/clientset/versioned" + allocationv1alpha1 "agones.dev/agones/pkg/client/clientset/versioned/typed/allocation/v1alpha1" + fakeallocationv1alpha1 "agones.dev/agones/pkg/client/clientset/versioned/typed/allocation/v1alpha1/fake" stablev1alpha1 "agones.dev/agones/pkg/client/clientset/versioned/typed/stable/v1alpha1" fakestablev1alpha1 "agones.dev/agones/pkg/client/clientset/versioned/typed/stable/v1alpha1/fake" "k8s.io/apimachinery/pkg/runtime" @@ -71,6 +73,16 @@ func (c *Clientset) Discovery() discovery.DiscoveryInterface { var _ clientset.Interface = &Clientset{} +// AllocationV1alpha1 retrieves the AllocationV1alpha1Client +func (c *Clientset) AllocationV1alpha1() allocationv1alpha1.AllocationV1alpha1Interface { + return &fakeallocationv1alpha1.FakeAllocationV1alpha1{Fake: &c.Fake} +} + +// Allocation retrieves the AllocationV1alpha1Client +func (c *Clientset) Allocation() allocationv1alpha1.AllocationV1alpha1Interface { + return &fakeallocationv1alpha1.FakeAllocationV1alpha1{Fake: &c.Fake} +} + // StableV1alpha1 retrieves the StableV1alpha1Client func (c *Clientset) StableV1alpha1() stablev1alpha1.StableV1alpha1Interface { return &fakestablev1alpha1.FakeStableV1alpha1{Fake: &c.Fake} diff --git a/pkg/client/clientset/versioned/fake/register.go b/pkg/client/clientset/versioned/fake/register.go index 695d559aac..57c571c61a 100644 --- a/pkg/client/clientset/versioned/fake/register.go +++ b/pkg/client/clientset/versioned/fake/register.go @@ -19,6 +19,7 @@ package fake import ( + allocationv1alpha1 "agones.dev/agones/pkg/apis/allocation/v1alpha1" stablev1alpha1 "agones.dev/agones/pkg/apis/stable/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" @@ -50,5 +51,6 @@ func init() { // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types // correctly. func AddToScheme(scheme *runtime.Scheme) { + allocationv1alpha1.AddToScheme(scheme) stablev1alpha1.AddToScheme(scheme) } diff --git a/pkg/client/clientset/versioned/scheme/register.go b/pkg/client/clientset/versioned/scheme/register.go index a6787f978f..9dbe79c8bb 100644 --- a/pkg/client/clientset/versioned/scheme/register.go +++ b/pkg/client/clientset/versioned/scheme/register.go @@ -19,6 +19,7 @@ package scheme import ( + allocationv1alpha1 "agones.dev/agones/pkg/apis/allocation/v1alpha1" stablev1alpha1 "agones.dev/agones/pkg/apis/stable/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" @@ -50,5 +51,6 @@ func init() { // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types // correctly. func AddToScheme(scheme *runtime.Scheme) { + allocationv1alpha1.AddToScheme(scheme) stablev1alpha1.AddToScheme(scheme) } diff --git a/pkg/client/clientset/versioned/typed/allocation/v1alpha1/allocation_client.go b/pkg/client/clientset/versioned/typed/allocation/v1alpha1/allocation_client.go new file mode 100644 index 0000000000..5264d6ae30 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/allocation/v1alpha1/allocation_client.go @@ -0,0 +1,90 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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. + +// This code was autogenerated. Do not edit directly. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "agones.dev/agones/pkg/apis/allocation/v1alpha1" + "agones.dev/agones/pkg/client/clientset/versioned/scheme" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + rest "k8s.io/client-go/rest" +) + +type AllocationV1alpha1Interface interface { + RESTClient() rest.Interface + GameServerAllocationsGetter +} + +// AllocationV1alpha1Client is used to interact with features provided by the allocation.agones.dev group. +type AllocationV1alpha1Client struct { + restClient rest.Interface +} + +func (c *AllocationV1alpha1Client) GameServerAllocations(namespace string) GameServerAllocationInterface { + return newGameServerAllocations(c, namespace) +} + +// NewForConfig creates a new AllocationV1alpha1Client for the given config. +func NewForConfig(c *rest.Config) (*AllocationV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &AllocationV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new AllocationV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *AllocationV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new AllocationV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *AllocationV1alpha1Client { + return &AllocationV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *AllocationV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/client/clientset/versioned/typed/allocation/v1alpha1/doc.go b/pkg/client/clientset/versioned/typed/allocation/v1alpha1/doc.go new file mode 100644 index 0000000000..b9cc0b0c24 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/allocation/v1alpha1/doc.go @@ -0,0 +1,20 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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. + +// This code was autogenerated. Do not edit directly. + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/pkg/client/clientset/versioned/typed/allocation/v1alpha1/fake/doc.go b/pkg/client/clientset/versioned/typed/allocation/v1alpha1/fake/doc.go new file mode 100644 index 0000000000..8b0bb0a971 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/allocation/v1alpha1/fake/doc.go @@ -0,0 +1,20 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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. + +// This code was autogenerated. Do not edit directly. + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/pkg/client/clientset/versioned/typed/allocation/v1alpha1/fake/fake_allocation_client.go b/pkg/client/clientset/versioned/typed/allocation/v1alpha1/fake/fake_allocation_client.go new file mode 100644 index 0000000000..112d6b6991 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/allocation/v1alpha1/fake/fake_allocation_client.go @@ -0,0 +1,40 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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. + +// This code was autogenerated. Do not edit directly. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "agones.dev/agones/pkg/client/clientset/versioned/typed/allocation/v1alpha1" + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeAllocationV1alpha1 struct { + *testing.Fake +} + +func (c *FakeAllocationV1alpha1) GameServerAllocations(namespace string) v1alpha1.GameServerAllocationInterface { + return &FakeGameServerAllocations{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeAllocationV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/client/clientset/versioned/typed/allocation/v1alpha1/fake/fake_gameserverallocation.go b/pkg/client/clientset/versioned/typed/allocation/v1alpha1/fake/fake_gameserverallocation.go new file mode 100644 index 0000000000..418c0e5efc --- /dev/null +++ b/pkg/client/clientset/versioned/typed/allocation/v1alpha1/fake/fake_gameserverallocation.go @@ -0,0 +1,46 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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. + +// This code was autogenerated. Do not edit directly. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "agones.dev/agones/pkg/apis/allocation/v1alpha1" + schema "k8s.io/apimachinery/pkg/runtime/schema" + testing "k8s.io/client-go/testing" +) + +// FakeGameServerAllocations implements GameServerAllocationInterface +type FakeGameServerAllocations struct { + Fake *FakeAllocationV1alpha1 + ns string +} + +var gameserverallocationsResource = schema.GroupVersionResource{Group: "allocation.agones.dev", Version: "v1alpha1", Resource: "gameserverallocations"} + +var gameserverallocationsKind = schema.GroupVersionKind{Group: "allocation.agones.dev", Version: "v1alpha1", Kind: "GameServerAllocation"} + +// Create takes the representation of a gameServerAllocation and creates it. Returns the server's representation of the gameServerAllocation, and an error, if there is any. +func (c *FakeGameServerAllocations) Create(gameServerAllocation *v1alpha1.GameServerAllocation) (result *v1alpha1.GameServerAllocation, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(gameserverallocationsResource, c.ns, gameServerAllocation), &v1alpha1.GameServerAllocation{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.GameServerAllocation), err +} diff --git a/pkg/client/clientset/versioned/typed/allocation/v1alpha1/gameserverallocation.go b/pkg/client/clientset/versioned/typed/allocation/v1alpha1/gameserverallocation.go new file mode 100644 index 0000000000..6da5e20a7d --- /dev/null +++ b/pkg/client/clientset/versioned/typed/allocation/v1alpha1/gameserverallocation.go @@ -0,0 +1,62 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// 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. + +// This code was autogenerated. Do not edit directly. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "agones.dev/agones/pkg/apis/allocation/v1alpha1" + rest "k8s.io/client-go/rest" +) + +// GameServerAllocationsGetter has a method to return a GameServerAllocationInterface. +// A group's client should implement this interface. +type GameServerAllocationsGetter interface { + GameServerAllocations(namespace string) GameServerAllocationInterface +} + +// GameServerAllocationInterface has methods to work with GameServerAllocation resources. +type GameServerAllocationInterface interface { + Create(*v1alpha1.GameServerAllocation) (*v1alpha1.GameServerAllocation, error) + GameServerAllocationExpansion +} + +// gameServerAllocations implements GameServerAllocationInterface +type gameServerAllocations struct { + client rest.Interface + ns string +} + +// newGameServerAllocations returns a GameServerAllocations +func newGameServerAllocations(c *AllocationV1alpha1Client, namespace string) *gameServerAllocations { + return &gameServerAllocations{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Create takes the representation of a gameServerAllocation and creates it. Returns the server's representation of the gameServerAllocation, and an error, if there is any. +func (c *gameServerAllocations) Create(gameServerAllocation *v1alpha1.GameServerAllocation) (result *v1alpha1.GameServerAllocation, err error) { + result = &v1alpha1.GameServerAllocation{} + err = c.client.Post(). + Namespace(c.ns). + Resource("gameserverallocations"). + Body(gameServerAllocation). + Do(). + Into(result) + return +} diff --git a/pkg/client/doc.go b/pkg/client/clientset/versioned/typed/allocation/v1alpha1/generated_expansion.go similarity index 78% rename from pkg/client/doc.go rename to pkg/client/clientset/versioned/typed/allocation/v1alpha1/generated_expansion.go index 19a5c9fecc..be9fb30aa1 100644 --- a/pkg/client/doc.go +++ b/pkg/client/clientset/versioned/typed/allocation/v1alpha1/generated_expansion.go @@ -12,5 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package client contains the generated client for the Custom Resource Definitions -package client +// This code was autogenerated. Do not edit directly. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +type GameServerAllocationExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/stable/v1alpha1/fake/fake_gameserverallocation.go b/pkg/client/clientset/versioned/typed/stable/v1alpha1/fake/fake_gameserverallocation.go deleted file mode 100644 index 35ff1d196c..0000000000 --- a/pkg/client/clientset/versioned/typed/stable/v1alpha1/fake/fake_gameserverallocation.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2018 Google Inc. All Rights Reserved. -// -// 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. - -// This code was autogenerated. Do not edit directly. - -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - v1alpha1 "agones.dev/agones/pkg/apis/stable/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - schema "k8s.io/apimachinery/pkg/runtime/schema" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - testing "k8s.io/client-go/testing" -) - -// FakeGameServerAllocations implements GameServerAllocationInterface -type FakeGameServerAllocations struct { - Fake *FakeStableV1alpha1 - ns string -} - -var gameserverallocationsResource = schema.GroupVersionResource{Group: "stable.agones.dev", Version: "v1alpha1", Resource: "gameserverallocations"} - -var gameserverallocationsKind = schema.GroupVersionKind{Group: "stable.agones.dev", Version: "v1alpha1", Kind: "GameServerAllocation"} - -// Get takes name of the gameServerAllocation, and returns the corresponding gameServerAllocation object, and an error if there is any. -func (c *FakeGameServerAllocations) Get(name string, options v1.GetOptions) (result *v1alpha1.GameServerAllocation, err error) { - obj, err := c.Fake. - Invokes(testing.NewGetAction(gameserverallocationsResource, c.ns, name), &v1alpha1.GameServerAllocation{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.GameServerAllocation), err -} - -// List takes label and field selectors, and returns the list of GameServerAllocations that match those selectors. -func (c *FakeGameServerAllocations) List(opts v1.ListOptions) (result *v1alpha1.GameServerAllocationList, err error) { - obj, err := c.Fake. - Invokes(testing.NewListAction(gameserverallocationsResource, gameserverallocationsKind, c.ns, opts), &v1alpha1.GameServerAllocationList{}) - - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &v1alpha1.GameServerAllocationList{ListMeta: obj.(*v1alpha1.GameServerAllocationList).ListMeta} - for _, item := range obj.(*v1alpha1.GameServerAllocationList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Watch returns a watch.Interface that watches the requested gameServerAllocations. -func (c *FakeGameServerAllocations) Watch(opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewWatchAction(gameserverallocationsResource, c.ns, opts)) - -} - -// Create takes the representation of a gameServerAllocation and creates it. Returns the server's representation of the gameServerAllocation, and an error, if there is any. -func (c *FakeGameServerAllocations) Create(gameServerAllocation *v1alpha1.GameServerAllocation) (result *v1alpha1.GameServerAllocation, err error) { - obj, err := c.Fake. - Invokes(testing.NewCreateAction(gameserverallocationsResource, c.ns, gameServerAllocation), &v1alpha1.GameServerAllocation{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.GameServerAllocation), err -} - -// Update takes the representation of a gameServerAllocation and updates it. Returns the server's representation of the gameServerAllocation, and an error, if there is any. -func (c *FakeGameServerAllocations) Update(gameServerAllocation *v1alpha1.GameServerAllocation) (result *v1alpha1.GameServerAllocation, err error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateAction(gameserverallocationsResource, c.ns, gameServerAllocation), &v1alpha1.GameServerAllocation{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.GameServerAllocation), err -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *FakeGameServerAllocations) UpdateStatus(gameServerAllocation *v1alpha1.GameServerAllocation) (*v1alpha1.GameServerAllocation, error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(gameserverallocationsResource, "status", c.ns, gameServerAllocation), &v1alpha1.GameServerAllocation{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.GameServerAllocation), err -} - -// Delete takes name of the gameServerAllocation and deletes it. Returns an error if one occurs. -func (c *FakeGameServerAllocations) Delete(name string, options *v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteAction(gameserverallocationsResource, c.ns, name), &v1alpha1.GameServerAllocation{}) - - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeGameServerAllocations) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(gameserverallocationsResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &v1alpha1.GameServerAllocationList{}) - return err -} - -// Patch applies the patch and returns the patched gameServerAllocation. -func (c *FakeGameServerAllocations) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.GameServerAllocation, err error) { - obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(gameserverallocationsResource, c.ns, name, data, subresources...), &v1alpha1.GameServerAllocation{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.GameServerAllocation), err -} diff --git a/pkg/client/clientset/versioned/typed/stable/v1alpha1/fake/fake_stable_client.go b/pkg/client/clientset/versioned/typed/stable/v1alpha1/fake/fake_stable_client.go index ccdc6198b2..bb29000b2e 100644 --- a/pkg/client/clientset/versioned/typed/stable/v1alpha1/fake/fake_stable_client.go +++ b/pkg/client/clientset/versioned/typed/stable/v1alpha1/fake/fake_stable_client.go @@ -44,10 +44,6 @@ func (c *FakeStableV1alpha1) GameServers(namespace string) v1alpha1.GameServerIn return &FakeGameServers{c, namespace} } -func (c *FakeStableV1alpha1) GameServerAllocations(namespace string) v1alpha1.GameServerAllocationInterface { - return &FakeGameServerAllocations{c, namespace} -} - func (c *FakeStableV1alpha1) GameServerSets(namespace string) v1alpha1.GameServerSetInterface { return &FakeGameServerSets{c, namespace} } diff --git a/pkg/client/clientset/versioned/typed/stable/v1alpha1/gameserverallocation.go b/pkg/client/clientset/versioned/typed/stable/v1alpha1/gameserverallocation.go deleted file mode 100644 index e2c7829706..0000000000 --- a/pkg/client/clientset/versioned/typed/stable/v1alpha1/gameserverallocation.go +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2018 Google Inc. All Rights Reserved. -// -// 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. - -// This code was autogenerated. Do not edit directly. - -// Code generated by client-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - v1alpha1 "agones.dev/agones/pkg/apis/stable/v1alpha1" - scheme "agones.dev/agones/pkg/client/clientset/versioned/scheme" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" -) - -// GameServerAllocationsGetter has a method to return a GameServerAllocationInterface. -// A group's client should implement this interface. -type GameServerAllocationsGetter interface { - GameServerAllocations(namespace string) GameServerAllocationInterface -} - -// GameServerAllocationInterface has methods to work with GameServerAllocation resources. -type GameServerAllocationInterface interface { - Create(*v1alpha1.GameServerAllocation) (*v1alpha1.GameServerAllocation, error) - Update(*v1alpha1.GameServerAllocation) (*v1alpha1.GameServerAllocation, error) - UpdateStatus(*v1alpha1.GameServerAllocation) (*v1alpha1.GameServerAllocation, error) - Delete(name string, options *v1.DeleteOptions) error - DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error - Get(name string, options v1.GetOptions) (*v1alpha1.GameServerAllocation, error) - List(opts v1.ListOptions) (*v1alpha1.GameServerAllocationList, error) - Watch(opts v1.ListOptions) (watch.Interface, error) - Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.GameServerAllocation, err error) - GameServerAllocationExpansion -} - -// gameServerAllocations implements GameServerAllocationInterface -type gameServerAllocations struct { - client rest.Interface - ns string -} - -// newGameServerAllocations returns a GameServerAllocations -func newGameServerAllocations(c *StableV1alpha1Client, namespace string) *gameServerAllocations { - return &gameServerAllocations{ - client: c.RESTClient(), - ns: namespace, - } -} - -// Get takes name of the gameServerAllocation, and returns the corresponding gameServerAllocation object, and an error if there is any. -func (c *gameServerAllocations) Get(name string, options v1.GetOptions) (result *v1alpha1.GameServerAllocation, err error) { - result = &v1alpha1.GameServerAllocation{} - err = c.client.Get(). - Namespace(c.ns). - Resource("gameserverallocations"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of GameServerAllocations that match those selectors. -func (c *gameServerAllocations) List(opts v1.ListOptions) (result *v1alpha1.GameServerAllocationList, err error) { - result = &v1alpha1.GameServerAllocationList{} - err = c.client.Get(). - Namespace(c.ns). - Resource("gameserverallocations"). - VersionedParams(&opts, scheme.ParameterCodec). - Do(). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested gameServerAllocations. -func (c *gameServerAllocations) Watch(opts v1.ListOptions) (watch.Interface, error) { - opts.Watch = true - return c.client.Get(). - Namespace(c.ns). - Resource("gameserverallocations"). - VersionedParams(&opts, scheme.ParameterCodec). - Watch() -} - -// Create takes the representation of a gameServerAllocation and creates it. Returns the server's representation of the gameServerAllocation, and an error, if there is any. -func (c *gameServerAllocations) Create(gameServerAllocation *v1alpha1.GameServerAllocation) (result *v1alpha1.GameServerAllocation, err error) { - result = &v1alpha1.GameServerAllocation{} - err = c.client.Post(). - Namespace(c.ns). - Resource("gameserverallocations"). - Body(gameServerAllocation). - Do(). - Into(result) - return -} - -// Update takes the representation of a gameServerAllocation and updates it. Returns the server's representation of the gameServerAllocation, and an error, if there is any. -func (c *gameServerAllocations) Update(gameServerAllocation *v1alpha1.GameServerAllocation) (result *v1alpha1.GameServerAllocation, err error) { - result = &v1alpha1.GameServerAllocation{} - err = c.client.Put(). - Namespace(c.ns). - Resource("gameserverallocations"). - Name(gameServerAllocation.Name). - Body(gameServerAllocation). - Do(). - Into(result) - return -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). - -func (c *gameServerAllocations) UpdateStatus(gameServerAllocation *v1alpha1.GameServerAllocation) (result *v1alpha1.GameServerAllocation, err error) { - result = &v1alpha1.GameServerAllocation{} - err = c.client.Put(). - Namespace(c.ns). - Resource("gameserverallocations"). - Name(gameServerAllocation.Name). - SubResource("status"). - Body(gameServerAllocation). - Do(). - Into(result) - return -} - -// Delete takes name of the gameServerAllocation and deletes it. Returns an error if one occurs. -func (c *gameServerAllocations) Delete(name string, options *v1.DeleteOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("gameserverallocations"). - Name(name). - Body(options). - Do(). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *gameServerAllocations) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("gameserverallocations"). - VersionedParams(&listOptions, scheme.ParameterCodec). - Body(options). - Do(). - Error() -} - -// Patch applies the patch and returns the patched gameServerAllocation. -func (c *gameServerAllocations) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.GameServerAllocation, err error) { - result = &v1alpha1.GameServerAllocation{} - err = c.client.Patch(pt). - Namespace(c.ns). - Resource("gameserverallocations"). - SubResource(subresources...). - Name(name). - Body(data). - Do(). - Into(result) - return -} diff --git a/pkg/client/clientset/versioned/typed/stable/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/stable/v1alpha1/generated_expansion.go index 35eee70af9..7ff564b1fb 100644 --- a/pkg/client/clientset/versioned/typed/stable/v1alpha1/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/stable/v1alpha1/generated_expansion.go @@ -26,6 +26,4 @@ type FleetAutoscalerExpansion interface{} type GameServerExpansion interface{} -type GameServerAllocationExpansion interface{} - type GameServerSetExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/stable/v1alpha1/stable_client.go b/pkg/client/clientset/versioned/typed/stable/v1alpha1/stable_client.go index 5890d9d272..c932ad05aa 100644 --- a/pkg/client/clientset/versioned/typed/stable/v1alpha1/stable_client.go +++ b/pkg/client/clientset/versioned/typed/stable/v1alpha1/stable_client.go @@ -31,7 +31,6 @@ type StableV1alpha1Interface interface { FleetAllocationsGetter FleetAutoscalersGetter GameServersGetter - GameServerAllocationsGetter GameServerSetsGetter } @@ -56,10 +55,6 @@ func (c *StableV1alpha1Client) GameServers(namespace string) GameServerInterface return newGameServers(c, namespace) } -func (c *StableV1alpha1Client) GameServerAllocations(namespace string) GameServerAllocationInterface { - return newGameServerAllocations(c, namespace) -} - func (c *StableV1alpha1Client) GameServerSets(namespace string) GameServerSetInterface { return newGameServerSets(c, namespace) } diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index 88a03f5ec6..156c689c3f 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -61,8 +61,6 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Stable().V1alpha1().FleetAutoscalers().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("gameservers"): return &genericInformer{resource: resource.GroupResource(), informer: f.Stable().V1alpha1().GameServers().Informer()}, nil - case v1alpha1.SchemeGroupVersion.WithResource("gameserverallocations"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Stable().V1alpha1().GameServerAllocations().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("gameserversets"): return &genericInformer{resource: resource.GroupResource(), informer: f.Stable().V1alpha1().GameServerSets().Informer()}, nil diff --git a/pkg/client/informers/externalversions/stable/v1alpha1/gameserverallocation.go b/pkg/client/informers/externalversions/stable/v1alpha1/gameserverallocation.go deleted file mode 100644 index ab6abccb47..0000000000 --- a/pkg/client/informers/externalversions/stable/v1alpha1/gameserverallocation.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2018 Google Inc. All Rights Reserved. -// -// 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. - -// This code was autogenerated. Do not edit directly. - -// Code generated by informer-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - time "time" - - stable_v1alpha1 "agones.dev/agones/pkg/apis/stable/v1alpha1" - versioned "agones.dev/agones/pkg/client/clientset/versioned" - internalinterfaces "agones.dev/agones/pkg/client/informers/externalversions/internalinterfaces" - v1alpha1 "agones.dev/agones/pkg/client/listers/stable/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - watch "k8s.io/apimachinery/pkg/watch" - cache "k8s.io/client-go/tools/cache" -) - -// GameServerAllocationInformer provides access to a shared informer and lister for -// GameServerAllocations. -type GameServerAllocationInformer interface { - Informer() cache.SharedIndexInformer - Lister() v1alpha1.GameServerAllocationLister -} - -type gameServerAllocationInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc - namespace string -} - -// NewGameServerAllocationInformer constructs a new informer for GameServerAllocation type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewGameServerAllocationInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredGameServerAllocationInformer(client, namespace, resyncPeriod, indexers, nil) -} - -// NewFilteredGameServerAllocationInformer constructs a new informer for GameServerAllocation type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewFilteredGameServerAllocationInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: func(options v1.ListOptions) (runtime.Object, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.StableV1alpha1().GameServerAllocations(namespace).List(options) - }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.StableV1alpha1().GameServerAllocations(namespace).Watch(options) - }, - }, - &stable_v1alpha1.GameServerAllocation{}, - resyncPeriod, - indexers, - ) -} - -func (f *gameServerAllocationInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredGameServerAllocationInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) -} - -func (f *gameServerAllocationInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&stable_v1alpha1.GameServerAllocation{}, f.defaultInformer) -} - -func (f *gameServerAllocationInformer) Lister() v1alpha1.GameServerAllocationLister { - return v1alpha1.NewGameServerAllocationLister(f.Informer().GetIndexer()) -} diff --git a/pkg/client/informers/externalversions/stable/v1alpha1/interface.go b/pkg/client/informers/externalversions/stable/v1alpha1/interface.go index 47e9a60e9b..a964b2d168 100644 --- a/pkg/client/informers/externalversions/stable/v1alpha1/interface.go +++ b/pkg/client/informers/externalversions/stable/v1alpha1/interface.go @@ -32,8 +32,6 @@ type Interface interface { FleetAutoscalers() FleetAutoscalerInformer // GameServers returns a GameServerInformer. GameServers() GameServerInformer - // GameServerAllocations returns a GameServerAllocationInformer. - GameServerAllocations() GameServerAllocationInformer // GameServerSets returns a GameServerSetInformer. GameServerSets() GameServerSetInformer } @@ -69,11 +67,6 @@ func (v *version) GameServers() GameServerInformer { return &gameServerInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } -// GameServerAllocations returns a GameServerAllocationInformer. -func (v *version) GameServerAllocations() GameServerAllocationInformer { - return &gameServerAllocationInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} -} - // GameServerSets returns a GameServerSetInformer. func (v *version) GameServerSets() GameServerSetInformer { return &gameServerSetInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/client/listers/stable/v1alpha1/expansion_generated.go b/pkg/client/listers/stable/v1alpha1/expansion_generated.go index e32fde5caa..2d5bfb8800 100644 --- a/pkg/client/listers/stable/v1alpha1/expansion_generated.go +++ b/pkg/client/listers/stable/v1alpha1/expansion_generated.go @@ -50,14 +50,6 @@ type GameServerListerExpansion interface{} // GameServerNamespaceLister. type GameServerNamespaceListerExpansion interface{} -// GameServerAllocationListerExpansion allows custom methods to be added to -// GameServerAllocationLister. -type GameServerAllocationListerExpansion interface{} - -// GameServerAllocationNamespaceListerExpansion allows custom methods to be added to -// GameServerAllocationNamespaceLister. -type GameServerAllocationNamespaceListerExpansion interface{} - // GameServerSetListerExpansion allows custom methods to be added to // GameServerSetLister. type GameServerSetListerExpansion interface{} diff --git a/pkg/client/listers/stable/v1alpha1/gameserverallocation.go b/pkg/client/listers/stable/v1alpha1/gameserverallocation.go deleted file mode 100644 index 9f7fa96dae..0000000000 --- a/pkg/client/listers/stable/v1alpha1/gameserverallocation.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2018 Google Inc. All Rights Reserved. -// -// 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. - -// This code was autogenerated. Do not edit directly. - -// Code generated by lister-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - v1alpha1 "agones.dev/agones/pkg/apis/stable/v1alpha1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" -) - -// GameServerAllocationLister helps list GameServerAllocations. -type GameServerAllocationLister interface { - // List lists all GameServerAllocations in the indexer. - List(selector labels.Selector) (ret []*v1alpha1.GameServerAllocation, err error) - // GameServerAllocations returns an object that can list and get GameServerAllocations. - GameServerAllocations(namespace string) GameServerAllocationNamespaceLister - GameServerAllocationListerExpansion -} - -// gameServerAllocationLister implements the GameServerAllocationLister interface. -type gameServerAllocationLister struct { - indexer cache.Indexer -} - -// NewGameServerAllocationLister returns a new GameServerAllocationLister. -func NewGameServerAllocationLister(indexer cache.Indexer) GameServerAllocationLister { - return &gameServerAllocationLister{indexer: indexer} -} - -// List lists all GameServerAllocations in the indexer. -func (s *gameServerAllocationLister) List(selector labels.Selector) (ret []*v1alpha1.GameServerAllocation, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.GameServerAllocation)) - }) - return ret, err -} - -// GameServerAllocations returns an object that can list and get GameServerAllocations. -func (s *gameServerAllocationLister) GameServerAllocations(namespace string) GameServerAllocationNamespaceLister { - return gameServerAllocationNamespaceLister{indexer: s.indexer, namespace: namespace} -} - -// GameServerAllocationNamespaceLister helps list and get GameServerAllocations. -type GameServerAllocationNamespaceLister interface { - // List lists all GameServerAllocations in the indexer for a given namespace. - List(selector labels.Selector) (ret []*v1alpha1.GameServerAllocation, err error) - // Get retrieves the GameServerAllocation from the indexer for a given namespace and name. - Get(name string) (*v1alpha1.GameServerAllocation, error) - GameServerAllocationNamespaceListerExpansion -} - -// gameServerAllocationNamespaceLister implements the GameServerAllocationNamespaceLister -// interface. -type gameServerAllocationNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all GameServerAllocations in the indexer for a given namespace. -func (s gameServerAllocationNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.GameServerAllocation, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.GameServerAllocation)) - }) - return ret, err -} - -// Get retrieves the GameServerAllocation from the indexer for a given namespace and name. -func (s gameServerAllocationNamespaceLister) Get(name string) (*v1alpha1.GameServerAllocation, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1alpha1.Resource("gameserverallocation"), name) - } - return obj.(*v1alpha1.GameServerAllocation), nil -} diff --git a/pkg/fleetallocation/controller.go b/pkg/fleetallocation/controller.go index f6ddcfde2f..f69f45b4b8 100644 --- a/pkg/fleetallocation/controller.go +++ b/pkg/fleetallocation/controller.go @@ -19,6 +19,7 @@ import ( "fmt" "sync" + "agones.dev/agones/pkg/apis" "agones.dev/agones/pkg/apis/stable" "agones.dev/agones/pkg/apis/stable/v1alpha1" "agones.dev/agones/pkg/client/clientset/versioned" @@ -274,9 +275,9 @@ func (c *Controller) allocate(f *v1alpha1.Fleet, fam *v1alpha1.MetaPatch) (*v1al } switch f.Spec.Scheduling { - case v1alpha1.Packed: + case apis.Packed: allocation = findReadyGameServerForAllocation(gsList, packedComparator) - case v1alpha1.Distributed: + case apis.Distributed: allocation = findReadyGameServerForAllocation(gsList, distributedComparator) } diff --git a/pkg/fleetallocation/controller_test.go b/pkg/fleetallocation/controller_test.go index a34d6c73b1..19572e6f61 100644 --- a/pkg/fleetallocation/controller_test.go +++ b/pkg/fleetallocation/controller_test.go @@ -22,6 +22,7 @@ import ( "sync" "testing" + "agones.dev/agones/pkg/apis" "agones.dev/agones/pkg/apis/stable/v1alpha1" agtesting "agones.dev/agones/pkg/testing" "agones.dev/agones/pkg/util/webhooks" @@ -285,7 +286,7 @@ func TestControllerAllocatePriority(t *testing.T) { run(t, "distributed", func(t *testing.T, c *Controller, f *v1alpha1.Fleet) { // make a copy, to avoid the race check f = f.DeepCopy() - f.Spec.Scheduling = v1alpha1.Distributed + f.Spec.Scheduling = apis.Distributed // should go node2, then node1 gs, err := c.allocate(f, nil) assert.Nil(t, err) diff --git a/pkg/fleets/controller_test.go b/pkg/fleets/controller_test.go index 78a70d86c2..4d12ff1ccf 100644 --- a/pkg/fleets/controller_test.go +++ b/pkg/fleets/controller_test.go @@ -21,6 +21,7 @@ import ( "testing" "time" + "agones.dev/agones/pkg/apis" "agones.dev/agones/pkg/apis/stable/v1alpha1" agtesting "agones.dev/agones/pkg/testing" "agones.dev/agones/pkg/util/webhooks" @@ -152,7 +153,7 @@ func TestControllerSyncFleet(t *testing.T) { gsSet.ObjectMeta.Name = "gsSet1" gsSet.ObjectMeta.UID = "1234" gsSet.Spec.Replicas = f.Spec.Replicas - gsSet.Spec.Scheduling = v1alpha1.Distributed + gsSet.Spec.Scheduling = apis.Distributed updated := false m.AgonesClient.AddReactor("list", "fleets", func(action k8stesting.Action) (bool, runtime.Object, error) { @@ -794,7 +795,7 @@ func defaultFixture() *v1alpha1.Fleet { }, Spec: v1alpha1.FleetSpec{ Replicas: 5, - Scheduling: v1alpha1.Packed, + Scheduling: apis.Packed, Template: v1alpha1.GameServerTemplateSpec{}, }, } diff --git a/pkg/gameserverallocations/controller.go b/pkg/gameserverallocations/controller.go index 48e641689f..e419556513 100644 --- a/pkg/gameserverallocations/controller.go +++ b/pkg/gameserverallocations/controller.go @@ -15,34 +15,37 @@ package gameserverallocations import ( - "encoding/json" + "fmt" + "io/ioutil" "math/rand" + "net/http" "strconv" "sync" "time" + "agones.dev/agones/pkg/apis" + "agones.dev/agones/pkg/apis/allocation/v1alpha1" "agones.dev/agones/pkg/apis/stable" - "agones.dev/agones/pkg/apis/stable/v1alpha1" + stablev1alpha1 "agones.dev/agones/pkg/apis/stable/v1alpha1" "agones.dev/agones/pkg/client/clientset/versioned" getterv1alpha1 "agones.dev/agones/pkg/client/clientset/versioned/typed/stable/v1alpha1" "agones.dev/agones/pkg/client/informers/externalversions" listerv1alpha1 "agones.dev/agones/pkg/client/listers/stable/v1alpha1" "agones.dev/agones/pkg/gameservers" - "agones.dev/agones/pkg/util/crd" + "agones.dev/agones/pkg/util/apiserver" + "agones.dev/agones/pkg/util/https" "agones.dev/agones/pkg/util/logfields" "agones.dev/agones/pkg/util/runtime" - "agones.dev/agones/pkg/util/webhooks" "agones.dev/agones/pkg/util/workerqueue" "github.com/heptiolabs/healthcheck" - "github.com/mattbaird/jsonpatch" "github.com/pkg/errors" "github.com/sirupsen/logrus" - admv1beta1 "k8s.io/api/admission/v1beta1" corev1 "k8s.io/api/core/v1" - extclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" - "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + k8sruntime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" @@ -66,31 +69,27 @@ type Controller struct { readyGameServers gameServerCacheEntry // Instead of selecting the top one, controller selects a random one // from the topNGameServerCount of Ready gameservers - topNGameServerCount int - crdGetter v1beta1.CustomResourceDefinitionInterface - gameServerSynced cache.InformerSynced - gameServerGetter getterv1alpha1.GameServersGetter - gameServerLister listerv1alpha1.GameServerLister - gameServerAllocationSynced cache.InformerSynced - gameServerAllocationGetter getterv1alpha1.GameServerAllocationsGetter - stop <-chan struct{} - workerqueue *workerqueue.WorkerQueue - gsWorkerqueue *workerqueue.WorkerQueue - recorder record.EventRecorder + topNGameServerCount int + gameServerSynced cache.InformerSynced + gameServerGetter getterv1alpha1.GameServersGetter + gameServerLister listerv1alpha1.GameServerLister + stop <-chan struct{} + workerqueue *workerqueue.WorkerQueue + recorder record.EventRecorder } // gameserver cache to keep the Ready state gameserver. type gameServerCacheEntry struct { mu sync.RWMutex - cache map[string]*v1alpha1.GameServer + cache map[string]*stablev1alpha1.GameServer } // Store saves the data in the cache. -func (e *gameServerCacheEntry) Store(key string, gs *v1alpha1.GameServer) { +func (e *gameServerCacheEntry) Store(key string, gs *stablev1alpha1.GameServer) { e.mu.Lock() defer e.mu.Unlock() if e.cache == nil { - e.cache = map[string]*v1alpha1.GameServer{} + e.cache = map[string]*stablev1alpha1.GameServer{} } e.cache[key] = gs.DeepCopy() } @@ -111,7 +110,7 @@ func (e *gameServerCacheEntry) Delete(key string) bool { } // Load returns the data from cache. It return true if the value exists in the cache -func (e *gameServerCacheEntry) Load(key string) (*v1alpha1.GameServer, bool) { +func (e *gameServerCacheEntry) Load(key string) (*stablev1alpha1.GameServer, bool) { e.mu.RLock() defer e.mu.RUnlock() val, ok := e.cache[key] @@ -120,7 +119,7 @@ func (e *gameServerCacheEntry) Load(key string) (*v1alpha1.GameServer, bool) { } // Range extracts data from the cache based on provided function f. -func (e *gameServerCacheEntry) Range(f func(key string, gs *v1alpha1.GameServer) bool) { +func (e *gameServerCacheEntry) Range(f func(key string, gs *stablev1alpha1.GameServer) bool) { e.mu.RLock() defer e.mu.RUnlock() for k, v := range e.cache { @@ -143,59 +142,42 @@ var allocationRetry = wait.Backoff{ } // NewController returns a controller for a GameServerAllocation -func NewController(wh *webhooks.WebHook, +func NewController(apiServer *apiserver.APIServer, health healthcheck.Handler, counter *gameservers.PerNodeCounter, topNGameServerCnt int, kubeClient kubernetes.Interface, - extClient extclientset.Interface, agonesClient versioned.Interface, agonesInformerFactory externalversions.SharedInformerFactory, ) *Controller { agonesInformer := agonesInformerFactory.Stable().V1alpha1() c := &Controller{ - counter: counter, - topNGameServerCount: topNGameServerCnt, - crdGetter: extClient.ApiextensionsV1beta1().CustomResourceDefinitions(), - gameServerSynced: agonesInformer.GameServers().Informer().HasSynced, - gameServerGetter: agonesClient.StableV1alpha1(), - gameServerLister: agonesInformer.GameServers().Lister(), - gameServerAllocationSynced: agonesInformer.GameServerAllocations().Informer().HasSynced, - gameServerAllocationGetter: agonesClient.StableV1alpha1(), + counter: counter, + topNGameServerCount: topNGameServerCnt, + gameServerSynced: agonesInformer.GameServers().Informer().HasSynced, + gameServerGetter: agonesClient.StableV1alpha1(), + gameServerLister: agonesInformer.GameServers().Lister(), } c.baseLogger = runtime.NewLoggerWithType(c) - c.workerqueue = workerqueue.NewWorkerQueue(c.syncDelete, c.baseLogger, logfields.GameServerAllocationKey, stable.GroupName+".GameServerAllocationController") - c.gsWorkerqueue = workerqueue.NewWorkerQueue(c.syncGameServers, c.baseLogger, logfields.GameServerKey, stable.GroupName+".GameServerUpdateController") - health.AddLivenessCheck("gameserverallocation-workerqueue", healthcheck.Check(c.workerqueue.Healthy)) - health.AddLivenessCheck("gameserverallocation-gameserver-workerqueue", healthcheck.Check(c.gsWorkerqueue.Healthy)) + c.workerqueue = workerqueue.NewWorkerQueue(c.syncGameServers, c.baseLogger, logfields.GameServerKey, stable.GroupName+".GameServerUpdateController") + health.AddLivenessCheck("gameserverallocation-gameserver-workerqueue", healthcheck.Check(c.workerqueue.Healthy)) eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(c.baseLogger.Infof) eventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) c.recorder = eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: "GameServerAllocation-controller"}) - kind := v1alpha1.Kind("GameServerAllocation") - wh.AddHandler("/mutate", kind, admv1beta1.Create, c.creationMutationHandler) - wh.AddHandler("/validate", kind, admv1beta1.Update, c.mutationValidationHandler) - - agonesInformer.GameServerAllocations().Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { - gsa := obj.(*v1alpha1.GameServerAllocation) - if gsa.Status.State == v1alpha1.GameServerAllocationUnAllocated || gsa.Status.State == v1alpha1.GameServerAllocationContention { - c.workerqueue.Enqueue(gsa) - } - }, - }) + c.registerAPIResource(apiServer) agonesInformer.GameServers().Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ UpdateFunc: func(oldObj, newObj interface{}) { // only interested in if the old / new state was/is Ready - oldGs := oldObj.(*v1alpha1.GameServer) - newGs := newObj.(*v1alpha1.GameServer) - if oldGs.Status.State == v1alpha1.GameServerStateReady || newGs.Status.State == v1alpha1.GameServerStateReady { + oldGs := oldObj.(*stablev1alpha1.GameServer) + newGs := newObj.(*stablev1alpha1.GameServer) + if oldGs.Status.State == stablev1alpha1.GameServerStateReady || newGs.Status.State == stablev1alpha1.GameServerStateReady { if key, ok := c.getKey(newGs); ok { - if newGs.Status.State == v1alpha1.GameServerStateReady { + if newGs.Status.State == stablev1alpha1.GameServerStateReady { c.readyGameServers.Store(key, newGs) } else { c.readyGameServers.Delete(key) @@ -208,32 +190,39 @@ func NewController(wh *webhooks.WebHook, return c } -// Run runs this controller. Will block until stop is closed. -// Runs threadiness number workers to process the rate limited queue -// Probably only needs 1 worker, as its just deleting unallocated GameServerAllocations -func (c *Controller) Run(workers int, stop <-chan struct{}) error { - err := crd.WaitForEstablishedCRD(c.crdGetter, "gameserverallocations."+stable.GroupName, c.baseLogger) - if err != nil { - return err +// registers the api resource for gameserverallocation +func (c *Controller) registerAPIResource(api *apiserver.APIServer) { + resource := metav1.APIResource{ + Name: "gameserverallocations", + SingularName: "gameserverallocation", + Namespaced: true, + Kind: "GameServerAllocation", + Verbs: []string{ + "create", + }, + ShortNames: []string{"gsa"}, } + api.AddAPIResource(v1alpha1.SchemeGroupVersion.String(), resource, c.allocationHandler) +} +// Run runs this controller. Will block until stop is closed. +// Ignores threadiness, as we only needs 1 worker for cache sync +func (c *Controller) Run(_ int, stop <-chan struct{}) error { c.stop = stop c.baseLogger.Info("Wait for cache sync") - if !cache.WaitForCacheSync(stop, c.gameServerAllocationSynced, c.gameServerSynced) { + if !cache.WaitForCacheSync(stop, c.gameServerSynced) { return errors.New("failed to wait for caches to sync") } // build the cache - err = c.syncReadyGSServerCache() + err := c.syncReadyGSServerCache() if err != nil { return err } - c.workerqueue.Run(workers, stop) - // we don't want mutiple workers refresh cache at the same time so one worker will be better. // Also we don't expect to have too many failures when allocating - c.gsWorkerqueue.Run(1, stop) + c.workerqueue.Run(1, stop) return nil } @@ -254,21 +243,53 @@ func (c *Controller) loggerForGameServerAllocation(gsa *v1alpha1.GameServerAlloc return c.loggerForGameServerAllocationKey(gsaName).WithField("gsa", gsa) } -// creationMutationHandler will intercept when a GameServerAllocation is created, and allocate it a GameServer -// assuming that one is available. If not, it will reject the AdmissionReview. -func (c *Controller) creationMutationHandler(review admv1beta1.AdmissionReview) (admv1beta1.AdmissionReview, error) { - c.baseLogger.WithField("review", review).Info("creationMutationHandler") - obj := review.Request.Object - gsa := &v1alpha1.GameServerAllocation{} +// allocationHandler CRDHandler for allocating a gameserver. Only accepts POST +// commands +func (c *Controller) allocationHandler(w http.ResponseWriter, r *http.Request, namespace string) error { + if r.Body != nil { + defer r.Body.Close() // nolint: errcheck + } + + log := https.LogRequest(c.baseLogger, r) - err := json.Unmarshal(obj.Raw, gsa) + if r.Method != http.MethodPost { + log.Warn("allocation handler only supports POST") + http.Error(w, "Method not supported", http.StatusMethodNotAllowed) + return nil + } + + gsa, err := c.allocationDeserialization(r, namespace) if err != nil { - c.baseLogger.WithError(err).Error("error unmarshalling json") - return review, errors.Wrapf(err, "error unmarshalling original GameServerAllocation json: %s", obj.Raw) + return err } - gsa.ApplyDefaults() - var gs *v1alpha1.GameServer + // server side validation + if causes, ok := gsa.Validate(); !ok { + status := &metav1.Status{ + Status: metav1.StatusFailure, + Message: fmt.Sprintf("GameServerAllocation is invalid: Invalid value: %#v", gsa), + Reason: metav1.StatusReasonInvalid, + Details: &metav1.StatusDetails{ + Kind: "GameServerAllocation", + Group: v1alpha1.SchemeGroupVersion.Group, + Causes: causes, + }, + Code: http.StatusUnprocessableEntity, + } + + var gvks []schema.GroupVersionKind + gvks, _, err = apiserver.Scheme.ObjectKinds(status) + if err != nil { + return errors.Wrap(err, "could not find objectkinds for status") + } + + status.TypeMeta = metav1.TypeMeta{Kind: gvks[0].Kind, APIVersion: gvks[0].Version} + + w.WriteHeader(http.StatusUnprocessableEntity) + return c.serialisation(r, w, status, apiserver.Codecs) + } + + var gs *stablev1alpha1.GameServer err = Retry(allocationRetry, func() error { gs, err = c.allocate(gsa) return err @@ -276,9 +297,8 @@ func (c *Controller) creationMutationHandler(review admv1beta1.AdmissionReview) if err != nil && err != ErrNoGameServerReady && err != ErrConflictInGameServerSelection { // this will trigger syncing of the cache (assuming cache might not be up to date) - c.gsWorkerqueue.EnqueueImmediately(gs) - - return review, err + c.workerqueue.EnqueueImmediately(gs) + return err } if err == ErrNoGameServerReady { @@ -286,9 +306,7 @@ func (c *Controller) creationMutationHandler(review admv1beta1.AdmissionReview) } else if err == ErrConflictInGameServerSelection { gsa.Status.State = v1alpha1.GameServerAllocationContention } else { - // When a GameServer is deleted, the GameServerAllocation should go with it - ref := metav1.NewControllerRef(gs, v1alpha1.SchemeGroupVersion.WithKind("GameServer")) - gsa.ObjectMeta.OwnerReferences = append(gsa.ObjectMeta.OwnerReferences, *ref) + gsa.ObjectMeta.Name = gs.ObjectMeta.Name gsa.Status.State = v1alpha1.GameServerAllocationAllocated gsa.Status.GameServerName = gs.ObjectMeta.Name gsa.Status.Ports = gs.Status.Ports @@ -296,77 +314,69 @@ func (c *Controller) creationMutationHandler(review admv1beta1.AdmissionReview) gsa.Status.NodeName = gs.Status.NodeName } - newFA, err := json.Marshal(gsa) + c.loggerForGameServerAllocation(gsa).Info("game server allocation") + + return c.serialisation(r, w, gsa, scheme.Codecs) +} + +// allocationDeserialization processes the request and namespace, and attempts to deserialise its values +// into a GameServerAllocation. Returns an error if it fails for whatever reason. +func (c *Controller) allocationDeserialization(r *http.Request, namespace string) (*v1alpha1.GameServerAllocation, error) { + gsa := &v1alpha1.GameServerAllocation{} + + gvks, _, err := scheme.Scheme.ObjectKinds(gsa) if err != nil { - c.baseLogger.WithError(err).Error("error marshalling") - return review, errors.Wrapf(err, "error marshalling GameServerAllocation %s to json", gsa.ObjectMeta.Name) + return gsa, errors.Wrap(err, "error getting objectkinds for gameserverallocation") } - patch, err := jsonpatch.CreatePatch(obj.Raw, newFA) - if err != nil { - c.baseLogger.WithError(err).Error("error creating the patch") - return review, errors.Wrapf(err, "error creating patch for GameServerAllocation %s", gsa.ObjectMeta.Name) + gsa.TypeMeta = metav1.TypeMeta{Kind: gvks[0].Kind, APIVersion: gvks[0].Version} + + mediaTypes := scheme.Codecs.SupportedMediaTypes() + info, ok := k8sruntime.SerializerInfoForMediaType(mediaTypes, r.Header.Get("Content-Type")) + if !ok { + return gsa, errors.New("Could not find deserializer") } - json, err := json.Marshal(patch) + b, err := ioutil.ReadAll(r.Body) if err != nil { - c.baseLogger.WithError(err).Error("error creating the json for the patch") - return review, errors.Wrapf(err, "error creating json for patch for GameServerAllocation %s", gs.ObjectMeta.Name) + return gsa, errors.Wrap(err, "could not read body") } - c.loggerForGameServerAllocation(gsa).WithField("patch", string(json)).Infof("patch created!") + gvk := v1alpha1.SchemeGroupVersion.WithKind("GameServerAllocation") + _, _, err = info.Serializer.Decode(b, &gvk, gsa) + if err != nil { + c.baseLogger.WithField("body", string(b)).Error("error decoding body") + return gsa, errors.Wrap(err, "error decoding body") + } - pt := admv1beta1.PatchTypeJSONPatch - review.Response.PatchType = &pt - review.Response.Patch = json + gsa.ObjectMeta.Namespace = namespace + gsa.ObjectMeta.CreationTimestamp = metav1.Now() + gsa.ApplyDefaults() - return review, nil + return gsa, nil } -// GameServerAllocation fleetName value -// nolint: dupl -func (c *Controller) mutationValidationHandler(review admv1beta1.AdmissionReview) (admv1beta1.AdmissionReview, error) { - c.baseLogger.WithField("review", review).Info("mutationValidationHandler") - - newGSA := &v1alpha1.GameServerAllocation{} - oldGSA := &v1alpha1.GameServerAllocation{} - - if err := json.Unmarshal(review.Request.Object.Raw, newGSA); err != nil { - return review, errors.Wrapf(err, "error unmarshalling new GameServerAllocation json: %s", review.Request.Object.Raw) - } - - if err := json.Unmarshal(review.Request.OldObject.Raw, oldGSA); err != nil { - return review, errors.Wrapf(err, "error unmarshalling old GameServerAllocation json: %s", review.Request.Object.Raw) - } - - if causes, ok := oldGSA.ValidateUpdate(newGSA); !ok { - review.Response.Allowed = false - details := metav1.StatusDetails{ - Name: review.Request.Name, - Group: review.Request.Kind.Group, - Kind: review.Request.Kind.Kind, - Causes: causes, - } - review.Response.Result = &metav1.Status{ - Status: metav1.StatusFailure, - Message: "GameServerAllocation update is invalid", - Reason: metav1.StatusReasonInvalid, - Details: &details, - } +// serialisation takes a runtime.Object, and serislises it to the ResponseWriter in the requested format +func (c *Controller) serialisation(r *http.Request, w http.ResponseWriter, obj k8sruntime.Object, codecs serializer.CodecFactory) error { + info, err := apiserver.AcceptedSerializer(r, codecs) + if err != nil { + return err } - return review, nil + w.Header().Set("Content-Type", info.MediaType) + err = info.Serializer.Encode(obj, w) + return errors.Wrapf(err, "error encoding %T", obj) } // allocate allocated a GameServer from a given Fleet -func (c *Controller) allocate(gsa *v1alpha1.GameServerAllocation) (*v1alpha1.GameServer, error) { - var allocation *v1alpha1.GameServer +func (c *Controller) allocate(gsa *v1alpha1.GameServerAllocation) (*stablev1alpha1.GameServer, error) { + var allocation *stablev1alpha1.GameServer var comparator findComparator switch gsa.Spec.Scheduling { - case v1alpha1.Packed: + case apis.Packed: comparator = packedComparator - case v1alpha1.Distributed: + case apis.Distributed: comparator = distributedComparator } @@ -381,7 +391,7 @@ func (c *Controller) allocate(gsa *v1alpha1.GameServerAllocation) (*v1alpha1.Gam } gsCopy := allocation.DeepCopy() - gsCopy.Status.State = v1alpha1.GameServerStateAllocated + gsCopy.Status.State = stablev1alpha1.GameServerStateAllocated c.patchMetadata(gsCopy, gsa.Spec.MetaPatch) @@ -399,7 +409,7 @@ func (c *Controller) allocate(gsa *v1alpha1.GameServerAllocation) (*v1alpha1.Gam } // patch the labels and annotations of an allocated GameServer with metadata from a GameServerAllocation -func (c *Controller) patchMetadata(gs *v1alpha1.GameServer, fam v1alpha1.MetaPatch) { +func (c *Controller) patchMetadata(gs *stablev1alpha1.GameServer, fam v1alpha1.MetaPatch) { // patch ObjectMeta labels if fam.Labels != nil { if gs.ObjectMeta.Labels == nil { @@ -420,27 +430,13 @@ func (c *Controller) patchMetadata(gs *v1alpha1.GameServer, fam v1alpha1.MetaPat } } -// syncDelete takes unallocated GameServerAllocations, and deletes them! -func (c *Controller) syncDelete(key string) error { - c.loggerForGameServerAllocationKey(key).Info("Deleting gameserverallocation") - namespace, name, err := cache.SplitMetaNamespaceKey(key) - if err != nil { - // don't return an error, as we don't want this retried - runtime.HandleError(c.loggerForGameServerAllocationKey(key), errors.Wrapf(err, "invalid resource key")) - return nil - } - - err = c.gameServerAllocationGetter.GameServerAllocations(namespace).Delete(name, nil) - return errors.Wrapf(err, "could not delete GameServerAllocation %s", key) -} - // findReadyGameServerForAllocation returns the most appropriate GameServer from the set, taking into account // preferred selectors, as well as the passed in comparator -func (c *Controller) findReadyGameServerForAllocation(gsa *v1alpha1.GameServerAllocation, comparator findComparator) (*v1alpha1.GameServer, error) { +func (c *Controller) findReadyGameServerForAllocation(gsa *v1alpha1.GameServerAllocation, comparator findComparator) (*stablev1alpha1.GameServer, error) { // track the best node count var bestCount *gameservers.NodeCount // the current GameServer from the node with the most GameServers (allocated, ready) - var bestGS *v1alpha1.GameServer + var bestGS *stablev1alpha1.GameServer selector, err := metav1.LabelSelectorAsSelector(&gsa.Spec.Required) if err != nil { @@ -457,18 +453,18 @@ func (c *Controller) findReadyGameServerForAllocation(gsa *v1alpha1.GameServerAl counts := c.counter.Counts() // track potential GameServers, one for each node - allocatableRequired := map[string]*v1alpha1.GameServer{} - allocatablePreferred := make([]map[string]*v1alpha1.GameServer, len(preferred)) + allocatableRequired := map[string]*stablev1alpha1.GameServer{} + allocatablePreferred := make([]map[string]*stablev1alpha1.GameServer, len(preferred)) // build the index of possible allocatable GameServers for _, gs := range gsList { - if gs.DeletionTimestamp.IsZero() && gs.Status.State == v1alpha1.GameServerStateReady { + if gs.DeletionTimestamp.IsZero() && gs.Status.State == stablev1alpha1.GameServerStateReady { allocatableRequired[gs.Status.NodeName] = gs for i, p := range preferred { if p.Matches(labels.Set(gs.Labels)) { if allocatablePreferred[i] == nil { - allocatablePreferred[i] = map[string]*v1alpha1.GameServer{} + allocatablePreferred[i] = map[string]*stablev1alpha1.GameServer{} } allocatablePreferred[i][gs.Status.NodeName] = gs } @@ -486,7 +482,7 @@ func (c *Controller) findReadyGameServerForAllocation(gsa *v1alpha1.GameServerAl } } - bestGSList := []v1alpha1.GameServer{} + var bestGSList []stablev1alpha1.GameServer for nodeName, gs := range allocationSet { count := counts[nodeName] // bestGS == nil: if there is no best GameServer, then this node & GameServer is the always the best @@ -528,7 +524,7 @@ func (c *Controller) syncReadyGSServerCache() error { } // convert list of current gameservers to map for faster access - currGameservers := make(map[string]*v1alpha1.GameServer) + currGameservers := make(map[string]*stablev1alpha1.GameServer) for _, gs := range gsList { if key, ok := c.getKey(gs); ok { currGameservers[key] = gs @@ -537,7 +533,7 @@ func (c *Controller) syncReadyGSServerCache() error { // first remove the gameservers are not in the list anymore tobeDeletedGSInCache := make([]string, 0) - c.readyGameServers.Range(func(key string, gs *v1alpha1.GameServer) bool { + c.readyGameServers.Range(func(key string, gs *stablev1alpha1.GameServer) bool { if _, ok := currGameservers[key]; !ok { tobeDeletedGSInCache = append(tobeDeletedGSInCache, key) } @@ -551,12 +547,12 @@ func (c *Controller) syncReadyGSServerCache() error { // refresh the cache of possible allocatable GameServers for key, gs := range currGameservers { if gsCache, ok := c.readyGameServers.Load(key); ok { - if !(gs.DeletionTimestamp.IsZero() && gs.Status.State == v1alpha1.GameServerStateReady) { + if !(gs.DeletionTimestamp.IsZero() && gs.Status.State == stablev1alpha1.GameServerStateReady) { c.readyGameServers.Delete(key) } else if gs.ObjectMeta.ResourceVersion != gsCache.ObjectMeta.ResourceVersion { c.readyGameServers.Store(key, gs) } - } else if gs.DeletionTimestamp.IsZero() && gs.Status.State == v1alpha1.GameServerStateReady { + } else if gs.DeletionTimestamp.IsZero() && gs.Status.State == stablev1alpha1.GameServerStateReady { c.readyGameServers.Store(key, gs) } } @@ -565,8 +561,8 @@ func (c *Controller) syncReadyGSServerCache() error { } // selectGameServers selects the appropriate gameservers from cache based on selector. -func (c *Controller) selectGameServers(selector labels.Selector) (res []*v1alpha1.GameServer) { - c.readyGameServers.Range(func(key string, gs *v1alpha1.GameServer) bool { +func (c *Controller) selectGameServers(selector labels.Selector) (res []*stablev1alpha1.GameServer) { + c.readyGameServers.Range(func(key string, gs *stablev1alpha1.GameServer) bool { if selector.Matches(labels.Set(gs.ObjectMeta.GetLabels())) { res = append(res, gs) } @@ -576,7 +572,7 @@ func (c *Controller) selectGameServers(selector labels.Selector) (res []*v1alpha } // getKey extract the key of gameserver object -func (c *Controller) getKey(gs *v1alpha1.GameServer) (string, bool) { +func (c *Controller) getKey(gs *stablev1alpha1.GameServer) (string, bool) { var key string ok := true var err error @@ -610,7 +606,7 @@ func Retry(backoff wait.Backoff, fn func() error) error { } // getRandomlySelectedGS selects a GS from the set of Gameservers randomly. This will reduce the contentions -func (c *Controller) getRandomlySelectedGS(gsa *v1alpha1.GameServerAllocation, bestGSList []v1alpha1.GameServer) *v1alpha1.GameServer { +func (c *Controller) getRandomlySelectedGS(gsa *v1alpha1.GameServerAllocation, bestGSList []stablev1alpha1.GameServer) *stablev1alpha1.GameServer { seed, err := strconv.Atoi(gsa.ObjectMeta.ResourceVersion) if err != nil { seed = 1234567 diff --git a/pkg/gameserverallocations/controller_test.go b/pkg/gameserverallocations/controller_test.go index 36a350b77d..71724a688a 100644 --- a/pkg/gameserverallocations/controller_test.go +++ b/pkg/gameserverallocations/controller_test.go @@ -15,25 +15,27 @@ package gameserverallocations import ( + "bytes" "encoding/json" "fmt" "net/http" + "net/http/httptest" "strconv" - "sync" "testing" "time" - "agones.dev/agones/pkg/apis/stable/v1alpha1" + "agones.dev/agones/pkg/apis" + "agones.dev/agones/pkg/apis/allocation/v1alpha1" + stablev1alpha1 "agones.dev/agones/pkg/apis/stable/v1alpha1" "agones.dev/agones/pkg/gameservers" agtesting "agones.dev/agones/pkg/testing" - "agones.dev/agones/pkg/util/webhooks" - applypatch "github.com/evanphx/json-patch" + "agones.dev/agones/pkg/util/apiserver" "github.com/heptiolabs/healthcheck" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" - admv1beta1 "k8s.io/api/admission/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" + k8sruntime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/watch" k8stesting "k8s.io/client-go/testing" "k8s.io/client-go/tools/cache" @@ -45,114 +47,99 @@ const ( n2 = "node2" ) -var ( - gvk = metav1.GroupVersionKind(v1alpha1.SchemeGroupVersion.WithKind("GameServerAllocation")) -) - -func TestControllerCreationMutationHandler(t *testing.T) { +func TestControllerAllocationHandler(t *testing.T) { t.Parallel() - f, _, gsList := defaultFixtures(3) - - gsa := v1alpha1.GameServerAllocation{ObjectMeta: metav1.ObjectMeta{Name: "fa-1"}, - Spec: v1alpha1.GameServerAllocationSpec{ - Required: metav1.LabelSelector{MatchLabels: map[string]string{v1alpha1.FleetNameLabel: f.ObjectMeta.Name}}, - }} - - c, m := newFakeController() - - gsWatch := watch.NewFake() - m.AgonesClient.AddWatchReactor("gameservers", k8stesting.DefaultWatchReactor(gsWatch, nil)) - m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, runtime.Object, error) { - return true, &v1alpha1.GameServerList{Items: gsList}, nil - }) - m.AgonesClient.AddReactor("update", "gameservers", func(action k8stesting.Action) (bool, runtime.Object, error) { - ua := action.(k8stesting.UpdateAction) - gs := ua.GetObject().(*v1alpha1.GameServer) - gsWatch.Modify(gs) - - return true, gs, nil - }) - _, cancel := agtesting.StartInformers(m) - defer cancel() - - // This call initializes the cache - err := c.syncReadyGSServerCache() - assert.Nil(t, err) - - test := func(gsa v1alpha1.GameServerAllocation, expectedState v1alpha1.GameServerAllocationState) { - review, err := newAdmissionReview(gsa) - assert.Nil(t, err) + t.Run("successful allocation", func(t *testing.T) { + f, _, gsList := defaultFixtures(3) - result, err := c.creationMutationHandler(review) + gsa := &v1alpha1.GameServerAllocation{ + Spec: v1alpha1.GameServerAllocationSpec{ + Required: metav1.LabelSelector{MatchLabels: map[string]string{stablev1alpha1.FleetNameLabel: f.ObjectMeta.Name}}, + }} - assert.Nil(t, err) - assert.True(t, result.Response.Allowed, fmt.Sprintf("%#v", result.Response)) - assert.Equal(t, admv1beta1.PatchTypeJSONPatch, *result.Response.PatchType) + c, m := newFakeController() + gsWatch := watch.NewFake() + m.AgonesClient.AddWatchReactor("gameservers", k8stesting.DefaultWatchReactor(gsWatch, nil)) + m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, k8sruntime.Object, error) { + return true, &stablev1alpha1.GameServerList{Items: gsList}, nil + }) + m.AgonesClient.AddReactor("update", "gameservers", func(action k8stesting.Action) (bool, k8sruntime.Object, error) { + ua := action.(k8stesting.UpdateAction) + gs := ua.GetObject().(*stablev1alpha1.GameServer) + gsWatch.Modify(gs) + return true, gs, nil + }) - patch, err := applypatch.DecodePatch(result.Response.Patch) - assert.Nil(t, err) + stop, cancel := agtesting.StartInformers(m) + defer cancel() - JSON, err := patch.Apply(result.Request.Object.Raw) + // This call initializes the cache + err := c.syncReadyGSServerCache() assert.Nil(t, err) - newGSA := &v1alpha1.GameServerAllocation{} - err = json.Unmarshal(JSON, newGSA) + err = c.counter.Run(0, stop) assert.Nil(t, err) - assert.Equal(t, v1alpha1.Packed, newGSA.Spec.Scheduling) - assert.Equal(t, expectedState, newGSA.Status.State) - if expectedState == v1alpha1.GameServerAllocationAllocated { - assert.NotEmpty(t, newGSA.ObjectMeta.OwnerReferences) - } else { - assert.Empty(t, newGSA.ObjectMeta.OwnerReferences) + test := func(gsa *v1alpha1.GameServerAllocation, expectedState v1alpha1.GameServerAllocationState) { + buf := bytes.NewBuffer(nil) + err := json.NewEncoder(buf).Encode(gsa) + assert.NoError(t, err) + r, err := http.NewRequest(http.MethodPost, "/", buf) + r.Header.Set("Content-Type", k8sruntime.ContentTypeJSON) + assert.NoError(t, err) + rec := httptest.NewRecorder() + err = c.allocationHandler(rec, r, "default") + assert.NoError(t, err) + ret := &v1alpha1.GameServerAllocation{} + err = json.Unmarshal(rec.Body.Bytes(), ret) + assert.NoError(t, err) + + assert.Equal(t, gsa.Spec.Required, ret.Spec.Required) + assert.True(t, expectedState == ret.Status.State, "Failed: %s vs %s", expectedState, ret.Status.State) } - } - - test(*gsa.DeepCopy(), v1alpha1.GameServerAllocationAllocated) - test(*gsa.DeepCopy(), v1alpha1.GameServerAllocationAllocated) - test(*gsa.DeepCopy(), v1alpha1.GameServerAllocationAllocated) - test(*gsa.DeepCopy(), v1alpha1.GameServerAllocationUnAllocated) - - gsa.DeepCopy() -} -func TestControllerMutationValidationHandler(t *testing.T) { - t.Parallel() - c, _ := newFakeController() + test(gsa.DeepCopy(), v1alpha1.GameServerAllocationAllocated) + test(gsa.DeepCopy(), v1alpha1.GameServerAllocationAllocated) + test(gsa.DeepCopy(), v1alpha1.GameServerAllocationAllocated) + test(gsa.DeepCopy(), v1alpha1.GameServerAllocationUnAllocated) + }) - gsa := v1alpha1.GameServerAllocation{ObjectMeta: metav1.ObjectMeta{Name: "fa-1", Namespace: defaultNs}, - Spec: v1alpha1.GameServerAllocationSpec{ - Required: metav1.LabelSelector{MatchLabels: map[string]string{v1alpha1.FleetNameLabel: "my-fleet-name"}}, - }, - } - gsa.ApplyDefaults() + t.Run("method not allowed", func(t *testing.T) { + c, _ := newFakeController() + r, err := http.NewRequest(http.MethodGet, "/", nil) + rec := httptest.NewRecorder() + assert.NoError(t, err) - t.Run("same fleetName", func(t *testing.T) { - review, err := newAdmissionReview(gsa) - assert.Nil(t, err) - review.Request.OldObject = *review.Request.Object.DeepCopy() + err = c.allocationHandler(rec, r, "default") + assert.NoError(t, err) - result, err := c.mutationValidationHandler(review) - assert.Nil(t, err) - assert.True(t, result.Response.Allowed) + assert.Equal(t, http.StatusMethodNotAllowed, rec.Code) }) - t.Run("different fleetname", func(t *testing.T) { - review, err := newAdmissionReview(gsa) - assert.Nil(t, err) - oldObject := gsa.DeepCopy() - oldObject.Spec.Required.MatchLabels[v1alpha1.FleetNameLabel] = "changed" - - gsaJSON, err := json.Marshal(oldObject) - assert.Nil(t, err) - review.Request.OldObject = runtime.RawExtension{Raw: gsaJSON} - - result, err := c.mutationValidationHandler(review) - assert.Nil(t, err) - assert.False(t, result.Response.Allowed) - assert.Equal(t, metav1.StatusReasonInvalid, result.Response.Result.Reason) - assert.NotNil(t, result.Response.Result.Details) + t.Run("invalid gameserverallocation", func(t *testing.T) { + c, _ := newFakeController() + gsa := &v1alpha1.GameServerAllocation{ + Spec: v1alpha1.GameServerAllocationSpec{ + Scheduling: "wrong", + }} + buf := bytes.NewBuffer(nil) + err := json.NewEncoder(buf).Encode(gsa) + assert.NoError(t, err) + r, err := http.NewRequest(http.MethodPost, "/", buf) + r.Header.Set("Content-Type", k8sruntime.ContentTypeJSON) + assert.NoError(t, err) + rec := httptest.NewRecorder() + err = c.allocationHandler(rec, r, "default") + assert.NoError(t, err) + + assert.Equal(t, http.StatusUnprocessableEntity, rec.Code) + + s := &metav1.Status{} + err = json.NewDecoder(rec.Body).Decode(s) + assert.NoError(t, err) + + assert.Equal(t, metav1.StatusReasonInvalid, s.Reason) }) } @@ -168,19 +155,19 @@ func TestControllerAllocate(t *testing.T) { gsList[3].ObjectMeta.DeletionTimestamp = &n - m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, runtime.Object, error) { - return true, &v1alpha1.GameServerList{Items: gsList}, nil + m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, k8sruntime.Object, error) { + return true, &stablev1alpha1.GameServerList{Items: gsList}, nil }) updated := false gsWatch := watch.NewFake() m.AgonesClient.AddWatchReactor("gameservers", k8stesting.DefaultWatchReactor(gsWatch, nil)) - m.AgonesClient.AddReactor("update", "gameservers", func(action k8stesting.Action) (bool, runtime.Object, error) { + m.AgonesClient.AddReactor("update", "gameservers", func(action k8stesting.Action) (bool, k8sruntime.Object, error) { ua := action.(k8stesting.UpdateAction) - gs := ua.GetObject().(*v1alpha1.GameServer) + gs := ua.GetObject().(*stablev1alpha1.GameServer) updated = true - assert.Equal(t, v1alpha1.GameServerStateAllocated, gs.Status.State) + assert.Equal(t, stablev1alpha1.GameServerStateAllocated, gs.Status.State) gsWatch.Modify(gs) return true, gs, nil @@ -198,14 +185,14 @@ func TestControllerAllocate(t *testing.T) { gsa := v1alpha1.GameServerAllocation{ObjectMeta: metav1.ObjectMeta{Name: "gsa-1"}, Spec: v1alpha1.GameServerAllocationSpec{ - Required: metav1.LabelSelector{MatchLabels: map[string]string{v1alpha1.FleetNameLabel: f.ObjectMeta.Name}}, + Required: metav1.LabelSelector{MatchLabels: map[string]string{stablev1alpha1.FleetNameLabel: f.ObjectMeta.Name}}, MetaPatch: fam, }} gsa.ApplyDefaults() gs, err := c.allocate(&gsa) assert.Nil(t, err) - assert.Equal(t, v1alpha1.GameServerStateAllocated, gs.Status.State) + assert.Equal(t, stablev1alpha1.GameServerStateAllocated, gs.Status.State) assert.True(t, updated) for key, value := range fam.Labels { v, ok := gs.ObjectMeta.Labels[key] @@ -221,13 +208,13 @@ func TestControllerAllocate(t *testing.T) { updated = false gs, err = c.allocate(&gsa) assert.Nil(t, err) - assert.Equal(t, v1alpha1.GameServerStateAllocated, gs.Status.State) + assert.Equal(t, stablev1alpha1.GameServerStateAllocated, gs.Status.State) assert.True(t, updated) updated = false gs, err = c.allocate(&gsa) assert.Nil(t, err) - assert.Equal(t, v1alpha1.GameServerStateAllocated, gs.Status.State) + assert.Equal(t, stablev1alpha1.GameServerStateAllocated, gs.Status.State) assert.True(t, updated) updated = false @@ -249,15 +236,15 @@ func TestControllerAllocatePriority(t *testing.T) { gsList[2].Status.NodeName = n1 gsList[3].Status.NodeName = n1 - m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, runtime.Object, error) { - return true, &v1alpha1.GameServerList{Items: gsList}, nil + m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, k8sruntime.Object, error) { + return true, &stablev1alpha1.GameServerList{Items: gsList}, nil }) gsWatch := watch.NewFake() m.AgonesClient.AddWatchReactor("gameservers", k8stesting.DefaultWatchReactor(gsWatch, nil)) - m.AgonesClient.AddReactor("update", "gameservers", func(action k8stesting.Action) (bool, runtime.Object, error) { + m.AgonesClient.AddReactor("update", "gameservers", func(action k8stesting.Action) (bool, k8sruntime.Object, error) { ua := action.(k8stesting.UpdateAction) - gs := ua.GetObject().(*v1alpha1.GameServer) + gs := ua.GetObject().(*stablev1alpha1.GameServer) gsWatch.Modify(gs) return true, gs, nil @@ -275,7 +262,7 @@ func TestControllerAllocatePriority(t *testing.T) { gas := &v1alpha1.GameServerAllocation{ObjectMeta: metav1.ObjectMeta{Name: "fa-1"}, Spec: v1alpha1.GameServerAllocationSpec{ - Required: metav1.LabelSelector{MatchLabels: map[string]string{v1alpha1.FleetNameLabel: f.ObjectMeta.Name}}, + Required: metav1.LabelSelector{MatchLabels: map[string]string{stablev1alpha1.FleetNameLabel: f.ObjectMeta.Name}}, }} gas.ApplyDefaults() @@ -310,7 +297,7 @@ func TestControllerAllocatePriority(t *testing.T) { run(t, "distributed", func(t *testing.T, c *Controller, gas *v1alpha1.GameServerAllocation) { // make a copy, to avoid the race check gas = gas.DeepCopy() - gas.Spec.Scheduling = v1alpha1.Distributed + gas.Spec.Scheduling = apis.Distributed // should go node2, then node1 gs, err := c.allocate(gas) assert.Nil(t, err) @@ -334,56 +321,6 @@ func TestControllerAllocatePriority(t *testing.T) { }) } -func TestControllerWithoutAllocateMutex(t *testing.T) { - t.Parallel() - - f, _, gsList := defaultFixtures(100) - c, m := newFakeController() - - m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, runtime.Object, error) { - return true, &v1alpha1.GameServerList{Items: gsList}, nil - }) - - gas := &v1alpha1.GameServerAllocation{ObjectMeta: metav1.ObjectMeta{Name: "fa-1"}, - Spec: v1alpha1.GameServerAllocationSpec{ - Required: metav1.LabelSelector{MatchLabels: map[string]string{v1alpha1.FleetNameLabel: f.ObjectMeta.Name}}, - }} - gas.ApplyDefaults() - - hasSync := m.AgonesInformerFactory.Stable().V1alpha1().GameServers().Informer().HasSynced - stop, cancel := agtesting.StartInformers(m, hasSync) - defer cancel() - - // This call initializes the cache - err := c.syncReadyGSServerCache() - assert.Nil(t, err) - - err = c.counter.Run(0, stop) - assert.Nil(t, err) - - wg := sync.WaitGroup{} - // start 10 threads, each one gets 10 allocations - allocate := func() { - defer wg.Done() - for i := 1; i <= 10; i++ { - review, err := newAdmissionReview(*gas.DeepCopy()) - assert.Nil(t, err) - _, err = c.creationMutationHandler(review) - assert.Nil(t, err) - } - } - - for i := 1; i <= 10; i++ { - wg.Add(1) - go allocate() - } - - logrus.Info("waiting...") - wg.Wait() - - assert.Equal(t, 0, len(c.readyGameServers.cache)) -} - func TestControllerFindPackedReadyGameServer(t *testing.T) { t.Parallel() @@ -404,17 +341,17 @@ func TestControllerFindPackedReadyGameServer(t *testing.T) { hasSync := m.AgonesInformerFactory.Stable().V1alpha1().GameServers().Informer().HasSynced n := metav1.Now() - gsList := []v1alpha1.GameServer{ - {ObjectMeta: metav1.ObjectMeta{Name: "gs6", Namespace: defaultNs, Labels: labels, DeletionTimestamp: &n}, Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateReady}}, - {ObjectMeta: metav1.ObjectMeta{Name: "gs1", Namespace: defaultNs, Labels: labels}, Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateReady}}, - {ObjectMeta: metav1.ObjectMeta{Name: "gs2", Namespace: defaultNs, Labels: labels}, Status: v1alpha1.GameServerStatus{NodeName: "node2", State: v1alpha1.GameServerStateReady}}, - {ObjectMeta: metav1.ObjectMeta{Name: "gs3", Namespace: defaultNs, Labels: labels}, Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateAllocated}}, - {ObjectMeta: metav1.ObjectMeta{Name: "gs4", Namespace: defaultNs, Labels: labels}, Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateAllocated}}, - {ObjectMeta: metav1.ObjectMeta{Name: "gs5", Namespace: defaultNs, Labels: labels}, Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateError}}, + gsList := []stablev1alpha1.GameServer{ + {ObjectMeta: metav1.ObjectMeta{Name: "gs6", Namespace: defaultNs, Labels: labels, DeletionTimestamp: &n}, Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateReady}}, + {ObjectMeta: metav1.ObjectMeta{Name: "gs1", Namespace: defaultNs, Labels: labels}, Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateReady}}, + {ObjectMeta: metav1.ObjectMeta{Name: "gs2", Namespace: defaultNs, Labels: labels}, Status: stablev1alpha1.GameServerStatus{NodeName: "node2", State: stablev1alpha1.GameServerStateReady}}, + {ObjectMeta: metav1.ObjectMeta{Name: "gs3", Namespace: defaultNs, Labels: labels}, Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateAllocated}}, + {ObjectMeta: metav1.ObjectMeta{Name: "gs4", Namespace: defaultNs, Labels: labels}, Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateAllocated}}, + {ObjectMeta: metav1.ObjectMeta{Name: "gs5", Namespace: defaultNs, Labels: labels}, Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateError}}, } - m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, runtime.Object, error) { - return true, &v1alpha1.GameServerList{Items: gsList}, nil + m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, k8sruntime.Object, error) { + return true, &stablev1alpha1.GameServerList{Items: gsList}, nil }) stop, cancel := agtesting.StartInformers(m, hasSync) @@ -430,22 +367,22 @@ func TestControllerFindPackedReadyGameServer(t *testing.T) { gs, err := c.findReadyGameServerForAllocation(gsa, packedComparator) assert.Nil(t, err) assert.Equal(t, "node1", gs.Status.NodeName) - assert.Equal(t, v1alpha1.GameServerStateReady, gs.Status.State) + assert.Equal(t, stablev1alpha1.GameServerStateReady, gs.Status.State) // mock that the first game server is allocated change := gsList[1].DeepCopy() - change.Status.State = v1alpha1.GameServerStateAllocated + change.Status.State = stablev1alpha1.GameServerStateAllocated watch.Modify(change) assert.True(t, cache.WaitForCacheSync(stop, hasSync)) gs, err = c.findReadyGameServerForAllocation(gsa, packedComparator) assert.Nil(t, err) assert.Equal(t, "node2", gs.Status.NodeName) - assert.Equal(t, v1alpha1.GameServerStateReady, gs.Status.State) + assert.Equal(t, stablev1alpha1.GameServerStateReady, gs.Status.State) - gsList[2].Status.State = v1alpha1.GameServerStateAllocated + gsList[2].Status.State = stablev1alpha1.GameServerStateAllocated change = gsList[2].DeepCopy() - change.Status.State = v1alpha1.GameServerStateAllocated + change.Status.State = stablev1alpha1.GameServerStateAllocated watch.Modify(change) assert.True(t, cache.WaitForCacheSync(stop, hasSync)) @@ -461,17 +398,17 @@ func TestControllerFindPackedReadyGameServer(t *testing.T) { hasSync := m.AgonesInformerFactory.Stable().V1alpha1().GameServers().Informer().HasSynced prefLabels := map[string]string{"role": "gameserver", "preferred": "true"} - gsList := []v1alpha1.GameServer{ - {ObjectMeta: metav1.ObjectMeta{Name: "gs1", Namespace: defaultNs, Labels: prefLabels}, Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateReady}}, - {ObjectMeta: metav1.ObjectMeta{Name: "gs2", Namespace: defaultNs, Labels: labels}, Status: v1alpha1.GameServerStatus{NodeName: "node2", State: v1alpha1.GameServerStateReady}}, - {ObjectMeta: metav1.ObjectMeta{Name: "gs3", Namespace: defaultNs, Labels: labels}, Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateReady}}, - {ObjectMeta: metav1.ObjectMeta{Name: "gs4", Namespace: defaultNs, Labels: prefLabels}, Status: v1alpha1.GameServerStatus{NodeName: "node2", State: v1alpha1.GameServerStateReady}}, - {ObjectMeta: metav1.ObjectMeta{Name: "gs5", Namespace: defaultNs, Labels: labels}, Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateReady}}, - {ObjectMeta: metav1.ObjectMeta{Name: "gs6", Namespace: defaultNs, Labels: labels}, Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateReady}}, + gsList := []stablev1alpha1.GameServer{ + {ObjectMeta: metav1.ObjectMeta{Name: "gs1", Namespace: defaultNs, Labels: prefLabels}, Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateReady}}, + {ObjectMeta: metav1.ObjectMeta{Name: "gs2", Namespace: defaultNs, Labels: labels}, Status: stablev1alpha1.GameServerStatus{NodeName: "node2", State: stablev1alpha1.GameServerStateReady}}, + {ObjectMeta: metav1.ObjectMeta{Name: "gs3", Namespace: defaultNs, Labels: labels}, Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateReady}}, + {ObjectMeta: metav1.ObjectMeta{Name: "gs4", Namespace: defaultNs, Labels: prefLabels}, Status: stablev1alpha1.GameServerStatus{NodeName: "node2", State: stablev1alpha1.GameServerStateReady}}, + {ObjectMeta: metav1.ObjectMeta{Name: "gs5", Namespace: defaultNs, Labels: labels}, Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateReady}}, + {ObjectMeta: metav1.ObjectMeta{Name: "gs6", Namespace: defaultNs, Labels: labels}, Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateReady}}, } - m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, runtime.Object, error) { - return true, &v1alpha1.GameServerList{Items: gsList}, nil + m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, k8sruntime.Object, error) { + return true, &stablev1alpha1.GameServerList{Items: gsList}, nil }) prefGsa := gsa.DeepCopy() @@ -493,10 +430,10 @@ func TestControllerFindPackedReadyGameServer(t *testing.T) { assert.Nil(t, err) assert.Equal(t, "node1", gs.Status.NodeName) assert.Equal(t, "gs1", gs.ObjectMeta.Name) - assert.Equal(t, v1alpha1.GameServerStateReady, gs.Status.State) + assert.Equal(t, stablev1alpha1.GameServerStateReady, gs.Status.State) change := gsList[0].DeepCopy() - change.Status.State = v1alpha1.GameServerStateAllocated + change.Status.State = stablev1alpha1.GameServerStateAllocated watch.Modify(change) assert.True(t, cache.WaitForCacheSync(stop, hasSync)) @@ -504,44 +441,44 @@ func TestControllerFindPackedReadyGameServer(t *testing.T) { assert.Nil(t, err) assert.Equal(t, "node2", gs.Status.NodeName) assert.Equal(t, "gs4", gs.ObjectMeta.Name) - assert.Equal(t, v1alpha1.GameServerStateReady, gs.Status.State) + assert.Equal(t, stablev1alpha1.GameServerStateReady, gs.Status.State) change = gsList[3].DeepCopy() - change.Status.State = v1alpha1.GameServerStateAllocated + change.Status.State = stablev1alpha1.GameServerStateAllocated watch.Modify(change) assert.True(t, cache.WaitForCacheSync(stop, hasSync)) gs, err = c.findReadyGameServerForAllocation(prefGsa, packedComparator) assert.Nil(t, err) assert.Equal(t, "node1", gs.Status.NodeName) - assert.Equal(t, v1alpha1.GameServerStateReady, gs.Status.State) + assert.Equal(t, stablev1alpha1.GameServerStateReady, gs.Status.State) }) t.Run("allocation trap", func(t *testing.T) { c, m := newFakeController() hasSync := m.AgonesInformerFactory.Stable().V1alpha1().GameServers().Informer().HasSynced - gsList := []v1alpha1.GameServer{ + gsList := []stablev1alpha1.GameServer{ {ObjectMeta: metav1.ObjectMeta{Name: "gs1", Labels: labels}, - Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateAllocated}}, + Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateAllocated}}, {ObjectMeta: metav1.ObjectMeta{Name: "gs2", Labels: labels}, - Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateAllocated}}, + Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateAllocated}}, {ObjectMeta: metav1.ObjectMeta{Name: "gs3", Labels: labels}, - Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateAllocated}}, + Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateAllocated}}, {ObjectMeta: metav1.ObjectMeta{Name: "gs4", Labels: labels}, - Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateAllocated}}, + Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateAllocated}}, {ObjectMeta: metav1.ObjectMeta{Name: "gs5", Labels: labels}, - Status: v1alpha1.GameServerStatus{NodeName: "node2", State: v1alpha1.GameServerStateReady}}, + Status: stablev1alpha1.GameServerStatus{NodeName: "node2", State: stablev1alpha1.GameServerStateReady}}, {ObjectMeta: metav1.ObjectMeta{Name: "gs6", Labels: labels}, - Status: v1alpha1.GameServerStatus{NodeName: "node2", State: v1alpha1.GameServerStateReady}}, + Status: stablev1alpha1.GameServerStatus{NodeName: "node2", State: stablev1alpha1.GameServerStateReady}}, {ObjectMeta: metav1.ObjectMeta{Name: "gs7", Labels: labels}, - Status: v1alpha1.GameServerStatus{NodeName: "node2", State: v1alpha1.GameServerStateReady}}, + Status: stablev1alpha1.GameServerStatus{NodeName: "node2", State: stablev1alpha1.GameServerStateReady}}, {ObjectMeta: metav1.ObjectMeta{Name: "gs8", Labels: labels}, - Status: v1alpha1.GameServerStatus{NodeName: "node2", State: v1alpha1.GameServerStateReady}}, + Status: stablev1alpha1.GameServerStatus{NodeName: "node2", State: stablev1alpha1.GameServerStateReady}}, } - m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, runtime.Object, error) { - return true, &v1alpha1.GameServerList{Items: gsList}, nil + m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, k8sruntime.Object, error) { + return true, &stablev1alpha1.GameServerList{Items: gsList}, nil }) stop, cancel := agtesting.StartInformers(m, hasSync) @@ -557,7 +494,7 @@ func TestControllerFindPackedReadyGameServer(t *testing.T) { gs, err := c.findReadyGameServerForAllocation(gsa, packedComparator) assert.Nil(t, err) assert.Equal(t, "node2", gs.Status.NodeName) - assert.Equal(t, v1alpha1.GameServerStateReady, gs.Status.State) + assert.Equal(t, stablev1alpha1.GameServerStateReady, gs.Status.State) }) } @@ -580,25 +517,25 @@ func TestControllerFindDistributedReadyGameServer(t *testing.T) { }, } - gsList := []v1alpha1.GameServer{ + gsList := []stablev1alpha1.GameServer{ {ObjectMeta: metav1.ObjectMeta{Name: "gs1", Namespace: defaultNs, Labels: labels}, - Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateReady}}, + Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateReady}}, {ObjectMeta: metav1.ObjectMeta{Name: "gs2", Namespace: defaultNs, Labels: labels}, - Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateReady}}, + Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateReady}}, {ObjectMeta: metav1.ObjectMeta{Name: "gs3", Namespace: defaultNs, Labels: labels}, - Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateReady}}, + Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateReady}}, {ObjectMeta: metav1.ObjectMeta{Name: "gs4", Namespace: defaultNs, Labels: labels}, - Status: v1alpha1.GameServerStatus{NodeName: "node1", State: v1alpha1.GameServerStateError}}, + Status: stablev1alpha1.GameServerStatus{NodeName: "node1", State: stablev1alpha1.GameServerStateError}}, {ObjectMeta: metav1.ObjectMeta{Name: "gs5", Namespace: defaultNs, Labels: labels}, - Status: v1alpha1.GameServerStatus{NodeName: "node2", State: v1alpha1.GameServerStateReady}}, + Status: stablev1alpha1.GameServerStatus{NodeName: "node2", State: stablev1alpha1.GameServerStateReady}}, {ObjectMeta: metav1.ObjectMeta{Name: "gs6", Namespace: defaultNs, Labels: labels}, - Status: v1alpha1.GameServerStatus{NodeName: "node2", State: v1alpha1.GameServerStateReady}}, + Status: stablev1alpha1.GameServerStatus{NodeName: "node2", State: stablev1alpha1.GameServerStateReady}}, {ObjectMeta: metav1.ObjectMeta{Name: "gs7", Namespace: defaultNs, Labels: labels}, - Status: v1alpha1.GameServerStatus{NodeName: "node3", State: v1alpha1.GameServerStateReady}}, + Status: stablev1alpha1.GameServerStatus{NodeName: "node3", State: stablev1alpha1.GameServerStateReady}}, } - m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, runtime.Object, error) { - return true, &v1alpha1.GameServerList{Items: gsList}, nil + m.AgonesClient.AddReactor("list", "gameservers", func(action k8stesting.Action) (bool, k8sruntime.Object, error) { + return true, &stablev1alpha1.GameServerList{Items: gsList}, nil }) stop, cancel := agtesting.StartInformers(m, hasSync) @@ -614,60 +551,60 @@ func TestControllerFindDistributedReadyGameServer(t *testing.T) { gs, err := c.findReadyGameServerForAllocation(gsa, distributedComparator) assert.Nil(t, err) assert.Equal(t, "node3", gs.Status.NodeName) - assert.Equal(t, v1alpha1.GameServerStateReady, gs.Status.State) + assert.Equal(t, stablev1alpha1.GameServerStateReady, gs.Status.State) change := gsList[6].DeepCopy() - change.Status.State = v1alpha1.GameServerStateAllocated + change.Status.State = stablev1alpha1.GameServerStateAllocated watch.Modify(change) assert.True(t, cache.WaitForCacheSync(stop, hasSync)) gs, err = c.findReadyGameServerForAllocation(gsa, distributedComparator) assert.Nil(t, err) assert.Equal(t, "node2", gs.Status.NodeName) - assert.Equal(t, v1alpha1.GameServerStateReady, gs.Status.State) + assert.Equal(t, stablev1alpha1.GameServerStateReady, gs.Status.State) change = gsList[4].DeepCopy() - change.Status.State = v1alpha1.GameServerStateAllocated + change.Status.State = stablev1alpha1.GameServerStateAllocated watch.Modify(change) assert.True(t, cache.WaitForCacheSync(stop, hasSync)) gs, err = c.findReadyGameServerForAllocation(gsa, distributedComparator) assert.Nil(t, err) assert.Equal(t, "node1", gs.Status.NodeName) - assert.Equal(t, v1alpha1.GameServerStateReady, gs.Status.State) + assert.Equal(t, stablev1alpha1.GameServerStateReady, gs.Status.State) change = gsList[0].DeepCopy() - change.Status.State = v1alpha1.GameServerStateAllocated + change.Status.State = stablev1alpha1.GameServerStateAllocated watch.Modify(change) assert.True(t, cache.WaitForCacheSync(stop, hasSync)) gs, err = c.findReadyGameServerForAllocation(gsa, distributedComparator) assert.Nil(t, err) assert.Equal(t, "node2", gs.Status.NodeName) - assert.Equal(t, v1alpha1.GameServerStateReady, gs.Status.State) + assert.Equal(t, stablev1alpha1.GameServerStateReady, gs.Status.State) change = gsList[5].DeepCopy() - change.Status.State = v1alpha1.GameServerStateAllocated + change.Status.State = stablev1alpha1.GameServerStateAllocated watch.Modify(change) assert.True(t, cache.WaitForCacheSync(stop, hasSync)) gs, err = c.findReadyGameServerForAllocation(gsa, distributedComparator) assert.Nil(t, err) assert.Equal(t, "node1", gs.Status.NodeName) - assert.Equal(t, v1alpha1.GameServerStateReady, gs.Status.State) + assert.Equal(t, stablev1alpha1.GameServerStateReady, gs.Status.State) change = gsList[1].DeepCopy() - change.Status.State = v1alpha1.GameServerStateAllocated + change.Status.State = stablev1alpha1.GameServerStateAllocated watch.Modify(change) assert.True(t, cache.WaitForCacheSync(stop, hasSync)) gs, err = c.findReadyGameServerForAllocation(gsa, distributedComparator) assert.Nil(t, err) assert.Equal(t, "node1", gs.Status.NodeName) - assert.Equal(t, v1alpha1.GameServerStateReady, gs.Status.State) + assert.Equal(t, stablev1alpha1.GameServerStateReady, gs.Status.State) change = gsList[2].DeepCopy() - change.Status.State = v1alpha1.GameServerStateAllocated + change.Status.State = stablev1alpha1.GameServerStateAllocated watch.Modify(change) assert.True(t, cache.WaitForCacheSync(stop, hasSync)) @@ -676,80 +613,84 @@ func TestControllerFindDistributedReadyGameServer(t *testing.T) { assert.Nil(t, gs) } -func TestControllerRunSync(t *testing.T) { - c, m := newFakeController() - watch := watch.NewFake() +func TestAllocationApiResource(t *testing.T) { + t.Parallel() - done := make(chan struct{}, 10) + _, m := newFakeController() + ts := httptest.NewServer(m.Mux) + defer ts.Close() - m.ExtClient.AddReactor("get", "customresourcedefinitions", func(action k8stesting.Action) (bool, runtime.Object, error) { - return true, agtesting.NewEstablishedCRD(), nil - }) - m.AgonesClient.AddWatchReactor("gameserverallocations", k8stesting.DefaultWatchReactor(watch, nil)) - m.AgonesClient.AddReactor("delete", "gameserverallocations", func(action k8stesting.Action) (bool, runtime.Object, error) { - da := action.(k8stesting.DeleteAction) - assert.Equal(t, "default", da.GetNamespace()) - assert.Equal(t, "allocation", da.GetName()) + client := ts.Client() - done <- struct{}{} + resp, err := client.Get(ts.URL + "/apis/" + v1alpha1.SchemeGroupVersion.String()) + if !assert.Nil(t, err) { + assert.FailNow(t, err.Error()) + } + defer resp.Body.Close() // nolint: errcheck - return true, nil, nil - }) + list := &metav1.APIResourceList{} + err = json.NewDecoder(resp.Body).Decode(list) + assert.Nil(t, err) + + assert.Len(t, list.APIResources, 1) + assert.Equal(t, "gameserverallocation", list.APIResources[0].SingularName) +} + +func TestControllerRunCacheSync(t *testing.T) { + c, m := newFakeController() + watch := watch.NewFake() + + m.AgonesClient.AddWatchReactor("gameservers", k8stesting.DefaultWatchReactor(watch, nil)) stop, cancel := agtesting.StartInformers(m) defer cancel() + assertCacheEntries := func(expected int) { + count := 0 + err := wait.PollImmediate(time.Second, 5*time.Second, func() (done bool, err error) { + count = 0 + c.readyGameServers.Range(func(key string, gs *stablev1alpha1.GameServer) bool { + count++ + return true + }) + + return count == expected, nil + }) + + assert.NoError(t, err, fmt.Sprintf("Should be %d values", expected)) + } + go func() { err := c.Run(1, stop) assert.Nil(t, err) }() - gsa := &v1alpha1.GameServerAllocation{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: defaultNs, - Name: "allocation", - }, - Status: v1alpha1.GameServerAllocationStatus{ - State: v1alpha1.GameServerAllocationUnAllocated, - }, + gs := stablev1alpha1.GameServer{ + ObjectMeta: metav1.ObjectMeta{Name: "gs1", Namespace: "default"}, + Status: stablev1alpha1.GameServerStatus{State: stablev1alpha1.GameServerStateStarting}, } - logrus.Info("adding game server allocation") - watch.Add(gsa.DeepCopy()) + logrus.Info("adding ready game server") + watch.Add(gs.DeepCopy()) - select { - case <-done: - case <-time.After(10 * time.Second): - assert.Fail(t, "should have got delete operation") - } + assertCacheEntries(0) - gsa.ObjectMeta.Name = "default2" - gsa.Status.State = v1alpha1.GameServerAllocationAllocated - watch.Add(gsa.DeepCopy()) + gs.Status.State = stablev1alpha1.GameServerStateReady + watch.Modify(gs.DeepCopy()) - select { - case <-done: - assert.Fail(t, "should not have got a delete operation") - case <-time.After(3 * time.Second): - } -} + assertCacheEntries(1) -func TestControllerSyncDelete(t *testing.T) { - c, m := newFakeController() + // try again, should be no change + gs.Status.State = stablev1alpha1.GameServerStateReady + watch.Modify(gs.DeepCopy()) - deleted := false - m.AgonesClient.AddReactor("delete", "gameserverallocations", func(action k8stesting.Action) (bool, runtime.Object, error) { - da := action.(k8stesting.DeleteAction) - assert.Equal(t, "default", da.GetNamespace()) - assert.Equal(t, "allocation", da.GetName()) - deleted = true + assertCacheEntries(1) - return true, nil, nil - }) + // now move it to Shutdown + gs.Status.State = stablev1alpha1.GameServerStateShutdown + watch.Modify(gs.DeepCopy()) - err := c.syncDelete("default/allocation") - assert.Nil(t, err) - assert.True(t, deleted) + assertCacheEntries(0) } func TestGetRandomlySelectedGS(t *testing.T) { @@ -786,26 +727,26 @@ func TestGetRandomlySelectedGS(t *testing.T) { assert.Equal(t, "gs1", selectedGS.ObjectMeta.Name) } -func defaultFixtures(gsLen int) (*v1alpha1.Fleet, *v1alpha1.GameServerSet, []v1alpha1.GameServer) { - f := &v1alpha1.Fleet{ +func defaultFixtures(gsLen int) (*stablev1alpha1.Fleet, *stablev1alpha1.GameServerSet, []stablev1alpha1.GameServer) { + f := &stablev1alpha1.Fleet{ ObjectMeta: metav1.ObjectMeta{ Name: "fleet-1", Namespace: defaultNs, UID: "1234", }, - Spec: v1alpha1.FleetSpec{ + Spec: stablev1alpha1.FleetSpec{ Replicas: 5, - Template: v1alpha1.GameServerTemplateSpec{}, + Template: stablev1alpha1.GameServerTemplateSpec{}, }, } f.ApplyDefaults() gsSet := f.GameServerSet() gsSet.ObjectMeta.Name = "gsSet1" - var gsList []v1alpha1.GameServer + var gsList []stablev1alpha1.GameServer for i := 1; i <= gsLen; i++ { gs := gsSet.GameServer() gs.ObjectMeta.Name = "gs" + strconv.Itoa(i) - gs.Status.State = v1alpha1.GameServerStateReady + gs.Status.State = stablev1alpha1.GameServerStateReady gsList = append(gsList, *gs) } return f, gsSet, gsList @@ -814,29 +755,10 @@ func defaultFixtures(gsLen int) (*v1alpha1.Fleet, *v1alpha1.GameServerSet, []v1a // newFakeController returns a controller, backed by the fake Clientset func newFakeController() (*Controller, agtesting.Mocks) { m := agtesting.NewMocks() - wh := webhooks.NewWebHook(http.NewServeMux()) + m.Mux = http.NewServeMux() counter := gameservers.NewPerNodeCounter(m.KubeInformerFactory, m.AgonesInformerFactory) - c := NewController(wh, healthcheck.NewHandler(), counter, 1, m.KubeClient, m.ExtClient, m.AgonesClient, m.AgonesInformerFactory) + api := apiserver.NewAPIServer(m.Mux) + c := NewController(api, healthcheck.NewHandler(), counter, 1, m.KubeClient, m.AgonesClient, m.AgonesInformerFactory) c.recorder = m.FakeRecorder return c, m } - -// newAdmissionReview -func newAdmissionReview(gsa v1alpha1.GameServerAllocation) (admv1beta1.AdmissionReview, error) { - raw, err := json.Marshal(gsa) - if err != nil { - return admv1beta1.AdmissionReview{}, err - } - review := admv1beta1.AdmissionReview{ - Request: &admv1beta1.AdmissionRequest{ - Kind: gvk, - Operation: admv1beta1.Create, - Object: runtime.RawExtension{ - Raw: raw, - }, - Namespace: defaultNs, - }, - Response: &admv1beta1.AdmissionResponse{Allowed: true}, - } - return review, err -} diff --git a/pkg/gameserversets/controller.go b/pkg/gameserversets/controller.go index ae28754299..da12a31b94 100644 --- a/pkg/gameserversets/controller.go +++ b/pkg/gameserversets/controller.go @@ -18,6 +18,7 @@ import ( "encoding/json" "sync" + "agones.dev/agones/pkg/apis" "agones.dev/agones/pkg/apis/stable" "agones.dev/agones/pkg/apis/stable/v1alpha1" "agones.dev/agones/pkg/client/clientset/versioned" @@ -357,7 +358,7 @@ func (c *Controller) syncGameServerSet(key string) error { // computeReconciliationAction computes the action to take to reconcile a game server set set given // the list of game servers that were found and target replica count. -func computeReconciliationAction(strategy v1alpha1.SchedulingStrategy, list []*v1alpha1.GameServer, +func computeReconciliationAction(strategy apis.SchedulingStrategy, list []*v1alpha1.GameServer, counts map[string]gameservers.NodeCount, targetReplicaCount int, maxCreations int, maxDeletions int, maxPending int) (int, []*v1alpha1.GameServer, bool) { var upCount int // up == Ready or will become ready @@ -457,7 +458,7 @@ func computeReconciliationAction(strategy v1alpha1.SchedulingStrategy, list []*v } if deleteCount > 0 { - if strategy == v1alpha1.Packed { + if strategy == apis.Packed { potentialDeletions = sortGameServersByLeastFullNodes(potentialDeletions, counts) } else { potentialDeletions = sortGameServersByNewFirst(potentialDeletions) diff --git a/pkg/gameserversets/controller_test.go b/pkg/gameserversets/controller_test.go index 93b66a7962..88bca9f2fe 100644 --- a/pkg/gameserversets/controller_test.go +++ b/pkg/gameserversets/controller_test.go @@ -21,6 +21,7 @@ import ( "testing" "time" + "agones.dev/agones/pkg/apis" "agones.dev/agones/pkg/apis/stable/v1alpha1" "agones.dev/agones/pkg/gameservers" agtesting "agones.dev/agones/pkg/testing" @@ -160,7 +161,7 @@ func TestComputeReconciliationAction(t *testing.T) { for _, tc := range cases { t.Run(tc.desc, func(t *testing.T) { - toAdd, toDelete, isPartial := computeReconciliationAction(v1alpha1.Distributed, tc.list, map[string]gameservers.NodeCount{}, + toAdd, toDelete, isPartial := computeReconciliationAction(apis.Distributed, tc.list, map[string]gameservers.NodeCount{}, tc.targetReplicaCount, maxTestCreationsPerBatch, maxTestDeletionsPerBatch, maxTestPendingPerBatch) assert.Equal(t, tc.wantNumServersToAdd, toAdd, "# of GameServers to add") @@ -178,7 +179,7 @@ func TestComputeReconciliationAction(t *testing.T) { } counts := map[string]gameservers.NodeCount{"node1": {Ready: 1}, "node3": {Ready: 2}} - toAdd, toDelete, isPartial := computeReconciliationAction(v1alpha1.Packed, list, counts, 2, + toAdd, toDelete, isPartial := computeReconciliationAction(apis.Packed, list, counts, 2, 1000, 1000, 1000) assert.Empty(t, toAdd) @@ -203,7 +204,7 @@ func TestComputeReconciliationAction(t *testing.T) { CreationTimestamp: metav1.Time{Time: now.Add(30 * time.Second)}}, Status: v1alpha1.GameServerStatus{State: v1alpha1.GameServerStateReady}}, } - toAdd, toDelete, isPartial := computeReconciliationAction(v1alpha1.Distributed, list, map[string]gameservers.NodeCount{}, + toAdd, toDelete, isPartial := computeReconciliationAction(apis.Distributed, list, map[string]gameservers.NodeCount{}, 2, 1000, 1000, 1000) assert.Empty(t, toAdd) @@ -597,7 +598,7 @@ func defaultFixture() *v1alpha1.GameServerSet { ObjectMeta: metav1.ObjectMeta{Namespace: "default", Name: "test", UID: "1234"}, Spec: v1alpha1.GameServerSetSpec{ Replicas: 10, - Scheduling: v1alpha1.Packed, + Scheduling: apis.Packed, Template: v1alpha1.GameServerTemplateSpec{}, }, } diff --git a/pkg/testing/controller.go b/pkg/testing/controller.go index 7b9e749e95..23bc730ff7 100644 --- a/pkg/testing/controller.go +++ b/pkg/testing/controller.go @@ -16,6 +16,7 @@ package testing import ( "context" + "net/http" gotesting "testing" "time" @@ -41,6 +42,7 @@ type Mocks struct { AgonesClient *agonesfake.Clientset AgonesInformerFactory externalversions.SharedInformerFactory FakeRecorder *record.FakeRecorder + Mux *http.ServeMux } // NewMocks creates a new set of fakes and mocks. diff --git a/site/content/en/docs/Getting Started/create-fleet.md b/site/content/en/docs/Getting Started/create-fleet.md index 9d6aa3f622..508893c61e 100644 --- a/site/content/en/docs/Getting Started/create-fleet.md +++ b/site/content/en/docs/Getting Started/create-fleet.md @@ -176,6 +176,7 @@ For the full details of the YAML file head to the [Fleet Specification Guide]({{ You should get back a response that looks like the following: +{{% feature expiryVersion="0.10.0" %}} ```yaml apiVersion: stable.agones.dev/v1alpha1 kind: GameServerAllocation @@ -210,10 +211,36 @@ status: port: 7623 state: Allocated ``` +{{% /feature %}} + +{{% feature publishVersion="0.10.0" %}} +```yaml +apiVersion: allocation.agones.dev/v1alpha1 +kind: GameServerAllocation +metadata: + creationTimestamp: 2019-02-19T02:13:12Z + name: simple-udp-dph9b-hfk24 + namespace: default +spec: + metadata: {} + required: + matchLabels: + stable.agones.dev/fleet: simple-udp + scheduling: Packed +status: + address: 192.168.122.152 + gameServerName: simple-udp-dph9b-hfk24 + nodeName: minikube + ports: + - name: default + port: 7714 + state: Allocated +``` +{{% /feature %}} If you look at the `status` section, there are several things to take note of. The `state` value will tell if a `GameServer` was allocated or not. If a `GameServer` could not be found, this will be set to `UnAllocated`. -{{% feature publishVersion="0.9.0" %}}If there are too many concurrent requests overwhelmed the system, `state` will be set to +{{% feature publishVersion="0.10.0" %}}If too many concurrent requests overwhelmed the system, `state` will be set to `Contention`even though there are available `GameServer`.{{% /feature %}} However, we see that the `status.state` value was set to `Allocated`. @@ -240,6 +267,11 @@ simple-udp-sdhzn-wng5k Ready 192.168.122.205 7709 minikube 53m simple-udp-sdhzn-wnhsw Ready 192.168.122.205 7478 minikube 52m ``` +{{% feature publishVersion="0.10.0" %}} +> `GameServerAllocations` are create only and not stored for performance reasons, so you won't be able to list + them after they have been created - but you can see their effects on `GameServers` +{{% /feature %}} + #### FleetAllocation We can do allocation of a GameServer for usage through a `FleetAllocation`, which will both return to us a `GameServer` (assuming one is available) diff --git a/site/content/en/docs/Installation/helm.md b/site/content/en/docs/Installation/helm.md index c75579375f..815b237b64 100644 --- a/site/content/en/docs/Installation/helm.md +++ b/site/content/en/docs/Installation/helm.md @@ -164,6 +164,7 @@ The following tables lists the configurable parameters of the Agones chart and t | Parameter | Description | Default | | --------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ---------------------- | +| `agones.registerApiService` | Registers the apiservice(s) used for the Kubernetes API extension | `true` | | `agones.controller.persistentLogs` | Store Agones controller logs in a temporary volume attached to a container for debugging | `true` | | `agones.controller.persistentLogsSizeLimitMB` | Maximum total size of all Agones container logs in MB | `10000` | diff --git a/site/content/en/docs/Reference/agones_crd_api_reference.html b/site/content/en/docs/Reference/agones_crd_api_reference.html index 0f88262e89..ffb1855014 100644 --- a/site/content/en/docs/Reference/agones_crd_api_reference.html +++ b/site/content/en/docs/Reference/agones_crd_api_reference.html @@ -3,7 +3,7 @@ description="Detailed list of Agones Custom Resource Definitions available" +++ -{{% feature publishVersion="0.8.0" %}} +{{% feature expiryVersion="0.9.0" %}}

Packages: